c++ - 如何获取 OpenSSL BIO_do_connect() 失败原因?

标签 c++ ssl openssl network-programming

我正在使用 Ubuntu 18.04/gcc 7.3/OpenSSL 1.1.0g 使 C++ 应用程序通过非阻塞 BIO API 执行 TLS/SSL 连接。

BIO_do_connect() 连接失败时,例如如果使用错误的主机名或端口,OpenSSL 不会报告任何错误。 ERR_get_error() 返回零,ERR_print_errors_xx() 不打印任何内容。

所以问题是 - 如何获得实际的连接失败原因,例如“连接被拒绝”或“主机未解析”等?

下面使用的代码片段:

#include <cstdio>
#include <cstring>
#include <iostream>

#include "openssl/bio.h"
#include "openssl/err.h"
#include "openssl/ssl.h"

int main(int argc, char *argv[])
{
    OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, nullptr);

    std::cout << OpenSSL_version(OPENSSL_VERSION) << std::endl;

    SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
    if (!ctx)
    {
        std::cerr << "Error creating SSL context:" << std::endl;
        ERR_print_errors_fp(stderr);
        return 1;
    }

    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
    SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);

    if(!SSL_CTX_load_verify_locations(ctx,
        "/etc/ssl/certs/ca-certificates.crt",
        nullptr))
    {
        std::cerr << "Error loading trust store into SSL context" << std::endl;
        ERR_print_errors_fp(stderr);
        return 1;
    }

    BIO* cbio = BIO_new_ssl_connect(ctx);

    SSL* ssl = nullptr;
    BIO_get_ssl(cbio, &ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    BIO_set_conn_hostname(cbio, "not_actually_existing_host.com:https");
    BIO_set_nbio(cbio, 1);

    std::cout << "Start connecting" << std::endl;

    next:
    if (BIO_do_connect(cbio) <= 0)
    {
        if (!BIO_should_retry(cbio))
        {
            std::cerr << "Error attempting to connect:" << std::endl;
            ERR_print_errors_fp(stderr); // <---- PRINTS NOTHING!!!
            BIO_free_all(cbio);
            SSL_CTX_free(ctx);
            return 1;
        }
        else goto next;
    }

    std::cout << "Connected OK" << std::endl;

    BIO_free_all(cbio);
    SSL_CTX_free(ctx);
    return 0;
}

最佳答案

这种方法终于对我有用了:

    const auto sysErrorCode = errno;
    const auto sslErrorCode = ERR_get_error();

    std::string errorDescription;
    if (sslErrorCode != 0) errorDescription = ERR_error_string(sslErrorCode, nullptr);
    if (sysErrorCode != 0)
    {
        if (!errorDescription.empty()) errorDescription += '\n';
        errorDescription += "System error, code=" + std::to_string(sysErrorCode);
        errorDescription += ", ";
        errorDescription += strerror(sysErrorCode);
    }

关于c++ - 如何获取 OpenSSL BIO_do_connect() 失败原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53299498/

相关文章:

c++ - 使用 fread 读取二进制文件时无法获得正确的元素数

c++ - 在段错误上优化的值

ssl - 查询-关于-Gnutls-构建

c# - Windows 应用商店应用程序 - C# - Https 客户端身份验证

c - 使用 nist vector 值作为输入的 openssl hmac 代码验证系统

c - 使用 Visual Studio 和 Openssl 进行 AES 256 CTR 加密/解密

ssl - PHP cURL - SSL 证书问题 : unable to get local issuer certificate

c++ - boost::ptr_vector 对比 std::vector<std::unique_ptr<T>>?

c++ - 如何在WP8上使用cpp使用 “Application.Current.Terminate”

apache - 一个 IP 地址上的一个 SSL 证书服务于多个域