diff options
author | robot-contrib <[email protected]> | 2022-09-21 14:47:18 +0300 |
---|---|---|
committer | robot-contrib <[email protected]> | 2022-09-21 14:47:18 +0300 |
commit | f904cb56d9b1584ffcc28e53dec706fe1dc15d6f (patch) | |
tree | fe2764cc64c10b674559b367741a172323b52bcd /contrib/libs/curl/lib/url.c | |
parent | 37a16126ac62d0af47b33d50c786b9adc009f6f3 (diff) |
Update contrib/libs/curl to 7.85.0
Diffstat (limited to 'contrib/libs/curl/lib/url.c')
-rw-r--r-- | contrib/libs/curl/lib/url.c | 312 |
1 files changed, 174 insertions, 138 deletions
diff --git a/contrib/libs/curl/lib/url.c b/contrib/libs/curl/lib/url.c index c099c16a0c0..ec3fb77b013 100644 --- a/contrib/libs/curl/lib/url.c +++ b/contrib/libs/curl/lib/url.c @@ -77,6 +77,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out); #endif /* USE_LIBIDN2 */ +#include "doh.h" #include "urldata.h" #include "netrc.h" @@ -153,6 +154,9 @@ static void conn_free(struct connectdata *conn); #define UNIX_SOCKET_PREFIX "localhost" #endif +/* Reject URLs exceeding this length */ +#define MAX_URL_LEN 0xffff + /* * get_protocol_family() * @@ -439,6 +443,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->info.wouldredirect); /* this destroys the channel and we cannot use it anymore after this */ + Curl_resolver_cancel(data); Curl_resolver_cleanup(data->state.async.resolver); Curl_http2_cleanup_dependencies(data); @@ -2024,6 +2029,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, if(!strcasecompare("file", data->state.up.scheme)) return CURLE_OUT_OF_MEMORY; } + else if(strlen(data->state.up.hostname) > MAX_URL_LEN) { + failf(data, "Too long host name (maximum is %d)", MAX_URL_LEN); + return CURLE_URL_MALFORMAT; + } #ifndef CURL_DISABLE_HSTS if(data->hsts && strcasecompare("http", data->state.up.scheme)) { @@ -2128,7 +2137,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, unsigned long port = strtoul(data->state.up.port, NULL, 10); conn->port = conn->remote_port = (data->set.use_port && data->state.allow_port) ? - (int)data->set.use_port : curlx_ultous(port); + data->set.use_port : curlx_ultous(port); } (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); @@ -2734,16 +2743,16 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, * connection that may exist registered to the same proxy host. ***********************************************************************/ if(proxy || socksproxy) { + curl_proxytype ptype = (curl_proxytype)conn->http_proxy.proxytype; if(proxy) { - result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype); + result = parse_proxy(data, conn, proxy, ptype); Curl_safefree(proxy); /* parse_proxy copies the proxy string */ if(result) goto out; } if(socksproxy) { - result = parse_proxy(data, conn, socksproxy, - conn->socks_proxy.proxytype); + result = parse_proxy(data, conn, socksproxy, ptype); /* parse_proxy copies the socks proxy string */ Curl_safefree(socksproxy); if(result) @@ -2964,7 +2973,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data, /* if set, we use this instead of the port possibly given in the URL */ char portbuf[16]; CURLUcode uc; - conn->remote_port = (unsigned short)data->set.use_port; + conn->remote_port = data->set.use_port; msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port); uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0); if(uc) @@ -3038,29 +3047,31 @@ static CURLcode override_login(struct Curl_easy *data, conn->user = strdup(*userp); if(!conn->user) return CURLE_OUT_OF_MEMORY; - /* don't update the user name below */ - userp = NULL; + } + /* no user was set but a password, set a blank user */ + if(userp && !*userp && *passwdp) { + *userp = strdup(""); + if(!*userp) + return CURLE_OUT_OF_MEMORY; } } #endif /* for updated strings, we update them in the URL */ - if(userp) { - if(*userp) { - CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp); - if(result) - return result; - } - if(data->state.aptr.user) { - uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user, - CURLU_URLENCODE); - if(uc) - return Curl_uc_to_curlcode(uc); - if(!*userp) { - *userp = strdup(data->state.aptr.user); - if(!*userp) - return CURLE_OUT_OF_MEMORY; - } + if(*userp) { + CURLcode result = Curl_setstropt(&data->state.aptr.user, *userp); + if(result) + return result; + } + if(data->state.aptr.user) { + uc = curl_url_set(data->state.uh, CURLUPART_USER, data->state.aptr.user, + CURLU_URLENCODE); + if(uc) + return Curl_uc_to_curlcode(uc); + if(!*userp) { + *userp = strdup(data->state.aptr.user); + if(!*userp) + return CURLE_OUT_OF_MEMORY; } } if(*passwdp) { @@ -3413,141 +3424,166 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, return result; } -/************************************************************* - * Resolve the address of the server or proxy - *************************************************************/ -static CURLcode resolve_server(struct Curl_easy *data, - struct connectdata *conn, - bool *async) +#ifdef USE_UNIX_SOCKETS +static CURLcode resolve_unix(struct Curl_easy *data, + struct connectdata *conn, + char *unix_path) { - CURLcode result = CURLE_OK; - timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + struct Curl_dns_entry *hostaddr = NULL; + bool longpath = FALSE; - DEBUGASSERT(conn); - DEBUGASSERT(data); - /************************************************************* - * Resolve the name of the server or proxy - *************************************************************/ - if(conn->bits.reuse) - /* We're reusing the connection - no need to resolve anything, and - idnconvert_hostname() was called already in create_conn() for the re-use - case. */ - *async = FALSE; + DEBUGASSERT(unix_path); + DEBUGASSERT(conn->dns_entry == NULL); - else { - /* this is a fresh connect */ - int rc; - struct Curl_dns_entry *hostaddr = NULL; + /* Unix domain sockets are local. The host gets ignored, just use the + * specified domain socket address. Do not cache "DNS entries". There is + * no DNS involved and we already have the filesystem path available. */ + hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + if(!hostaddr) + return CURLE_OUT_OF_MEMORY; -#ifdef USE_UNIX_SOCKETS - char *unix_path = NULL; + hostaddr->addr = Curl_unix2addr(unix_path, &longpath, + conn->bits.abstract_unix_socket); + if(!hostaddr->addr) { + if(longpath) + /* Long paths are not supported for now */ + failf(data, "Unix socket path too long: '%s'", unix_path); + free(hostaddr); + return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY; + } - if(conn->unix_domain_socket) - unix_path = conn->unix_domain_socket; -#ifndef CURL_DISABLE_PROXY - else if(conn->socks_proxy.host.name - && !strncmp(UNIX_SOCKET_PREFIX"/", - conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) - unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; + hostaddr->inuse++; + conn->dns_entry = hostaddr; + return CURLE_OK; +} #endif - if(unix_path) { - /* Unix domain sockets are local. The host gets ignored, just use the - * specified domain socket address. Do not cache "DNS entries". There is - * no DNS involved and we already have the filesystem path available */ +#ifndef CURL_DISABLE_PROXY +static CURLcode resolve_proxy(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + struct Curl_dns_entry *hostaddr = NULL; + struct hostname *host; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + int rc; - hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); - if(!hostaddr) - result = CURLE_OUT_OF_MEMORY; - else { - bool longpath = FALSE; - hostaddr->addr = Curl_unix2addr(unix_path, &longpath, - conn->bits.abstract_unix_socket); - if(hostaddr->addr) - hostaddr->inuse++; - else { - /* Long paths are not supported for now */ - if(longpath) { - failf(data, "Unix socket path too long: '%s'", unix_path); - result = CURLE_COULDNT_RESOLVE_HOST; - } - else - result = CURLE_OUT_OF_MEMORY; - free(hostaddr); - hostaddr = NULL; - } - } - } - else + DEBUGASSERT(conn->dns_entry == NULL); + + host = conn->bits.socksproxy ? &conn->socks_proxy.host : + &conn->http_proxy.host; + + conn->hostname_resolve = strdup(host->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; + + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + conn->dns_entry = hostaddr; + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + else if(rc == CURLRESOLV_TIMEDOUT) + return CURLE_OPERATION_TIMEDOUT; + else if(!hostaddr) { + failf(data, "Couldn't resolve proxy '%s'", host->dispname); + return CURLE_COULDNT_RESOLVE_PROXY; + } + + return CURLE_OK; +} #endif - if(!CONN_IS_PROXIED(conn)) { - struct hostname *connhost; - if(conn->bits.conn_to_host) - connhost = &conn->conn_to_host; - else - connhost = &conn->host; +static CURLcode resolve_ip(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + struct Curl_dns_entry *hostaddr = NULL; + struct hostname *connhost; + timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + int rc; - /* If not connecting via a proxy, extract the port from the URL, if it is - * there, thus overriding any defaults that might have been set above. */ - if(conn->bits.conn_to_port) - conn->port = conn->conn_to_port; - else - conn->port = conn->remote_port; + DEBUGASSERT(conn->dns_entry == NULL); - /* Resolve target host right on */ - conn->hostname_resolve = strdup(connhost->name); - if(!conn->hostname_resolve) - return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, - &hostaddr, timeout_ms); - if(rc == CURLRESOLV_PENDING) - *async = TRUE; - - else if(rc == CURLRESOLV_TIMEDOUT) { - failf(data, "Failed to resolve host '%s' with timeout after %ld ms", - connhost->dispname, - Curl_timediff(Curl_now(), data->progress.t_startsingle)); - result = CURLE_OPERATION_TIMEDOUT; - } - else if(!hostaddr) { - failf(data, "Could not resolve host: %s", connhost->dispname); - result = CURLE_COULDNT_RESOLVE_HOST; - /* don't return yet, we need to clean up the timeout first */ - } - } -#ifndef CURL_DISABLE_PROXY - else { - /* This is a proxy that hasn't been resolved yet. */ + connhost = conn->bits.conn_to_host ? &conn->conn_to_host : &conn->host; - struct hostname * const host = conn->bits.socksproxy ? - &conn->socks_proxy.host : &conn->http_proxy.host; + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ + conn->port = conn->bits.conn_to_port ? conn->conn_to_port : + conn->remote_port; - /* resolve proxy */ - conn->hostname_resolve = strdup(host->name); - if(!conn->hostname_resolve) - return CURLE_OUT_OF_MEMORY; - rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, - &hostaddr, timeout_ms); + /* Resolve target host right on */ + conn->hostname_resolve = strdup(connhost->name); + if(!conn->hostname_resolve) + return CURLE_OUT_OF_MEMORY; - if(rc == CURLRESOLV_PENDING) - *async = TRUE; + rc = Curl_resolv_timeout(data, conn->hostname_resolve, (int)conn->port, + &hostaddr, timeout_ms); + conn->dns_entry = hostaddr; + if(rc == CURLRESOLV_PENDING) + *async = TRUE; + else if(rc == CURLRESOLV_TIMEDOUT) { + failf(data, "Failed to resolve host '%s' with timeout after %ld ms", + connhost->dispname, + Curl_timediff(Curl_now(), data->progress.t_startsingle)); + return CURLE_OPERATION_TIMEDOUT; + } + else if(!hostaddr) { + failf(data, "Could not resolve host: %s", connhost->dispname); + return CURLE_COULDNT_RESOLVE_HOST; + } - else if(rc == CURLRESOLV_TIMEDOUT) - result = CURLE_OPERATION_TIMEDOUT; + return CURLE_OK; +} - else if(!hostaddr) { - failf(data, "Couldn't resolve proxy '%s'", host->dispname); - result = CURLE_COULDNT_RESOLVE_PROXY; - /* don't return yet, we need to clean up the timeout first */ - } - } +/* Perform a fresh resolve */ +static CURLcode resolve_fresh(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ +#ifdef USE_UNIX_SOCKETS + char *unix_path = conn->unix_domain_socket; + +#ifndef CURL_DISABLE_PROXY + if(!unix_path && conn->socks_proxy.host.name && + !strncmp(UNIX_SOCKET_PREFIX"/", + conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) + unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; #endif - DEBUGASSERT(conn->dns_entry == NULL); - conn->dns_entry = hostaddr; + + if(unix_path) { + conn->transport = TRNSPRT_UNIX; + return resolve_unix(data, conn, unix_path); } +#endif - return result; +#ifndef CURL_DISABLE_PROXY + if(CONN_IS_PROXIED(conn)) + return resolve_proxy(data, conn, async); +#endif + + return resolve_ip(data, conn, async); +} + +/************************************************************* + * Resolve the address of the server or proxy + *************************************************************/ +static CURLcode resolve_server(struct Curl_easy *data, + struct connectdata *conn, + bool *async) +{ + DEBUGASSERT(conn); + DEBUGASSERT(data); + + /* Resolve the name of the server or proxy */ + if(conn->bits.reuse) { + /* We're reusing the connection - no need to resolve anything, and + idnconvert_hostname() was called already in create_conn() for the re-use + case. */ + *async = FALSE; + return CURLE_OK; + } + + return resolve_fresh(data, conn, async); } /* |