正确处理SSL_shutdown

cmi*_*idi 9 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);
Run Code Online (Sandbox Code Playgroud)

abl*_*igh 12

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.
Run Code Online (Sandbox Code Playgroud)

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

如果你有非阻塞的BIO,同样适用,除​​了你需要经历整个SSL_ERROR_WANT_READ和钻井平台的事实SSL_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.
Run Code Online (Sandbox Code Playgroud)

所以你有两个重复级别.你叫SSL_shutdown"第一"时间,但如果你重复SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE绕去后select()以正常的方式循环,只能算"第一个" SSL_shutdown,如果你得到一个非为已完成SSL_ERROR_WANT_的错误代码(在这种情况下,失败),或者你a 01返回.如果你得到1回报,你就完成了.如果你得到一个0返回,并且你想要双向关闭,那么你必须进行第二次调用,你需要再次检查SSL_ERROR_WANT_READSSL_ERROR_WANT_WRITE重试select; 不应该返回1,但可能返回0或错误.

不简单.

  • 请注意,使用 TLS 1.3,您无法跳过第二个“SSL_shutdown”,特别是当流量纯粹是本地到远程时。例如,请参阅 https://github.com/openssl/openssl/issues/7948 (2认同)