From 2cb6ba672da5fc000a1b1b8b5496c6459eb34378 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 5 May 2026 17:01:41 +0200 Subject: [PATCH] hsts: rename Curl_hsts() to hsts_check() and make it static It is no longer used outside of hsts.c Closes #21507 --- lib/hsts.c | 117 ++++++++++++++++++++++-------------------- lib/hsts.h | 4 +- tests/unit/unit1660.c | 4 +- 3 files changed, 65 insertions(+), 60 deletions(-) diff --git a/lib/hsts.c b/lib/hsts.c index 261dffc479..856b525a62 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -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) diff --git a/lib/hsts.h b/lib/hsts.h index 93b9980729..d4c7fe826b 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -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, diff --git a/tests/unit/unit1660.c b/tests/unit/unit1660.c index bc68a76c46..62b4ea0095 100644 --- a/tests/unit/unit1660.c +++ b/tests/unit/unit1660.c @@ -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 */ }