hsts: rename Curl_hsts() to hsts_check() and make it static

It is no longer used outside of hsts.c

Closes #21507
This commit is contained in:
Daniel Stenberg 2026-05-05 17:01:41 +02:00
parent 80214dca6b
commit 2cb6ba672d
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 65 additions and 60 deletions

View file

@ -130,6 +130,62 @@ static CURLcode hsts_create(struct hsts *h,
return CURLE_OK;
}
/*
* Return the matching HSTS entry, or NULL if the given hostname is not
* currently an HSTS one.
*
* The 'subdomain' argument tells the function if subdomain matching should be
* attempted.
*
* @unittest 1660
*/
UNITTEST struct stsentry *hsts_check(struct hsts *h, const char *hostname,
size_t hlen, bool subdomain);
UNITTEST struct stsentry *hsts_check(struct hsts *h, const char *hostname,
size_t hlen, bool subdomain)
{
struct stsentry *bestsub = NULL;
if(h) {
time_t now = time(NULL);
struct Curl_llist_node *e;
struct Curl_llist_node *n;
size_t blen = 0;
if((hlen > MAX_HSTS_HOSTLEN) || !hlen)
return NULL;
if(hostname[hlen - 1] == '.')
/* remove the trailing dot */
--hlen;
for(e = Curl_llist_head(&h->list); e; e = n) {
struct stsentry *sts = Curl_node_elem(e);
size_t ntail;
n = Curl_node_next(e);
if(sts->expires <= now) {
/* remove expired entries */
Curl_node_remove(&sts->node);
hsts_free(sts);
continue;
}
ntail = strlen(sts->host);
if((subdomain && sts->includeSubDomains) && (ntail < hlen)) {
size_t offs = hlen - ntail;
if((hostname[offs - 1] == '.') &&
curl_strnequal(&hostname[offs], sts->host, ntail) &&
(ntail > blen)) {
/* save the tail match with the longest tail */
bestsub = sts;
blen = ntail;
}
}
/* avoid curl_strequal because the hostname is not null-terminated */
if((hlen == ntail) && curl_strnequal(hostname, sts->host, hlen))
return sts;
}
}
return bestsub;
}
CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
const char *header)
{
@ -203,7 +259,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
if(!expires) {
/* remove the entry if present verbatim (without subdomain match) */
sts = Curl_hsts(h, hostname, hlen, FALSE);
sts = hsts_check(h, hostname, hlen, FALSE);
if(sts) {
Curl_node_remove(&sts->node);
hsts_free(sts);
@ -218,7 +274,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
expires += now;
/* check if it already exists */
sts = Curl_hsts(h, hostname, hlen, FALSE);
sts = hsts_check(h, hostname, hlen, FALSE);
if(sts) {
/* update these fields */
sts->expires = expires;
@ -230,57 +286,6 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
return CURLE_OK;
}
/*
* Return TRUE if the given hostname is currently an HSTS one.
*
* The 'subdomain' argument tells the function if subdomain matching should be
* attempted.
*/
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
size_t hlen, bool subdomain)
{
struct stsentry *bestsub = NULL;
if(h) {
time_t now = time(NULL);
struct Curl_llist_node *e;
struct Curl_llist_node *n;
size_t blen = 0;
if((hlen > MAX_HSTS_HOSTLEN) || !hlen)
return NULL;
if(hostname[hlen - 1] == '.')
/* remove the trailing dot */
--hlen;
for(e = Curl_llist_head(&h->list); e; e = n) {
struct stsentry *sts = Curl_node_elem(e);
size_t ntail;
n = Curl_node_next(e);
if(sts->expires <= now) {
/* remove expired entries */
Curl_node_remove(&sts->node);
hsts_free(sts);
continue;
}
ntail = strlen(sts->host);
if((subdomain && sts->includeSubDomains) && (ntail < hlen)) {
size_t offs = hlen - ntail;
if((hostname[offs - 1] == '.') &&
curl_strnequal(&hostname[offs], sts->host, ntail) &&
(ntail > blen)) {
/* save the tail match with the longest tail */
bestsub = sts;
blen = ntail;
}
}
/* avoid curl_strequal because the hostname is not null-terminated */
if((hlen == ntail) && curl_strnequal(hostname, sts->host, hlen))
return sts;
}
}
return bestsub;
}
/*
* Send this HSTS entry to the write callback.
*/
@ -437,7 +442,7 @@ static CURLcode hsts_add_host_expire(struct hsts *h,
if(hostlen) {
/* only add it if not already present */
e = Curl_hsts(h, host, hostlen, subdomain);
e = hsts_check(h, host, hostlen, subdomain);
if(!e)
result = hsts_create(h, host, hostlen, subdomain, expires);
/* 'host' is not necessarily null terminated */
@ -612,8 +617,8 @@ CURLcode Curl_hsts_loadfiles(struct Curl_easy *data)
bool Curl_hsts_applies(struct hsts *h, const struct Curl_peer *dest)
{
return !!Curl_hsts(h, dest->hostname,
strlen(dest->hostname), TRUE);
return !!hsts_check(h, dest->hostname,
strlen(dest->hostname), TRUE);
}
#if defined(DEBUGBUILD) || defined(UNITTESTS)

View file

@ -25,6 +25,8 @@
***************************************************************************/
#include "curl_setup.h"
struct hsts;
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS)
#include "llist.h"
@ -54,8 +56,6 @@ struct hsts *Curl_hsts_init(void);
void Curl_hsts_cleanup(struct hsts **hp);
CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
const char *header);
struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
size_t hlen, bool subdomain);
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
const char *file);
CURLcode Curl_hsts_loadfile(struct Curl_easy *data,

View file

@ -138,7 +138,7 @@ static CURLcode test_unit1660(const char *arg)
}
chost = headers[i].chost ? headers[i].chost : headers[i].host;
e = Curl_hsts(h, chost, strlen(chost), TRUE);
e = hsts_check(h, chost, strlen(chost), TRUE);
showsts(e, chost);
}
@ -147,7 +147,7 @@ static CURLcode test_unit1660(const char *arg)
/* verify that it is exists for 7 seconds */
chost = "expire.example";
for(i = 100; i < 110; i++) {
e = Curl_hsts(h, chost, strlen(chost), TRUE);
e = hsts_check(h, chost, strlen(chost), TRUE);
showsts(e, chost);
deltatime++; /* another second passed */
}