]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
openssl: Don't ignore CA paths when using Windows CA store (redux)
authorJay Satiro <raysatiro@yahoo.com>
Thu, 5 Jan 2023 23:32:27 +0000 (18:32 -0500)
committerJay Satiro <raysatiro@yahoo.com>
Tue, 17 Jan 2023 08:32:58 +0000 (03:32 -0500)
.. and remove 'experimental' designation from CURLSSLOPT_NATIVE_CA.

This commit restores the behavior of CURLSSLOPT_NATIVE_CA so that it
does not override CURLOPT_CAINFO / CURLOPT_CAPATH, or the hardcoded
default locations. Instead the native Windows CA store can be used at
the same time.

---

This behavior was originally added over two years ago in abbc5d60
(#5585) but then 83393b1a (#7892) broke it over a year ago, I assume
inadvertently.

The CURLSSLOPT_NATIVE_CA feature was marked experimental and likely
rarely used.

Ref: https://github.com/curl/curl/pull/5585
Ref: https://github.com/curl/curl/pull/7892
Ref: https://curl.se/mail/lib-2023-01/0019.html

Closes https://github.com/curl/curl/pull/10244

docs/EXPERIMENTAL.md
docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.3
docs/libcurl/opts/CURLOPT_SSL_OPTIONS.3
lib/vtls/openssl.c

index ce46c214d5d477a681c4932f9af06e50595a81bf..6b7145df68440d48c4f6dd68489628f0271f6fbe 100644 (file)
@@ -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
index 9202d0c41eb0cd179b9f83752c9af7eec33949ff..a3c7ad9aa4a6f94d1a36e5497d6f24ebbe265fd8 100644 (file)
@@ -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
index 34688dcb95f525f82559e88b8e9d3287fa750ff3..9b743f234d212f4823e0bed385b1c62119ca0e36 100644 (file)
@@ -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
index 715515fcfb3e981402041ed1a101ee4fe26f1491..9ebb5e991f0c19d5ca2f0ddefd7565fd9ef84cbf 100644 (file)
@@ -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);