]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_operate: reuse the schannel backend check
authorDaniel Stenberg <daniel@haxx.se>
Thu, 17 Oct 2024 14:01:08 +0000 (16:01 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 18 Oct 2024 06:13:53 +0000 (08:13 +0200)
The transfer_per_config is called once per new transfer. It now saves
the result of the first TLS backend check done so that subsequent
invokes are more efficient and reuses the existing knowledge.

This change also splits the logic into several smaller functions.

Closes #15323

src/tool_operate.c

index 1e19fcff6facccac9887ea30ce0aac17f22b1e89..f38fffe096527db573d4ab3d30566dbe96de6677 100644 (file)
@@ -3026,6 +3026,92 @@ static CURLcode serial_transfers(struct GlobalConfig *global,
   return result;
 }
 
+static CURLcode is_using_schannel(int *using)
+{
+  CURLcode result = CURLE_OK;
+  static int using_schannel = -1; /* -1 = not checked
+                                     0 = nope
+                                     1 = yes */
+  if(using_schannel == -1) {
+    CURL *curltls = curl_easy_init();
+    /* The TLS backend remains, so keep the info */
+    struct curl_tlssessioninfo *tls_backend_info = NULL;
+
+    if(!curltls)
+      result = CURLE_OUT_OF_MEMORY;
+    else {
+      result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR,
+                                 &tls_backend_info);
+      if(!result)
+        using_schannel =
+          (tls_backend_info->backend == CURLSSLBACKEND_SCHANNEL);
+    }
+    curl_easy_cleanup(curltls);
+    if(result)
+      return result;
+  }
+  *using = using_schannel;
+  return result;
+}
+
+/* Set the CA cert locations specified in the environment. For Windows if no
+ * environment-specified filename is found then check for CA bundle default
+ * filename curl-ca-bundle.crt in the user's PATH.
+ *
+ * If Schannel is the selected SSL backend then these locations are ignored.
+ * We allow setting CA location for Schannel only when explicitly specified by
+ * the user via CURLOPT_CAINFO / --cacert.
+ */
+
+static CURLcode cacertpaths(struct OperationConfig *config)
+{
+  CURLcode result = CURLE_OUT_OF_MEMORY;
+  char *env = curl_getenv("CURL_CA_BUNDLE");
+  if(env) {
+    config->cacert = strdup(env);
+    curl_free(env);
+    if(!config->cacert)
+      goto fail;
+  }
+  else {
+    env = curl_getenv("SSL_CERT_DIR");
+    if(env) {
+      config->capath = strdup(env);
+      curl_free(env);
+      if(!config->capath)
+        goto fail;
+    }
+    env = curl_getenv("SSL_CERT_FILE");
+    if(env) {
+      config->cacert = strdup(env);
+      curl_free(env);
+      if(!config->cacert)
+        goto fail;
+    }
+  }
+
+#ifdef _WIN32
+  if(!env) {
+#if defined(CURL_CA_SEARCH_SAFE)
+    char *cacert = NULL;
+    FILE *cafile = Curl_execpath("curl-ca-bundle.crt", &cacert);
+    if(cafile) {
+      fclose(cafile);
+      config->cacert = strdup(cacert);
+    }
+#elif !defined(CURL_WINDOWS_UWP) && !defined(CURL_DISABLE_CA_SEARCH)
+    result = FindWin32CACert(config, TEXT("curl-ca-bundle.crt"));
+    if(result)
+      goto fail;
+#endif
+  }
+#endif
+  return CURLE_OK;
+fail:
+  free(config->capath);
+  return result;
+}
+
 /* setup a transfer for the given config */
 static CURLcode transfer_per_config(struct GlobalConfig *global,
                                     struct OperationConfig *config,
@@ -3057,82 +3143,16 @@ static CURLcode transfer_per_config(struct GlobalConfig *global,
      !config->cacert &&
      !config->capath &&
      (!config->insecure_ok || (config->doh_url && !config->doh_insecure_ok))) {
-    CURL *curltls = curl_easy_init();
-    struct curl_tlssessioninfo *tls_backend_info = NULL;
+    int using_schannel = -1;
 
-    /* With the addition of CAINFO support for Schannel, this search could find
-     * a certificate bundle that was previously ignored. To maintain backward
-     * compatibility, only perform this search if not using Schannel.
-     */
-    result = curl_easy_getinfo(curltls, CURLINFO_TLS_SSL_PTR,
-                               &tls_backend_info);
-    if(result) {
-      curl_easy_cleanup(curltls);
-      return result;
-    }
+    result = is_using_schannel(&using_schannel);
 
-    /* Set the CA cert locations specified in the environment. For Windows if
-     * no environment-specified filename is found then check for CA bundle
-     * default filename curl-ca-bundle.crt in the user's PATH.
-     *
-     * If Schannel is the selected SSL backend then these locations are
-     * ignored. We allow setting CA location for Schannel only when explicitly
-     * specified by the user via CURLOPT_CAINFO / --cacert.
+    /* With the addition of CAINFO support for Schannel, this search could
+     * find a certificate bundle that was previously ignored. To maintain
+     * backward compatibility, only perform this search if not using Schannel.
      */
-    if(tls_backend_info->backend != CURLSSLBACKEND_SCHANNEL) {
-      char *env;
-      env = curl_getenv("CURL_CA_BUNDLE");
-      if(env) {
-        config->cacert = strdup(env);
-        curl_free(env);
-        if(!config->cacert) {
-          curl_easy_cleanup(curltls);
-          errorf(global, "out of memory");
-          return CURLE_OUT_OF_MEMORY;
-        }
-      }
-      else {
-        env = curl_getenv("SSL_CERT_DIR");
-        if(env) {
-          config->capath = strdup(env);
-          curl_free(env);
-          if(!config->capath) {
-            curl_easy_cleanup(curltls);
-            errorf(global, "out of memory");
-            return CURLE_OUT_OF_MEMORY;
-          }
-          capath_from_env = true;
-        }
-        env = curl_getenv("SSL_CERT_FILE");
-        if(env) {
-          config->cacert = strdup(env);
-          curl_free(env);
-          if(!config->cacert) {
-            if(capath_from_env)
-              free(config->capath);
-            curl_easy_cleanup(curltls);
-            errorf(global, "out of memory");
-            return CURLE_OUT_OF_MEMORY;
-          }
-        }
-      }
-
-#ifdef _WIN32
-      if(!env) {
-#if defined(CURL_CA_SEARCH_SAFE)
-        char *cacert = NULL;
-        FILE *cafile = Curl_execpath("curl-ca-bundle.crt", &cacert);
-        if(cafile) {
-          fclose(cafile);
-          config->cacert = strdup(cacert);
-        }
-#elif !defined(CURL_WINDOWS_UWP) && !defined(CURL_DISABLE_CA_SEARCH)
-        result = FindWin32CACert(config, TEXT("curl-ca-bundle.crt"));
-#endif
-      }
-#endif
-    }
-    curl_easy_cleanup(curltls);
+    if(!result && !using_schannel)
+      result = cacertpaths(config);
   }
 
   if(!result)