commit efc286b7a62af0568fdcbf3c68791c9955182128 Author: Daniel Stenberg Date: Thu Oct 27 13:54:27 2022 +0200 noproxy: also match with adjacent comma If the host name is an IP address and the noproxy string contained that IP address with a following comma, it would erroneously not match. Extended test 1614 to verify this combo as well. Reported-by: Henning Schild Fixes #9813 Closes #9814 diff --git a/lib/noproxy.c b/lib/noproxy.c index 3409dab6f..58bc69a2d 100644 --- a/lib/noproxy.c +++ b/lib/noproxy.c @@ -192,18 +192,22 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) /* FALLTHROUGH */ case TYPE_IPV6: { const char *check = token; - char *slash = strchr(check, '/'); + char *slash; unsigned int bits = 0; char checkip[128]; + if(tokenlen >= sizeof(checkip)) + /* this cannot match */ + break; + /* copy the check name to a temp buffer */ + memcpy(checkip, check, tokenlen); + checkip[tokenlen] = 0; + check = checkip; + + slash = strchr(check, '/'); /* if the slash is part of this token, use it */ - if(slash && (slash < &check[tokenlen])) { + if(slash) { bits = atoi(slash + 1); - /* copy the check name to a temp buffer */ - if(tokenlen >= sizeof(checkip)) - break; - memcpy(checkip, check, tokenlen); - checkip[ slash - check ] = 0; - check = checkip; + *slash = 0; /* null terminate there */ } if(type == TYPE_IPV6) match = Curl_cidr6_match(name, check, bits); diff --git a/tests/data/test1614 b/tests/data/test1614 index 4a9d54eb6..73bdbb4e0 100644 --- a/tests/data/test1614 +++ b/tests/data/test1614 @@ -16,7 +16,7 @@ unittest proxy -cidr comparisons +noproxy and cidr comparisons diff --git a/tests/unit/unit1614.c b/tests/unit/unit1614.c index 60285450c..c2f563a0d 100644 --- a/tests/unit/unit1614.c +++ b/tests/unit/unit1614.c @@ -77,6 +77,20 @@ UNITTEST_START { NULL, NULL, 0, FALSE} /* end marker */ }; struct noproxy list[]= { + { "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}, + { "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}, + { "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}, commit b830f9ba9e94acf672cd191993ff679fa888838b Author: Daniel Stenberg Date: Fri Oct 28 10:51:49 2022 +0200 noproxy: fix tail-matching Also ignore trailing dots in both host name and comparison pattern. Regression in 7.86.0 (from 1e9a538e05c0) Extended test 1614 to verify better. Reported-by: Henning Schild Fixes #9821 Closes #9822 diff --git a/lib/noproxy.c b/lib/noproxy.c index 58bc69a2d..2832ae166 100644 --- a/lib/noproxy.c +++ b/lib/noproxy.c @@ -153,9 +153,14 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) } else { unsigned int address; + namelen = strlen(name); if(1 == Curl_inet_pton(AF_INET, name, &address)) type = TYPE_IPV4; - namelen = strlen(name); + else { + /* ignore trailing dots in the host name */ + if(name[namelen - 1] == '.') + namelen--; + } } while(*p) { @@ -177,12 +182,23 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) if(tokenlen) { switch(type) { case TYPE_HOST: - if(*token == '.') { - ++token; - --tokenlen; - /* tailmatch */ - match = (tokenlen <= namelen) && - strncasecompare(token, name + (namelen - tokenlen), namelen); + /* ignore trailing dots in the token to check */ + if(token[tokenlen - 1] == '.') + tokenlen--; + + if(tokenlen && (*token == '.')) { + /* A: example.com matches '.example.com' + B: www.example.com matches '.example.com' + C: nonexample.com DOES NOT match '.example.com' + */ + if((tokenlen - 1) == namelen) + /* case A, exact match without leading dot */ + match = strncasecompare(token + 1, name, namelen); + else if(tokenlen < namelen) + /* case B, tailmatch with leading dot */ + match = strncasecompare(token, name + (namelen - tokenlen), + tokenlen); + /* case C passes through, not a match */ } else match = (tokenlen == namelen) && diff --git a/tests/unit/unit1614.c b/tests/unit/unit1614.c index c2f563a0d..8f62b70d4 100644 --- a/tests/unit/unit1614.c +++ b/tests/unit/unit1614.c @@ -77,6 +77,15 @@ 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}, + { "www.example.com", "localhost,example.com,.example.de", FALSE}, { "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}, commit b1953c1933b369b1217ef0f16053e26da63488c3 Author: Daniel Stenberg Date: Sun Nov 6 23:19:51 2022 +0100 noproxy: tailmatch like in 7.85.0 and earlier A regfression in 7.86.0 (via 1e9a538e05c010) made the tailmatch work differently than before. This restores the logic to how it used to work: All names listed in NO_PROXY are tailmatched against the used domain name, if the lengths are identical it needs a full match. Update the docs, update test 1614. Reported-by: Stuart Henderson Fixes #9842 Closes #9858 diff --git a/docs/libcurl/opts/CURLOPT_NOPROXY.3 b/docs/libcurl/opts/CURLOPT_NOPROXY.3 index 5e4c32130..dc3cf7c10 100644 --- a/docs/libcurl/opts/CURLOPT_NOPROXY.3 +++ b/docs/libcurl/opts/CURLOPT_NOPROXY.3 @@ -40,10 +40,6 @@ list is matched as either a domain which contains the hostname, or the hostname itself. For example, "ample.com" would match ample.com, ample.com:80, and www.ample.com, but not www.example.com or ample.com.org. -If the name in the \fInoproxy\fP list has a leading period, it is a domain -match against the provided host name. This way ".example.com" will switch off -proxy use for both "www.example.com" as well as for "foo.example.com". - Setting the \fInoproxy\fP string to "" (an empty string) will explicitly enable the proxy for all host names, even if there is an environment variable set for it. diff --git a/lib/noproxy.c b/lib/noproxy.c index 2832ae166..fb856e4fa 100644 --- a/lib/noproxy.c +++ b/lib/noproxy.c @@ -187,22 +187,24 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) tokenlen--; if(tokenlen && (*token == '.')) { - /* A: example.com matches '.example.com' - B: www.example.com matches '.example.com' - C: nonexample.com DOES NOT match '.example.com' - */ - if((tokenlen - 1) == namelen) - /* case A, exact match without leading dot */ - match = strncasecompare(token + 1, name, namelen); - else if(tokenlen < namelen) - /* case B, tailmatch with leading dot */ - match = strncasecompare(token, name + (namelen - tokenlen), - tokenlen); - /* case C passes through, not a match */ + /* ignore leading token dot as well */ + token++; + tokenlen--; } - else - match = (tokenlen == namelen) && - strncasecompare(token, name, namelen); + /* A: example.com matches 'example.com' + B: www.example.com matches 'example.com' + C: nonexample.com DOES NOT match 'example.com' + */ + if(tokenlen == namelen) + /* case A, exact match */ + match = strncasecompare(token, name, namelen); + else if(tokenlen < namelen) { + /* case B, tailmatch domain */ + match = (name[namelen - tokenlen - 1] == '.') && + strncasecompare(token, name + (namelen - tokenlen), + tokenlen); + } + /* case C passes through, not a match */ break; case TYPE_IPV4: /* FALLTHROUGH */ diff --git a/tests/unit/unit1614.c b/tests/unit/unit1614.c index 8f62b70d4..523d102bf 100644 --- a/tests/unit/unit1614.c +++ b/tests/unit/unit1614.c @@ -85,7 +85,8 @@ UNITTEST_START { "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}, - { "www.example.com", "localhost,example.com,.example.de", FALSE}, + { "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},