【问题标题】:using openssl with its unblocked bio, ssl_read return SSL_ERROR_SYSCALL and SSL_ERROR_WANT_READ使用 openssl 及其未阻止的 bio,ssl_read 返回 SSL_ERROR_SYSCALL 和 SSL_ERROR_WANT_READ
【发布时间】:2015-05-26 11:46:59
【问题描述】:

我使用 zeromq 和 openssl 来编写我的服务器和客户端。

握手成功后,客户端再次向服务器发送消息时,服务器中的ssl_read()返回-1,ssl_get_erro()返回SSL_ERROR_SYSCALL,

当服务器再次收到消息时,这种情况会重复。我找不到原因。我需要 BIO_flush() 吗?我真的很感激你,即使只是给我一些灵感来解决这个问题。


好吧,我的程序太复杂了,无法显示。我被要求在 rpcz 中添加 ssl 以提高其安全性(我不知道 rpcz 是否流行到足以让大多数人知道。用我的话来说,它结合了 zeromq、protobuf 和 rpc 来实现远程过程调用)。 所以有很多代码,我认为在这里显示它们并没有帮助。

我正在尝试提供更多详细信息。

握手成功后,当服务器尝试解密它接收到的数据时,使用这样的方法

`{
  //.......
  bio_write();
  //.......
  ssl_read();
}`

结果 bio_write() 通过返回数据的数量成功地将数据写入 bio,但 ssl_read() 总是返回 -1。所以我使用 ssl_get_error() 来检查错误号,它返回 SSL_ERROR_SYSCALL,对于下一个接收到的数据,它返回 SSL_ERROR_WANT_READ。

希望有人可以帮助解释为什么 ssl_read 返回这些代码?我认为如果 ssl 连接没有成功握手, ssl_write() 不会返回正数。所以可能问题不在于 ssl 连接。


再次添加一些细节

void TLSZmq::ssl_decrypt()
{
    //........
    ERR_clear_error();
    int rc = BIO_write(rbio,zmq_to_ssl->data(),zmq_to_ssl->size()); 
    ERR_get_error();
    check_ssl_err(rc); //written by myself
    //.........
    ERR_clear_error();      
    aread = SSL_read(ssl_,buffer,BUFFERSIZE);
    ERR_get_error();
    check_ssl_err(rc); //written by myself
    //..........
}

  void TLSZmq::check_ssl_err(int rc)
{
    //...................
    int err = SSL_get_error(ssl_, rc);
    if (err == SSL_ERROR_NONE)
    {
        std::cout<<"SSL_ERROR_NONE:"<<SSL_ERROR_NONE<<std::endl;
    }
    else if (err == SSL_ERROR_WANT_READ ) 
    { 
        std::cout<<"SSL_ERROR_WANT_READ:"<<SSL_ERROR_WANT_READ<<std::endl;
    }
    else if (SSL_ERROR_SYSCALL)
    {
        std::cout<<"SSL_ERROR_SYSCALL:"<<SSL_ERROR_SYSCALL<<std::endl;          

    }

    //.....................
}

我不确定这是检查错误堆栈或其他内容的正确方法。当出现 SSL_ERROR_SYSCALL 时,ERR_get_error() 返回一个奇怪的数字,如 336130315,当出现 SSL_ERROR_WANT_READ 时,ERR_get_error() 返回 0。

我还测试了握手后解密过程使用的 ssl 连接(SSL* ssl)与握手期间使用的相同。

呃……我们说的是 openssl 对吧? rc 获取 openssl 的 BIO_write() 函数的返回值。附言我已经指出,我使用 zeromq 套接字发送消息。我很迷惑。通过或调用 perror() 获取 errno 是否有意义?


非常感谢您抽出宝贵时间阅读本文。

【问题讨论】:

  • 欢迎来到堆栈溢出!请格式化您的 cmets 以提高可读性,并尽量避免重复您的帮助请求(例如,任何建议?)。
  • 很难在没有看到任何代码的情况下深入了解您的情况。错误可能来自多种原因。
  • 如果您收到归因于任何系统调用的错误,您必须: print errno;调用perror(); 或打印由str_error(). 产生的字符串,在执行任何其他可能更改errno. 的系统调用之前,您必须这样做,并且您必须在您的问题中发布结果。我会说你手上可能有一个ECONNRESET,但如果没有你的进一步信息,就不可能确定。如果您从任何系统调用或 SSL 函数中得到 -1,则几乎可以肯定连接会丢失,并且几乎可以肯定地继续下去是徒劳的。
  • 从您的编辑来看,您在更改之前收到的errno 还很不清楚。例如,rc 设置在哪里?它的设置是什么?不要编写这样的代码,当然也不要编写晦涩难懂的错误处理代码。尽可能简单。
  • 呃……我们说的是 openssl 对吧? rc 获取 openssl 的 BIO_write() 函数的返回值。附言我已经指出,我使用 zeromq 套接字发送消息。我很迷惑。通过或调用 perror() 获取 errno 是否有意义?

标签: c++ ssl openssl zeromq


【解决方案1】:

SSL 连接不是可以独立使用的解密功能和加密功能。如果您想要一个块或流密码,您可以使用 OpenSSL 代码来获取其中的一些部分。但是你不能那样使用 SSL 本身

可以使用 BIO 对来允许 SSL 在 TCP 以外的传输层上运行。但是您必须复制 TCP 的语义——它很复杂,而且代码看起来与您上面的代码完全不同。 (例如,TCP 允许在任何时候向任一方向传输。您不能复制它。SSL 设计为在 TCP 之上分层,需要您复制它才能在其他传输上工作。)

如果你想要一个流密码,就用一个。

【讨论】:

  • 事实上,也许他正在在他的原生阅读上获得 EWOULDBLOCK。在他告诉我们之前,这是任何人的猜测。
  • @EJP 如果是这样,他应该忽略它。 SSL 引擎可能会在本机读取时获得EWOULDBLOCK,但仍可能在不等待它们完成的情况下继续前进。试图“看穿” SSL 引擎是错误的——他应该按照 SSL 引擎的指示去做。
  • 伙计们,我没有使用winsock....所以这不是套接字的错TAT...我只使用openssl的未阻塞生物进行加密和解密,并将通信的东西留给zeromq .在这种情况下,我什至不必了解 TCP 是什么...... TAT
  • @601492584 你不能那样使用 SSL。 SSL 需要诸如协议协商之类的东西。如果你想要一个块或流密码,你可以为它们使用 OpenSSL,但不能使用SSL_read。您是否尝试在 SSL 引擎和 zeromq 连接之间使用 SSL 和代理?如果是这样,那你就all错了。
  • 是的,你可以这样做。但是你必须复制 TCP 的语义。你不能说“我只是给 SSL 引擎一些明文,所以现在它要发送加密数据”,因为 TCP 这样做。您确实必须复制 TCP 的全双工“我可以随时发送和接收”语义,允许 SSL 引擎这样做。而且你必须使用 BIO 对。
猜你喜欢
  • 2019-03-26
  • 1970-01-01
  • 2016-10-21
  • 2020-03-07
  • 2019-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多