正确处理SSL_shutdown

时间:2015-01-20 22:08:27

标签: c++ c openssl

SSL_shutdown上的openssl文档指出: 因此,如果双向关闭尚未完成(第一次调用的返回值为0),建议检查SSL_shutdown()的返回值并再次调用SSL_shutdown()。

https://www.openssl.org/docs/ssl/SSL_shutdown.html

我在下面有一个代码片段,我从SSL_shutdown检查返回值0并再次调用它,我一直在使用它。我的问题是,可以忽略第二次调用时SSL_shutdown的返回值,或者我们应该继续重试SSL_shutdown,直到返回1(双向关闭完成)。

 int r = SSL_shutdown(ssl);
 //error handling here if r < 0 
 if(!r)
 {

     shutdown(fd,1);
     SSL_shutdown(ssl); //how should I handle return value and error handling here is it required?? 
 }
 SSL_free(ssl);
 SSLMap.erase(fd);
 shutdown(fd,2);
 close(fd);

1 个答案:

答案 0 :(得分:11)

openssl 是一种黑暗艺术。

首先,您引用的页面具有HTML-ified错误的返回值。这是man-page 实际上所说的内容:

  RETURN VALUES

   The following return values can occur:

   0   The shutdown is not yet finished. Call SSL_shutdown() for a second
       time, if a bidirectional shutdown shall be performed.  The output
       of SSL_get_error(3) may be misleading, as an erroneous
       SSL_ERROR_SYSCALL may be flagged even though no error occurred.

   1   The shutdown was successfully completed. The "close notify" alert
       was sent and the peer's "close notify" alert was received.

   -1  The shutdown was not successful because a fatal error occurred
       either at the protocol level or a connection failure occurred. It
       can also occur if action is need to continue the operation for non-
       blocking BIOs.  Call SSL_get_error(3) with the return value ret to
       find out the reason.

如果您有阻止BIO,事情就相对简单了。如果您想要双向关机,则第一次呼叫时0表示您需要再次呼叫SSL_shutdown。 1意味着你已经完成了。 A -1表示错误。在第二次调用时(只有在返回0时才会执行),然后启动双向关闭。逻辑规定你不能再回到0(因为它是一个阻塞的BIO并且将完成第一步)。 A -1表示错误,1表示完成。

如果你有非阻塞的BIO,同样适用,除​​了你需要经历整个SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE严格的事实,即:

   If the underlying BIO is non-blocking, SSL_shutdown() will also return
   when the underlying BIO could not satisfy the needs of SSL_shutdown()
   to continue the handshake. In this case a call to SSL_get_error() with
   the return value of SSL_shutdown() will yield SSL_ERROR_WANT_READ or
   SSL_ERROR_WANT_WRITE. The calling process then must repeat the call
   after taking appropriate action to satisfy the needs of SSL_shutdown().
   The action depends on the underlying BIO. When using a non-blocking
   socket, nothing is to be done, but select() can be used to check for
   the required condition. When using a buffering BIO, like a BIO pair,
   data must be written into or retrieved out of the BIO before being able
   to continue.

所以你有两个重复级别。如果您以正常方式绕过SSL_shutdown循环后获得SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE,则只需将select()称为“第一次” SSL_shutdown如果您收到非SSL_ERROR_WANT_错误代码(在这种情况下失败了),或者您获得01返回,则表示已完成。如果你得到1回复,你就完成了。如果您获得0返回,并且您想要双向关机,那么您必须进行第二次通话,您需要再次检查SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE并重试选择;不应返回1,但可能返回0或错误。

不简单。