Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenSSL 1.0.1 SSL_read()函数在某些https网站上返回0字节_Ssl_Https_Openssl_Httpclient - Fatal编程技术网

OpenSSL 1.0.1 SSL_read()函数在某些https网站上返回0字节

OpenSSL 1.0.1 SSL_read()函数在某些https网站上返回0字节,ssl,https,openssl,httpclient,Ssl,Https,Openssl,Httpclient,我正试图通过openssl1.0.1u创建一个https客户端,它可以访问使用ssl协议的网站。 当访问大多数https网站(如google.com、yahoo.com、facebook.com等)时,它运行良好,并且返回主页内容。但是,有些网站(相对较小的网站),服务器返回0字节,以下是一些详细信息: 我使用SSLv23\u method()创建我的openssl上下文: this->_sslContext = SSL_CTX_new(SSLv23_method()); // SSLv2

我正试图通过
openssl1.0.1u
创建一个https客户端,它可以访问使用ssl协议的网站。 当访问大多数https网站(如google.com、yahoo.com、facebook.com等)时,它运行良好,并且返回主页内容。但是,有些网站(相对较小的网站),服务器返回0字节,以下是一些详细信息:

我使用
SSLv23\u method()
创建我的openssl上下文:

this->_sslContext = SSL_CTX_new(SSLv23_method()); // SSLv23_method: Negotiate highest available SSL/TLS version
然后我发现在以下调用序列中(向前列出):

对于某些网站(失败的情况),函数
SSL\u read()
返回0字节,因为在函数
ssl3\u read\u bytes()
中,我将
警报描述设置为
SSL\u AD\u CLOSE\u NOTIFY
,然后函数只返回0,以下是源代码:

...
if (alert_level == SSL3_AL_WARNING) 
        {
            s->s3->warn_alert = alert_descr;
            if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
                s->shutdown |= SSL_RECEIVED_SHUTDOWN;
                return (0);
            }
有人能给我一些提示来解决这个问题吗?谢谢

==更新===

根据他的建议,我发布了发送请求/获取响应的源代码。我的小型实验性https客户端由
Socket
SSLSocket
类和一个助手
WebpageFetcher
类组成。函数
WebpageFetcher::fetchPage
用于发送https请求并从私有函数
WebpageFetcher::\u getResponse()

调用工厂函数时,我将参数
usesl
true
一起传递,因此我得到的套接字是一个SSLSocket实例,它覆盖默认函数
connect()
\u send()
\u recv()
,以让openssl执行实际工作。下面是我的SSLSocket类的构造函数,它派生自类Socket:

SSLSocket::SSLSocket(bool isServerSocket, int port, int socketType, int socketProtocol, int uOptions, wchar_t * strBindingAddress, wchar_t * cerPath, wchar_t * keyPath, wchar_t * keyPass) :
    Socket(isServerSocket, port, socketType, socketProtocol, uOptions, strBindingAddress)
{
    // Register the error strings
    SSL_load_error_strings();

    // Register the available ciphers and digests
    SSL_library_init();

    // Create an SSL_CTX structure by choosing a SSL/TLS protocol version
    this->_sslContext = SSL_CTX_new(SSLv23_method()); // Use SSL 2 or SSL 3

    // Create an SSL struct (client only, server does not need one)
    this->_sslHandle = (this->_isServer ? NULL : SSL_new(this->_sslContext));
    bool success = false;

    if (!this->_isServer) // is Client socket
    {
        success = (this->_sslHandle != NULL);
    }
    else if (cerPath != NULL && keyPath != NULL) // is Server socket
    {
        success = ......
    }

    if (!success)
        this->close();
}
下面是函数覆盖父类套接字中的虚拟函数,它允许openssl执行相关工作:

bool SSLSocket::connect(wchar_t * strDestination, int port, int timeout)
{
    SocketAddress socketAddress(strDestination, port);
    return this->connect(&socketAddress, timeout);
}
bool SSLSocket::connect(SocketAddress * sockAddress, int timeout)
{
    bool success = 
        (this->_sslHandle != NULL && 
        Socket::connect(sockAddress, timeout) &&                // Regular TCP connection
        SSL_set_fd(this->_sslHandle, (int)this->_hSocket) == 1 &&   // Connect the SSL struct to our connection
        SSL_connect(this->_sslHandle) == 1);                    // Initiate SSL handshake

    if (!success)
        this->close();

    return success;
}

int SSLSocket::_recv(void * lpBuffer, int size, int flags)
{
    MonitorLock cs(&_mutex);
    return SSL_read(this->_sslHandle, lpBuffer, size);
}

int SSLSocket::_send(const void * lpBuffer, int size, int flags)
{
    return SSL_write(this->_sslHandle, lpBuffer, size);
}

1.0.1u是一个非常旧的OpenSSL版本(当前版本为1.1.1k,3.0目前正在进行alpha测试)。OpenSSL开发团队在2016年底放弃了对1.0.1系列的支持
ssl\u read()
返回0表示服务器关闭了TCP连接,可能是因为您使用的是如此旧的版本。例如,1.0.1是支持TLS1.2的第一个版本,但您的代码没有使用SNI,而大多数现代web服务器在使用TLS1.2时都需要SNI。你需要升级你的OpenSSL。嗨,雷米,我高度相信你的预测是正确的,因为所有失败的案例都是当我尝试访问托管在共享web服务器上的https网站并使用某种虚拟域时。我对TLS/SSL握手和SNI非常陌生,只是想知道您是否可以提供一个指向好教程的链接?这可能会让我得到最终的答案。嗨,雷米,我采纳了你的建议,找到了SNI的教程,然后我在连接之前添加了“SSL\u set\u tlsext\u host\u name(SSL,domainName)”,效果很好!如果你能再发一次,我可以接受你的建议。
SSLSocket::SSLSocket(bool isServerSocket, int port, int socketType, int socketProtocol, int uOptions, wchar_t * strBindingAddress, wchar_t * cerPath, wchar_t * keyPath, wchar_t * keyPass) :
    Socket(isServerSocket, port, socketType, socketProtocol, uOptions, strBindingAddress)
{
    // Register the error strings
    SSL_load_error_strings();

    // Register the available ciphers and digests
    SSL_library_init();

    // Create an SSL_CTX structure by choosing a SSL/TLS protocol version
    this->_sslContext = SSL_CTX_new(SSLv23_method()); // Use SSL 2 or SSL 3

    // Create an SSL struct (client only, server does not need one)
    this->_sslHandle = (this->_isServer ? NULL : SSL_new(this->_sslContext));
    bool success = false;

    if (!this->_isServer) // is Client socket
    {
        success = (this->_sslHandle != NULL);
    }
    else if (cerPath != NULL && keyPath != NULL) // is Server socket
    {
        success = ......
    }

    if (!success)
        this->close();
}
bool SSLSocket::connect(wchar_t * strDestination, int port, int timeout)
{
    SocketAddress socketAddress(strDestination, port);
    return this->connect(&socketAddress, timeout);
}
bool SSLSocket::connect(SocketAddress * sockAddress, int timeout)
{
    bool success = 
        (this->_sslHandle != NULL && 
        Socket::connect(sockAddress, timeout) &&                // Regular TCP connection
        SSL_set_fd(this->_sslHandle, (int)this->_hSocket) == 1 &&   // Connect the SSL struct to our connection
        SSL_connect(this->_sslHandle) == 1);                    // Initiate SSL handshake

    if (!success)
        this->close();

    return success;
}

int SSLSocket::_recv(void * lpBuffer, int size, int flags)
{
    MonitorLock cs(&_mutex);
    return SSL_read(this->_sslHandle, lpBuffer, size);
}

int SSLSocket::_send(const void * lpBuffer, int size, int flags)
{
    return SSL_write(this->_sslHandle, lpBuffer, size);
}