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

时间:2015-03-23 13:07:40

标签: c++ ssl openssl zeromq

我使用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 个答案:

答案 0 :(得分:1)

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

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

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