正确处理SSL_shutdown [英] Handling SSL_shutdown correctly

查看:633
本文介绍了正确处理SSL_shutdown的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在SSL_shutdown OpenSSL的文档指出:
因此建议,检查SSL_shutdown(返回值),并再次呼吁SSL_shutdown(),如果双向停机尚未完成(第一次调用的返回值为0)。

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

我有一个code段下面,我检查来自SSL_shutdown返回值为0,并再次调用它,这是我一直在使用。我的问题是,什么情况下可以忽略第二呼叫SSL_shutdown的返回值,或者我们应该继续重试SSL_shutdown直到1(双向停机完成)返回。

  INT R = SSL_shutdown(SSL);
 //错误处理这里如果为r 0
 如果(!R)
 {     关闭(FD,1);
     SSL_shutdown(SSL); //我应该怎么处理返回值和错误处理这里需要它?
 }
 SSL_free(SSL);
 SSLMap.erase(FD);
 关闭(FD,2);
 关闭(FD);


解决方案

的OpenSSL 是有点暗的艺术。

首先,你所引用的页面已经严重HTML的指明分数的返回值。下面是该名男子页的真正的说道:

 返回值   可能会出现以下返回值:   0关机尚未完成。呼叫SSL_shutdown()如属第二
       一次,如果应进行双向关闭。输出
       SSL_get_error的(3)可以是误导,因为错误的
       SSL_ERROR_SYSCALL可被标记,即使没有发生错误。   1关机已成功完成。 关闭通知警报
       发送和接收对方的关闭通知警报。   -1关闭未成功,因为发生了致命错误
       无论在协议级或连接故障的发生。它
       如果动作是需要继续对非操作也可能发生
       阻塞BIOS。呼叫SSL_get_error(3)与返回值ret到
       找出原因。

如果你有阻止BIOS,事情就比较简单。在第一次调用A 0意味着你需要,如果你想有一个双向停机再打电话 SSL_shutdown 。 A 1意味着大功告成。 A -1意味着一个错误。在第二个电话(你只有当你得到了一个0回做),然后双向停机启动。从逻辑上讲,你不能得到一个0回来(因为它是一个阻塞BIO和将完成的第一步)。 A -1表示错误,和1表示完成。

如果您有无阻塞的BIOS,同​​样适用,节省您需要去通过全 SSL_ERROR_WANT_READ SSL_ERROR_WANT_WRITE 繁琐程序,即:

 如果底层的BIO是非阻塞,SSL_shutdown()也将返回
   当底层BIO不能满足SSL_shutdown的需求()
   继续握手。在这种情况下SSL_get_error()的调用与
   SSL_shutdown()的返回值将产生SSL_ERROR_WANT_READ或
   SSL_ERROR_WANT_WRITE。然后调用进程必须重复调用
   采取适当的行动,以满足SSL_shutdown的需要()之后。
   的操作取决于底层的BIO。当使用非阻挡
   插座,没有什么是必须要做的,但选择()可以用来检查
   所需要的条件。当使用一个缓冲BIO,就像一个BIO对,
   数据必须写入或能够之前检索出的生物
   接着说。

所以,你有重复的两个层次。你叫 SSL_shutdown 第一个时间,但如果你重复 SSL_ERROR_WANT_READ SSL_ERROR_WANT_WRITE 以正常的方式围绕选择()循环会后,只算第一个 SSL_shutdown 为已完成,如果你得到一个非 SSL_ERROR_WANT _ 错误code(在这种情况下,它失败了),或者你收到了 0 1 的回报。如果你收到了 1 回报,你所做的一切。如果你收到了 0 回报,你想有一个双向停机,那么你必须做第二个电话,在其再次你将需要检查 SSL_ERROR_WANT_READ SSL_ERROR_WANT_WRITE 并重新选择;这不应该返回 1 ,但可能返回0或错误。

并不简单。

The openssl documentation on SSL_shutdown states that : It is therefore recommended, to check the return value of SSL_shutdown() and call SSL_shutdown() again, if the bidirectional shutdown is not yet complete (return value of the first call is 0).

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

I have a code snippet below where I check for return value 0 from SSL_shutdown and call it again, which I have been using. My question is, is it okay to disregard the return value of SSL_shutdown on the second call or we should keep retrying SSL_shutdown until a 1(bidirectional shutdown complete) is returned.

 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);

解决方案

openssl is a bit of a dark art.

Firstly the page you referenced has HTML-ified the return values badly. Here's what the man-page actually says:

  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.

If you have blocking BIOs, things are relatively simple. A 0 on the first call means you need to call SSL_shutdown again if you want a bidirectional shutdown. A 1 means you're done. A -1 means an error. On the second call (which you only do if you got a 0 back), then a bidirectional shutdown is initiated. Logic dictates you can't get a 0 back again (because it's a blocking BIO and will have completed the first step). A -1 indicates an error, and a 1 indicates completion.

If you have non-blocking BIOs, the same applies, save for the fact you need to go through the whole SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE rigmarole, i.e.:

   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.

So you have two levels of repetition. You call SSL_shutdown the 'first' time but repeat if you get SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE after going around the select() loop in the normal way, and only count the 'first' SSL_shutdown as done if you get a non SSL_ERROR_WANT_ error code (in which case it failed), or you get a 0 or 1 return. If you get a 1 return, you've done. If you get a 0 return, and you want a bidirectional shutdown, then you have to do the second call, on which again you will need to check for SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE and retry select; that should not return 1, but may return 0 or an error.

Not simple.

这篇关于正确处理SSL_shutdown的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆