使用libcurl无法获取完整CA证书链的技术求助
问题:libcurl无法获取api.dropboxapi.com完整CA链(缺失Root CA)
我想要获取api.dropboxapi.com的Root CA以通过SSL校验,但使用libcurl仅能获取2个证书,而该域名实际有3个证书。测试环境为WSL2 Debian,测试代码如下:
#include <stdio.h> #include <curl/curl.h> static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) { (void)stream; (void)ptr; return size * nmemb; } int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://api.dropboxapi.com/"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wrfu); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); res = curl_easy_perform(curl); if(!res) { struct curl_certinfo *certinfo; res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &certinfo); if(!res && certinfo) { int i; printf("%d certs!\n", certinfo->num_of_certs); for(i = 0; i < certinfo->num_of_certs; i++) { struct curl_slist *slist; for(slist = certinfo->certinfo[i]; slist; slist = slist->next) printf("%s\n", slist->data); } } } curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
输出结果显示Root CA缺失,但youtube.com、google.com等其他域名可以获取完整CA链。测试更多使用DigiCert签名CA的网站,均存在相同问题。请问这类网站是否需要额外步骤才能获取完整CA链?
解答
这是因为部分CA(比如DigiCert)的根证书已经被系统信任库收录,libcurl在处理证书链时,默认不会返回已被本地信任的根证书——它只会返回服务器发送的中间证书和叶证书,根证书因为已经在本地信任池中,所以不会被包含在CURLINFO_CERTINFO的结果里。
如果确实需要获取完整的根证书,可以通过以下两种方式解决:
- 禁用系统信任库,指定自定义CA路径:
设置CURLOPT_CAINFO指向一个不包含该根证书的CA文件,或者设置CURLOPT_CAPATH指向对应的目录,这样libcurl会要求服务器发送完整的证书链,包括根证书。
注意:这样做会关闭系统默认的信任校验,需要手动管理信任的CA,可能带来安全风险。 - 从本地信任库提取根证书:
既然根证书已经在系统信任池中,直接从Debian系统的CA存储目录/etc/ssl/certs/里找到对应的DigiCert根证书文件(比如DigiCert_Global_Root_CA.pem),直接读取即可。
另外,你代码里设置了CURLOPT_SSL_VERIFYPEER=0和CURLOPT_SSL_VERIFYHOST=0,这会关闭SSL校验,建议在正式环境中开启,避免安全问题。
内容的提问来源于stack exchange,提问作者AllsVoid
相关产品推荐
相关产品推荐

