Ignore:
Timestamp:
Feb 24, 2010 5:43:34 AM (12 years ago)
Author:
nanang
Message:

Ticket #1032:

  • Initial version of server domain name verification:
    • Updated SSL certificate info, especially identities info
    • Updated verification mechanism as in the specifications in ticket desc.
    • Added server domain name info in pjsip_tx_data.
    • Added alternative API for acquiring transport and creating transport of transport factory to include pjsip_tx_data param.
    • Server identity match criteria:
      • full host name match
      • wild card not accepted
      • if identity is URI, it must be SIP/SIPS URI
  • Initial version of transport state notifications:
    • Added new API to set transport state callback in PJSIP and PJSUA.
    • Defined states: connected/disconnected, accepted/rejected, verification errors.
  • Minors:
    • Updated SSL socket test: dump verification result, test of requiring client cert, and few minors.
    • Updated test cert to include subjectAltName extensions.
    • Added SSL certificate dump function.
    • Updated max number of socket async operations in Symbian sample apps (RSocketServ::Connect()) to 32 (was default 8).
File:
1 edited

Legend:

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

    r3020 r3106  
    4646#include <openssl/ssl.h> 
    4747#include <openssl/err.h> 
     48#include <openssl/x509v3.h> 
    4849 
    4950 
     
    153154    pj_ioqueue_op_key_t   handshake_op_key; 
    154155    pj_timer_entry        timer; 
     156    pj_status_t           verify_status; 
    155157 
    156158    pj_sock_t             sock; 
     
    208210#define PJ_SSL_ERRNO_SPACE_SIZE         PJ_ERRNO_SPACE_SIZE 
    209211 
     212#define STATUS_FROM_SSL_ERR(err, status) { \ 
     213    status = ERR_GET_LIB(err)*300 + ERR_GET_REASON(err);\ 
     214    pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
     215    if (status) status += PJ_SSL_ERRNO_START;\ 
     216} 
     217 
    210218#define GET_SSL_STATUS(status) { \ 
    211219    unsigned long e = ERR_get_error();\ 
    212     status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\ 
    213     pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
    214     if (status) status += PJ_SSL_ERRNO_START;\ 
     220    STATUS_FROM_SSL_ERR(e, status);\ 
    215221} 
    216222 
     
    236242    { 
    237243        const char *tmp = NULL; 
    238         tmp = ERR_reason_error_string(ssl_err); 
     244 
     245        if (ssl_err >= 300) 
     246            tmp = ERR_reason_error_string(ssl_err); 
     247        else 
     248            tmp = X509_verify_cert_error_string(ssl_err); 
    239249 
    240250        if (tmp) { 
     
    263273static pj_ssl_cipher openssl_ciphers[100]; 
    264274static unsigned openssl_cipher_num; 
     275 
     276/* OpenSSL application data index */ 
     277static int sslsock_idx; 
    265278 
    266279 
     
    330343    } 
    331344 
     345    /* Create OpenSSL application data index for SSL socket */ 
     346    sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
     347 
    332348    return PJ_SUCCESS; 
    333349} 
     
    356372 
    357373 
    358 /* Create and initialize new SSL context */ 
    359 static pj_status_t create_ssl_ctx(pj_ssl_sock_t *ssock, SSL_CTX **p_ctx) 
     374/* SSL password callback. */ 
     375static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) 
     376{ 
     377    pj_ssl_sock_t *ssock; 
     378    SSL *ossl_ssl; 
     379    int err; 
     380 
     381    /* Get SSL instance */ 
     382    ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx,  
     383                                    SSL_get_ex_data_X509_STORE_CTX_idx()); 
     384    pj_assert(ossl_ssl); 
     385 
     386    /* Get SSL socket instance */ 
     387    ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx); 
     388    pj_assert(ssock); 
     389 
     390    /* Store verification status */ 
     391    err = X509_STORE_CTX_get_error(x509_ctx); 
     392    switch (err) { 
     393    case X509_V_OK: 
     394        break; 
     395 
     396    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 
     397        ssock->verify_status |= PJ_SSL_CERT_EISSUER_NOT_FOUND; 
     398        break; 
     399 
     400    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 
     401    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 
     402    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: 
     403    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: 
     404        ssock->verify_status |= PJ_SSL_CERT_EINVALID_FORMAT; 
     405        break; 
     406 
     407    case X509_V_ERR_CERT_NOT_YET_VALID: 
     408    case X509_V_ERR_CERT_HAS_EXPIRED: 
     409        ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD; 
     410        break; 
     411 
     412    case X509_V_ERR_UNABLE_TO_GET_CRL: 
     413    case X509_V_ERR_CRL_NOT_YET_VALID: 
     414    case X509_V_ERR_CRL_HAS_EXPIRED: 
     415    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: 
     416    case X509_V_ERR_CRL_SIGNATURE_FAILURE: 
     417    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: 
     418    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: 
     419        ssock->verify_status |= PJ_SSL_CERT_ECRL_FAILURE; 
     420        break;   
     421 
     422    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 
     423    case X509_V_ERR_CERT_UNTRUSTED: 
     424    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 
     425    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 
     426        ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED; 
     427        break;   
     428 
     429    case X509_V_ERR_CERT_SIGNATURE_FAILURE: 
     430    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: 
     431    case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: 
     432    case X509_V_ERR_AKID_SKID_MISMATCH: 
     433    case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: 
     434    case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: 
     435        ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH; 
     436        break; 
     437 
     438    case X509_V_ERR_CERT_REVOKED: 
     439        ssock->verify_status |= PJ_SSL_CERT_EREVOKED; 
     440        break;   
     441 
     442    case X509_V_ERR_INVALID_PURPOSE: 
     443    case X509_V_ERR_CERT_REJECTED: 
     444    case X509_V_ERR_INVALID_CA: 
     445        ssock->verify_status |= PJ_SSL_CERT_EINVALID_PURPOSE; 
     446        break; 
     447 
     448    case X509_V_ERR_CERT_CHAIN_TOO_LONG: /* not really used */ 
     449    case X509_V_ERR_PATH_LENGTH_EXCEEDED: 
     450        ssock->verify_status |= PJ_SSL_CERT_ECHAIN_TOO_LONG; 
     451        break; 
     452 
     453    /* Unknown errors */ 
     454    case X509_V_ERR_OUT_OF_MEM: 
     455    default: 
     456        ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN; 
     457        break; 
     458    } 
     459 
     460    /* When verification is not requested just return ok here, however 
     461     * application can still get the verification status. 
     462     */ 
     463    if (PJ_FALSE == ssock->param.verify_peer) 
     464        preverify_ok = 1; 
     465 
     466    return preverify_ok; 
     467} 
     468 
     469/* Setting SSL sock cipher list */ 
     470static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock); 
     471 
     472 
     473/* Create and initialize new SSL context and instance */ 
     474static pj_status_t create_ssl(pj_ssl_sock_t *ssock) 
    360475{ 
    361476    SSL_METHOD *ssl_method; 
     
    365480    pj_status_t status; 
    366481         
    367     pj_assert(ssock && p_ctx); 
     482    pj_assert(ssock); 
    368483 
    369484    cert = ssock->cert; 
     
    394509    } 
    395510 
    396     /* Create SSL context for the listener */ 
     511    /* Create SSL context */ 
    397512    ctx = SSL_CTX_new(ssl_method); 
    398513    if (ctx == NULL) { 
     
    456571    } 
    457572 
     573    /* Create SSL instance */ 
     574    ssock->ossl_ctx = ctx; 
     575    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
     576    if (ssock->ossl_ssl == NULL) { 
     577        GET_SSL_STATUS(status); 
     578        return status; 
     579    } 
     580 
     581    /* Set SSL sock as application data of SSL instance */ 
     582    SSL_set_ex_data(ssock->ossl_ssl, sslsock_idx, ssock); 
    458583 
    459584    /* SSL verification options */ 
    460     if (ssock->param.verify_peer) { 
    461         mode = SSL_VERIFY_PEER; 
    462     } else { 
    463         mode = SSL_VERIFY_NONE; 
    464     } 
    465  
     585    mode = SSL_VERIFY_PEER; 
    466586    if (ssock->is_server && ssock->param.require_client_cert) 
    467         mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_PEER; 
    468  
    469     SSL_CTX_set_verify(ctx, mode, NULL); 
    470  
    471     *p_ctx = ctx; 
     587        mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 
     588 
     589    SSL_set_verify(ssock->ossl_ssl, mode, &verify_cb); 
     590 
     591    /* Set cipher list */ 
     592    status = set_cipher_list(ssock); 
     593    if (status != PJ_SUCCESS) 
     594        return status; 
     595 
     596    /* Setup SSL BIOs */ 
     597    ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
     598    ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
     599    BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
     600    BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
     601    SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    472602 
    473603    return PJ_SUCCESS; 
     
    475605 
    476606 
    477 /* Destroy SSL context */ 
    478 static void destroy_ssl_ctx(SSL_CTX *ctx) 
    479 { 
    480     SSL_CTX_free(ctx); 
     607/* Destroy SSL context and instance */ 
     608static void destroy_ssl(pj_ssl_sock_t *ssock) 
     609{ 
     610    /* Destroy SSL instance */ 
     611    if (ssock->ossl_ssl) { 
     612        SSL_shutdown(ssock->ossl_ssl); 
     613        SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 
     614        ssock->ossl_ssl = NULL; 
     615    } 
     616 
     617    /* Destroy SSL context */ 
     618    if (ssock->ossl_ctx) { 
     619        SSL_CTX_free(ssock->ossl_ctx); 
     620        ssock->ossl_ctx = NULL; 
     621    } 
    481622 
    482623    /* Potentially shutdown OpenSSL library if this is the last 
     
    492633    ssock->ssl_state = SSL_STATE_NULL; 
    493634 
    494     if (ssock->ossl_ssl) { 
    495         SSL_shutdown(ssock->ossl_ssl); 
    496         SSL_free(ssock->ossl_ssl); /* this will also close BIOs */ 
    497         ssock->ossl_ssl = NULL; 
    498     } 
    499     if (ssock->ossl_ctx) { 
    500         destroy_ssl_ctx(ssock->ossl_ctx); 
    501         ssock->ossl_ctx = NULL; 
    502     } 
     635    destroy_ssl(ssock); 
     636 
    503637    if (ssock->asock) { 
    504638        pj_activesock_close(ssock->asock); 
     
    640774 
    641775 
    642 /* Get certificate info from OpenSSL X509 */ 
     776/* Get Common Name field string from a general name string */ 
     777static void get_cn_from_gen_name(const pj_str_t *gen_name, pj_str_t *cn) 
     778{ 
     779    pj_str_t CN_sign = {"/CN=", 4}; 
     780    char *p, *q; 
     781 
     782    pj_bzero(cn, sizeof(cn)); 
     783 
     784    p = pj_strstr(gen_name, &CN_sign); 
     785    if (!p) 
     786        return; 
     787 
     788    p += 4; /* shift pointer to value part */ 
     789    pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr)); 
     790    q = pj_strchr(cn, '/'); 
     791    if (q) 
     792        cn->slen = q - p; 
     793} 
     794 
     795 
     796/* Get certificate info from OpenSSL X509, in case the certificate info 
     797 * hal already populated, this function will check if the contents need  
     798 * to be updated by inspecting the issuer and the serial number. 
     799 */ 
    643800static void get_cert_info(pj_pool_t *pool, pj_ssl_cert_info *ci, X509 *x) 
    644801{ 
    645     pj_ssl_cert_info info; 
    646     char buf1[256]; 
    647     char buf2[256]; 
    648  
    649     pj_assert(pool && ci); 
    650  
    651     if (!x) { 
    652         pj_bzero(ci, sizeof(pj_ssl_cert_info)); 
     802    pj_bool_t update_needed; 
     803    char buf[512]; 
     804    pj_uint8_t serial_no[64] = {0}; /* should be >= sizeof(ci->serial_no) */ 
     805    pj_uint8_t *p; 
     806    unsigned len; 
     807    GENERAL_NAMES *names = NULL; 
     808 
     809    pj_assert(pool && ci && x); 
     810 
     811    /* Get issuer */ 
     812    X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof(buf)); 
     813 
     814    /* Get serial no */ 
     815    p = (pj_uint8_t*) M_ASN1_STRING_data(X509_get_serialNumber(x)); 
     816    len = M_ASN1_STRING_length(X509_get_serialNumber(x)); 
     817    if (len > sizeof(ci->serial_no))  
     818        len = sizeof(ci->serial_no); 
     819    pj_memcpy(serial_no + sizeof(ci->serial_no) - len, p, len); 
     820 
     821    /* Check if the contents need to be updated. */ 
     822    update_needed = pj_strcmp2(&ci->issuer.info, buf) ||  
     823                    pj_memcmp(ci->serial_no, serial_no, sizeof(ci->serial_no)); 
     824    if (!update_needed) 
    653825        return; 
    654     } 
    655  
    656     pj_bzero(&info, sizeof(info)); 
    657  
    658     /* Populate cert info */ 
    659     info.subject = pj_str(X509_NAME_oneline(X509_get_subject_name(x),buf1, 
    660                                             sizeof(buf1))); 
    661     info.issuer = pj_str(X509_NAME_oneline(X509_get_issuer_name(x), buf2, 
    662                                            sizeof(buf2))); 
    663     info.version = X509_get_version(x) + 1; 
    664     parse_ossl_asn1_time(&info.validity_start, &info.validity_use_gmt, 
     826 
     827    /* Update cert info */ 
     828 
     829    pj_bzero(ci, sizeof(pj_ssl_cert_info)); 
     830 
     831    /* Version */ 
     832    ci->version = X509_get_version(x) + 1; 
     833 
     834    /* Issuer */ 
     835    pj_strdup2(pool, &ci->issuer.info, buf); 
     836    get_cn_from_gen_name(&ci->issuer.info, &ci->issuer.cn); 
     837 
     838    /* Serial number */ 
     839    pj_memcpy(ci->serial_no, serial_no, sizeof(ci->serial_no)); 
     840 
     841    /* Subject */ 
     842    pj_strdup2(pool, &ci->subject.info,  
     843               X509_NAME_oneline(X509_get_subject_name(x), 
     844                                 buf, sizeof(buf))); 
     845    get_cn_from_gen_name(&ci->subject.info, &ci->subject.cn); 
     846 
     847    /* Validity */ 
     848    parse_ossl_asn1_time(&ci->validity.start, &ci->validity.gmt, 
    665849                         X509_get_notBefore(x)); 
    666     parse_ossl_asn1_time(&info.validity_end, &info.validity_use_gmt, 
     850    parse_ossl_asn1_time(&ci->validity.end, &ci->validity.gmt, 
    667851                         X509_get_notAfter(x)); 
    668852 
    669     /* Update certificate info */ 
    670     if (pj_strcmp(&ci->subject, &info.subject)) 
    671         pj_strdup(pool, &ci->subject, &info.subject); 
    672     if (pj_strcmp(&ci->issuer, &info.issuer)) 
    673         pj_strdup(pool, &ci->issuer, &info.issuer); 
    674     ci->version = info.version; 
    675     ci->validity_start = info.validity_start; 
    676     ci->validity_end = info.validity_end; 
    677     ci->validity_use_gmt = info.validity_use_gmt; 
     853    /* Subject Alternative Name extension */ 
     854    if (ci->version >= 3) { 
     855        names = (GENERAL_NAMES*) X509_get_ext_d2i(x, NID_subject_alt_name, 
     856                                                  NULL, NULL); 
     857    } 
     858    if (names) { 
     859        unsigned i, cnt; 
     860 
     861        cnt = sk_GENERAL_NAME_num(names); 
     862        ci->subj_alt_name.entry = pj_pool_calloc(pool, cnt,  
     863                                            sizeof(*ci->subj_alt_name.entry)); 
     864 
     865        for (i = 0; i < cnt; ++i) { 
     866            unsigned char *p = 0; 
     867            pj_ssl_cert_name_type type = PJ_SSL_CERT_NAME_UNKNOWN; 
     868            const GENERAL_NAME *name; 
     869             
     870            name = sk_GENERAL_NAME_value(names, i); 
     871 
     872            switch (name->type) { 
     873                case GEN_EMAIL: 
     874                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     875                    type = PJ_SSL_CERT_NAME_RFC822; 
     876                    break; 
     877                case GEN_DNS: 
     878                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     879                    type = PJ_SSL_CERT_NAME_DNS; 
     880                    break; 
     881                case GEN_URI: 
     882                    len = ASN1_STRING_to_UTF8(&p, name->d.ia5); 
     883                    type = PJ_SSL_CERT_NAME_URI; 
     884                    break; 
     885                case GEN_IPADD: 
     886                    p = ASN1_STRING_data(name->d.ip); 
     887                    len = ASN1_STRING_length(name->d.ip); 
     888                    type = PJ_SSL_CERT_NAME_IP; 
     889                    break; 
     890                default: 
     891                    break; 
     892            } 
     893 
     894            if (p && len && type != PJ_SSL_CERT_NAME_UNKNOWN) { 
     895                ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type; 
     896                if (type == PJ_SSL_CERT_NAME_IP) { 
     897                    int af = pj_AF_INET(); 
     898                    if (len == sizeof(pj_in6_addr)) af = pj_AF_INET6(); 
     899                    pj_inet_ntop2(af, p, buf, sizeof(buf)); 
     900                    pj_strdup2(pool,  
     901                          &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, 
     902                          buf); 
     903                } else { 
     904                    pj_strdup2(pool,  
     905                          &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name,  
     906                          (char*)p); 
     907                    OPENSSL_free(p); 
     908                } 
     909                ci->subj_alt_name.cnt++; 
     910            } 
     911        } 
     912    } 
    678913} 
    679914 
     
    690925    /* Active local certificate */ 
    691926    x = SSL_get_certificate(ssock->ossl_ssl); 
    692     get_cert_info(ssock->pool, &ssock->local_cert_info, x); 
    693     /* Don't free local's X509! */ 
     927    if (x) { 
     928        get_cert_info(ssock->pool, &ssock->local_cert_info, x); 
     929        /* Don't free local's X509! */ 
     930    } else { 
     931        pj_bzero(&ssock->local_cert_info, sizeof(pj_ssl_cert_info)); 
     932    } 
    694933 
    695934    /* Active remote certificate */ 
    696935    x = SSL_get_peer_certificate(ssock->ossl_ssl); 
    697     get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
    698     /* Free peer's X509 */ 
    699     X509_free(x); 
     936    if (x) { 
     937        get_cert_info(ssock->pool, &ssock->remote_cert_info, x); 
     938        /* Free peer's X509 */ 
     939        X509_free(x); 
     940    } else { 
     941        pj_bzero(&ssock->remote_cert_info, sizeof(pj_ssl_cert_info)); 
     942    } 
    700943} 
    701944 
     
    12321475 
    12331476    /* Create SSL context */ 
    1234     status = create_ssl_ctx(ssock, &ssock->ossl_ctx); 
     1477    status = create_ssl(ssock); 
    12351478    if (status != PJ_SUCCESS) 
    12361479        goto on_return; 
    1237  
    1238     /* Create SSL instance */ 
    1239     ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    1240     if (ssock->ossl_ssl == NULL) { 
    1241         GET_SSL_STATUS(status); 
    1242         goto on_return; 
    1243     } 
    1244  
    1245     /* Set cipher list */ 
    1246     status = set_cipher_list(ssock); 
    1247     if (status != PJ_SUCCESS) 
    1248         goto on_return; 
    1249  
    1250     /* Setup SSL BIOs */ 
    1251     ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
    1252     ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
    1253     BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
    1254     BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
    1255     SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    12561480 
    12571481    /* Prepare read buffer */ 
     
    13521576 
    13531577    /* Create SSL context */ 
    1354     status = create_ssl_ctx(ssock, &ssock->ossl_ctx); 
     1578    status = create_ssl(ssock); 
    13551579    if (status != PJ_SUCCESS) 
    13561580        goto on_return; 
    1357  
    1358     /* Create SSL instance */ 
    1359     ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    1360     if (ssock->ossl_ssl == NULL) { 
    1361         GET_SSL_STATUS(status); 
    1362         goto on_return; 
    1363     } 
    1364  
    1365     /* Set cipher list */ 
    1366     status = set_cipher_list(ssock); 
    1367     if (status != PJ_SUCCESS) 
    1368         goto on_return; 
    1369  
    1370     /* Setup SSL BIOs */ 
    1371     ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
    1372     ssock->ossl_wbio = BIO_new(BIO_s_mem()); 
    1373     BIO_set_close(ssock->ossl_rbio, BIO_CLOSE); 
    1374     BIO_set_close(ssock->ossl_wbio, BIO_CLOSE); 
    1375     SSL_set_bio(ssock->ossl_ssl, ssock->ossl_rbio, ssock->ossl_wbio); 
    13761581 
    13771582    /* Prepare read buffer */ 
     
    16521857     
    16531858    if (info->established) { 
     1859        const SSL_CIPHER *cipher; 
     1860 
    16541861        /* Current cipher */ 
    1655         const SSL_CIPHER *cipher; 
    1656  
    16571862        cipher = SSL_get_current_cipher(ssock->ossl_ssl); 
    16581863        info->cipher = (cipher->id & 0x00FFFFFF); 
     
    16621867 
    16631868        /* Certificates info */ 
    1664         info->local_cert_info = ssock->local_cert_info; 
    1665         info->remote_cert_info = ssock->remote_cert_info; 
     1869        info->local_cert_info = &ssock->local_cert_info; 
     1870        info->remote_cert_info = &ssock->remote_cert_info; 
     1871 
     1872        /* Verification status */ 
     1873        info->verify_status = ssock->verify_status; 
    16661874    } 
    16671875 
Note: See TracChangeset for help on using the changeset viewer.