2

在我的 C++ 应用程序中,我使用 OpenSSL 连接到使用非阻塞 BIO 的服务器。我正在为 mac OS X 和 iOS 开发。

第一次调用SSL_shutdown()返回 0。这意味着我必须SSL_shutdown()再次调用:

可能会出现以下返回值:

0 关机尚未完成。如果要执行双向关闭,则再次调用 SSL_shutdown()。SSL_get_error 的输出可能会产生误导,因为即使没有发生错误,也可能会标记错误的 SSL_ERROR_SYSCALL。

<0 关闭不成功,因为在协议级别发生了致命错误或发生了连接故障。如果需要采取措施继续非阻塞 BIO 的操作,也会发生这种情况。使用返回值 ret 调用 SSL_get_error 以找出原因。

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

到目前为止,上帝。第二次调用时出现问题SSL_shutdown()。这将返回 -1,这意味着发生了错误(见上文)。现在,如果我检查SSL_get_error()我得到错误SSL_ERROR_SYSCALL,这反过来应该意味着发生了系统错误。但现在抓住了。如果我检查errno它返回 0 -> 未知错误。到目前为止我所读到的关于这个问题的内容是,这可能意味着服务器只是“挂断了”,但老实说,这并不能让我满意。

这是我的关闭实现:

int result = 0;
int shutdownResult;
while ((shutdownResult = SSL_shutdown(sslHandle)) != 1) { //close connection 1 means everything is shut down ok
  if (shutdownResult == 0) { //we are supposed to call shutdown again
    continue;
  } else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_READ) {
                [...] //omitted want read code, in this case the application never reaches this point
  } else if (SSL_get_error(sslHandle, shutdownResult) == SSL_ERROR_WANT_WRITE) {
                [...] //omitted want write code, in this case the application never reaches this point
  } else {
    logError("Error in ssl shutdown, ssl error: " + std::to_string(SSL_get_error(sslHandle, shutdownResult)) + ", system error: " + std::string(strerror(errno))); //something went wrong
    break;
  }
} 

运行应用程序日志时:

ERROR:: ssl 关闭错误,ssl 错误:5,系统错误:未定义错误:0

那么这里只是服务器关闭连接还是存在更关键的问题?我只是错过了一些非常明显的东西吗?

4

1 回答 1

5

完全关闭 SSL 包括两部分:

  • 向对等方发送“关闭通知”警报
  • 从对等方接收“关闭通知”警报

第一个 SSL_shutdown 返回 0,这意味着它确实向对等方发送了“关闭通知”,但还没有收到任何回复。SSL_shutdown 的第二次调用失败,因为对等方没有正确关闭 SSL 并返回“关闭通知”,而是关闭了底层 TCP 连接。

这种行为实际上很常见,您通常可以忽略该错误。无论如何都应该关闭底层 TCP 连接并不重要。但是,当您想在同一个 TCP 连接上以纯文本继续时,通常需要适当的 SSL 关闭,就像 FTPS 连接中的 CCC 命令所需要的一样(但即使有各种实现也无法正确处理这种情况)。

于 2015-07-24T14:35:14.350 回答