BIO_do_handshake() 总是返回 0
Posted
技术标签:
【中文标题】BIO_do_handshake() 总是返回 0【英文标题】:BIO_do_handshake() always return 0 【发布时间】:2013-03-30 12:36:57 【问题描述】: int rtn = BIO_do_handshake(sbio);
printf("\n.. returns %d .. \n",rtn);
if( rtn <= 0)
fprintf(stderr, "Error in SSL handshake\n");
ERR_print_errors_fp(stderr);
我从here写这个代码
但是 BIO_do_handshake() 为什么总是返回 0 呢?
证书很好!
有什么想法吗?
请帮帮我..
谢谢
【问题讨论】:
ERR_print_errors_fp(stderr);
打印到 stderr 的内容是什么? OpenSSL 说的是什么错误?
【参考方案1】:
我们确实需要查看更多代码,但这里是我使用BIO_new_ssl_connect
和朋友的方式。你打电话给BIO_new_ssl_connect
了吗?你打电话给BIO_set_conn_hostname
了吗?你打电话给BIO_do_connconnect
了吗?
下面的代码连接到 www.random.org 并将结果打印到屏幕上。还有一些你必须做的其他检查,但它们超出了BIO_new_ssl_connect
和朋友的热门使用范围。
此外,bio 读取循环并不可靠,因此请勿在生产代码中使用它(该示例用于其他目的)。最后,您可以使用ERR_print_errors_fp
处理打印错误。在生产中,我做其他事情,所以ERR_print_errors_fp
通常是不够的(因此是简单的fprintf
的原因)。
long ret = 1;
unsigned long ssl_err = 0;
SSL_CTX* ctx = NULL;
BIO *bio = NULL, *out = NULL;
SSL *ssl = NULL;
/* Cipher suites, https://www.openssl.org/docs/apps/ciphers.html */
const char* const PREFERRED_CIPHERS = "kEECDH:kEDH:kRSA:AESGCM:AES256:AES128:3DES:SHA256:SHA84:SHA1:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM!MD5";
do
/* https://www.openssl.org/docs/ssl/SSL_library_init.html */
ret = SSL_library_init();
ssl_err = ERR_get_error();
ASSERT(ret == 1);
if(!(ret == 1))
fprintf(stderr, "SSL_library_init: %lu (0x%lx)\n", ssl_err , ssl_err);
break; /* failed */
/* https://www.openssl.org/docs/ssl/SSL_CTX_new.html */
const SSL_METHOD* method = SSLv23_method();
ssl_err = ERR_get_error();
ASSERT(NULL != method);
if(!(NULL != method))
fprintf(stderr, "SSLv23_method failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break; /* failed */
/* http://www.openssl.org/docs/ssl/ctx_new.html */
ctx = SSL_CTX_new(method);
ssl_err = ERR_get_error();
ASSERT(ctx != NULL);
if(!(ctx != NULL))
fprintf(stderr, "SSL_CTX_new failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break; /* failed */
/* https://www.openssl.org/docs/ssl/ctx_set_verify.html */
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, bio_pin_pubkey_callback);
/* Cannot fail ??? */
/* https://www.openssl.org/docs/ssl/ctx_set_verify.html */
SSL_CTX_set_verify_depth(ctx, 5);
/* Cannot fail ??? */
/* Remove most egregious. Because SSLv2 and SSLv3 have been removed, */
/* a TLSv1.0 handshake is used. The client accepts TLSv1.0 and above. */
const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
long old_opts = SSL_CTX_set_options(ctx, flags);
UNUSED(old_opts);
/* http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html */
ret = SSL_CTX_load_verify_locations(ctx, "random-org-chain.pem", NULL);
ssl_err = ERR_get_error();
ASSERT(1 == ret);
if(!(1 == ret))
/* Non-fatal, but something else will probably break later */
fprintf(stderr, "SSL_CTX_load_verify_locations failed: %lu (0x%lx)\n", ssl_err , ssl_err);
/* break; */
/* https://www.openssl.org/docs/crypto/BIO_f_ssl.html */
bio = BIO_new_ssl_connect(ctx);
ssl_err = ERR_get_error();
ASSERT(bio != NULL);
if(!(bio != NULL))
fprintf(stderr, "BIO_new_ssl_connect failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break; /* failed */
/* https://www.openssl.org/docs/crypto/BIO_f_ssl.html */
/* This copies an internal pointer. No need to free. */
BIO_get_ssl(bio, &ssl);
ssl_err = ERR_get_error();
ASSERT(ssl != NULL);
if(!(ssl != NULL))
fprintf(stderr, "BIO_get_ssl failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break; /* failed */
/* https://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_CONTEXTS */
/* https://www.openssl.org/docs/ssl/SSL_CTX_set_cipher_list.html */
ret = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
ssl_err = ERR_get_error();
ASSERT(1 == ret);
if(!(1 == ret))
fprintf(stderr, "SSL_set_cipher_list failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break;
/* https://www.openssl.org/docs/crypto/BIO_s_connect.html */
ret = BIO_set_conn_hostname(bio, HOST_NAME ":" HOST_PORT);
ssl_err = ERR_get_error();
ASSERT(1 == ret);
if(!(1 == ret))
fprintf(stderr, "BIO_set_conn_hostname failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break;
/* https://www.openssl.org/docs/crypto/BIO_s_file.html */
out = BIO_new_fp(stdout, BIO_NOCLOSE);
ssl_err = ERR_get_error();
ASSERT(NULL != out);
if(!(NULL != out))
fprintf(stderr, "BIO_new_fp failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break;
/* https://www.openssl.org/docs/crypto/BIO_s_connect.html */
ret = BIO_do_connect(bio);
ssl_err = ERR_get_error();
ASSERT(1 == ret);
if(!(1 == ret))
fprintf(stderr, "BIO_do_connect failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break;
/* https://www.openssl.org/docs/crypto/BIO_f_ssl.html */
ret = BIO_do_handshake(bio);
ssl_err = ERR_get_error();
ASSERT(1 == ret);
if(!(1 == ret))
fprintf(stderr, "BIO_do_handshake failed: %lu (0x%lx)\n", ssl_err , ssl_err);
break;
/* Could examine ssl here to get connection info */
BIO_write(out, "\n", 1);
BIO_puts(bio, "GET / HTTP/1.0\r\nConnection: close\r\n\r\n");
BIO_READ_TOP:
char buff[1536]; int len = 0;
/* https://www.openssl.org/docs/crypto/BIO_read.html */
len = BIO_read(bio, buff, sizeof(buff));
if(len > 0)
BIO_write(out, buff, len);
if(BIO_should_retry(bio)) goto BIO_READ_TOP;
func_ret = SUCCESS;
while (0);
if(out)
BIO_free(out);
if(bio != NULL)
BIO_free_all(bio);
if(NULL != ctx)
SSL_CTX_free(ctx);
【讨论】:
来自https://www.openssl.org/docs/ssl/SSL_library_init.html
,我看到SSL_library_init()
总是返回1,丢弃返回值是安全的。可以从代码中减少几行。以上是关于BIO_do_handshake() 总是返回 0的主要内容,如果未能解决你的问题,请参考以下文章