"错误的数据包长度"更新到OpenSSL 0.9.8.zf后出错

时间:2015-06-29 09:33:52

标签: c openssl

我在Android项目中使用的是OpenSSL 0.9.8h版本。我将其更新为0.9.8.zf版本,但现在它不起作用。

突出显示问题的两个功能是 initialize_client_ctx initialize_client_ctx 。当我致电 SSL_connect 时,我会收到 SSL_ERROR_SSL 错误值。通过检查细节,我检索了一个"错误的数据包长度"错误(error:14092073:SSL routines:SSL3_GET_SERVER_HELLO:bad packet length)。

代码中的点在注释中指出。该代码适用于以前的版本。我还附上了一个Wireshark捕获文件。有什么想法吗?

enter image description here

SSL_CTX *initialize_client_ctx(const char *keyfile, const char *certfile,
                           const char *password, int transport)
{
SSL_METHOD *meth = NULL;
X509 *cert = NULL;
SSL_CTX *ctx;

if (transport == IPPROTO_UDP) {
    meth = DTLSv1_client_method();
} else if (transport == IPPROTO_TCP) {
    meth = TLSv1_client_method();
} else {
    return NULL;
}

ctx = SSL_CTX_new(meth);

if (ctx == NULL) {
    //print ... Couldn't create SSL_CTX
    return NULL;
}

if (password[0] != '\0') {
    SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
    SSL_CTX_set_default_passwd_cb(ctx, password_cb);
}

if (tls_client_local_cn_name[0] != '\0') {
    cert = _tls_set_certificate(ctx, tls_client_local_cn_name);
}

if (cert==NULL && certfile[0] != '\0') {
    //print several warnings....
}

if (cert!=NULL)
{
    X509_free(cert);
    cert = NULL;
}



/* Load the CAs we trust */
{
    char *caFile = 0, *caFolder = 0;
    int fd = open(eXosip_tls_ctx_params.root_ca_cert, O_RDONLY);
    if (fd >= 0) {
        struct stat fileStat;
        if (fstat(fd, &fileStat) < 0) {
        } else {
            if (S_ISDIR(fileStat.st_mode)) {
                caFolder = eXosip_tls_ctx_params.root_ca_cert;
            } else {
                caFile = eXosip_tls_ctx_params.root_ca_cert;
            }
        }
        close(fd);
    }

    {
        int verify_mode = SSL_VERIFY_PEER;

        SSL_CTX_set_verify(ctx, verify_mode, &verify_cb);
        SSL_CTX_set_verify_depth(ctx, ex_verify_depth + 1);
    }
}

SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 |
                    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
                    SSL_OP_CIPHER_SERVER_PREFERENCE);

if(!SSL_CTX_set_cipher_list(ctx,"ALL")) {
    //print ...  set_cipher_list: cannot set anonymous DH cipher
    SSL_CTX_free(ctx);
    return NULL;
}

return ctx;
}



static int _tls_tl_ssl_connect_socket(struct socket_tab *sockinfo)
{
X509 *cert;
BIO *sbio;
int res;

if (sockinfo->ssl_ctx == NULL) {
    sockinfo->ssl_ctx =
        initialize_client_ctx(eXosip_tls_ctx_params.client.priv_key,
                              eXosip_tls_ctx_params.client.cert,
                              eXosip_tls_ctx_params.client.priv_key_pw,
                              IPPROTO_TCP);

    sockinfo->ssl_conn = SSL_new(sockinfo->ssl_ctx);
    if (sockinfo->ssl_conn == NULL) {
        return -1;
    }
    sbio = BIO_new_socket(sockinfo->socket, BIO_NOCLOSE);

    if (sbio == NULL) {
        return -1;
    }
    SSL_set_bio(sockinfo->ssl_conn, sbio, sbio);

}

do {
    struct timeval tv;
    int fd;
    fd_set readfds;

    res = SSL_connect(sockinfo->ssl_conn);

    res = SSL_get_error(sockinfo->ssl_conn, res);
    if (res == SSL_ERROR_NONE) {
        //printf... SSL_connect succeeded
        break;
    }

    if (res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE) {

        //<-- here there is a problem res == SSL_ERROR_SSL

        //print ERR_reason_error_string(ERR_get_error()));
        //print ERR_error_string(ERR_get_error(), NULL));

        return -1;
    }

    tv.tv_sec = SOCKET_TIMEOUT / 1000;
    tv.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
    //retry the connection
    fd = SSL_get_fd(sockinfo->ssl_conn);
    FD_ZERO(&readfds);
    FD_SET(fd, &readfds);
    res = select(fd + 1, &readfds, NULL, NULL, &tv);
    if (res < 0) {
        //print error
        return -1;
    } else if (res > 0) {
        //print...connetrion done! 
    } else {
        //socket timeout, no data to read
        return 1;
    }
} while (!SSL_is_init_finished(sockinfo->ssl_conn));

if (SSL_is_init_finished(sockinfo->ssl_conn)) {
    //print.. SSL_is_init_finished done
} else {
    //print.. failed
}

cert = SSL_get_peer_certificate(sockinfo->ssl_conn);
if (cert != 0) {
    int cert_err;
    tls_dump_cert_info("tls_connect: remote certificate: ", cert);
    cert_err = SSL_get_verify_result(sockinfo->ssl_conn);
    if (cert_err != X509_V_OK) {
        //print... Failed to verify remote certificate
        tls_dump_verification_failure(cert_err);
        if (eXosip_tls_ctx_params.server.cert[0] != '\0') {
            X509_free(cert);
            return -1;
        } else if (cert_err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
                   && cert_err != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
                   && cert_err != X509_V_ERR_CRL_HAS_EXPIRED
                   && cert_err != X509_V_ERR_CERT_HAS_EXPIRED
                   && cert_err != X509_V_ERR_CERT_REVOKED
                   && cert_err != X509_V_ERR_CERT_UNTRUSTED
                   && cert_err != X509_V_ERR_CERT_REJECTED) {
            X509_free(cert);
            return -1;
        }

    }

    X509_free(cert);
} else {
    //print .. No certificate received
    /* X509_free is not necessary because no cert-object was created -> cert == NULL */
    if (eXosip_tls_ctx_params.server.cert[0] == '\0') {
 #ifdef ENABLE_ADH
        /* how can we guess a user want ADH... specific APIs.. */
        sockinfo->ssl_state = 3;
        return 0;
 #endif
    }

    return -1;
}

sockinfo->ssl_state = 3;
return 0;
 }

1 个答案:

答案 0 :(得分:2)

已解决感谢Eric Tsui帮助我找出问题所在。 &#39;你好&#39;我在握手中从服务器收到的长度为零。为了解决这个问题,我按照以下方式修改了文件openssl / ssl / s3_clnt.c(切换长度控件):

diff -ur ./s3_clnt.c ./original/s3_clnt.c
--- submodules/externals/openssl/ssl/s3_clnt.c  2015-06-29 14:59:56.723462992 +0200
+++ ../../opensslOrig/s3_clnt.c 2015-06-29 15:00:22.487464221 +0200
@@ -868,12 +868,14 @@
 }
#endif

+#ifndef OPENSSL_NO_TLSEXT
 if (p != (d + n)) {
     /* wrong packet length */
     al = SSL_AD_DECODE_ERROR;
     SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
     goto f_err;
 }
+#endif

 return (1);
f_err: