diff options
-rw-r--r-- | docs/EXPERIMENTAL.md | 1 | ||||
-rw-r--r-- | docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 | 6 | ||||
-rw-r--r-- | docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 | 5 | ||||
-rw-r--r-- | lib/vtls/openssl.c | 55 |
4 files changed, 45 insertions, 22 deletions
diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md index ce46c214d..6b7145df6 100644 --- a/docs/EXPERIMENTAL.md +++ b/docs/EXPERIMENTAL.md @@ -20,6 +20,5 @@ Experimental support in curl means: - The Hyper HTTP backend - HTTP/3 support and options - - `CURLSSLOPT_NATIVE_CA` (No configure option, feature built in when supported) - The rustls backend - WebSocket diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 index 9202d0c41..a3c7ad9aa 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3 @@ -60,6 +60,12 @@ offline distribution points for those SSL backends where such behavior is present. This option is only supported for Schannel (the native Windows SSL library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes precedence. (Added in 7.70.0) +.IP CURLSSLOPT_NATIVE_CA +Tell libcurl to use the operating system's native CA store for certificate +verification. Works only on Windows when built to use OpenSSL. If you set this +option and also set a CA certificate file or directory then during verification +those certificates are searched in addition to the native CA store. +(Added in 7.71.0) .IP CURLSSLOPT_AUTO_CLIENT_CERT Tell libcurl to automatically locate and use a client certificate for authentication, when requested by the server. This option is only supported diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 index 34688dcb9..9b743f234 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 +++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3 @@ -61,8 +61,9 @@ library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes precedence. (Added in 7.70.0) .IP CURLSSLOPT_NATIVE_CA Tell libcurl to use the operating system's native CA store for certificate -verification. Works only on Windows when built to use OpenSSL. This option is -experimental and behavior is subject to change. +verification. Works only on Windows when built to use OpenSSL. If you set this +option and also set a CA certificate file or directory then during verification +those certificates are searched in addition to the native CA store. (Added in 7.71.0) .IP CURLSSLOPT_AUTO_CLIENT_CERT Tell libcurl to automatically locate and use a client certificate for diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 715515fcf..9ebb5e991 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -3066,6 +3066,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, const char * const ssl_crlfile = ssl_config->primary.CRLfile; const bool verifypeer = conn_config->verifypeer; bool imported_native_ca = false; + bool imported_ca_info_blob = false; if(!store) return CURLE_OUT_OF_MEMORY; @@ -3225,33 +3226,49 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, /* Only warn if no certificate verification is required. */ infof(data, "error importing CA certificate blob, continuing anyway"); } + else { + imported_ca_info_blob = true; + infof(data, "successfully imported CA certificate blob"); + } } - if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) { + if(verifypeer && (ssl_cafile || ssl_capath)) { #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ - if(ssl_cafile && - !X509_STORE_load_file(store, ssl_cafile)) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate file: %s", ssl_cafile); - return CURLE_SSL_CACERT_BADFILE; + if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) { + if(!imported_native_ca && !imported_ca_info_blob) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate file: %s", ssl_cafile); + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "error setting certificate file, continuing anyway"); } - if(ssl_capath && - !X509_STORE_load_path(store, ssl_capath)) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate path: %s", ssl_capath); - return CURLE_SSL_CACERT_BADFILE; + if(ssl_capath && !X509_STORE_load_path(store, ssl_capath)) { + if(!imported_native_ca && !imported_ca_info_blob) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate path: %s", ssl_capath); + return CURLE_SSL_CACERT_BADFILE; + } + else + infof(data, "error setting certificate path, continuing anyway"); } #else /* tell OpenSSL where to find CA certificates that are used to verify the server's certificate. */ if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) { - /* Fail if we insist on successfully verifying the server. */ - failf(data, "error setting certificate verify locations:" - " CAfile: %s CApath: %s", - ssl_cafile ? ssl_cafile : "none", - ssl_capath ? ssl_capath : "none"); - return CURLE_SSL_CACERT_BADFILE; + if(!imported_native_ca && !imported_ca_info_blob) { + /* Fail if we insist on successfully verifying the server. */ + failf(data, "error setting certificate verify locations:" + " CAfile: %s CApath: %s", + ssl_cafile ? ssl_cafile : "none", + ssl_capath ? ssl_capath : "none"); + return CURLE_SSL_CACERT_BADFILE; + } + else { + infof(data, "error setting certificate verify locations," + " continuing anyway"); + } } #endif infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); @@ -3259,8 +3276,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, } #ifdef CURL_CA_FALLBACK - if(verifypeer && - !ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) { + if(verifypeer && !ssl_cafile && !ssl_capath && + !imported_native_ca && !imported_ca_info_blob) { /* verifying the peer without any CA certificates won't work so use openssl's built-in default as fallback */ X509_STORE_set_default_paths(store); |