問題描述
關于 SSL_shutdown
的 OpenSSL 文檔指出:
The OpenSSL documentation on SSL_shutdown
states that:
因此建議檢查SSL_shutdown()
的返回值并再次調用SSL_shutdown()
,如果雙向關閉尚未完成(返回值第一個調用是 0).
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).
https://www.openssl.org/docs/ssl/SSL_shutdown.html
我在下面有一個代碼片段,我在其中檢查 SSL_shutdown
的返回值 0 并再次調用它,我一直在使用它.我的問題是,是否可以在第二次調用時忽略 SSL_shutdown
的返回值,或者我們應該繼續重試 SSL_shutdown
直到返回 1(雙向關閉完成).
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
有點像黑暗藝術.
openssl
is a bit of a dark art.
首先,您引用的頁面對返回值進行了 HTML 化處理.這是手冊頁實際上所說的:
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.
如果您有阻塞 BIO,事情就相對簡單了.第一次調用時為 0 意味著如果您想要完全雙向關閉,則需要再次調用 SSL_shutdown
.基本上這意味著您發送了 close_notify 警報但還沒有回復).1 表示您之前收到了來自其他對等方的 close_notify 警報,并且您已經完全完成了.-1 表示不可恢復的錯誤.在第二次調用時(只有在返回 0 時才這樣做),然后啟動雙向關閉(即現在等待對方向您發送close_notify"警報).邏輯決定你不能再得到一個 0(因為它是一個阻塞的 BIO 并且已經完成了第一步).-1 表示錯誤,1 表示完成成功.
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 full bidirectional shutdown. Basically it means that you sent a close_notify alert but haven't one back yet). A 1 would mean you previously received a close_notify alert from the other peer, and you're totally done. A -1 means an unrecoverable error. On the second call (which you only do if you got a 0 back), then a bidirectional shutdown is initiated (i.e. now wait from the other side for them to send you their "close_notify" alert). 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 success.
如果你有非阻塞 BIO,同樣的可能是 0 然后 1"的返回值適用,除了你需要遍歷整個 SSL_ERROR_WANT_READ
和 SSL_ERROR_WANT_WRITE
也很啰嗦,即:
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, 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.
所以你有兩個級別的重復.您在第一次"調用 SSL_shutdown
,但如果在繞過 select()
或 SSL_ERROR_WANT_WRITE
后得到 SSL_ERROR_WANT_READ
或 SSL_ERROR_WANT_WRITE
,請重復> 以正常方式循環,如果您得到非 SSL_ERROR_WANT_
錯誤代碼(在這種情況下它失敗),則僅將第一個"SSL_shutdown
視為已完成,或者您得到0
或 1
返回.如果你得到 1
返回,你就完成了.如果您得到 0
返回,并且您想要雙向關閉,那么您必須進行第二次調用,再次需要檢查 SSL_ERROR_WANT_READ
或 SSL_ERROR_WANT_WRITE
并重試選擇;不應返回 1
,但可能返回 0 或錯誤.
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.
不簡單.
來自 docs 的更多注釋:調用 之后SSL_shutdown
并在第一次返回0"時,您可以選擇調用 SSL_read
而不是 SSL_shutdown
(以防對等方仍在向您發送任何數據在那個 SSL 套接字上),并且我猜希望"他們最終從他們這邊向您發送關閉消息,以刷新管道.
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 然后 1"的1")的第二次調用,然后只需繼續關閉套接字,內核應該注意丟棄現在被忽略"的 close_notify 警報,大概他們應該發送...
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的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!