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)
{
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);
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;
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.
*/
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 */
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)