httpsrr: send HTTPS query to the right target

When the target host is on a different port than 443, the name
"_[port]._https.[name]" shall be used.

Fixes #19301
Reported-by: Gunni on github
Closes #19324
This commit is contained in:
Daniel Stenberg 2025-11-01 20:21:25 +01:00
parent 6a97bc2c97
commit 8d0bfe74fb
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 31 additions and 5 deletions

View File

@ -730,6 +730,9 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
int *waitp)
{
struct async_ares_ctx *ares = &data->state.async.ares;
#ifdef USE_HTTPSRR
char *rrname = NULL;
#endif
*waitp = 0; /* default to synchronous response */
if(async_ares_init_lazy(data))
@ -742,6 +745,15 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
data->state.async.hostname = strdup(hostname);
if(!data->state.async.hostname)
return NULL;
#ifdef USE_HTTPSRR
if(port != 443) {
rrname = curl_maprintf("_%d_.https.%s", port, hostname);
if(!rrname) {
free(data->state.async.hostname);
return NULL;
}
}
#endif
/* initial status - failed */
ares->ares_status = ARES_ENOTFOUND;
@ -814,11 +826,14 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data,
#endif
#ifdef USE_HTTPSRR
{
CURL_TRC_DNS(data, "asyn-ares: fire off query for HTTPSRR");
CURL_TRC_DNS(data, "asyn-ares: fire off query for HTTPSRR: %s",
rrname ? rrname : data->state.async.hostname);
memset(&ares->hinfo, 0, sizeof(ares->hinfo));
ares->hinfo.port = -1;
ares->hinfo.rrname = rrname;
ares->num_pending++; /* one more */
ares_query_dnsrec(ares->channel, data->state.async.hostname,
ares_query_dnsrec(ares->channel,
rrname ? rrname : data->state.async.hostname,
ARES_CLASS_IN, ARES_REC_TYPE_HTTPS,
async_ares_rr_done, data, NULL);
}

View File

@ -361,12 +361,18 @@ static void async_thrdd_rr_done(void *user_data, ares_status_t status,
thrdd->rr.result = Curl_httpsrr_from_ares(data, dnsrec, &thrdd->rr.hinfo);
}
static CURLcode async_rr_start(struct Curl_easy *data)
static CURLcode async_rr_start(struct Curl_easy *data, int port)
{
struct async_thrdd_ctx *thrdd = &data->state.async.thrdd;
int status;
char *rrname = NULL;
DEBUGASSERT(!thrdd->rr.channel);
if(port != 443) {
rrname = curl_maprintf("_%d_.https.%s", port, data->conn->host.name);
if(!rrname)
return CURLE_OUT_OF_MEMORY;
}
status = ares_init_options(&thrdd->rr.channel, NULL, 0);
if(status != ARES_SUCCESS) {
thrdd->rr.channel = NULL;
@ -383,8 +389,9 @@ static CURLcode async_rr_start(struct Curl_easy *data)
memset(&thrdd->rr.hinfo, 0, sizeof(thrdd->rr.hinfo));
thrdd->rr.hinfo.port = -1;
thrdd->rr.hinfo.rrname = rrname;
ares_query_dnsrec(thrdd->rr.channel,
data->conn->host.name, ARES_CLASS_IN,
rrname ? rrname : data->conn->host.name, ARES_CLASS_IN,
ARES_REC_TYPE_HTTPS,
async_thrdd_rr_done, data, NULL);
CURL_TRC_DNS(data, "Issued HTTPS-RR request for %s", data->conn->host.name);
@ -454,7 +461,7 @@ static bool async_thrdd_init(struct Curl_easy *data,
}
#ifdef USE_HTTPSRR_ARES
if(async_rr_start(data))
if(async_rr_start(data, port))
infof(data, "Failed HTTPS RR operation");
#endif
CURL_TRC_DNS(data, "resolve thread started for of %s:%d", hostname, port);

View File

@ -152,6 +152,7 @@ void Curl_httpsrr_cleanup(struct Curl_https_rrinfo *rrinfo)
Curl_safefree(rrinfo->echconfiglist);
Curl_safefree(rrinfo->ipv4hints);
Curl_safefree(rrinfo->ipv6hints);
Curl_safefree(rrinfo->rrname);
}
@ -206,6 +207,7 @@ CURLcode Curl_httpsrr_from_ares(struct Curl_easy *data,
}
}
out:
Curl_safefree(hinfo->rrname);
return result;
}

View File

@ -38,6 +38,7 @@
struct Curl_easy;
struct Curl_https_rrinfo {
char *rrname; /* if NULL, the same as the URL hostname */
/*
* Fields from HTTPS RR. The only mandatory fields are priority and target.
* See https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2

View File

@ -4,6 +4,7 @@
HTTP
HTTP GET
DOH
httpsrr
</keywords>
</info>