summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/EXPERIMENTAL.md1
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.36
-rw-r--r--docs/libcurl/opts/CURLOPT_SSL_OPTIONS.35
-rw-r--r--lib/vtls/openssl.c55
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);