From 53bcf55b4538067e6dc36242168866becb987bb7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 12 Oct 2022 10:47:59 +0200 Subject: [PATCH] url: use IDN decoded names for HSTS checks Reported-by: Hiroki Kurosawa Closes #9791 CVE: CVE-2022-42916 Upstream-Status: Backport [https://github.com/curl/curl/commit/53bcf55b4538067e6dc36242168866becb987bb7] Signed-off-by: Bhabu Bindu Comments: Refreshed hunk --- lib/url.c | 91 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/lib/url.c b/lib/url.c index a3be56bced9de..690c53c81a3c1 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2012,10 +2012,56 @@ if(!strcasecompare("file", data->state.up.scheme)) return CURLE_OUT_OF_MEMORY; } + hostname = data->state.up.hostname; + + if(hostname && hostname[0] == '[') { + /* This looks like an IPv6 address literal. See if there is an address + scope. */ + size_t hlen; + conn->bits.ipv6_ip = TRUE; + /* cut off the brackets! */ + hostname++; + hlen = strlen(hostname); + hostname[hlen - 1] = 0; + + zonefrom_url(uh, data, conn); + } + + /* make sure the connect struct gets its own copy of the host name */ + conn->host.rawalloc = strdup(hostname ? hostname : ""); + if(!conn->host.rawalloc) + return CURLE_OUT_OF_MEMORY; + conn->host.name = conn->host.rawalloc; + + /************************************************************* + * IDN-convert the hostnames + *************************************************************/ + result = Curl_idnconvert_hostname(data, &conn->host); + if(result) + return result; + if(conn->bits.conn_to_host) { + result = Curl_idnconvert_hostname(data, &conn->conn_to_host); + if(result) + return result; + } +#ifndef CURL_DISABLE_PROXY + if(conn->bits.httpproxy) { + result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); + if(result) + return result; + } + if(conn->bits.socksproxy) { + result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); + if(result) + return result; + } +#endif #ifndef CURL_DISABLE_HSTS + /* HSTS upgrade */ if(data->hsts && strcasecompare("http", data->state.up.scheme)) { - if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { + /* This MUST use the IDN decoded name */ + if(Curl_hsts(data->hsts, conn->host.name, TRUE)) { char *url; Curl_safefree(data->state.up.scheme); uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0); @@ -2145,26 +2191,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); - hostname = data->state.up.hostname; - if(hostname && hostname[0] == '[') { - /* This looks like an IPv6 address literal. See if there is an address - scope. */ - size_t hlen; - conn->bits.ipv6_ip = TRUE; - /* cut off the brackets! */ - hostname++; - hlen = strlen(hostname); - hostname[hlen - 1] = 0; - - zonefrom_url(uh, data, conn); - } - - /* make sure the connect struct gets its own copy of the host name */ - conn->host.rawalloc = strdup(hostname ? hostname : ""); - if(!conn->host.rawalloc) - return CURLE_OUT_OF_MEMORY; - conn->host.name = conn->host.rawalloc; - #ifdef ENABLE_IPV6 if(data->set.scope_id) /* Override any scope that was set above. */ @@ -3713,29 +3739,6 @@ static CURLcode create_conn(struct Curl_easy *data, if(result) goto out; - /************************************************************* - * IDN-convert the hostnames - *************************************************************/ - result = Curl_idnconvert_hostname(data, &conn->host); - if(result) - goto out; - if(conn->bits.conn_to_host) { - result = Curl_idnconvert_hostname(data, &conn->conn_to_host); - if(result) - goto out; - } -#ifndef CURL_DISABLE_PROXY - if(conn->bits.httpproxy) { - result = Curl_idnconvert_hostname(data, &conn->http_proxy.host); - if(result) - goto out; - } - if(conn->bits.socksproxy) { - result = Curl_idnconvert_hostname(data, &conn->socks_proxy.host); - if(result) - goto out; - } -#endif /************************************************************* * Check whether the host and the "connect to host" are equal.