【问题标题】:openssl BIO_do_connect returns 0 for sslopenssl BIO_do_connect 为 ssl 返回 0
【发布时间】:2014-02-03 17:31:37
【问题描述】:

这是我尝试连接到 google.com:443 的简单 openssl 客户端测试用例。

根据手册,BIO_do_connect 应该返回 1、0 或 -1。 Google 没有为我找到返回 0 的任何人,但它为我找到了。

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

int main()
{
    SSL_load_error_strings();
    SSL_library_init();
    ERR_load_BIO_strings();
    OpenSSL_add_all_algorithms();

    SSL_CTX *p_ssl_ctx = NULL;
    SSL     *p_ssl     = NULL;
    BIO     * bio      = NULL;
    int r = 0;

    // init ssl context
    p_ssl_ctx = SSL_CTX_new(SSLv2_client_method());   /* Create new context */
    if (p_ssl_ctx == NULL)
    {
        ERR_print_errors_fp(stderr);
        return 3;
    }

    const char *store_path = "/etc/ssl/certs/ca-certificates.crt";
    r = SSL_CTX_load_verify_locations(p_ssl_ctx, store_path, NULL);
    if (r == 0) {
        fprintf(stderr, "Unable to load the trust store from %s.\n", store_path);
        return 4;
    }

    bio = BIO_new_ssl_connect(p_ssl_ctx);
    if (!bio) {
        fprintf(stderr, "no bio \n");
        return 5;
    }

    BIO_get_ssl(bio, &p_ssl);
    if (!(p_ssl)) {
        fprintf(stderr, "no ssl\n");
        return 6;
    }

    SSL_set_mode(p_ssl, SSL_MODE_AUTO_RETRY);
    BIO_set_conn_hostname(bio, "www.google.com:443");

    r  = BIO_do_connect(bio);
    if (r < 1) {
        fprintf(stderr, "BIO_new_ssl_connect failed: %lu (0x%lx)\n", r, r);
        fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        ERR_print_errors_fp(stderr);
        perror("bio");
        return 7;
    }

    if (SSL_get_verify_result(p_ssl) != X509_V_OK) {
        fprintf(stderr, "Unable to verify connection result.\n");
        return 8;
    }

    return 0;
}

返回:

BIO_new_ssl_connect failed: 0 (0x0)
Error: (null)
error:00000000:lib(0):func(0):reason(0)
bio: Success

那么我该如何从中得到实际的错误呢?

【问题讨论】:

    标签: ssl openssl libssl libcrypto


    【解决方案1】:

    要在代码中获取 SSL 连接的最后状态,您可以添加类似 fprintf(stderr,"p_ssl state: %s\n",SSL_state_string_long(p_ssl)); 的内容。

    更一般地,我建议您添加这样的信息回调:http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html

    对于您的情况,您必须将 SSLv2_client_method() 替换为 TLSv1_client_method() 之类的内容。

    【讨论】:

    • 所有这些建议都非常好。我现在得到有用的调试信息。但是请解释一下为什么它是 TLSv1_client_method 而不是 SSLv2?
    • SSLv2 由于许多安全问题已被弃用,并在许多网站(包括google.com)中被禁用。当你使用 SSL_CTX_new(SSLv2_client_method()) 时,你告诉 openssl 只使用 sslv2 协议。
    • 这个 fprintf 返回我“SSLv2/v3 读取服务器你好 A”。这是什么意思?
    猜你喜欢
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2019-03-13
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多