Ignore:
Timestamp:
Nov 4, 2009 5:08:32 PM (11 years ago)
Author:
nanang
Message:

Ticket #957:

  • Applied workaround solution for getting local address problem with getsockname on win IOCP by using parent local address instead.
  • Fixed SSL socket not to return PJ_FALSE in active socket accept callback, to keep accepting connections.
  • Applied workaround solution for OpenSSL error mapping, as OpenSSL error codes are big numbers that won't fit pj_status_t.
  • Minor updates, e.g: using pj_perror(), removing some logs, OpenSSL error print callback.
  • Minor updates on SSL unit test, e.g: start_read() before start sending, additional ioqueue poll to cleanup sockets, add timeout feature to https client test.
File:
1 edited

Legend:

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

    r2972 r2986  
    193193                                         PJ_ERRNO_SPACE_SIZE*6) 
    194194 
    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  
     195#define PJ_SSL_ERRNO_SPACE_SIZE         PJ_ERRNO_SPACE_SIZE 
     196 
     197#define GET_SSL_STATUS(status) { \ 
     198    unsigned long e = ERR_get_error();\ 
     199    status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\ 
     200    pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
     201    if (status) status += PJ_SSL_ERRNO_START;\ 
     202} 
    205203 
    206204/* 
     
    211209{ 
    212210    pj_str_t errstr; 
    213     unsigned long ssl_err = PJ_STATUS_TO_OSSL(status); 
     211    unsigned long ssl_err = status; 
     212 
     213    if (ssl_err) { 
     214        unsigned long l, r; 
     215        ssl_err -= PJ_SSL_ERRNO_START; 
     216        l = ssl_err/300; 
     217        r = ssl_err%300; 
     218        ssl_err = ERR_PACK(l, 0, r); 
     219    } 
    214220 
    215221#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0) 
    216222 
    217     ERR_error_string_n(ssl_err, buf, bufsize); 
    218     errstr = pj_str(buf); 
    219  
    220 #else 
     223    { 
     224        const char *tmp = NULL; 
     225        tmp = ERR_reason_error_string(ssl_err); 
     226 
     227        if (tmp) { 
     228            pj_ansi_strncpy(buf, tmp, bufsize); 
     229            errstr = pj_str(buf); 
     230            return errstr; 
     231        } 
     232    } 
     233 
     234#endif  /* PJ_HAS_ERROR_STRING */ 
    221235 
    222236    errstr.ptr = buf; 
     
    224238                                   "Unknown OpenSSL error %d", 
    225239                                   ssl_err); 
    226  
    227 #endif  /* PJ_HAS_ERROR_STRING */ 
    228240 
    229241    return errstr; 
     
    337349    pj_ssl_cert_t *cert; 
    338350    int mode, rc; 
     351    pj_status_t status; 
    339352         
    340353    pj_assert(ssock && p_ctx); 
     
    370383    ctx = SSL_CTX_new(ssl_method); 
    371384    if (ctx == NULL) { 
    372         PJ_LOG(1,(ssock->pool->obj_name, "Error creating OpenSSL context")); 
    373         return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     385        GET_SSL_STATUS(status); 
     386        return status; 
    374387    } 
    375388 
     
    382395 
    383396            if (rc != 1) { 
     397                GET_SSL_STATUS(status); 
    384398                PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file " 
    385399                          "'%s'", cert->CA_file.ptr)); 
    386400                SSL_CTX_free(ctx); 
    387                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     401                return status; 
    388402            } 
    389403        } 
     
    403417 
    404418            if(rc != 1) { 
     419                GET_SSL_STATUS(status); 
    405420                PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate " 
    406421                          "chain file '%s'", cert->cert_file.ptr)); 
    407422                SSL_CTX_free(ctx); 
    408                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     423                return status; 
    409424            } 
    410425        } 
     
    418433 
    419434            if(rc != 1) { 
     435                GET_SSL_STATUS(status); 
    420436                PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key " 
    421437                          "from '%s'", cert->privkey_file.ptr)); 
    422438                SSL_CTX_free(ctx); 
    423                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     439                return status; 
    424440            } 
    425441        } 
     
    543559    /* Finally, set chosen cipher list */ 
    544560    ret = SSL_set_cipher_list(ssock->ossl_ssl, buf); 
    545     if (ret < 1) 
    546         return PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
     561    if (ret < 1) { 
     562        pj_status_t status; 
     563        GET_SSL_STATUS(status); 
     564        return status; 
     565    } 
    547566 
    548567    return PJ_SUCCESS; 
     
    688707        if (status != PJ_SUCCESS) { 
    689708            /* Handshake failed in accepting, destroy our self silently. */ 
     709 
     710            char errmsg[PJ_ERR_MSG_SIZE]; 
     711            char buf[PJ_INET6_ADDRSTRLEN+10]; 
     712 
     713            pj_strerror(status, errmsg, sizeof(errmsg)); 
     714            PJ_LOG(3,(ssock->pool->obj_name, "Handshake failed in accepting " 
     715                      "%s: %s", 
     716                      pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3), 
     717                      errmsg)); 
     718 
    690719            pj_ssl_sock_close(ssock); 
    691720            return PJ_FALSE; 
     
    875904        { 
    876905            /* Handshake fails */ 
     906            GET_SSL_STATUS(status); 
    877907            pj_lock_release(ssock->write_mutex); 
    878             return PJ_STATUS_FROM_OSSL(err); 
     908            return status; 
    879909        } 
    880910    } 
     
    922952        nwritten = BIO_write(ssock->ossl_rbio, data, size); 
    923953        if (nwritten < size) { 
    924             status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     954            GET_SSL_STATUS(status); 
    925955            goto on_error; 
    926956        } 
     
    9951025                if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
    9961026                { 
    997                     char errmsg[PJ_ERR_MSG_SIZE]; 
    998  
    999                     pj_strerror(status, errmsg, sizeof(errmsg)); 
    1000                     PJ_LOG(1,(ssock->pool->obj_name, "SSL_read() failed: %s", 
    1001                               errmsg)); 
    1002  
    10031027                    /* Reset SSL socket state, then return PJ_FALSE */ 
     1028                    GET_SSL_STATUS(status); 
    10041029                    reset_ssl_sock_state(ssock); 
    10051030                    goto on_error; 
     
    10181043 
    10191044                    if (status != PJ_SUCCESS && 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, "Failed to flush " 
    1024                                   "delayed send: %s", errmsg)); 
     1045                        pj_perror(1, ssock->pool->obj_name, status,  
     1046                                  "Failed to flush delayed send", 0); 
    10251047                        goto on_error; 
    10261048                    } 
    10271049                } else if (status != PJ_EPENDING) { 
    1028                     char errmsg[PJ_ERR_MSG_SIZE]; 
    1029  
    1030                     pj_strerror(status, errmsg, sizeof(errmsg)); 
    1031                     PJ_LOG(1,(ssock->pool->obj_name, "Renegotiation failed: " 
    1032                               "%s", errmsg)); 
     1050                    pj_perror(1, ssock->pool->obj_name, status,  
     1051                              "Renegotiation failed", 0); 
    10331052                    goto on_error; 
    10341053                } 
     
    11221141    unsigned i; 
    11231142    pj_status_t status; 
    1124     char buf[64]; 
    11251143 
    11261144    PJ_UNUSED_ARG(src_addr_len); 
    1127  
    1128     PJ_LOG(4,(ssock_parent->pool->obj_name, "Incoming connection from %s", 
    1129               pj_sockaddr_print(src_addr, buf, sizeof(buf), 3))); 
    11301145 
    11311146    /* Create new SSL socket instance */ 
     
    11501165    status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,  
    11511166                                 &ssock->addr_len); 
    1152     if (status != PJ_SUCCESS) 
    1153         goto on_return; 
     1167    if (status != PJ_SUCCESS) { 
     1168        /* This fails on few envs, e.g: win IOCP, just tolerate this and 
     1169         * use parent local address instead. 
     1170         */ 
     1171        pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr); 
     1172    } 
    11541173 
    11551174    /* Set remote address */ 
     
    11641183    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    11651184    if (ssock->ossl_ssl == NULL) { 
    1166         PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
    1167         status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     1185        GET_SSL_STATUS(status); 
    11681186        goto on_return; 
    11691187    } 
     
    12451263    SSL_set_accept_state(ssock->ossl_ssl); 
    12461264    status = do_handshake(ssock); 
    1247     if (status != PJ_EPENDING) 
    1248         goto on_return; 
    1249  
     1265 
     1266on_return: 
     1267    if (ssock && status != PJ_EPENDING) 
     1268        on_handshake_complete(ssock, status); 
     1269 
     1270    /* Must return PJ_TRUE whatever happened, as active socket must  
     1271     * continue listening. 
     1272     */ 
    12501273    return PJ_TRUE; 
    1251  
    1252 on_return: 
    1253     return on_handshake_complete(ssock, status); 
    12541274} 
    12551275 
     
    12801300    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    12811301    if (ssock->ossl_ssl == NULL) { 
    1282         PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
    1283         status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     1302        GET_SSL_STATUS(status); 
    12841303        goto on_return; 
    12851304    } 
     
    17231742        } else { 
    17241743            /* Some problem occured */ 
    1725             status = PJ_STATUS_FROM_OSSL(err); 
     1744            GET_SSL_STATUS(status); 
    17261745        } 
    17271746    } else { 
     
    20182037    ret = SSL_renegotiate(ssock->ossl_ssl); 
    20192038    if (ret <= 0) { 
    2020         status = PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
     2039        GET_SSL_STATUS(status); 
    20212040    } else { 
    20222041        status = do_handshake(ssock); 
Note: See TracChangeset for help on using the changeset viewer.