我正在使用 openssl 与远程服务器建立 TLS 连接。
以下是代码片段:
if ((ret = SSL_connect(c->ssl)) <= 0) {
ret = SSL_get_error(c->ssl, ret);
if((err = ERR_get_error())) {
SSL_load_error_strings();
ERR_load_crypto_strings();
CRERROR(LOGSSLUTILS, "SSL connect err code:[%lu](%s)\n", err, ERR_error_string(err, NULL));
CRERROR(LOGSSLUTILS, "Error is %s \n",ERR_reason_error_string(err));
}
}
由于某种未知原因,ssl_connect 失败,我只想使用 ERR_error_string 来确定原因,输出为:
SSL connect err code:[336077172] (error:14082174:lib(20):func(130):reason(372))
Error: cmrSSLlInit:174 Error is (null)
如你所见,我只能获取错误代码,但无法获取可读的错误字符串。
如何获取可读的错误字符串?
由于某种未知的原因,ssl_connect 失败了,我只想 使用 ERR_error_string 确定原因,输出为:
SSL connect err code:[336077172] (error:14082174:lib(20):func(130):reason(372))
$ openssl errstr 0x14082174
error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small
对于
DH key too small
,在 Stack Overflow 上签出 SSL 操作失败,代码为 1:dh 密钥太小。缺点是,早期版本的 OpenSSL 使用 512 位 DH 组。太小了,需要用2048位组。
如何获取可读的错误字符串?
要记录像
error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small
这样的字符串,我相信你可以调用err_print_errors
和ERR_print_errors_fp
。这些函数打印整个错误堆栈。另请参阅 ERR_print_errors
手册页。
获取所有排队线程本地错误的一种方法是使用下面建议的代码片段here:
#include <openssl/err.h>
string getOpenSSLError()
{
BIO *bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
char *buf;
size_t len = BIO_get_mem_data(bio, &buf);
string ret(buf, len);
BIO_free(bio);
return ret;
}
我用它来打印最新的错误
ctx = SSL_CTX_new(method);
if(ctx == NULL)
{
printf("%s", ERR_error_string(ERR_get_error(), NULL));
}
您在示例代码中调用
SSL_load_error_strings()
和 ERR_load_crypto_strings()
太晚了。它们应该在程序开始时立即调用 - 然后您应该从 OpenSSL 中获取可读的错误字符串。 @jww 关于 DH 组太小的说法是正确的。理想情况下,服务器需要重新配置更大的组。如果这不可能,则尝试使用非 DHE 密码套件进行连接(即使用基于 ECDHE 的密码套件)
这是因为我在编译 openssl 时包含了“no-err”选项。 所以 Err_error_string 返回 NULL