Browse Source

noproxy: support for space-separated names is deprecated

To be removed in July 2024.

Assisted-by: Michael Osipov
Fixes #10209
Closes #10215
Daniel Stenberg 1 year ago
parent
commit
7ad8a7ba9e
5 changed files with 88 additions and 44 deletions
  1. 19 0
      docs/DEPRECATE.md
  2. 12 1
      lib/noproxy.c
  3. 2 1
      lib/noproxy.h
  4. 5 1
      lib/url.c
  5. 50 41
      tests/unit/unit1614.c

+ 19 - 0
docs/DEPRECATE.md

@@ -52,6 +52,25 @@ We remove support for building curl with the gskit TLS library in August 2023.
 - build breakages in this code take weeks or more to get detected
 - fixing gskit code is mostly done "flying blind"
 
+## space-separated `NOPROXY` patterns
+
+When specifying patterns/domain names for curl that should *not* go through a
+proxy, the curl tool features the `--noproxy` command line option and the
+library supports the `NO_PROXY` environment variable and the `CURLOPT_NOPROXY`
+libcurl option.
+
+They all set the same list of patterns. This list is documented to be a set of
+**comma-separated** names, but can also be provided separated with just
+space. The ability to just use spaces for this has never been documented but
+some users may still have come to rely on this.
+
+Several other tools and utilities also parse the `NO_PROXY` environment
+variable but do not consider a space to be a valid separator. Using spaces for
+separator is probably less portable and might cause more friction than commas
+do. Users should use commas for this for greater portability.
+
+curl will remove the support for space-separated names in July 2024.
+
 ## past removals
 
  - Pipelining

+ 12 - 1
lib/noproxy.c

@@ -119,8 +119,10 @@ enum nametype {
 * Checks if the host is in the noproxy list. returns TRUE if it matches and
 * therefore the proxy should NOT be used.
 ****************************************************************/
-bool Curl_check_noproxy(const char *name, const char *no_proxy)
+bool Curl_check_noproxy(const char *name, const char *no_proxy,
+                        bool *spacesep)
 {
+  *spacesep = FALSE;
   /*
    * If we don't have a hostname at all, like for example with a FILE
    * transfer, we have nothing to interrogate the noproxy list with.
@@ -244,6 +246,15 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy)
         if(match)
           return TRUE;
       } /* if(tokenlen) */
+      /* pass blanks after pattern */
+      while(ISBLANK(*p))
+        p++;
+      /* if not a comma! */
+      if(*p && (*p != ',')) {
+        *spacesep = TRUE;
+        continue;
+      }
+      /* pass any number of commas */
       while(*p == ',')
         p++;
     } /* while(*p) */

+ 2 - 1
lib/noproxy.h

@@ -37,7 +37,8 @@ UNITTEST bool Curl_cidr6_match(const char *ipv6,
                                unsigned int bits);
 #endif
 
-bool Curl_check_noproxy(const char *name, const char *no_proxy);
+bool Curl_check_noproxy(const char *name, const char *no_proxy,
+                        bool *spacesep);
 
 #endif
 

+ 5 - 1
lib/url.c

@@ -2401,6 +2401,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
   char *socksproxy = NULL;
   char *no_proxy = NULL;
   CURLcode result = CURLE_OK;
+  bool spacesep = FALSE;
 
   /*************************************************************
    * Extract the user and password from the authentication string
@@ -2447,7 +2448,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
   }
 
   if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
-                        data->set.str[STRING_NOPROXY] : no_proxy)) {
+                        data->set.str[STRING_NOPROXY] : no_proxy,
+                        &spacesep)) {
     Curl_safefree(proxy);
     Curl_safefree(socksproxy);
   }
@@ -2456,6 +2458,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
     /* if the host is not in the noproxy list, detect proxy. */
     proxy = detect_proxy(data, conn);
 #endif /* CURL_DISABLE_HTTP */
+  if(spacesep)
+    infof(data, "space-separated NOPROXY patterns are deprecated");
 
   Curl_safefree(no_proxy);
 

+ 50 - 41
tests/unit/unit1614.c

@@ -46,6 +46,7 @@ struct noproxy {
   const char *a;
   const char *n;
   bool match;
+  bool space; /* space separated */
 };
 
 UNITTEST_START
@@ -77,50 +78,52 @@ UNITTEST_START
     { NULL, NULL, 0, FALSE} /* end marker */
   };
   struct noproxy list[]= {
-    { "www.example.com", "localhost,.example.com,.example.de", TRUE},
-    { "www.example.com.", "localhost,.example.com,.example.de", TRUE},
-    { "example.com", "localhost,.example.com,.example.de", TRUE},
-    { "example.com.", "localhost,.example.com,.example.de", TRUE},
-    { "www.example.com", "localhost,.example.com.,.example.de", TRUE},
-    { "www.example.com", "localhost,www.example.com.,.example.de", TRUE},
-    { "example.com", "localhost,example.com,.example.de", TRUE},
-    { "example.com.", "localhost,example.com,.example.de", TRUE},
-    { "nexample.com", "localhost,example.com,.example.de", FALSE},
-    { "www.example.com", "localhost,example.com,.example.de", TRUE},
-    { "127.0.0.1", "127.0.0.1,localhost", TRUE},
-    { "127.0.0.1", "127.0.0.1,localhost,", TRUE},
-    { "127.0.0.1", "127.0.0.1/8,localhost,", TRUE},
-    { "127.0.0.1", "127.0.0.1/28,localhost,", TRUE},
-    { "127.0.0.1", "127.0.0.1/31,localhost,", TRUE},
-    { "127.0.0.1", "localhost,127.0.0.1", TRUE},
+    { "www.example.com", "localhost .example.com .example.de", TRUE, TRUE},
+    { "www.example.com", "localhost,.example.com,.example.de", TRUE, FALSE},
+    { "www.example.com.", "localhost,.example.com,.example.de", TRUE, FALSE},
+    { "example.com", "localhost,.example.com,.example.de", TRUE, FALSE},
+    { "example.com.", "localhost,.example.com,.example.de", TRUE, FALSE},
+    { "www.example.com", "localhost,.example.com.,.example.de", TRUE, FALSE},
+    { "www.example.com", "localhost,www.example.com.,.example.de",
+      TRUE, FALSE},
+    { "example.com", "localhost,example.com,.example.de", TRUE, FALSE},
+    { "example.com.", "localhost,example.com,.example.de", TRUE, FALSE},
+    { "nexample.com", "localhost,example.com,.example.de", FALSE, FALSE},
+    { "www.example.com", "localhost,example.com,.example.de", TRUE, FALSE},
+    { "127.0.0.1", "127.0.0.1,localhost", TRUE, FALSE},
+    { "127.0.0.1", "127.0.0.1,localhost,", TRUE, FALSE},
+    { "127.0.0.1", "127.0.0.1/8,localhost,", TRUE, FALSE},
+    { "127.0.0.1", "127.0.0.1/28,localhost,", TRUE, FALSE},
+    { "127.0.0.1", "127.0.0.1/31,localhost,", TRUE, FALSE},
+    { "127.0.0.1", "localhost,127.0.0.1", TRUE, FALSE},
     { "127.0.0.1", "localhost,127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1."
       "127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127."
-      "0.0.1.127.0.0.1.127.0.0." /* 128 bytes "address" */, FALSE},
+      "0.0.1.127.0.0.1.127.0.0." /* 128 bytes "address" */, FALSE, FALSE},
     { "127.0.0.1", "localhost,127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1."
       "127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127.0.0.1.127."
-      "0.0.1.127.0.0.1.127.0.0" /* 127 bytes "address" */, FALSE},
-    { "localhost", "localhost,127.0.0.1", TRUE},
-    { "localhost", "127.0.0.1,localhost", TRUE},
-    { "foobar", "barfoo", FALSE},
-    { "foobar", "foobar", TRUE},
-    { "192.168.0.1", "foobar", FALSE},
-    { "192.168.0.1", "192.168.0.0/16", TRUE},
-    { "192.168.0.1", "192.168.0.0/24", TRUE},
-    { "192.168.0.1", "192.168.0.0/32", FALSE},
-    { "192.168.0.1", "192.168.0.0", FALSE},
-    { "192.168.1.1", "192.168.0.0/24", FALSE},
-    { "192.168.1.1", "foo, bar, 192.168.0.0/24", FALSE},
-    { "192.168.1.1", "foo, bar, 192.168.0.0/16", TRUE},
-    { "[::1]", "foo, bar, 192.168.0.0/16", FALSE},
-    { "[::1]", "foo, bar, ::1/64", TRUE},
-    { "bar", "foo, bar, ::1/64", TRUE},
-    { "BAr", "foo, bar, ::1/64", TRUE},
-    { "BAr", "foo,,,,,              bar, ::1/64", TRUE},
-    { "www.example.com", "foo, .example.com", TRUE},
-    { "www.example.com", "www2.example.com, .example.net", FALSE},
-    { "example.com", ".example.com, .example.net", TRUE},
-    { "nonexample.com", ".example.com, .example.net", FALSE},
-    { NULL, NULL, FALSE}
+      "0.0.1.127.0.0.1.127.0.0" /* 127 bytes "address" */, FALSE, FALSE},
+    { "localhost", "localhost,127.0.0.1", TRUE, FALSE},
+    { "localhost", "127.0.0.1,localhost", TRUE, FALSE},
+    { "foobar", "barfoo", FALSE, FALSE},
+    { "foobar", "foobar", TRUE, FALSE},
+    { "192.168.0.1", "foobar", FALSE, FALSE},
+    { "192.168.0.1", "192.168.0.0/16", TRUE, FALSE},
+    { "192.168.0.1", "192.168.0.0/24", TRUE, FALSE},
+    { "192.168.0.1", "192.168.0.0/32", FALSE, FALSE},
+    { "192.168.0.1", "192.168.0.0", FALSE, FALSE},
+    { "192.168.1.1", "192.168.0.0/24", FALSE, FALSE},
+    { "192.168.1.1", "foo, bar, 192.168.0.0/24", FALSE, FALSE},
+    { "192.168.1.1", "foo, bar, 192.168.0.0/16", TRUE, FALSE},
+    { "[::1]", "foo, bar, 192.168.0.0/16", FALSE, FALSE},
+    { "[::1]", "foo, bar, ::1/64", TRUE, FALSE},
+    { "bar", "foo, bar, ::1/64", TRUE, FALSE},
+    { "BAr", "foo, bar, ::1/64", TRUE, FALSE},
+    { "BAr", "foo,,,,,              bar, ::1/64", TRUE, FALSE},
+    { "www.example.com", "foo, .example.com", TRUE, FALSE},
+    { "www.example.com", "www2.example.com, .example.net", FALSE, FALSE},
+    { "example.com", ".example.com, .example.net", TRUE, FALSE},
+    { "nonexample.com", ".example.com, .example.net", FALSE, FALSE},
+    { NULL, NULL, FALSE, FALSE}
   };
   for(i = 0; list4[i].a; i++) {
     bool match = Curl_cidr4_match(list4[i].a, list4[i].n, list4[i].bits);
@@ -141,13 +144,19 @@ UNITTEST_START
     }
   }
   for(i = 0; list[i].a; i++) {
-    bool match = Curl_check_noproxy(list[i].a, list[i].n);
+    bool spacesep = FALSE;
+    bool match = Curl_check_noproxy(list[i].a, list[i].n, &spacesep);
     if(match != list[i].match) {
       fprintf(stderr, "%s in %s should %smatch\n",
               list[i].a, list[i].n,
               list[i].match ? "": "not ");
       err++;
     }
+    if(spacesep != list[i].space) {
+      fprintf(stderr, "%s is claimed to be %sspace separated\n",
+              list[i].n, list[i].space?"":"NOT ");
+      err++;
+    }
   }
   return err;
 }