]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
proxy: optimized env lookups
authorStefan Eissing <stefan@eissing.org>
Thu, 25 Jun 2026 11:14:17 +0000 (13:14 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 26 Jun 2026 11:50:20 +0000 (13:50 +0200)
Optimize proxy env var lookups for the commen case of 'https' and 'http'
urls. We do this for every transfer.

Closes #22168

lib/proxy.c

index 920dc455986d0c467ec1daa022c3c290ac3c41ec..28738a15d6a807cbbd7bf0d9c60ba61fc50125f5 100644 (file)
@@ -282,8 +282,6 @@ UNITTEST bool proxy_check_noproxy(const char *name, const char *no_proxy)
 static char *proxy_detect_proxy(struct Curl_easy *data,
                                 const struct Curl_scheme *scheme)
 {
-  char *proxy = NULL;
-
   /* If proxy was not specified, we check for default proxy environment
    * variables, to enable i.e Lynx compliance:
    *
@@ -301,58 +299,63 @@ static char *proxy_detect_proxy(struct Curl_easy *data,
    * For compatibility, the all-uppercase versions of these variables are
    * checked if the lowercase versions do not exist.
    */
-  char proxy_env[20];
-  const char *envp;
-  VERBOSE(envp = proxy_env);
-
-  curl_msnprintf(proxy_env, sizeof(proxy_env), "%s_proxy", scheme->name);
-
-  /* read the protocol proxy: */
-  proxy = curl_getenv(proxy_env);
+  const char *env_name = NULL;
+  char *proxy = NULL;
+  char name_buf[20];
+
+  /* Try scheme specific env var first, unless http(s).
+   * lowercase first, then uppercase. */
+  if((scheme != &Curl_scheme_https) && (scheme != &Curl_scheme_http)) {
+    curl_msnprintf(name_buf, sizeof(name_buf), "%s_proxy", scheme->name);
+    env_name = name_buf;
+    proxy = curl_getenv(env_name);
+    if(!proxy) {
+      Curl_strntoupper(name_buf, name_buf, sizeof(name_buf));
+      proxy = curl_getenv(env_name);
+    }
+  }
 
-  /*
-   * We do not try the uppercase version of HTTP_PROXY because of
-   * security reasons:
-   *
-   * When curl is used in a webserver application
-   * environment (cgi or php), this environment variable can
-   * be controlled by the web server user by setting the
-   * http header 'Proxy:' to some value.
-   *
-   * This can cause 'internal' http/ftp requests to be
-   * arbitrarily redirected by any external attacker.
-   */
-  if(!proxy && !curl_strequal("http_proxy", proxy_env)) {
-    /* There was no lowercase variable, try the uppercase version: */
-    Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
-    proxy = curl_getenv(proxy_env);
+  if(!proxy &&
+     ((scheme == &Curl_scheme_https) || (scheme == &Curl_scheme_wss))) {
+    /* Not found, check 'https' env vars, also for 'wss'.
+     * Again, first lowercase then uppercase. */
+    env_name = "https_proxy";
+    proxy = curl_getenv(env_name);
+    if(!proxy) {
+      env_name = "HTTPS_PROXY";
+      proxy = curl_getenv(env_name);
+    }
+  }
+  else if(!proxy &&
+          ((scheme == &Curl_scheme_http) || (scheme == &Curl_scheme_ws))) {
+    /* Not found, check 'http' env vars, also for 'ws'.
+     * We do NOT try the uppercase version 'HTTP_PROXY' because of
+     * security reasons:
+     *
+     * When curl is used in a webserver application
+     * environment (cgi or php), this environment variable can
+     * be controlled by the web server user by setting the
+     * http header 'Proxy:' to some value.
+     *
+     * This can cause 'internal' http/ftp requests to be
+     * arbitrarily redirected by any external attacker.
+     */
+    env_name = "http_proxy";
+    proxy = curl_getenv(env_name);
   }
 
   if(!proxy) {
-#ifndef CURL_DISABLE_WEBSOCKETS
-    /* websocket proxy fallbacks */
-    if(curl_strequal("ws_proxy", proxy_env)) {
-      proxy = curl_getenv("http_proxy");
-    }
-    else if(curl_strequal("wss_proxy", proxy_env)) {
-      proxy = curl_getenv("https_proxy");
-      if(!proxy)
-        proxy = curl_getenv("HTTPS_PROXY");
-    }
+    /* still not found, last resort checks. */
+    env_name = "all_proxy";
+    proxy = curl_getenv(env_name);
     if(!proxy) {
-#endif
-      envp = "all_proxy";
-      proxy = curl_getenv(envp); /* default proxy to use */
-      if(!proxy) {
-        envp = "ALL_PROXY";
-        proxy = curl_getenv(envp);
-      }
-#ifndef CURL_DISABLE_WEBSOCKETS
+      env_name = "ALL_PROXY";
+      proxy = curl_getenv(env_name);
     }
-#endif
   }
+
   if(proxy)
-    infof(data, "Uses proxy env variable %s == '%s'", envp, proxy);
+    infof(data, "Uses proxy env variable %s == '%s'", env_name, proxy);
 
   return proxy;
 }