问题描述
为了理解SSL/TLS
,我在Windows-7
上下载了OpenSSL-1.0.2k
并使用Cygwin
gcc
64 bit
编译器进行了编译.我从 c 中的OpenSSL服务器/客户端示例,并使用cygwin gcc
进行了编译.第一次编译成功.我使用以下命令从cmd
执行了服务器和客户端.
In order to understand SSL/TLS
, I downloaded OpenSSL-1.0.2k
on Windows-7
and compiled with Cygwin
gcc
64 bit
compiler. I took off-the-shelf
example of server/client from OpenSSL server/client example in c and compiled with cygwin gcc
. Compilation is successful on the first go. I executed server and client from cmd
with following commands.
(Server) D:\>ssl-server.exe 5000
(Client) D:\>ssl-client.exe 127.0.0.1 5000
客户端退出时没有任何响应,但另一方面,服务器显示它已建立连接,例如;
Client exits without any response but on the other hand, server displays that it has made a connection, e.g;
Connection: 127.0.0.1:50475
并无限期地等待下一行.
and waits on next line infinitely.
然后我开始调试服务器端,发现过程void Servlet(SSL* ssl)
中的SSL_accept()
返回值-1
,这是不期望的.我从OpenSSL
openSSL DOC 查阅了文档.
Then I started debugging server side and found that , SSL_accept()
in procedure void Servlet(SSL* ssl)
returns a value of -1
, which is not expected. I consulted Documentation from OpenSSL
openSSL DOC;
SSL_get_error()
返回SSL_ERROR_SYSCALL
.我在调用后立即检查了errno
的值,然后看到了no error
. Servlet
方法的完整代码如下.其余代码与链接中的相同.
SSL_get_error()
returns SSL_ERROR_SYSCALL
. I checked the value of errno
right after this call and I see no error
. Complete code of Servlet
method follows. Rest of the code is same as in link.
void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{ char buf[1024];
char reply[1024];
int sd, bytes;
const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n";
int ret;
ret = SSL_accept(ssl); /* do SSL-protocol accept */
if ( ret == -1 )
{
// printf(" SSL_accept() returned -1\n");
switch(SSL_get_error(ssl, ret) )
{
case SSL_ERROR_SYSCALL:
perror("errno");
break;
default:
printf( "default" );
break;
}
exit(-1);
}
else if ( ret == 0)
{
printf(" SSL_accept() returned 0\n");
exit(-1);
}
else if ( ret == 1) // The TLS/SSL connection has been established.
{
ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
if ( bytes > 0 )
{
buf[bytes] = 0;
printf("Client msg: \"%s\"\n", buf);
sprintf(reply, HTMLecho, buf); /* construct reply */
SSL_write(ssl, reply, strlen(reply)); /* send reply */
}
else
ERR_print_errors_fp(stderr);
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
推荐答案
- 当您未遇到枚举的SSL_ERROR_情况之一时,应跟踪
SSL_get_error()
的值,以便可以开始调试.而不是仅仅举起手来. - 在这种情况下,值是
SSL_ERROR_SYSCALL
.您没有在您认为应该的地方抓到它,因为case (SSL_ERROR_SYSCALL || SSL_ERROR_SSL || SSL_ERROR_WANT_CONNECT || SSL_ERROR_WANT_ACCEPT):
并没有按照您的想法进行.由于||
的语义,它将变成case 1
.每个值应该有单独的case
语句. 根据您引用的文档, - SSL_ERROR_SYSCALL表示基础错误在
errno
中,这意味着您随后应跟踪那个.而不是仅仅举起你的手.并请注意,必须在调用任何其他系统调用之前完成 (例如通过printf()
通过write()
),这样可能有助于立即保存errno
. - 您可以使用
printf("errno=%d\n", errno)
直接打印errno
,但是打印错误 message 会更有用,您可以使用perror()
或printf("error=%s\n", syserror(errno))
进行打印. /li> -
SSL_get_error()
的值不是errno
的值,也不是您开始时使用的原始-1.errno
值来自errno
变量. - 但是您不应该对这些事情做任何
SSL_accept()
返回-1,在这里没有实际证据.
- When you don't hit one of the SSL_ERROR_ cases you have enumerated, you should trace the value of
SSL_get_error()
so you can start debugging. Rather than just throwing up your hands. - In this case the value was
SSL_ERROR_SYSCALL
. You didn't catch it where you thought you should becausecase (SSL_ERROR_SYSCALL || SSL_ERROR_SSL || SSL_ERROR_WANT_CONNECT || SSL_ERROR_WANT_ACCEPT):
doesn't do what you think. It will turn intocase 1
because of the semantics of||
. There should be separatecase
statements for each value. - SSL_ERROR_SYSCALL means that the underlying error is in
errno
, as per the documentation you quoted yourself, which means that you should then trace that. Rather than just throwing up your hands. And note that you must do so before calling any other system calls (such aswrite()
viaprintf()
), so it might help to saveerrno
immediately. - You can either print
errno
directly withprintf("errno=%d\n", errno)
, but it would be more useful to print the error message, which you can do with eitherperror()
orprintf("error=%s\n", syserror(errno))
. - The value of
SSL_get_error()
is not anerrno
value, and neither is the original -1 you started with. Anerrno
value comes from theerrno
variable. - However you shouldn't do any of these things unless
SSL_accept()
returned -1, for which there is no actual evidence here.
因此,这里完全没有错误是完全有可能的.
So it is entirely possible that there is no error here at all.
这篇关于SSL_accept()失败,返回值-1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!