C &引用;“错误数据包长度”;更新到OpenSSL 0.9.8.zf后出错

C &引用;“错误数据包长度”;更新到OpenSSL 0.9.8.zf后出错,c,openssl,C,Openssl,我在一个Android项目中使用了OpenSSL版本0.9.8h。我将其更新为0.9.8.zf版本,但现在它不工作 突出显示问题的两个功能是初始化\u客户端\u ctx和初始化\u客户端\u ctx。当我调用SSL\u connect时,我得到一个SSL\u ERROR\u SSL错误值。通过检查详细信息,我检索到一个“坏数据包长度”错误(错误:14092073:SSL例程:SSL3\u GET\u SERVER\u HELLO:bad packet length) 代码中的点在注释中表示。该代

我在一个Android项目中使用了OpenSSL版本0.9.8h。我将其更新为0.9.8.zf版本,但现在它不工作

突出显示问题的两个功能是
初始化\u客户端\u ctx
初始化\u客户端\u ctx
。当我调用
SSL\u connect
时,我得到一个
SSL\u ERROR\u SSL
错误值。通过检查详细信息,我检索到一个“坏数据包长度”错误(
错误:14092073:SSL例程:SSL3\u GET\u SERVER\u HELLO:bad packet length

代码中的点在注释中表示。该代码与以前的版本配合得很好。我还附上一个Wireshark捕获文件。有什么想法吗

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;
 }

SSL\u CTX*初始化\u客户端\u CTX(const char*keyfile,const char*certfile,
常量字符*密码,整数传输)
{
SSL_方法*meth=NULL;
X509*证书=空;
SSL_CTX*CTX;
if(传输==IPPROTO_UDP){
meth=DTLSv1_client_method();
}else if(传输==IPPROTO_TCP){
meth=TLSv1_client_method();
}否则{
返回NULL;
}
ctx=SSL\u ctx\u新(meth);
如果(ctx==NULL){
//打印…无法创建SSL\u CTX
返回NULL;
}
如果(密码[0]!='\0'){
SSL\u CTX\u set\u default\u passwd\u cb\u userdata(CTX,(void*)密码);
SSL_CTX_set_default_passwd_cb(CTX,password_cb);
}
如果(tls\u客户端\u本地\u cn\u名称[0]!='\0'){
证书=\u tls\u set\u证书(ctx、tls\u客户端\u本地\u cn\u名称);
}
if(cert==NULL&&certfile[0]!='\0'){
//打印几个警告。。。。
}
如果(证书!=NULL)
{
X509_免费(证书);
cert=NULL;
}
/*加载我们信任的CA*/
{
char*caFile=0,*caFolder=0;
int fd=打开(仅限eXosip_tls_ctx_params.root_ca_cert);
如果(fd>=0){
struct stat fileStat;
if(fstat(fd,&fileStat)<0){
}否则{
if(S_ISDIR(文件状态st_模式)){
caFolder=eXosip_tls_ctx_params.root_ca_cert;
}否则{
caFile=eXosip\u tls\u ctx\u params.root\u ca\u cert;
}
}
关闭(fd);
}
{
int verify\u mode=SSL\u verify\u PEER;
SSL\u CTX\u set\u verify(CTX、verify\u模式和verify\u cb);
SSL\u CTX\u设置\u验证深度(CTX,ex\u验证深度+1);
}
}
SSL_CTX_set_选项(CTX、SSL_OP_ALL、SSL_OP_NO、SSLv2|
SSL_OP_NO_SESSION_recoveration_ON_regotiation_|
SSL_OP_密码_服务器_首选项);
如果(!SSL\u CTX\u set\u cipher\u list(CTX,“ALL”)){
//打印…设置密码列表:无法设置匿名DH密码
SSL_-CTX_-free(CTX);
返回NULL;
}
返回ctx;
}
静态int\u tls\u tl\u ssl\u connect\u套接字(结构套接字\u选项卡*sockinfo)
{
X509*证书;
生物技术*sbio;
国际关系;
如果(sockinfo->ssl\u ctx==NULL){
sockinfo->ssl\u ctx=
初始化_client_ctx(eXosip_tls_ctx_params.client.priv_密钥,
eXosip_tls_ctx_params.client.cert,
eXosip_tls_ctx_params.client.priv_key_pw,
IPPROTO_(TCP);
sockinfo->ssl\u conn=ssl\u new(sockinfo->ssl\u ctx);
如果(sockinfo->ssl\u conn==NULL){
返回-1;
}
sbio=BIO_new_socket(sockinfo->socket,BIO_NOCLOSE);
如果(sbio==NULL){
返回-1;
}
SSL\u set\u bio(sockinfo->SSL\u conn,sbio,sbio);
}
做{
结构时间值电视;
int-fd;
fd_设置读取FDS;
res=SSL\u connect(sockinfo->SSL\u conn);
res=SSL\u get\u错误(sockinfo->SSL\u conn,res);
如果(res==SSL\u错误\u无){
//printf…SSL\u连接成功
打破
}
如果(res!=SSL\u错误\u需要\u读取和&res!=SSL\u错误\u需要\u写入){
//ssl_conn),;
FD_零(&readfds);
FD_集(FD和readfds);
res=选择(fd+1和读取FDS、NULL、NULL和tv);
如果(res<0){
//打印错误
返回-1;
}否则,如果(分辨率>0){
//打印…连接完成!
}否则{
//套接字超时,没有要读取的数据
返回1;
}
}而(!SSL_是_init_finished(sockinfo->SSL_conn));
如果(SSL_是_init_finished(sockinfo->SSL_conn)){
//打印..SSL\u初始化完成了吗
}否则{
//打印..失败
}
cert=SSL\u获取\u对等\u证书(sockinfo->SSL\u conn);
如果(证书!=0){
内部证书错误;
tls_转储_证书信息(“tls_连接:远程证书:”,证书);
cert\u err=SSL\u get\u verify\u result(sockinfo->SSL\u conn);
如果(证书错误!=X509\u V\u正常){
//打印…验证远程证书失败
tls转储验证失败(证书错误);
if(eXosip_tls_ctx_params.server.cert[0]!='\0'){
X509_免费(证书);
返回-1;
}否则,如果(证书错误!=X509\u V\u错误\u深度\u零\u自签名\u证书
&&证书错误!=X509\u V\u err\u自签名\u证书链中
&&证书错误!=X509\u V\u err\u CRL\u已过期
&&证书错误!=X509证书已过期
&&证书错误!=X509证书已撤销
&&证书错误!=X509证书不可信
&&证书错误!=X509(证书错误被拒绝){
X509_免费(证书);
返回-1;
}
}
X509_免费(证书);
}否则{
//打印..未收到证书
/*X509_free不是必需的,因为没有创建证书对象->证书==NULL*/
if(eXosip_tls_ctx_params.server.cert[0]=='\0'){
#ifdef启用_ADH
/*我们怎么能猜测用户想要ADH…特定的API*/
sockinfo->ssl_state=3;
返回0;
#恩迪夫
}
返回-1;
}
sockinfo->ssl_state=3;
返回0;
}

解决了多亏Eric Tsui帮助我解决了这个问题。我在握手中从服务器收到的“hello”的长度为零。为了解决这个问题,我用以下方式修改了文件openssl/ssl/s3_clnt.c(关闭长度控制):


也许你可以用最新的Openssl库试试,比如[Openssl-1.0.2c]()?因为它在旧版本中工作,我想这可能是0.9.8.zfI ca带来的问题/错误
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: