mirror of
https://github.com/curl/curl.git
synced 2026-07-25 04:27:15 +03:00
lib: hostname related cleanups
* format `data->state.aptr.host` without crlf, so signatures do not need to strip it again. Add the crlf when adding the header to the request dynbuf * check `connect-to` strings on normalized hostname and user supplied hostname (when those differ) * libssh: always use the peer for setting ssh option SSH_OPTIONS_HOST, preserve ipv6 [] enclosure, use IDN converted hostname otherwise. This is the libssh documented expectation. Do NOT use strings from URL parsing. Closes #22128
This commit is contained in:
parent
58771cf4f3
commit
d786a85f19
4 changed files with 50 additions and 36 deletions
59
lib/http.c
59
lib/http.c
|
|
@ -2000,17 +2000,17 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
|
|||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct dynamically_allocated_data *aptr = &data->state.aptr;
|
||||
const char *ptr;
|
||||
const char *ptr = NULL;
|
||||
|
||||
curlx_safefree(aptr->host);
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
curlx_safefree(data->req.cookiehost);
|
||||
#endif
|
||||
|
||||
ptr = Curl_checkheaders(data, STRCONST("Host"));
|
||||
if(ptr &&
|
||||
(!data->state.this_is_a_follow ||
|
||||
Curl_peer_equal(data->state.initial_origin, data->state.origin))) {
|
||||
if(Curl_peer_equal(data->state.initial_origin, data->state.origin))
|
||||
ptr = Curl_checkheaders(data, STRCONST("Host"));
|
||||
|
||||
if(ptr) {
|
||||
#ifndef CURL_DISABLE_COOKIES
|
||||
/* If we have a given custom Host: header, we extract the hostname in
|
||||
order to possibly use it for cookie reasons later on. We only allow the
|
||||
|
|
@ -2047,30 +2047,40 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
|
|||
#endif
|
||||
|
||||
if(!curl_strequal("Host:", ptr)) {
|
||||
aptr->host = curl_maprintf("Host:%s\r\n", &ptr[5]);
|
||||
aptr->host = curl_maprintf("Host:%s", &ptr[5]);
|
||||
if(!aptr->host)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Use the hostname as present in the URL if it was IPv6. */
|
||||
char *host = (data->state.origin->user_hostname[0] == '[') ?
|
||||
data->state.origin->user_hostname : data->state.origin->hostname;
|
||||
/* This is the HTTP Host: header, so we want
|
||||
* - for ipv6 origins: "[ipv6-address]" where the ipv6 address is
|
||||
* found in origin->hostname, stripped of zoneid/scopeid.
|
||||
* - the (IDN converted) origin->hostname (DNS name or ipv4) otherwise.
|
||||
* Note: zoneid/scopeid only applies to local routing and has no
|
||||
* meaning on the remote HTTP server (eg. would confuse it). */
|
||||
bool ipv6 = (bool)data->state.origin->ipv6;
|
||||
struct dynbuf tmp;
|
||||
size_t hlen;
|
||||
CURLcode result;
|
||||
|
||||
if(((conn->given->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS)) &&
|
||||
(data->state.origin->port == PORT_HTTPS)) ||
|
||||
((conn->given->protocol & (CURLPROTO_HTTP | CURLPROTO_WS)) &&
|
||||
(data->state.origin->port == PORT_HTTP)))
|
||||
/* if(HTTPS on port 443) OR (HTTP on port 80) then do not include
|
||||
the port number in the host string */
|
||||
aptr->host = curl_maprintf("Host: %s\r\n", host);
|
||||
else
|
||||
aptr->host = curl_maprintf("Host: %s:%d\r\n",
|
||||
host, data->state.origin->port);
|
||||
curlx_dyn_init(&tmp, DYN_HTTP_REQUEST);
|
||||
result = curlx_dyn_addn(&tmp, STRCONST("Host: "));
|
||||
if(!result && ipv6)
|
||||
result = curlx_dyn_addn(&tmp, STRCONST("["));
|
||||
if(!result)
|
||||
result = curlx_dyn_add(&tmp, data->state.origin->hostname);
|
||||
if(!result && ipv6)
|
||||
result = curlx_dyn_addn(&tmp, STRCONST("]"));
|
||||
if(!result &&
|
||||
((data->state.origin->port != data->state.origin->scheme->defport) ||
|
||||
(data->state.origin->scheme->family != conn->scheme->family))) {
|
||||
result = curlx_dyn_addf(&tmp, ":%u", data->state.origin->port);
|
||||
}
|
||||
|
||||
if(!aptr->host)
|
||||
/* without Host: we cannot make a nice request */
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
aptr->host = result ? NULL : curlx_dyn_take(&tmp, &hlen);
|
||||
curlx_dyn_free(&tmp);
|
||||
return result;
|
||||
}
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
@ -2896,8 +2906,11 @@ static CURLcode http_add_hd(struct Curl_easy *data,
|
|||
break;
|
||||
|
||||
case H1_HD_HOST:
|
||||
if(data->state.aptr.host)
|
||||
if(data->state.aptr.host) {
|
||||
result = curlx_dyn_add(req, data->state.aptr.host);
|
||||
if(!result)
|
||||
result = curlx_dyn_addn(req, STRCONST("\r\n"));
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
|
|
|
|||
|
|
@ -401,11 +401,8 @@ static CURLcode make_headers(struct Curl_easy *data,
|
|||
if(!Curl_checkheaders(data, STRCONST("Host"))) {
|
||||
char *fullhost;
|
||||
|
||||
if(data->state.aptr.host) {
|
||||
/* remove /r/n as the separator for canonical request must be '\n' */
|
||||
size_t pos = strcspn(data->state.aptr.host, "\n\r");
|
||||
fullhost = curlx_memdup0(data->state.aptr.host, pos);
|
||||
}
|
||||
if(data->state.aptr.host)
|
||||
fullhost = curlx_strdup(data->state.aptr.host);
|
||||
else
|
||||
fullhost = curl_maprintf("host:%s", hostname);
|
||||
|
||||
|
|
|
|||
18
lib/url.c
18
lib/url.c
|
|
@ -1856,14 +1856,16 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
|
|||
/* check whether the URL's hostname matches. Use the URL hostname
|
||||
* when it was an IPv6 address. Otherwise use the connection's hostname
|
||||
* that has IDN conversion. */
|
||||
const char *hostname_to_match = (dest->user_hostname[0] == '[') ?
|
||||
dest->user_hostname : dest->hostname;
|
||||
size_t hlen = strlen(hostname_to_match);
|
||||
host_match = curl_strnequal(ptr, hostname_to_match, hlen);
|
||||
ptr += hlen;
|
||||
|
||||
host_match = host_match && *ptr == ':';
|
||||
ptr++;
|
||||
size_t hlen = strlen(dest->hostname);
|
||||
host_match = curl_strnequal(ptr, dest->hostname, hlen);
|
||||
if(!host_match && (dest->user_hostname != dest->hostname)) {
|
||||
/* hostname was normalized, could be IPv6 or IDN */
|
||||
hlen = strlen(dest->user_hostname);
|
||||
host_match = curl_strnequal(ptr, dest->user_hostname, hlen);
|
||||
}
|
||||
host_match = host_match && ptr[hlen] == ':';
|
||||
if(host_match)
|
||||
ptr += hlen + 1;
|
||||
}
|
||||
|
||||
if(host_match) {
|
||||
|
|
|
|||
|
|
@ -2585,6 +2585,8 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
|
|||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
/* For ipv6 origins, use the `user_hostname` that has the "[]" enclosure.
|
||||
* Otherwise, use `hostname` that is IDN converted. */
|
||||
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST,
|
||||
conn->origin->ipv6 ?
|
||||
conn->origin->user_hostname : conn->origin->hostname);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue