[英]Handling SSL_shutdown correctly
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);
openssl
有點黑暗藝術。
首先,您引用的頁面對返回值進行了 HTML 化處理。 這是手冊頁的實際內容:
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 表示完成成功。
如果你有非阻塞 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.
所以你有兩個級別的重復。 你叫SSL_shutdown
“第一”時間,但重復,如果你得到SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
繞來繞去后select()
循環以正常的方式,只算“第一” SSL_shutdown
為已完成,如果你得到一個非SSL_ERROR_WANT_
錯誤代碼(其中如果失敗),或者您會得到0
或1
回報。 如果你得到1
回報,你就完成了。 如果返回0
,並且想要雙向關閉,則必須進行第二次調用,再次調用時需要檢查SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
試選擇; 不應返回1
,但可能返回 0 或錯誤。
不簡單。
文檔中的更多注釋:在第一次調用SSL_shutdown
並返回“0”之后,您可以選擇調用SSL_read
而不是SSL_shutdown
(以防對等方仍在該 SSL 套接字上向您發送任何數據),並且,我猜測,“希望”他們最終會從他們身邊向您發送一條關閉消息,以沖洗管道。
此外,如果您計划在關閉完成后“無論如何”關閉套接字,您可以完全跳過對SSL_shutdown
的第二次調用(“0 然后 1”的“1”),然后繼續關閉套接字,內核應該注意丟棄“現在被忽略”的 close_notify 警報,大概他們應該發送......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.