openssl BIO_do_connect为ssl返回0

openssl BIO_do_connect为ssl返回0,ssl,openssl,libssl,libcrypto,Ssl,Openssl,Libssl,Libcrypto,下面是我尝试连接到google.com的简单openssl客户端测试用例:443 根据手册,BIO_do_connect应返回1、0或-1。 谷歌没有为我找到任何它返回0的人,这是为我做的 #include <stdio.h> #include <openssl/ssl.h> #include <openssl/err.h> int main() { SSL_load_error_strings(); SSL_library_init();

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

根据手册,BIO_do_connect应返回1、0或-1。 谷歌没有为我找到任何它返回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;
}

那么,如何从中获取实际错误呢?

要在代码中获取SSL连接的最后状态,可以添加类似于
fprintf(stderr,“p_SSL状态:%s\n”,SSL_状态字符串长度(p_SSL))

一般来说,我建议您添加如下信息回调:


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

所有这些建议都非常好。我现在得到了有用的调试信息。但请解释一下为什么它是TLSv1_client_方法而不是SSLv2?SSLv2因许多安全问题而被弃用,并且在许多网站(包括)中被禁用。当您使用SSL_CTX_new(SSLv2_client_method())时,您告诉openssl仅使用SSLv2协议。此fprintf返回我“SSLv2/v3读取服务器hello A”。这是什么意思?
BIO_new_ssl_connect failed: 0 (0x0)
Error: (null)
error:00000000:lib(0):func(0):reason(0)
bio: Success