2016-11-09 4032 views
1

我是SSL套接字编程的新手,我的第一个任务是让SSL服务器客户端工作和理解。SSL_Accept失败,SSL_get_error返回1

我已经获得了浮动在Web上的服务器和客户端源代码,并将它们与我的openssl库(从源代码编译)进行了编译。

当我启动服务器时,我可以使用accept系统调用来创建一个正常的clientfd,但SSL_accept失败。

clientsocketfd = accept(serversocketfd, NULL, 0); 
serverssl = SSL_new(ssl_server_ctx); 
if(!serverssl) 
{ 
    printf("Error SSL_new\n"); 
    return -1; 
} 
SSL_set_fd(serverssl, clientsocketfd); 

if((ret = SSL_accept(serverssl))!= 1) 
{ 
    printf("Handshake Error %d\n", SSL_get_error(serverssl, ret)); 
    return -1; 
} 

SSL_accept失败打印Handshake error 1

为什么SSL_accept因错误1失败?


Server源:

/*---------------------------------------------------------------------*/ 
/*--- main - create SSL socket server.        ---*/ 
/*---------------------------------------------------------------------*/ 
int main(int count, char *strings[]) 
{ SSL_CTX *ctx; 
    int server; 
    char *portnum; 

    if (count != 2) 
    { 
     printf("Usage: %s <portnum>\n", strings[0]); 
     exit(0); 
    } 
    portnum = strings[1]; 
    SSL_library_init(); 
    ctx = InitServerCTX();                /* initialize SSL */ 
    LoadCertificates(ctx, "newreq.pem", "newreq.pem"); /* load certs */ 
    server = OpenListener(atoi(portnum));        /* create server socket */ 
    while (1) 
    { struct sockaddr_in addr; 
     int len = sizeof(addr); 
     SSL *ssl; 

     int client = accept(server, (struct sockaddr*)&addr, &len);    /* accept connection as usual */ 
     printf("Connection: %s:%d\n", 
       inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 
     ssl = SSL_new(ctx);            /* get new SSL state with context */ 
     SSL_set_fd(ssl, client);            /* set connection socket to SSL state */ 
     Servlet(ssl);                 /* service connection */ 
    } 
    close(server);                    /* close server socket */ 
    SSL_CTX_free(ctx);                 /* release context */ 
} 

/*---------------------------------------------------------------------*/ 
/*--- InitServerCTX - initialize SSL server and create context  ---*/ 
/*---------------------------------------------------------------------*/ 
SSL_CTX* InitServerCTX(void) 
{ SSL_METHOD *method; 
    SSL_CTX *ctx; 

    OpenSSL_add_all_algorithms();    /* load & register all cryptos, etc. */ 
    SSL_load_error_strings();     /* load all error messages */ 
    method = SSLv3_server_method();    /* create new server-method instance */ 
    ctx = SSL_CTX_new(method);     /* create new context from method */ 
    if (ctx == NULL) 
    { 
     ERR_print_errors_fp(stderr); 
     abort(); 
    } 
    return ctx; 
} 

OpenSSL的版本和编译选项如下folows:

/usr/bin/openssl version -a 
OpenSSL 1.0.2g 1 Mar 2016 
built on: reproducible build, date unspecified 
platform: debian-amd64 
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) 
compiler: cc -I. -I.. -I../include -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT 
-DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -g -O2 -fstack-protector-strong 
-Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wl, 
-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int 
-DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT 
-DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM 
-DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM 
-DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM 
OPENSSLDIR: "/usr/lib/ssl" 
+0

中有示例代码检查所有返回值。评论风格将您的评论方式放到代码的右侧有多大用处?你可以*看到*这些评论,而不必玩弄滚动条?像这样评论是一个坏主意。你花了多少时间创建漂亮的ASCII艺术盒子评论? –

回答

1

显然,在SSLv3已经在与一些Linux发行版分发包禁用(如Ubuntu的16.04):

ope nssl(1.0.2g-1ubuntu1)xenial;紧急程度=中

  • 与Debian合并,剩余的更改。
    • 禁用SSLv3的不改变ABI:
      • 的debian /补丁/无sslv3.patch:禁用SSLv3的不使用 无SSL3法选项
      • 的debian /规则:不要使用无-ssl3法,不要磕碰的soname
      • 的debian /补丁/引擎-path.patch:不撞的soname
      • 的debian /补丁/版本script.patch:不撞的soname
      • 的debian /patches/soname.patch:删除d
      • 的debian/lib目录*:不撞的soname

因此你需要用另一种方法:

method = SSLv3_server_method(); 
+0

嗨,谢谢,我使用了ubuntu 14.04,并且代码继续超过了创建方法的错误。我在SSL_accept期间出现错误,虽然正常的accept pass和客户端连接fd正在创建,我该如何解决这个问题。 – RootPhoenix

+0

您使用的是哪个Ubuntu版本并不重要,它在您使用的Ubuntu的SSL v1.0.2g包中被禁用,因此您可以返回Ubuntu 16.04并根据需要降级您的包。或更改SSL服务器方法。 –

0

SSL_accept状态的手册页:

如果底层BIO是非阻塞的,那么当底层BIO不能满足SSL_accept()到 的需求时,SSL_accept()也会返回 继续握手,表示问题由返回值-1表示。 在这种情况下,调用SSL_get_error()返回值为 SSL_accept()将产生SSL_ERROR_WANT_READ或SSL_ERROR_WANT_WRITE。 调用进程则要采取适当行动 满足SSL_accept()的需求后重复调用...

我相信,这意味着你的代码应该是这个样子:

while (1) 
{ 
    int acc = SSL_accept(ssl); 
    if (acc == 0) 
    { 
     /* Hard error */ 
     exit(-1); 
    } 
    else if (acc == -1) 
    { 
     int err = SSL_get_error(ssl, ret); 
     if (err == SSL_ERROR_WANT_READ) 
     { 
      /* Wait for data to be read */ 
     } 
     else if (err == SSL_ERROR_WANT_WRITE) 
     { 
      /* Write data to continue */ 
     } 
     else if (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL) 
     { 
      /* Hard error */ 
      exit(-1); 
     } 
     else if (err == SSL_ERROR_ZERO_RETURN) 
     { 
      /* Same as error */ 
      exit(-1); 
     } 
    } 
    else 
    { 
     /* Continue */ 
     break; 
    } 
} 

的OpenSSL在<openssl src>/apps/s_client.c<openssl src>/apps/s_server.c

相关问题