noproxy: tailmatch like in 7.85.0 and earlier

A regfression in 7.86.0 (via 1e9a538e05) 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
This commit is contained in:
Daniel Stenberg 2022-11-06 23:19:51 +01:00
parent 592107fa16
commit b1953c1933
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 19 additions and 20 deletions

View file

@ -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.

View file

@ -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 */

View file

@ -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},