我想使用 OpenSSL 验证 HTTPS 证书链。经过反复试验,我设法使用s_client
openssl s_client -connect google.com:https -CApath root < /dev/null
其中root
包含我从上游下载的两个用于 Google 的根 CA 证书(我不确定两者是否都是必需的,但这种方式有效)。
$ ls -1 root
594f1775.0 // generated by c_rehash
7999be0d.0 // generated by c_rehash
Equifax_Secure_Certificate_Authority.pem
GeoTrust_Global_CA.pem
上面的openssl s_client
命令工作正常并按1
预期返回。
depth=3 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
verify return:1
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify return:1
depth=1 /C=US/O=Google Inc/CN=Google Internet Authority G2
verify return:1
depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
verify return:1
到目前为止,一切都很好。但是,当我尝试使用libssl
(ie OpenSSL APIs) 实现相同的功能时,我无法让它工作。我已经root
将 dir 指定为CAPath
(via SSL_CTX_load_verify_locations
),但它一直给出错误 20:
20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:无法获取本地颁发者证书,找不到颁发者证书:如果找不到不受信任的证书的颁发者证书,则会发生这种情况。
我已经调试了一段时间,但一点头绪都没有。任何帮助表示赞赏!
#include <openssl/ssl.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/bn.h>
#include <openssl/asn1.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 1024
int main()
{
BIO * bio;
SSL * ssl;
SSL_CTX * ctx;
int p;
/* Set up the library */
ERR_load_BIO_strings();
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
/* Set up the SSL context */
const SSL_METHOD *meth = SSLv23_client_method();
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return -1;
}
char* store_path = "./root";
if(!SSL_CTX_load_verify_locations(ctx, NULL, store_path))
{
fprintf(stderr, "Can't load trusted CA from %s\n", store_path);
return -1;
}
/* Setup the connection */
bio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
// Set
SSL_CTX_set_verify_depth(ctx, 50);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Create and setup the connection */
BIO_set_conn_hostname(bio, "www.google.com:https");
if(BIO_do_connect(bio) <= 0)
{
ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
if(SSL_get_verify_result(ssl) != X509_V_OK)
{
fprintf(stderr, "Verification Error: %ld\n", SSL_get_verify_result(ssl));
ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Close the connection and free the context */
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}