summaryrefslogtreecommitdiffstats
path: root/contrib/libs/curl/lib/url.c
diff options
context:
space:
mode:
authorrobot-contrib <[email protected]>2022-09-21 14:47:18 +0300
committerrobot-contrib <[email protected]>2022-09-21 14:47:18 +0300
commitf904cb56d9b1584ffcc28e53dec706fe1dc15d6f (patch)
treefe2764cc64c10b674559b367741a172323b52bcd /contrib/libs/curl/lib/url.c
parent37a16126ac62d0af47b33d50c786b9adc009f6f3 (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.c312
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);
}
/*