Ignore:
Timestamp:
Oct 26, 2009 3:47:52 PM (14 years ago)
Author:
nanang
Message:

Ticket #957:

  • Added features in secure socket: handshake timeout timer, certificate info, renegotiation API.
  • Added unit test for secure socket, along with testing purpose certificate & private key.
  • Updated build configs for secure socket.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c

    r2950 r2970  
    2626#include <pj/log.h> 
    2727#include <pj/math.h> 
     28#include <pj/os.h> 
    2829#include <pj/pool.h> 
    2930#include <pj/string.h> 
     31#include <pj/timer.h> 
    3032 
    3133 
    3234/* Only build when PJ_HAS_SSL_SOCK is enabled */ 
    33 //#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK!=0 
     35#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK!=0 
    3436 
    3537#define THIS_FILE               "ssl_sock_ossl.c" 
     
    130132    pj_ssl_sock_param     param; 
    131133    pj_ssl_cert_t        *cert; 
     134     
     135    pj_ssl_cert_info      local_cert_info; 
     136    pj_ssl_cert_info      remote_cert_info; 
    132137 
    133138    pj_bool_t             is_server; 
    134139    enum ssl_state        ssl_state; 
    135140    pj_ioqueue_op_key_t   handshake_op_key; 
     141    pj_timer_entry        handshake_timer; 
    136142 
    137143    pj_sock_t             sock; 
     
    180186 */ 
    181187 
    182 /* ssl_report_error() */ 
    183 static void ssl_report_error(const char *sender, int level,  
    184                              pj_status_t status, 
    185                              const char *format, ...) 
    186 { 
    187     va_list marker; 
    188  
    189     va_start(marker, format); 
    190  
    191 #if PJ_LOG_MAX_LEVEL > 0 
    192     if (status != PJ_SUCCESS) { 
    193         char err_format[PJ_ERR_MSG_SIZE + 512]; 
    194         int len; 
    195  
    196         len = pj_ansi_snprintf(err_format, sizeof(err_format), 
    197                                "%s: ", format); 
    198         pj_strerror(status, err_format+len, sizeof(err_format)-len); 
    199          
    200         pj_log(sender, level, err_format, marker); 
    201  
    202     } else { 
    203         unsigned long ssl_err; 
    204  
    205         ssl_err = ERR_get_error(); 
    206  
    207         if (ssl_err == 0) { 
    208             pj_log(sender, level, format, marker); 
    209         } else { 
    210             char err_format[512]; 
    211             int len; 
    212  
    213             len = pj_ansi_snprintf(err_format, sizeof(err_format), 
    214                                    "%s: ", format); 
    215             ERR_error_string(ssl_err, err_format+len); 
    216              
    217             pj_log(sender, level, err_format, marker); 
    218         } 
    219     } 
    220 #endif 
    221  
    222     va_end(marker); 
    223 } 
    224  
     188/** 
     189 * Mapping from OpenSSL error codes to pjlib error space. 
     190 */ 
     191 
     192#define PJ_SSL_ERRNO_START              (PJ_ERRNO_START_USER + \ 
     193                                         PJ_ERRNO_SPACE_SIZE*6) 
     194 
     195#define PJ_SSL_ERRNO_SPACE_SIZE         5000 
     196 
     197#define PJ_STATUS_FROM_OSSL(ossl_err)   (ossl_err == SSL_ERROR_NONE? \ 
     198                                         PJ_SUCCESS : \ 
     199                                         (PJ_SSL_ERRNO_START + ossl_err)) 
     200 
     201#define PJ_STATUS_TO_OSSL(status)       (status == PJ_SUCCESS? \ 
     202                                         SSL_ERROR_NONE : \ 
     203                                        (status - PJ_SSL_ERRNO_START)) 
     204 
     205 
     206/* 
     207 * Get error string of OpenSSL. 
     208 */ 
     209static pj_str_t ssl_strerror(pj_status_t status,  
     210                             char *buf, pj_size_t bufsize) 
     211{ 
     212    pj_str_t errstr; 
     213    unsigned long ssl_err = PJ_STATUS_TO_OSSL(status); 
     214 
     215#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0) 
     216 
     217    ERR_error_string_n(ssl_err, buf, bufsize); 
     218    errstr = pj_str(buf); 
     219 
     220#else 
     221 
     222    errstr.ptr = buf; 
     223    errstr.slen = pj_ansi_snprintf(buf, bufsize,  
     224                                   "Unknown OpenSSL error %d", 
     225                                   ssl_err); 
     226 
     227#endif  /* PJ_HAS_ERROR_STRING */ 
     228 
     229    return errstr; 
     230} 
    225231 
    226232 
    227233/* OpenSSL library initialization counter */ 
    228234static int openssl_init_count; 
     235static int openssl_reg_strerr; 
    229236 
    230237/* OpenSSL available ciphers */ 
    231 static pj_ssl_cipher openssl_ciphers[64]; 
     238static pj_ssl_cipher openssl_ciphers[100]; 
    232239static unsigned openssl_cipher_num; 
    233240 
     
    239246        return PJ_SUCCESS; 
    240247 
     248    /* Register error subsystem */ 
     249    if (!openssl_reg_strerr) { 
     250        pj_status_t status; 
     251 
     252        openssl_reg_strerr = 1; 
     253        status = pj_register_strerror(PJ_SSL_ERRNO_START,  
     254                                      PJ_SSL_ERRNO_SPACE_SIZE,  
     255                                      &ssl_strerror); 
     256        pj_assert(status == PJ_SUCCESS); 
     257    } 
     258 
     259    /* Init OpenSSL lib */ 
    241260    SSL_library_init(); 
    242261    SSL_load_error_strings(); 
     
    345364        break; 
    346365    default: 
    347         ssl_report_error(THIS_FILE, 4, PJ_EINVAL, 
    348                          "Error creating SSL context"); 
    349366        return PJ_EINVAL; 
    350367    } 
     
    353370    ctx = SSL_CTX_new(ssl_method); 
    354371    if (ctx == NULL) { 
    355         ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    356                          "Error creating SSL context"); 
    357         return PJ_EINVAL; 
     372        PJ_LOG(1,(ssock->pool->obj_name, "Error creating OpenSSL context")); 
     373        return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    358374    } 
    359375 
     
    366382 
    367383            if (rc != 1) { 
    368                 ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    369                                  "Error loading/verifying CA list file '%s'", 
    370                                  cert->CA_file.ptr); 
     384                PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file " 
     385                          "'%s'", cert->CA_file.ptr)); 
    371386                SSL_CTX_free(ctx); 
    372                 return PJ_EINVAL; 
     387                return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    373388            } 
    374  
    375             PJ_LOG(5,(THIS_FILE, "CA file successfully loaded from '%s'", 
    376                       cert->CA_file.ptr)); 
    377389        } 
    378390     
     
    391403 
    392404            if(rc != 1) { 
    393                 ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    394                                  "Error loading certificate chain file '%s'", 
    395                                  cert->cert_file.ptr); 
     405                PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate " 
     406                          "chain file '%s'", cert->cert_file.ptr)); 
    396407                SSL_CTX_free(ctx); 
    397                 return PJ_EINVAL; 
     408                return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    398409            } 
    399  
    400             PJ_LOG(5,(THIS_FILE, "TLS certificate successfully loaded from '%s'", 
    401                       cert->cert_file.ptr)); 
    402410        } 
    403411 
     
    410418 
    411419            if(rc != 1) { 
    412                 ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    413                                  "Error adding private key from '%s'", 
    414                                  cert->privkey_file.ptr); 
     420                PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key " 
     421                          "from '%s'", cert->privkey_file.ptr)); 
    415422                SSL_CTX_free(ctx); 
    416                 return PJ_EINVAL; 
     423                return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    417424            } 
    418  
    419             PJ_LOG(5,(THIS_FILE, "Private key successfully loaded from '%s'", 
    420                       cert->privkey_file.ptr)); 
    421425        } 
    422426    } 
     
    431435 
    432436    if (ssock->is_server && ssock->param.require_client_cert) 
    433         mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 
     437        mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER; 
    434438 
    435439    SSL_CTX_set_verify(ctx, mode, NULL); 
    436  
    437     PJ_LOG(5,(THIS_FILE, "Verification mode set to %d", mode)); 
    438440 
    439441    *p_ctx = ctx; 
     
    472474        pj_activesock_close(ssock->asock); 
    473475        ssock->asock = NULL; 
     476        ssock->sock = PJ_INVALID_SOCKET; 
     477    } 
     478    if (ssock->sock != PJ_INVALID_SOCKET) { 
     479        pj_sock_close(ssock->sock); 
    474480        ssock->sock = PJ_INVALID_SOCKET; 
    475481    } 
     
    529535    /* Finally, set chosen cipher list */ 
    530536    ret = SSL_set_cipher_list(ssock->ossl_ssl, buf); 
    531     if (ret < 1) { 
    532         ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    533                          "Error setting cipher list"); 
    534         return PJ_EINVAL; 
    535     } 
     537    if (ret < 1) 
     538        return PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
    536539 
    537540    return PJ_SUCCESS; 
     541} 
     542 
     543 
     544/* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */ 
     545static pj_bool_t parse_ossl_asn1_time(pj_time_val *tv, pj_bool_t *gmt, 
     546                                      const ASN1_TIME *tm) 
     547{ 
     548    unsigned long parts[7] = {0}; 
     549    char *p, *end; 
     550    unsigned len; 
     551    pj_bool_t utc; 
     552    pj_parsed_time pt; 
     553    int i; 
     554 
     555    utc = tm->type == V_ASN1_UTCTIME; 
     556    p = (char*)tm->data; 
     557    len = tm->length; 
     558    end = p + len - 1; 
     559 
     560    /* GMT */ 
     561    *gmt = (*end == 'Z'); 
     562 
     563    /* parse parts */ 
     564    for (i = 0; i < 7 && p < end; ++i) { 
     565        pj_str_t st; 
     566 
     567        if (i==0 && !utc) { 
     568            /* 4 digits year part for non-UTC time format */ 
     569            st.slen = 4; 
     570        } else if (i==6) { 
     571            /* fraction of seconds */ 
     572            if (*p == '.') ++p; 
     573            st.slen = end - p + 1; 
     574        } else { 
     575            /* other parts always 2 digits length */ 
     576            st.slen = 2; 
     577        } 
     578        st.ptr = p; 
     579 
     580        parts[i] = pj_strtoul(&st); 
     581        p += st.slen; 
     582    } 
     583 
     584    /* encode parts to pj_time_val */ 
     585    pt.year = parts[0]; 
     586    if (utc) 
     587        pt.year += (pt.year < 50)? 2000:1900; 
     588    pt.mon = parts[1] - 1; 
     589    pt.day = parts[2]; 
     590    pt.hour = parts[3]; 
     591    pt.min = parts[4]; 
     592    pt.sec = parts[5]; 
     593    pt.msec = parts[6]; 
     594 
     595    pj_time_encode(&pt, tv); 
     596 
     597    return PJ_TRUE; 
     598} 
     599 
     600 
     601/* Get certificate info from OpenSSL X509 */ 
     602static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x) 
     603{ 
     604    pj_ssl_cert_info info; 
     605    char buf1[256]; 
     606    char buf2[256]; 
     607 
     608    pj_assert(pool && ci); 
     609 
     610    if (!x) { 
     611        pj_bzero(ci, sizeof(pj_ssl_cert_info)); 
     612        return; 
     613    } 
     614 
     615    pj_bzero(&info, sizeof(info)); 
     616 
     617    /* Populate cert info */ 
     618    info.subject = pj_str(X509_NAME_oneline(X509_get_subject_name(x),buf1, 
     619                                            sizeof(buf1))); 
     620    info.issuer = pj_str(X509_NAME_oneline(X509_get_issuer_name(x), buf2, 
     621                                           sizeof(buf2))); 
     622    info.version = X509_get_version(x) + 1; 
     623    parse_ossl_asn1_time(&info.validity_start, &info.validity_use_gmt, 
     624                         X509_get_notBefore(x)); 
     625    parse_ossl_asn1_time(&info.validity_end, &info.validity_use_gmt, 
     626                         X509_get_notAfter(x)); 
     627 
     628    /* Update certificate info */ 
     629    if (pj_strcmp(&ci->subject, &info.subject)) 
     630        pj_strdup(pool, &ci->subject, &info.subject); 
     631    if (pj_strcmp(&ci->issuer, &info.issuer)) 
     632        pj_strdup(pool, &ci->issuer, &info.issuer); 
     633    ci->version = info.version; 
     634    ci->validity_start = info.validity_start; 
     635    ci->validity_end = info.validity_end; 
     636    ci->validity_use_gmt = info.validity_use_gmt; 
     637} 
     638 
     639 
     640/* Update local & remote certificates info. This function should be 
     641 * called after handshake or renegotiation successfully completed. 
     642 */ 
     643static void update_certs_info(pj_ssl_sock_t *ssock) 
     644{ 
     645    X509 *x; 
     646 
     647    pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED); 
     648 
     649    /* Active local certificate */ 
     650    x = SSL_get_certificate(ssock->ossl_ssl); 
     651    get_cert_info(ssock->pool, &ssock->local_cert_info, x); 
     652    /* Don't free local's X509! */ 
     653 
     654    /* Active remote certificate */ 
     655    x = SSL_get_peer_certificate(ssock->ossl_ssl); 
     656    get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
     657    /* Free peer's X509 */ 
     658    X509_free(x); 
    538659} 
    539660 
     
    547668                                       pj_status_t status) 
    548669{ 
     670    /* Cancel handshake timer */ 
     671    if (ssock->param.timer_heap) 
     672        pj_timer_heap_cancel(ssock->param.timer_heap, &ssock->handshake_timer); 
     673 
     674    /* Update certificates info on successful handshake */ 
     675    if (status == PJ_SUCCESS) 
     676        update_certs_info(ssock); 
     677 
    549678    /* Accepting */ 
    550679    if (ssock->is_server) { 
     
    708837} 
    709838 
     839 
     840static void handshake_timeout_cb(pj_timer_heap_t *th, 
     841                                 struct pj_timer_entry *te) 
     842{ 
     843    pj_ssl_sock_t *ssock = (pj_ssl_sock_t*)te->user_data; 
     844 
     845    PJ_UNUSED_ARG(th); 
     846 
     847    PJ_LOG(1,(ssock->pool->obj_name, "SSL handshake timeout after %d.%ds", 
     848              ssock->param.timeout.sec, ssock->param.timeout.msec)); 
     849 
     850    on_handshake_complete(ssock, PJ_ETIMEDOUT); 
     851} 
     852 
     853 
     854/* Asynchronouse handshake */ 
    710855static pj_status_t do_handshake(pj_ssl_sock_t *ssock) 
    711856{ 
     
    722867        { 
    723868            /* Handshake fails */ 
    724             ssl_report_error(THIS_FILE, 4, PJ_SUCCESS,  
    725                              "SSL_do_handshake()"); 
    726869            pj_lock_release(ssock->write_mutex); 
    727             return PJ_ECANCELLED; 
     870            return PJ_STATUS_FROM_OSSL(err); 
    728871        } 
    729872    } 
     
    767910 
    768911    /* Socket error or closed */ 
    769     if (data == NULL || size < 0) 
    770         goto on_error; 
    771  
    772     /* Consume the whole data */ 
    773     nwritten = BIO_write(ssock->ossl_rbio, data, size); 
    774     if (nwritten < size) { 
    775         status = PJ_ENOMEM; 
    776         ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, "BIO_write()"); 
    777         goto on_error; 
     912    if (data && size > 0) { 
     913        /* Consume the whole data */ 
     914        nwritten = BIO_write(ssock->ossl_rbio, data, size); 
     915        if (nwritten < size) { 
     916            status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     917            goto on_error; 
     918        } 
    778919    } 
    779920 
     
    803944             */ 
    804945            pj_lock_acquire(ssock->write_mutex); 
    805  
    806946            size_ = SSL_read(ssock->ossl_ssl, data_, size_); 
    807             if (size_ > 0) { 
    808                 pj_lock_release(ssock->write_mutex); 
     947            pj_lock_release(ssock->write_mutex); 
     948 
     949            if (size_ > 0 || status != PJ_SUCCESS) { 
    809950                if (ssock->param.cb.on_data_read) { 
    810951                    pj_bool_t ret; 
    811952                    pj_size_t remainder_ = 0; 
    812953 
    813                     buf->len += size_; 
     954                    if (size_ > 0) 
     955                        buf->len += size_; 
    814956                 
    815957                    ret = (*ssock->param.cb.on_data_read)(ssock, buf->data, 
     
    826968                    buf->len = remainder_; 
    827969                } 
     970 
     971                /* Active socket signalled connection closed/error, this has 
     972                 * been signalled to the application along with any remaining 
     973                 * buffer. So, let's just reset SSL socket now. 
     974                 */ 
     975                if (status != PJ_SUCCESS) { 
     976                    reset_ssl_sock_state(ssock); 
     977                    return PJ_FALSE; 
     978                } 
     979 
    828980            } else { 
     981 
    829982                int err = SSL_get_error(ssock->ossl_ssl, size); 
    830983                 
     
    834987                if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
    835988                { 
     989                    char errmsg[PJ_ERR_MSG_SIZE]; 
     990 
     991                    pj_strerror(status, errmsg, sizeof(errmsg)); 
     992                    PJ_LOG(1,(ssock->pool->obj_name, "SSL_read() failed: %s", 
     993                              errmsg)); 
     994 
    836995                    /* Reset SSL socket state, then return PJ_FALSE */ 
    837                     ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, "SSL_read()"); 
     996                    reset_ssl_sock_state(ssock); 
     997                    goto on_error; 
     998                } 
     999 
     1000                status = do_handshake(ssock); 
     1001                if (status == PJ_SUCCESS) { 
     1002                    /* Renegotiation completed */ 
     1003 
     1004                    /* Update certificates */ 
     1005                    update_certs_info(ssock); 
     1006 
     1007                    pj_lock_acquire(ssock->write_mutex); 
     1008                    status = flush_delayed_send(ssock); 
    8381009                    pj_lock_release(ssock->write_mutex); 
    839                     reset_ssl_sock_state(ssock); 
    840                     return PJ_FALSE; 
    841                 } 
    842  
    843                 /* SSL may write something in case of re-negotiation */ 
    844                 status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0); 
    845                 pj_lock_release(ssock->write_mutex); 
    846                 if (status != PJ_SUCCESS && status != PJ_EPENDING) 
     1010 
     1011                    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     1012                        char errmsg[PJ_ERR_MSG_SIZE]; 
     1013 
     1014                        pj_strerror(status, errmsg, sizeof(errmsg)); 
     1015                        PJ_LOG(1,(ssock->pool->obj_name, "Failed to flush " 
     1016                                  "delayed send: %s", errmsg)); 
     1017                        goto on_error; 
     1018                    } 
     1019                } else if (status != PJ_EPENDING) { 
     1020                    char errmsg[PJ_ERR_MSG_SIZE]; 
     1021 
     1022                    pj_strerror(status, errmsg, sizeof(errmsg)); 
     1023                    PJ_LOG(1,(ssock->pool->obj_name, "Renegotiation failed: " 
     1024                              "%s", errmsg)); 
    8471025                    goto on_error; 
    848  
    849                 /* If re-negotiation has been completed, start flushing 
    850                  * delayed send. 
    851                  */ 
    852                 if (!SSL_renegotiate_pending(ssock->ossl_ssl)) { 
    853                     status = flush_delayed_send(ssock); 
    854                     if (status != PJ_SUCCESS && status != PJ_EPENDING) 
    855                         goto on_error; 
    8561026                } 
    8571027 
     
    9441114    unsigned i; 
    9451115    pj_status_t status; 
     1116    char buf[64]; 
    9461117 
    9471118    PJ_UNUSED_ARG(src_addr_len); 
     1119 
     1120    PJ_LOG(4,(ssock_parent->pool->obj_name, "Incoming connection from %s", 
     1121              pj_sockaddr_print(src_addr, buf, sizeof(buf), 3))); 
    9481122 
    9491123    /* Create new SSL socket instance */ 
     
    9821156    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    9831157    if (ssock->ossl_ssl == NULL) { 
    984         ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    985                          "Error creating SSL connection object"); 
    986         status = PJ_EINVAL; 
     1158        PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
     1159        status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    9871160        goto on_return; 
    9881161    } 
     
    10501223    ssock->write_state.len = 0; 
    10511224 
     1225    /* Start handshake timer */ 
     1226    if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 || 
     1227        ssock->param.timeout.msec != 0)) 
     1228    { 
     1229        pj_timer_entry_init(&ssock->handshake_timer, 0, ssock,  
     1230                            &handshake_timeout_cb); 
     1231        pj_timer_heap_schedule(ssock->param.timer_heap, &ssock->handshake_timer, 
     1232                               &ssock->param.timeout); 
     1233    } 
     1234 
    10521235    /* Start SSL handshake */ 
    10531236    ssock->ssl_state = SSL_STATE_HANDSHAKING; 
     
    10891272    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    10901273    if (ssock->ossl_ssl == NULL) { 
    1091         ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, 
    1092                          "Error creating SSL connection object"); 
    1093         status = PJ_EINVAL; 
     1274        PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
     1275        status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
    10941276        goto on_return; 
    10951277    } 
     
    11351317    ssock->write_state.len = 0; 
    11361318 
     1319    /* Start handshake timer */ 
     1320    if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 || 
     1321        ssock->param.timeout.msec != 0)) 
     1322    { 
     1323        pj_timer_entry_init(&ssock->handshake_timer, 0, ssock,  
     1324                            &handshake_timeout_cb); 
     1325        pj_timer_heap_schedule(ssock->param.timer_heap, 
     1326                               &ssock->handshake_timer, 
     1327                               &ssock->param.timeout); 
     1328    } 
     1329 
     1330#ifdef SSL_set_tlsext_host_name 
     1331    /* Set server name to connect */ 
     1332    if (ssock->param.server_name.slen) { 
     1333        /* Server name is null terminated already */ 
     1334        if (!SSL_set_tlsext_host_name(ssock->ossl_ssl,  
     1335                                      ssock->param.server_name.ptr)) 
     1336        { 
     1337            char err_str[PJ_ERR_MSG_SIZE]; 
     1338 
     1339            ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str)); 
     1340            PJ_LOG(3,(ssock->pool->obj_name, "SSL_set_tlsext_host_name() " 
     1341                "failed: %s", err_str)); 
     1342        } 
     1343    } 
     1344#endif 
     1345 
    11371346    /* Start SSL handshake */ 
    11381347    ssock->ssl_state = SSL_STATE_HANDSHAKING; 
    11391348    SSL_set_connect_state(ssock->ossl_ssl); 
     1349 
    11401350    status = do_handshake(ssock); 
    11411351    if (status != PJ_EPENDING) 
     
    11861396                                            const pj_ssl_cert_t *cert) 
    11871397{ 
     1398    pj_ssl_cert_t *cert_; 
     1399 
    11881400    PJ_ASSERT_RETURN(ssock && pool && cert, PJ_EINVAL); 
    11891401 
    1190     ssock->cert = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t); 
    1191     pj_strdup_with_null(pool, &ssock->cert->CA_file, &cert->CA_file); 
    1192     pj_strdup_with_null(pool, &ssock->cert->cert_file, &cert->cert_file); 
    1193     pj_strdup_with_null(pool, &ssock->cert->privkey_file, &cert->privkey_file); 
    1194     pj_strdup_with_null(pool, &ssock->cert->privkey_pass, &cert->privkey_pass); 
     1402    cert_ = PJ_POOL_ZALLOC_T(pool, pj_ssl_cert_t); 
     1403    pj_memcpy(cert_, cert, sizeof(cert)); 
     1404    pj_strdup_with_null(pool, &cert_->CA_file, &cert->CA_file); 
     1405    pj_strdup_with_null(pool, &cert_->cert_file, &cert->cert_file); 
     1406    pj_strdup_with_null(pool, &cert_->privkey_file, &cert->privkey_file); 
     1407    pj_strdup_with_null(pool, &cert_->privkey_pass, &cert->privkey_pass); 
     1408 
     1409    ssock->cert = cert_; 
    11951410 
    11961411    return PJ_SUCCESS; 
     
    12631478            ssock->param.ciphers[i] = param->ciphers[i]; 
    12641479    } 
    1265     pj_strdup_with_null(pool, &ssock->param.servername,  
    1266                         &param->servername); 
     1480 
     1481    /* Server name must be null-terminated */ 
     1482    pj_strdup_with_null(pool, &ssock->param.server_name,  
     1483                        &param->server_name); 
    12671484 
    12681485    /* Finally */ 
     
    13461563        /* Remote address */ 
    13471564        pj_sockaddr_cp(&info->remote_addr, &ssock->rem_addr); 
     1565 
     1566        /* Certificates info */ 
     1567        info->local_cert_info = ssock->local_cert_info; 
     1568        info->remote_cert_info = ssock->remote_cert_info; 
    13481569    } 
    13491570 
     
    14901711            status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0); 
    14911712            if (status == PJ_SUCCESS || status == PJ_EPENDING) 
     1713                /* Just return PJ_EBUSY when re-negotiation is on progress */ 
    14921714                status = PJ_EBUSY; 
    14931715        } else { 
    14941716            /* Some problem occured */ 
    1495             ssl_report_error(THIS_FILE, 4, PJ_SUCCESS, "SSL_write()"); 
    1496             status = PJ_ECANCELLED; 
     1717            status = PJ_STATUS_FROM_OSSL(err); 
    14971718        } 
    14981719    } else { 
     
    17771998 
    17781999 
    1779 //#endif  /* PJ_HAS_SSL_SOCK */ 
    1780  
     2000PJ_DEF(pj_status_t) pj_ssl_sock_renegotiate(pj_ssl_sock_t *ssock) 
     2001{ 
     2002    int ret; 
     2003    pj_status_t status; 
     2004 
     2005    PJ_ASSERT_RETURN(ssock->ssl_state == SSL_STATE_ESTABLISHED, PJ_EINVALIDOP); 
     2006 
     2007    if (SSL_renegotiate_pending(ssock->ossl_ssl)) 
     2008        return PJ_EPENDING; 
     2009 
     2010    ret = SSL_renegotiate(ssock->ossl_ssl); 
     2011    if (ret <= 0) { 
     2012        status = PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
     2013    } else { 
     2014        status = do_handshake(ssock); 
     2015    } 
     2016 
     2017    return status; 
     2018} 
     2019 
     2020#endif  /* PJ_HAS_SSL_SOCK */ 
     2021 
Note: See TracChangeset for help on using the changeset viewer.