From 37092a33b75cc856d307d44f2fad81bcab2e5d0a Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 4 Sep 2019 23:49:30 +0200 Subject: urlapi: verify the IPv6 numerical address It needs to parse correctly. Otherwise it could be tricked into letting through a-f using host names that libcurl would then resolve. Like '[ab.be]'. Reported-by: Thomas Vegas --- lib/urlapi.c | 17 +++++++++++++---- tests/libtest/lib1560.c | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/urlapi.c b/lib/urlapi.c index d07e4f5df..03efccd7b 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -29,6 +29,7 @@ #include "url.h" #include "escape.h" #include "curl_ctype.h" +#include "inet_pton.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -591,20 +592,22 @@ static CURLUcode junkscan(char *part) static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) { - const char *l = NULL; /* accepted characters */ size_t len; size_t hlen = strlen(hostname); if(hostname[0] == '[') { + char dest[16]; /* fits a binary IPv6 address */ + const char *l = "0123456789abcdefABCDEF::."; hostname++; - l = "0123456789abcdefABCDEF::."; hlen -= 2; - } - if(l) { + if(hostname[hlen] != ']') + return CURLUE_MALFORMED_INPUT; + /* only valid letters are ok */ len = strspn(hostname, l); if(hlen != len) { + hlen = len; if(hostname[len] == '%') { /* this could now be '%[zone id]' */ char zoneid[16]; @@ -628,6 +631,12 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname) return CURLUE_MALFORMED_INPUT; /* hostname is fine */ } +#ifdef ENABLE_IPV6 + hostname[hlen] = 0; /* end the address there */ + if(1 != Curl_inet_pton(AF_INET6, hostname, dest)) + return CURLUE_MALFORMED_INPUT; + hostname[hlen] = ']'; /* restore ending bracket */ +#endif } else { /* letters from the second string is not ok */ diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c index 1185096d8..85884474e 100644 --- a/tests/libtest/lib1560.c +++ b/tests/libtest/lib1560.c @@ -140,6 +140,10 @@ static struct testcase get_parts_list[] ={ "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]", CURLU_DEFAULT_SCHEME, 0, CURLUE_OK}, #endif + {"http://[ab.be:1]/x", "", + CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, + {"http://[ab.be]/x", "", + CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT}, /* URL without host name */ {"http://a:b@/x", "", CURLU_DEFAULT_SCHEME, 0, CURLUE_NO_HOST}, -- cgit v1.2.1