Ignore:
Timestamp:
Jul 27, 2017 6:07:54 AM (7 years ago)
Author:
ming
Message:

Fixed #2030: Improve error handling in OpenSSL socket

File:
1 edited

Legend:

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

    r5623 r5631  
    299299#define MAX_OSSL_ERR_REASON             1200 
    300300 
    301 static pj_status_t STATUS_FROM_SSL_ERR(pj_ssl_sock_t *ssock, 
    302                                        unsigned long err) 
     301 
     302static char *SSLErrorString (int err) 
     303{ 
     304    switch (err) { 
     305    case SSL_ERROR_NONE: 
     306        return "SSL_ERROR_NONE"; 
     307    case SSL_ERROR_ZERO_RETURN: 
     308        return "SSL_ERROR_ZERO_RETURN"; 
     309    case SSL_ERROR_WANT_READ: 
     310        return "SSL_ERROR_WANT_READ"; 
     311    case SSL_ERROR_WANT_WRITE: 
     312        return "SSL_ERROR_WANT_WRITE"; 
     313    case SSL_ERROR_WANT_CONNECT: 
     314        return "SSL_ERROR_WANT_CONNECT"; 
     315    case SSL_ERROR_WANT_ACCEPT: 
     316        return "SSL_ERROR_WANT_ACCEPT"; 
     317    case SSL_ERROR_WANT_X509_LOOKUP: 
     318        return "SSL_ERROR_WANT_X509_LOOKUP"; 
     319    case SSL_ERROR_SYSCALL: 
     320        return "SSL_ERROR_SYSCALL"; 
     321    case SSL_ERROR_SSL: 
     322        return "SSL_ERROR_SSL"; 
     323    default: 
     324        return "SSL_ERROR_UNKNOWN"; 
     325    } 
     326} 
     327 
     328#define ERROR_LOG(msg, err) \ 
     329    PJ_LOG(2,("SSL", "%s (%s): Level: %d err: <%lu> <%s-%s-%s> len: %d", \ 
     330              msg, action, level, err, \ 
     331              (ERR_lib_error_string(err)? ERR_lib_error_string(err): "???"), \ 
     332              (ERR_func_error_string(err)? ERR_func_error_string(err):"???"),\ 
     333              (ERR_reason_error_string(err)? \ 
     334               ERR_reason_error_string(err): "???"), len)); 
     335 
     336static void SSLLogErrors(char * action, int ret, int ssl_err, int len) 
     337{ 
     338    char *ssl_err_str = SSLErrorString(ssl_err); 
     339 
     340    if (!action) { 
     341        action = "UNKNOWN"; 
     342    } 
     343 
     344    switch (ssl_err) { 
     345    case SSL_ERROR_SYSCALL: 
     346    { 
     347        unsigned long err2 = ERR_get_error(); 
     348        if (err2) { 
     349            int level = 0; 
     350            while (err2) { 
     351                ERROR_LOG("SSL_ERROR_SYSCALL", err2); 
     352                level++; 
     353                err2 = ERR_get_error(); 
     354            } 
     355        } else if (ret == 0) { 
     356            /* An EOF was observed that violates the protocol */ 
     357 
     358            /* The TLS/SSL handshake was not successful but was shut down 
     359             * controlled and by the specifications of the TLS/SSL protocol. 
     360             */ 
     361        } else if (ret == -1) { 
     362            /* BIO error - look for more info in errno... */ 
     363            char errStr[250] = ""; 
     364            strerror_r(errno, errStr, sizeof(errStr)); 
     365            /* for now - continue logging these if they occur.... */ 
     366            PJ_LOG(4,("SSL", "BIO error, SSL_ERROR_SYSCALL (%s): " 
     367                             "errno: <%d> <%s> len: %d", 
     368                             action, errno, errStr, len)); 
     369        } else { 
     370            /* ret!=0 & ret!=-1 & nothing on error stack - is this valid??? */ 
     371            PJ_LOG(2,("SSL", "SSL_ERROR_SYSCALL (%s) ret: %d len: %d", 
     372                      action, ret, len)); 
     373        } 
     374        break; 
     375    } 
     376    case SSL_ERROR_SSL: 
     377    { 
     378        unsigned long err2 = ERR_get_error(); 
     379        int level = 0; 
     380 
     381        while (err2) { 
     382            ERROR_LOG("SSL_ERROR_SSL", err2); 
     383            level++; 
     384            err2 = ERR_get_error(); 
     385        } 
     386        break; 
     387    } 
     388    default: 
     389        PJ_LOG(2,("SSL", "%lu [%s] (%s) ret: %d len: %d", 
     390                  ssl_err, ssl_err_str, action, ret, len)); 
     391        break; 
     392    } 
     393} 
     394 
     395 
     396static pj_status_t GET_STATUS_FROM_SSL_ERR(unsigned long err) 
    303397{ 
    304398    pj_status_t status; 
    305  
    306     /* General SSL error, dig more from OpenSSL error queue */ 
    307     if (err == SSL_ERROR_SSL) 
    308         err = ERR_get_error(); 
    309399 
    310400    /* OpenSSL error range is much wider than PJLIB errno space, so 
     
    318408 
    319409    status += PJ_SSL_ERRNO_START; 
     410    return status; 
     411} 
     412 
     413/* err contains ERR_get_error() status */ 
     414static pj_status_t STATUS_FROM_SSL_ERR(char *action, pj_ssl_sock_t *ssock, 
     415                                       unsigned long err) 
     416{ 
     417    int level = 0; 
     418    int len = 0; //dummy 
     419 
     420    ERROR_LOG("STATUS_FROM_SSL_ERR", err); 
     421    level++; 
     422 
     423    /* General SSL error, dig more from OpenSSL error queue */ 
     424    if (err == SSL_ERROR_SSL) { 
     425        err = ERR_get_error(); 
     426        ERROR_LOG("STATUS_FROM_SSL_ERR", err); 
     427    } 
     428 
    320429    ssock->last_err = err; 
    321     return status; 
     430    return GET_STATUS_FROM_SSL_ERR(err); 
     431} 
     432 
     433/* err contains SSL_get_error() status */ 
     434static pj_status_t STATUS_FROM_SSL_ERR2(char *action, pj_ssl_sock_t *ssock, 
     435                                        int ret, int err, int len) 
     436{ 
     437    unsigned long ssl_err = err; 
     438 
     439    if (err == SSL_ERROR_SSL) { 
     440        ssl_err = ERR_peek_error(); 
     441    } 
     442 
     443    /* Dig for more from OpenSSL error queue */ 
     444    SSLLogErrors(action, ret, err, len); 
     445 
     446    ssock->last_err = ssl_err; 
     447    return GET_STATUS_FROM_SSL_ERR(ssl_err); 
    322448} 
    323449 
    324450static pj_status_t GET_SSL_STATUS(pj_ssl_sock_t *ssock) 
    325451{ 
    326     return STATUS_FROM_SSL_ERR(ssock, ERR_get_error()); 
     452    return STATUS_FROM_SSL_ERR("status", ssock, ERR_get_error()); 
    327453} 
    328454 
     
    15151641                err = ERR_get_error(); 
    15161642                if (err != SSL_ERROR_NONE) 
    1517                     status = STATUS_FROM_SSL_ERR(ssock, err); 
     1643                    status = STATUS_FROM_SSL_ERR("connecting", ssock, err); 
    15181644            } 
    15191645            reset_ssl_sock_state(ssock); 
     
    18341960 
    18351961    if (err < 0) { 
    1836         err = SSL_get_error(ssock->ossl_ssl, err); 
    1837         if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ)  
     1962        int err2 = SSL_get_error(ssock->ossl_ssl, err); 
     1963        if (err2 != SSL_ERROR_NONE && err2 != SSL_ERROR_WANT_READ) 
    18381964        { 
    18391965            /* Handshake fails */ 
    1840             status = STATUS_FROM_SSL_ERR(ssock, err); 
     1966            status = STATUS_FROM_SSL_ERR2("Handshake", ssock, err, err2, 0); 
    18411967            return status; 
    18421968        } 
     
    19142040            void *data_ = (pj_int8_t*)buf->data + buf->len; 
    19152041            int size_ = (int)(ssock->read_size - buf->len); 
     2042            int len = size_; 
    19162043 
    19172044            /* SSL_read() may write some data to BIO write when re-negotiation 
     
    19662093                if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
    19672094                { 
    1968                     /* Reset SSL socket state, then return PJ_FALSE */ 
    1969                     status = STATUS_FROM_SSL_ERR(ssock, err); 
    1970                     reset_ssl_sock_state(ssock); 
    1971                     goto on_error; 
     2095                    if (err == SSL_ERROR_SYSCALL && size_ == -1 && 
     2096                        ERR_peek_error() == 0 && errno == 0) 
     2097                    { 
     2098                        status = STATUS_FROM_SSL_ERR2("Read", ssock, size_, 
     2099                                                      err, len); 
     2100                        PJ_LOG(4,("SSL", "SSL_read() = -1, with " 
     2101                                         "SSL_ERROR_SYSCALL, no SSL error, " 
     2102                                         "and errno = 0 - skip BIO error")); 
     2103                        /* Ignore these errors */ 
     2104                    } else { 
     2105                        /* Reset SSL socket state, then return PJ_FALSE */ 
     2106                        status = STATUS_FROM_SSL_ERR2("Read", ssock, size_, 
     2107                                                      err, len); 
     2108                        reset_ssl_sock_state(ssock); 
     2109                        goto on_error; 
     2110                    } 
    19722111                } 
    19732112 
     
    28572996        } else { 
    28582997            /* Some problem occured */ 
    2859             status = STATUS_FROM_SSL_ERR(ssock, err); 
     2998            status = STATUS_FROM_SSL_ERR2("Write", ssock, nwritten, err, size); 
    28602999        } 
    28613000    } else { 
Note: See TracChangeset for help on using the changeset viewer.