ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

curl/libcurl CURLOPT_CAINFO 完整指南:CA 证书包路径设置与 TLS 校验原理

curl/libcurl CURLOPT_CAINFO 完整指南:CA 证书包路径设置与 TLS 校验原理 curl/libcurl CURLOPT_CAINFO 完整指南CA 证书包路径设置与 TLS 校验原理【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl本指南围绕 libcurl 的CURLOPT_CAINFO选项系统讲解如何为 HTTPS 等 TLS 连接指定 CACertificate Authority证书包文件既给出可直接复制的 C 语言调用示例也结合 curl 仓库中 lib/setopt.c、lib/vtls/vtls_config.c、lib/getinfo.c 等源码讲清默认值来源、与CURLINFO_CAINFO的关系、与CURLOPT_CAINFO_BLOB/CURLOPT_CAPATH的配合以及命令行工具curl --cacert的等价用法。读完你将掌握何时必须显式指定 CA 包、如何查询内置默认路径、如何用 PEM 格式证书文件完成对服务器的身份校验并理解各 TLS 后端OpenSSL、Schannel、wolfSSL 等下的行为差异。CURLOPT_CAINFO 是什么CURLOPT_CAINFO用于给 libcurl 设置CA 证书包CA bundle文件的路径这个文件里存放一个或多个用于校验对端peer证书的可信 CA 证书。其官方定义见 docs/libcurl/opts/CURLOPT_CAINFO.mdPass a char pointer to a null-terminated string naming a file holding one or more certificates to verify the peer with.当 libcurl 建立 TLS 连接如 HTTPS时它会用这个文件中的 CA 证书去验证服务器证书链是否可信从而抵御中间人攻击。该选项的 C API 原型为#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);该选项适用于TLS 协议HTTPS、FTPS、IMAPS、SMTPS 等对所有 TLS 后端OpenSSL、GnuTLS、mbedTLS、wolfSSL、rustls、Schannel 等均有效自 libcurl 7.4.2 起加入Schannel 后端支持则在 7.60 加入相关选项CURLINFO_CAINFO、CURLOPT_CAINFO_BLOB、CURLOPT_CAPATH、CURLOPT_CA_CACHE_TIMEOUT、CURLOPT_SSL_VERIFYHOST、CURLOPT_SSL_VERIFYPEER。基础用法与完整可运行示例官方文档给出的最小示例docs/libcurl/opts/CURLOPT_CAINFO.md如下设置 URL 与 CA 包路径后执行请求int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com/); curl_easy_setopt(curl, CURLOPT_CAINFO, /etc/certs/cabundle.pem); result curl_easy_perform(curl); curl_cleanup_cc(curl); } }需要注意的语义细节字符串生命周期curl_easy_setopt内部会复制该字符串走Curl_setstropt存储到STRING_SSL_CAFILE见 lib/setopt.c因此应用程序不必在设置选项之后继续保留该字符串可以安全地释放或复用缓冲区多次设置覆盖重复调用该选项时最后一次设置的字符串覆盖之前的值传入NULL则再次禁用该选项恢复默认行为与CURLOPT_SSL_VERIFYPEER的关系如果CURLOPT_SSL_VERIFYPEER被设为 0关闭对端证书校验那么CURLOPT_CAINFO指向的文件甚至可以不真实存在因为校验根本不会发生。反之只要校验开启指定的 CA 包文件必须可读且内容有效否则握手会失败。从源码看CURLOPT_CAINFO的处理位于 lib/setopt.c 的setopt_cptr_ssl()分支中该分支在USE_SSL或USE_SSH编译条件下生效case CURLOPT_CAINFO: /* * Set CA info for SSL connection. Specify filename of the CA certificate */ result Curl_setstropt(data, STRING_SSL_CAFILE, ptr); >#define CURL_CA_BUNDLE /QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDBCMake 构建系统通过 lib/curl_config-cmake.h.in 的#cmakedefine CURL_CA_BUNDLE ${CURL_CA_BUNDLE}注入该宏lib/version.c 则在curl_version_info()的cainfo字段中向调用方暴露该编译期路径。默认值注入的源码逻辑默认路径不是setopt阶段设置的而是在连接建立前的配置完成阶段注入。见 lib/vtls/vtls_config.c 的Curl_ssl_easy_config_complete()if(Curl_ssl_backend() ! CURLSSLBACKEND_SCHANNEL) { #if defined(USE_APPLE_SECTRUST) || defined(CURL_CA_NATIVE) if(!sslc-custom_capath !sslc-custom_cafile !sslc-custom_cablob) sslc-primary.native_ca_store TRUE; #endif #ifdef CURL_CA_PATH if(!sslc-custom_capath !CURL_EASY_STR(data, STRING_SSL_CAPATH)) { result Curl_setstropt(data, STRING_SSL_CAPATH, CURL_CA_PATH); ... } #endif #ifdef CURL_CA_BUNDLE if(!sslc-custom_cafile !CURL_EASY_STR(data, STRING_SSL_CAFILE)) { result Curl_setstropt(data, STRING_SSL_CAFILE, CURL_CA_BUNDLE); ... } #endif }从源码结构可以清晰看到两条规则只要用户显式设置过CURLOPT_CAINFOcustom_cafile为真或已存在STRING_SSL_CAFILE就不再注入内置默认路径Schannel 后端完全跳过默认路径注入——这正是文档所说使用 Schannel 构建时该选项默认不设置的实现依据Schannel 默认使用 Windows 根证书存储Windows store of root certificates。用 CURLINFO_CAINFO 查询默认值文档明确建议默认值可以用CURLINFO_CAINFO查出来。该查询接口自 7.84.0 加入的示例见 docs/libcurl/opts/CURLINFO_CAINFO.mdint main(void) { CURL *curl curl_easy_init(); if(curl) { char *cainfo NULL; curl_easy_getinfo(curl, CURLINFO_CAINFO, cainfo); if(cainfo) { printf(default CA info path: %s\n, cainfo); } curl_easy_cleanup(curl); } }其底层实现位于 lib/getinfo.ccase CURLINFO_CAINFO: #ifdef CURL_CA_BUNDLE *param_charp CURL_CA_BUNDLE; #else *param_charp NULL; #endif break;注意两点若编译时未定义CURL_CA_BUNDLE查询结果指针为NULL文档特别提醒当 libcurl 被构建为支持多个 TLS 库时该查询可能返回字符串即使当前实际启用的 TLS 库并不支持CURLOPT_CAINFO例如 Schannel 场景下。CURL_CA_BUNDLE 环境变量命令行工具侧对命令行工具curl而言还有一个额外的默认来源环境变量CURL_CA_BUNDLE。根据 docs/cmdline-opts/cacert.md 的说明只要 TLS 后端不是 Schannelcurl 识别该环境变量并将其作为 CA 证书包路径而--cacert选项会覆盖该环境变量。另外在 Windows 上curl 会自动在 curl.exe 所在目录、当前工作目录及 PATH 中查找名为curl-ca-bundle.crt的 CA 文件curl 8.11.0 起可通过构建期选项禁用或限制该搜索行为。与 CURLOPT_CAINFO_BLOB、CURLOPT_CAPATH 的分工CURLOPT_CAINFO_BLOB当 CA 证书不便于以文件路径形式提供时例如证书内容在内存中、由其他组件动态生成可改用 Blob 接口传入内存中的 PEM 数据。源码中它同样写入data-set.blobs[BLOB_CAINFO]并在配置完成阶段被复制到sslc-primary.ca_info_blob见 lib/vtls/vtls_config.c。两条路径二选一Blob 优先于文件路径被后端消费见 lib/vtls/openssl.c 中conn_config-ca_info_blob ? NULL : conn_config-CAfile的判断。CURLOPT_CAPATH指定目录而不是文件目录中存放经openssl c_rehash等工具预处理过的多个 CA 证书哈希符号链接形式。setopt源码lib/setopt.c显示它仅在 TLS 后端支持 CA 目录SSLSUPP_CA_PATH时才生效否则返回CURLE_NOT_BUILT_IN——例如 Windows 上 Schannel 就不支持该能力。在同一个请求中CURLOPT_CAINFO与CURLOPT_CAPATH可以同时设置TLS 后端会同时从文件与目录加载 CA 集合以 OpenSSL 后端为例握手日志中会分别打印CAfile: ...与CApath: ...见 lib/vtls/openssl.c 附近的信息输出。后端行为差异OpenSSL、Schannel 与其他OpenSSL以及 GnuTLS、mbedTLS、wolfSSL、rustls这些传统后端在握手初始化时会把conn_config-CAfile交给底层库加载。以 OpenSSL 为例lib/vtls/openssl.c 中/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ if(!X509_STORE_load_file(store, ssl_cafile)) { ... } infof(data, CAfile: %s, ssl_cafile);OpenSSL 3.0 之后使用X509_STORE_load_file()加载 CA 文件到 X509 存储中构建时未设置默认路径且用户未指定时CAfile为空会落入无法加载任何 CA的分支通过设置CURLOPT_VERBOSE为 1可在调试日志中看到CAfile:一行用于确认实际使用的 CA 包路径相同的CAfile/CApath配置同样作用于代理连接STRING_SSL_CAFILE_PROXY与CURLOPT_PROXY_CAINFO见 lib/vtls/vtls_config.c。SchannelWindows根据官方文档与 docs/cmdline-opts/cacert.mdCURLOPT_CAINFO在Windows 7 或更高版本的 Schannel 后端下受支持但官方建议 Windows 8 之后再使用因为从 Windows 8 开始行为更可靠Schannel 的默认行为是使用Windows 根证书存储此时该选项不设置源码中Curl_ssl_backend() ! CURLSSLBACKEND_SCHANNEL判断即跳过默认路径注入该选项在 Schannel 下主要是为与其他 SSL 引擎保持向后兼容而提供推荐做法是直接使用 Windows 根证书存储而不是自定义 CA 文件。证书格式要求CURLOPT_CAINFO指定的文件通常应为PEM 格式且可以包含多个 CA 证书顺序拼接在同一文件中。这也是分发 CA bundle 的通行做法例如 curl 官方维护的curl-ca-bundle.crt即为一组 PEM 证书的合集。命令行工具的--cacert帮助文本docs/cmdline-opts/cacert.md同样强调The file may contain multiple CA certificates. The certificate(s) must be in PEM format.命令行等价用法curl --cacertlibcurl 库的CURLOPT_CAINFO对应命令行工具的--cacert file选项。在 src/tool_getparam.c 中注册{cacert, ARG_FILE|ARG_TLS, , C_CACERT},其参数解析src/tool_getparam.c会用existingfile()校验文件必须真实存在case C_CACERT: /* --cacert */ err existingfile(config-cacert, a, nextarg); break;随后该路径会以CURLOPT_CAINFO形式传递给 libcurl。典型命令行用法# 使用自定义 CA 包校验服务器证书 curl --cacert /etc/certs/cabundle.pem https://example.com/ # 配合 -v 查看实际加载的 CAfile 路径 curl --cacert /etc/certs/cabundle.pem -v https://example.com/ # 临时取消校验仅用于调试切勿用于生产 curl --insecure https://example.com/相关选项还包括--capath dir对应CURLOPT_CAPATH指定 CA 证书目录和--proxy-cacert file对应CURLOPT_PROXY_CAINFO见 src/tool_getparam.c 与 docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md用于 HTTPS 代理场景下校验代理服务器证书。返回值与错误处理curl_easy_setopt(curl, CURLOPT_CAINFO, path)返回CURLcodeCURLE_OK (0)设置成功非零值表示出错具体错误码参见 libcurl 错误码文档docs/libcurl/curl_easy_getinfo.md 中提到的libcurl-errors一节。需要注意设置选项本身通常不会校验文件是否存在文件可读性、内容合法性要到 TLS 握手阶段才被实际检查。因此建议在应用启动阶段用CURLINFO_CAINFO查询默认值确认构建时的内置路径若使用自定义路径提前用文件访问或加载测试验证路径有效开启CURLOPT_VERBOSE观察握手日志中的CAfile:行快速定位 CA 加载问题。实践清单何时必须显式设置 CURLOPT_CAINFO综合以上机制以下场景必须显式设置CURLOPT_CAINFO场景原因构建 libcurl 时未配置默认 CA 路径未定义CURL_CA_BUNDLE无内置默认值CURLINFO_CAINFO返回 NULL不设置则无法验证对端证书需要校验私有 CA 签发的服务器证书企业内网、自建 PKI内置系统 CA 包不含该私有根证书必须追加私有 CA 文件需要替换发行版默认 CA 包如定制安全策略用自定义 bundle 覆盖编译期内置路径测试环境使用自签名证书生成包含测试 CA 的 PEM 文件并指定之同时保留对端校验不建议用--insecure走生产逻辑相反在标准公网 HTTPS 场景下使用系统包管理器安装的 curl/libcurl 通常已内置正确的 CA 路径无需显式设置而 Schannel 后端推荐直接依赖 Windows 根证书存储。参考文档与源码索引选项官方文档docs/libcurl/opts/CURLOPT_CAINFO.md默认值查询接口docs/libcurl/opts/CURLINFO_CAINFO.md、lib/getinfo.c命令行等价选项docs/cmdline-opts/cacert.md、src/tool_getparam.c参数存储与默认值注入lib/setopt.c、lib/vtls/vtls_config.cOpenSSL 后端加载实现lib/vtls/openssl.c平台默认路径示例lib/config-os400.h、lib/curl_config-cmake.h.in代理侧对应选项docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表