summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/url.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/url.c')
-rw-r--r--libs/libcurl/src/url.c611
1 files changed, 281 insertions, 330 deletions
diff --git a/libs/libcurl/src/url.c b/libs/libcurl/src/url.c
index 1114c6c12e..be5ffca2d8 100644
--- a/libs/libcurl/src/url.c
+++ b/libs/libcurl/src/url.c
@@ -73,10 +73,11 @@
#endif
#elif defined(USE_WIN32_IDN)
-/* prototype for curl_win32_idn_to_ascii() */
-bool curl_win32_idn_to_ascii(const char *in, char **out);
+/* prototype for Curl_win32_idn_to_ascii() */
+bool Curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_LIBIDN2 */
+#include "doh.h"
#include "urldata.h"
#include "netrc.h"
@@ -105,6 +106,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "urlapi-int.h"
#include "system_win32.h"
#include "hsts.h"
+#include "noproxy.h"
/* And now for the protocols */
#include "ftp.h"
@@ -127,7 +129,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "http_proxy.h"
#include "conncache.h"
#include "multihandle.h"
-#include "dotdot.h"
#include "strdup.h"
#include "setopt.h"
#include "altsvc.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()
*
@@ -164,7 +168,7 @@ static void conn_free(struct connectdata *conn);
*
* Returns the family as a single bit protocol identifier.
*/
-static unsigned int get_protocol_family(const struct Curl_handler *h)
+static curl_prot_t get_protocol_family(const struct Curl_handler *h)
{
DEBUGASSERT(h);
DEBUGASSERT(h->family);
@@ -188,6 +192,16 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_http,
#endif
+#ifdef USE_WEBSOCKETS
+#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
+ &Curl_handler_wss,
+#endif
+
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_ws,
+#endif
+#endif
+
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
@@ -439,6 +453,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);
@@ -563,11 +578,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
-
- /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
- define since we internally only use the lower 16 bits for the passed
- in bitmask to not conflict with the private bits */
- set->allowed_protocols = (unsigned int)CURLPROTO_ALL;
+ set->allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
CURLPROTO_FTPS;
@@ -618,7 +629,6 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
- set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
@@ -741,15 +751,6 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
DEBUGASSERT(data);
infof(data, "Closing connection %ld", conn->connection_id);
-#ifndef USE_HYPER
- if(conn->connect_state && conn->connect_state->prot_save) {
- /* If this was closed with a CONNECT in progress, cleanup this temporary
- struct arrangement */
- data->req.p.http = NULL;
- Curl_safefree(conn->connect_state->prot_save);
- }
-#endif
-
/* possible left-overs from the async name resolvers */
Curl_resolver_cancel(data);
@@ -864,7 +865,7 @@ void Curl_disconnect(struct Curl_easy *data,
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
- if(conn->bits.connect_only)
+ if(conn->connect_only)
/* treat the connection as dead in CONNECT_ONLY situations */
dead_connection = TRUE;
@@ -948,19 +949,11 @@ socks_proxy_info_matches(const struct proxy_info *data,
/* the user information is case-sensitive
or at least it is not defined as case-insensitive
see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */
- if(!data->user != !needle->user)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->user &&
- needle->user &&
- strcmp(data->user, needle->user) != 0)
- return FALSE;
- if(!data->passwd != !needle->passwd)
- return FALSE;
- /* curl_strequal does a case insentive comparison, so do not use it here! */
- if(data->passwd &&
- needle->passwd &&
- strcmp(data->passwd, needle->passwd) != 0)
+
+ /* curl_strequal does a case insensitive comparison,
+ so do not use it here! */
+ if(Curl_timestrcmp(data->user, needle->user) ||
+ Curl_timestrcmp(data->passwd, needle->passwd))
return FALSE;
return TRUE;
}
@@ -1210,7 +1203,7 @@ ConnectionExists(struct Curl_easy *data,
check = curr->ptr;
curr = curr->next;
- if(check->bits.connect_only || check->bits.close)
+ if(check->connect_only || check->bits.close)
/* connect-only or to-be-closed connections will not be reused */
continue;
@@ -1362,10 +1355,10 @@ ConnectionExists(struct Curl_easy *data,
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd) ||
- !Curl_safecmp(needle->sasl_authzid, check->sasl_authzid) ||
- !Curl_safecmp(needle->oauth_bearer, check->oauth_bearer)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd) ||
+ Curl_timestrcmp(needle->sasl_authzid, check->sasl_authzid) ||
+ Curl_timestrcmp(needle->oauth_bearer, check->oauth_bearer)) {
/* one of them was different */
continue;
}
@@ -1441,8 +1434,8 @@ ConnectionExists(struct Curl_easy *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
- if(strcmp(needle->user, check->user) ||
- strcmp(needle->passwd, check->passwd)) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd)) {
/* we prefer a credential match, but this is at least a connection
that can be reused and "upgraded" to NTLM */
@@ -1464,8 +1457,10 @@ ConnectionExists(struct Curl_easy *data,
if(!check->http_proxy.user || !check->http_proxy.passwd)
continue;
- if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
- strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
continue;
}
else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
@@ -1637,7 +1632,7 @@ CURLcode Curl_idnconvert_hostname(struct Curl_easy *data,
#elif defined(USE_WIN32_IDN)
char *ace_hostname = NULL;
- if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
+ if(Curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
host->encalloc = ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
@@ -1668,7 +1663,7 @@ void Curl_free_idnconverted_hostname(struct hostname *host)
}
#elif defined(USE_WIN32_IDN)
free(host->encalloc); /* must be freed with free() since this was
- allocated by curl_win32_idn_to_ascii */
+ allocated by Curl_win32_idn_to_ascii */
host->encalloc = NULL;
#else
(void)host;
@@ -1794,7 +1789,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->proxy_ssl_config.ssl_options = data->set.proxy_ssl.primary.ssl_options;
#endif
conn->ip_version = data->set.ipver;
- conn->bits.connect_only = data->set.connect_only;
+ conn->connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
@@ -1838,15 +1833,18 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
}
/* returns the handler if the given scheme is built-in */
-const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
+const struct Curl_handler *Curl_builtin_scheme(const char *scheme,
+ size_t schemelen)
{
const struct Curl_handler * const *pp;
const struct Curl_handler *p;
/* Scan protocol handler table and match against 'scheme'. The handler may
be changed later when the protocol specific setup function is called. */
+ if(schemelen == CURL_ZERO_TERMINATED)
+ schemelen = strlen(scheme);
for(pp = protocols; (p = *pp) != NULL; pp++)
- if(strcasecompare(p->scheme, scheme))
- /* Protocol found in table. Check if allowed */
+ if(strncasecompare(p->scheme, scheme, schemelen) && !p->scheme[schemelen])
+ /* Protocol found in table. */
return p;
return NULL; /* not found */
}
@@ -1856,7 +1854,8 @@ static CURLcode findprotocol(struct Curl_easy *data,
struct connectdata *conn,
const char *protostr)
{
- const struct Curl_handler *p = Curl_builtin_scheme(protostr);
+ const struct Curl_handler *p = Curl_builtin_scheme(protostr,
+ CURL_ZERO_TERMINATED);
if(p && /* Protocol found in table. Check if allowed */
(data->set.allowed_protocols & p->protocol)) {
@@ -1980,7 +1979,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
- !Curl_is_absolute_url(data->state.url, NULL, 0)) {
+ !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) {
char *url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
data->state.url);
if(!url)
@@ -2024,10 +2023,60 @@ 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;
+ }
+ 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);
@@ -2078,7 +2127,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
return Curl_uc_to_curlcode(uc);
}
- if(!data->state.aptr.user) {
+ if(!data->set.str[STRING_USERNAME]) {
/* we don't use the URL API's URL decoder option here since it rejects
control codes and we want to allow them for some schemes in the user
and password fields */
@@ -2128,31 +2177,11 @@ 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);
- 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. */
@@ -2250,83 +2279,6 @@ void Curl_free_request_state(struct Curl_easy *data)
#ifndef CURL_DISABLE_PROXY
-/****************************************************************
-* Checks if the host is in the noproxy list. returns true if it matches
-* and therefore the proxy should NOT be used.
-****************************************************************/
-static bool check_noproxy(const char *name, const char *no_proxy)
-{
- /* no_proxy=domain1.dom,host.domain2.dom
- * (a comma-separated list of hosts which should
- * not be proxied, or an asterisk to override
- * all proxy variables)
- */
- if(no_proxy && no_proxy[0]) {
- size_t tok_start;
- size_t tok_end;
- const char *separator = ", ";
- size_t no_proxy_len;
- size_t namelen;
- char *endptr;
- if(strcasecompare("*", no_proxy)) {
- return TRUE;
- }
-
- /* NO_PROXY was specified and it wasn't just an asterisk */
-
- no_proxy_len = strlen(no_proxy);
- if(name[0] == '[') {
- /* IPv6 numerical address */
- endptr = strchr(name, ']');
- if(!endptr)
- return FALSE;
- name++;
- namelen = endptr - name;
- }
- else
- namelen = strlen(name);
-
- for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
- while(tok_start < no_proxy_len &&
- strchr(separator, no_proxy[tok_start]) != NULL) {
- /* Look for the beginning of the token. */
- ++tok_start;
- }
-
- if(tok_start == no_proxy_len)
- break; /* It was all trailing separator chars, no more tokens. */
-
- for(tok_end = tok_start; tok_end < no_proxy_len &&
- strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
- /* Look for the end of the token. */
- ;
-
- /* To match previous behavior, where it was necessary to specify
- * ".local.com" to prevent matching "notlocal.com", we will leave
- * the '.' off.
- */
- if(no_proxy[tok_start] == '.')
- ++tok_start;
-
- if((tok_end - tok_start) <= namelen) {
- /* Match the last part of the name to the domain we are checking. */
- const char *checkn = name + namelen - (tok_end - tok_start);
- if(strncasecompare(no_proxy + tok_start, checkn,
- tok_end - tok_start)) {
- if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
- /* We either have an exact match, or the previous character is a .
- * so it is within the same domain, so no proxy for this host.
- */
- return TRUE;
- }
- }
- } /* if((tok_end - tok_start) <= namelen) */
- } /* for(tok_start = 0; tok_start < no_proxy_len;
- tok_start = tok_end + 1) */
- } /* NO_PROXY was specified and it wasn't just an asterisk */
-
- return FALSE;
-}
#ifndef CURL_DISABLE_HTTP
/****************************************************************
@@ -2366,7 +2318,7 @@ static char *detect_proxy(struct Curl_easy *data,
/* Now, build <protocol>_proxy and check for such a one to use */
while(*protop)
- *envp++ = (char)tolower((int)*protop++);
+ *envp++ = Curl_raw_tolower(*protop++);
/* append _proxy */
strcpy(envp, "_proxy");
@@ -2695,8 +2647,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
}
}
- if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
- data->set.str[STRING_NOPROXY] : no_proxy)) {
+ if(Curl_check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+ data->set.str[STRING_NOPROXY] : no_proxy)) {
Curl_safefree(proxy);
Curl_safefree(socksproxy);
}
@@ -2734,16 +2686,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)
@@ -2893,15 +2845,15 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
(psep && psep > osep ? (size_t)(psep - osep) :
(size_t)(login + len - osep)) - 1 : 0);
- /* Allocate the user portion buffer */
- if(userp && ulen) {
+ /* Allocate the user portion buffer, which can be zero length */
+ if(userp) {
ubuf = malloc(ulen + 1);
if(!ubuf)
result = CURLE_OUT_OF_MEMORY;
}
/* Allocate the password portion buffer */
- if(!result && passwdp && plen) {
+ if(!result && passwdp && psep) {
pbuf = malloc(plen + 1);
if(!pbuf) {
free(ubuf);
@@ -2964,7 +2916,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)
@@ -2986,14 +2938,6 @@ static CURLcode override_login(struct Curl_easy *data,
char **passwdp = &conn->passwd;
char **optionsp = &conn->options;
-#ifndef CURL_DISABLE_NETRC
- if(data->set.use_netrc == CURL_NETRC_REQUIRED && data->state.aptr.user) {
- Curl_safefree(*userp);
- Curl_safefree(*passwdp);
- Curl_safefree(data->state.aptr.user); /* disable user+password */
- }
-#endif
-
if(data->set.str[STRING_OPTIONS]) {
free(*optionsp);
*optionsp = strdup(data->set.str[STRING_OPTIONS]);
@@ -3002,22 +2946,23 @@ static CURLcode override_login(struct Curl_easy *data,
}
#ifndef CURL_DISABLE_NETRC
+ if(data->set.use_netrc == CURL_NETRC_REQUIRED) {
+ Curl_safefree(*userp);
+ Curl_safefree(*passwdp);
+ }
conn->bits.netrc = FALSE;
if(data->set.use_netrc && !data->set.str[STRING_USERNAME]) {
- bool netrc_user_changed = FALSE;
- bool netrc_passwd_changed = FALSE;
int ret;
bool url_provided = FALSE;
- if(data->state.up.user) {
- /* there was a user name in the URL */
- userp = &data->state.up.user;
+ if(data->state.aptr.user) {
+ /* there was a user name in the URL. Use the URL decoded version */
+ userp = &data->state.aptr.user;
url_provided = TRUE;
}
ret = Curl_parsenetrc(conn->host.name,
userp, passwdp,
- &netrc_user_changed, &netrc_passwd_changed,
data->set.str[STRING_NETRC_FILE]);
if(ret > 0) {
infof(data, "Couldn't find host %s in the %s file; using defaults",
@@ -3038,29 +2983,35 @@ 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(*userp) {
+ CURLcode result;
+ if(data->state.aptr.user != *userp) {
+ /* nothing to do then */
+ 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(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 +3364,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_host(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_host(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);
}
/*
@@ -3754,29 +3730,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.
@@ -3989,13 +3942,11 @@ static CURLcode create_conn(struct Curl_easy *data,
be able to do that if we have reached the limit of how many
connections we are allowed to open. */
- if(conn->handler->flags & PROTOPT_ALPN_NPN) {
+ if(conn->handler->flags & PROTOPT_ALPN) {
/* The protocol wants it, so set the bits if enabled in the easy handle
(default) */
if(data->set.ssl_enable_alpn)
conn->bits.tls_enable_alpn = TRUE;
- if(data->set.ssl_enable_npn)
- conn->bits.tls_enable_npn = TRUE;
}
if(waitpipe)