From d8cae791f47c90f1f1c2b4d052c3e64a3919d92d Mon Sep 17 00:00:00 2001 From: Claes Jakobsson Date: Thu, 27 Dec 2018 14:23:13 +0100 Subject: [PATCH] hostip: support wildcard hosts This adds support for wildcard hosts in CURLOPT_RESOLVE. These are try-last so any non-wildcard entry is resolved first. If specified, any host not matched by another CURLOPT_RESOLVE config will use this as fallback. Example send a.com to 10.0.0.1 and everything else to 10.0.0.2: curl --resolve *:443:10.0.0.2 --resolve a.com:443:10.0.0.1 \ https://a.com https://b.com This is probably quite similar to using: --connect-to a.com:443:10.0.0.1:443 --connect-to :443:10.0.0.2:443 Closes #3406 Reviewed-by: Daniel Stenberg --- docs/cmdline-opts/resolve.d | 6 ++++ lib/hostip.c | 30 ++++++++++++++++++++ lib/urldata.h | 1 + tests/data/Makefile.inc | 2 +- tests/data/test1458 | 56 +++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 tests/data/test1458 diff --git a/docs/cmdline-opts/resolve.d b/docs/cmdline-opts/resolve.d index 9e1457b5e..9c37525bd 100644 --- a/docs/cmdline-opts/resolve.d +++ b/docs/cmdline-opts/resolve.d @@ -11,6 +11,10 @@ the number used for the specific protocol the host will be used for. It means you need several entries if you want to provide address for the same host but different ports. +By specifying '*' as host you can tell curl to resolve any host and specific +port pair to the specified address. Wildcard is resolved last so any --resolve +with a specific host and port will be used first. + The provided address set by this option will be used even if --ipv4 or --ipv6 is set to make curl use another IP version. @@ -18,4 +22,6 @@ Support for providing the IP address within [brackets] was added in 7.57.0. Support for providing multiple IP addresses per entry was added in 7.59.0. +Support for resolving with wildcard was added in 7.64.0. + This option can be used many times to add many host names to resolve. diff --git a/lib/hostip.c b/lib/hostip.c index f589a0b2c..89b88e932 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -312,6 +312,26 @@ fetch_addr(struct connectdata *conn, /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + /* No entry found in cache, check if we might have a wildcard entry */ + if(!dns && data->change.wildcard_resolve) { + /* + * Free the previous entry_id before requesting a new one to avoid leaking + * memory + */ + free(entry_id); + + entry_id = create_hostcache_id("*", port); + + /* If we can't create the entry id, fail */ + if(!entry_id) + return dns; + + entry_len = strlen(entry_id); + + /* See if it's already in our dns cache */ + dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1); + } + if(dns && (data->set.dns_cache_timeout != -1)) { /* See whether the returned entry is stale. Done before we release lock */ struct hostcache_prune_data user; @@ -872,6 +892,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) char hostname[256]; int port = 0; + /* Default is no wildcard found */ + data->change.wildcard_resolve = false; + for(hostp = data->change.resolve; hostp; hostp = hostp->next) { if(!hostp->data) continue; @@ -1052,6 +1075,13 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } infof(data, "Added %s:%d:%s to DNS cache\n", hostname, port, addresses); + + /* Wildcard hostname */ + if(hostname[0] == '*' && hostname[1] == '\0') { + infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n", + hostname, port); + data->change.wildcard_resolve = true; + } } } data->change.resolve = NULL; /* dealt with now */ diff --git a/lib/urldata.h b/lib/urldata.h index a2655e9e0..11bbbc03e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1397,6 +1397,7 @@ struct DynamicStatic { curl_easy_setopt(COOKIEFILE) calls */ struct curl_slist *resolve; /* set to point to the set.resolve list when this should be dealt with in pretransfer */ + bool wildcard_resolve; /* Set to true if any resolve change is a wildcard */ }; /* diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index 9c31d907e..59635be04 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -167,7 +167,7 @@ test1424 test1425 test1426 test1427 \ test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \ test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \ test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \ -test1452 test1453 test1454 test1455 test1456 test1457 \ +test1452 test1453 test1454 test1455 test1456 test1457 test1458\ test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ test1516 test1517 test1518 test1519 test1520 test1521 test1522 \ diff --git a/tests/data/test1458 b/tests/data/test1458 new file mode 100644 index 000000000..072e43ce9 --- /dev/null +++ b/tests/data/test1458 @@ -0,0 +1,56 @@ + + + +HTTP +HTTP GET +--resolve + + + +# +# Server-side + + +HTTP/1.1 200 OK +Date: Thu, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +ETag: "21025-dc7-39462498" +Accept-Ranges: bytes +Content-Length: 6 +Connection: close +Content-Type: text/html +Funny-head: yesyes + +-foo- + + + +# +# Client-side + + +http + + +HTTP with wildcard --resolve + + +--resolve *:%HTTPPORT:%HOSTIP http://example.com:%HTTPPORT/1458 + + + +# +# Verify data after the test has been "shot" + + +^User-Agent:.* + + +GET /1458 HTTP/1.1 +Host: example.com:%HTTPPORT +Accept: */* + + + +