正确处理SSL_shutdown
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
"第一次"时间,但如果在以正常方式绕过select()
循环后出现SSL_ERROR_WANT_READ
或SSL_ERROR_WANT_WRITE
,则重复,并且仅在收到非SSL_ERROR_WANT_
错误代码(在这种情况下失败)或获得0
或1
返回时才将"第一次"SSL_shutdown
计为完成。如果你得到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警报,大概他们应该即将发送......
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 使用 OpenSSL 从内存中读取原始 SSL/TLS 证书
- Mongocxx无法使用SSL连接到mongoDB
- 如何使用MinGW编译器和SSL支持静态编译Qt
- curl_easy_perform() 失败:SSL 对等证书或 SSH 远程密钥不正常
- 如何在 Windows 中通过 SSL 端口枚举域控制器
- 我需要帮助来缩短检索 SSL 证书的执行时间
- Windows 和 Android 应用程序是否需要 SSL?
- 如何使用QWebEngineView忽略SSL证书错误
- 抽象类析构函数与继承"Shutdown"函数
- CPPRestSdk给出错误SSL错误:WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA
- 成功完成TLS握手后,服务器关闭时出现错误的SSL例程:SSL3_GET_RECORD:错误的版本号
- 如何从 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> 获取本机套接字文件描述器?
- Qt 错误消息"qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed"
- OCCI:使用SSL钱包身份验证连接到OracleDB
- 如何在Mac OSX上的Qt中使用pkcs12 / pfx成功执行SSL加密?
- 使用 qt 进行 SSL 握手期间出错
- 提升 Asio SSL 无法第二次接收数据(第一次确定)
- 打开 SSL 查询客户端证书
- boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::shutdown() 做什么?