本文介绍了SSL_accept()失败,返回值-1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了理解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 */
}

推荐答案

  1. 当您未遇到枚举的SSL_ERROR_情况之一时,应跟踪SSL_get_error()的值,以便可以开始调试.而不是仅仅举起手来.
  2. 在这种情况下,值是SSL_ERROR_SYSCALL.您没有在您认为应该的地方抓到它,因为case (SSL_ERROR_SYSCALL || SSL_ERROR_SSL || SSL_ERROR_WANT_CONNECT || SSL_ERROR_WANT_ACCEPT):并没有按照您的想法进行.由于||的语义,它将变成case 1.每个值应该有单独的case语句.
  3. 根据您引用的文档,
  4. SSL_ERROR_SYSCALL表示基础错误在errno中,这意味着您随后应跟踪那个.而不是仅仅举起你的手.并请注意,必须在调用任何其他系统调用之前完成 (例如通过printf()通过write()),这样可能有助于立即保存errno.
  5. 您可以使用printf("errno=%d\n", errno)直接打印errno,但是打印错误 message 会更有用,您可以使用perror()printf("error=%s\n", syserror(errno))进行打印. /li>
  6. SSL_get_error()的值不是errno的值,也不是您开始时使用的原始-1. errno值来自errno变量.
  7. 但是您不应该对这些事情做任何 SSL_accept()返回-1,在这里没有实际证据.
  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.
  2. In this case the value was SSL_ERROR_SYSCALL. You didn't catch it where you thought you should because case (SSL_ERROR_SYSCALL || SSL_ERROR_SSL || SSL_ERROR_WANT_CONNECT || SSL_ERROR_WANT_ACCEPT): doesn't do what you think. It will turn into case 1 because of the semantics of ||. There should be separate case statements for each value.
  3. 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 as write() via printf()), so it might help to save errno immediately.
  4. You can either print errno directly with printf("errno=%d\n", errno), but it would be more useful to print the error message, which you can do with either perror() or printf("error=%s\n", syserror(errno)).
  5. The value of SSL_get_error() is not an errno value, and neither is the original -1 you started with. An errno value comes from the errno variable.
  6. 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 11:46
查看更多