[英]Handling SSL_shutdown correctly
The OpenSSL documentation on SSL_shutdown
states that: SSL_shutdown
上的 OpenSSL 文档指出:
It is therefore recommended, to check the return value of
SSL_shutdown()
and callSSL_shutdown()
again, if the bidirectional shutdown is not yet complete (return value of the first call is 0).因此,如果双向关闭尚未完成(第一次调用的返回值为 0),建议检查SSL_shutdown()
的返回值并再次调用SSL_shutdown()
)。
https://www.openssl.org/docs/ssl/SSL_shutdown.html 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.我在下面有一个代码片段,我在其中检查SSL_shutdown
返回值 0 并再次调用它,我一直在使用它。 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.我的问题是,在第二次调用时忽略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);
openssl
is a bit of a dark art. openssl
有点黑暗艺术。
Firstly the page you referenced has HTML-ified the return values badly.首先,您引用的页面对返回值进行了 HTML 化处理。 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.如果您有阻塞 BIO,事情就相对简单了。 A 0 on the first call means you need to call SSL_shutdown
again if you want a full bidirectional shutdown.第一次调用时为 0 意味着如果您想要完全双向关闭,则需要再次调用SSL_shutdown
。 Basically it means that you sent a close_notify alert but haven't one back yet).基本上这意味着您发送了 close_notify 警报但还没有回复)。 A 1 would mean you previously received a close_notify alert from the other peer, and you're totally done. 1 表示您之前收到了来自其他对等方的 close_notify 警报,并且您完全完成了。 A -1 means an unrecoverable error. -1 表示不可恢复的错误。 On the second call (which you only do if you got a 0 back), then a bidirectional shutdown is initiated (ie now wait from the other side for them to send you their "close_notify" alert).在第二次调用时(只有在返回 0 时才这样做),然后启动双向关闭(即现在等待对方向您发送“close_notify”警报)。 Logic dictates you can't get a 0 back again (because it's a blocking BIO and will have completed the first step).逻辑决定你不能再次得到 0(因为它是一个阻塞的 BIO 并且已经完成了第一步)。 A -1 indicates an error, and a 1 indicates completion success. -1 表示错误,1 表示完成成功。
If you have non-blocking BIOs, the same "possibly 0 then 1" return values apply, save for the fact you need to go through the whole SSL_ERROR_WANT_READ
and SSL_ERROR_WANT_WRITE
rigmarole as well, ie:如果你有非阻塞 BIO,同样的“可能 0 然后 1”返回值适用,除了你需要通过整个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.
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.你叫SSL_shutdown
“第一”时间,但重复,如果你得到SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
绕来绕去后select()
循环以正常的方式,只算“第一” SSL_shutdown
为已完成,如果你得到一个非SSL_ERROR_WANT_
错误代码(其中如果失败),或者您会得到0
或1
回报。 If you get a 1
return, you've done.如果你得到1
回报,你就完成了。 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;如果返回0
,并且想要双向关闭,则必须进行第二次调用,再次调用时需要检查SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
试选择; that should not return 1
, but may return 0 or an error.不应返回1
,但可能返回 0 或错误。
Not simple.不简单。
Couple more notes from the docs : after calling SSL_shutdown
and getting a "0" back the first time, you could optionally then call SSL_read
instead of SSL_shutdown
(in case the peer is still sending you any data on that SSL socket), and, I guess, "hope" that they eventually send you a close message from their side, to flush the pipes. 文档中的更多注释:在第一次调用SSL_shutdown
并返回“0”之后,您可以选择调用SSL_read
而不是SSL_shutdown
(以防对等方仍在该 SSL 套接字上向您发送任何数据),并且,我猜测,“希望”他们最终会从他们身边向您发送一条关闭消息,以冲洗管道。
Also if you're planning on closing the socket after shutdown completion "anyway" you could entirely skip the second call to SSL_shutdown
(the "1" of the "0 then 1") and just go ahead and close the socket, the kernel should take care of discarding the "now ignored" close_notify alert that presumably they should be about to send...此外,如果您计划在关闭完成后“无论如何”关闭套接字,您可以完全跳过对SSL_shutdown
的第二次调用(“0 然后 1”的“1”),然后继续关闭套接字,内核应该注意丢弃“现在被忽略”的 close_notify 警报,大概他们应该发送......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.