首页 文章

使用openssl及其未阻止的bio,ssl_read返回SSL_ERROR_SYSCALL和SSL_ERROR_WANT_READ

提问于
浏览
1

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

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

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


好吧,我的程序太复杂了,无法显示 . 我被要求将ssl添加到rpcz以提高其安全性(我不知道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 socket发送消息,我已经指出了 . 我很迷惑 . 获得errno或调用perror()是否有意义?


非常感谢您抽出时间阅读本文 .

1 回答

  • 1

    SSL连接不是可以独立使用的解密功能和加密功能 . 如果你想要一个块或流密码,你可以使用OpenSSL代码获得一些 . 但是你不能以这种方式使用SSL .

    可以使用BIO对来允许SSL在TCP之外的传输层上操作 . 但是你必须复制TCP的语义 - 它很复杂,代码看起来与你上面的代码完全不同 . (例如,TCP允许在任何时间向任一方向传输 . 您不会复制它 . 设计为在TCP之上分层的SSL,要求您复制它以便在其他传输上工作 . )

    如果你想要一个流密码,只需使用一个密码 .

相关问题