summaryrefslogtreecommitdiff
path: root/lib/hsts.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2020-11-02 23:17:01 +0100
committerDaniel Stenberg <daniel@haxx.se>2020-11-03 16:08:48 +0100
commit2cfc4ed98347047249b8f7f91ad513a4b0b84e45 (patch)
tree6e69f05aeeb76db0a7f15f9c8314f1e983ed42e8 /lib/hsts.c
parent7385610d0c74c6a254fea5e4cd6e1d559d848c8c (diff)
downloadcurl-2cfc4ed98347047249b8f7f91ad513a4b0b84e45.tar.gz
hsts: add read/write callbacks
- read/write callback options - man pages for the 4 new setopts - test 1915 verifies the callbacks Closes #5896
Diffstat (limited to 'lib/hsts.c')
-rw-r--r--lib/hsts.c109
1 files changed, 102 insertions, 7 deletions
diff --git a/lib/hsts.c b/lib/hsts.c
index 7eb3cda03..53b6d202b 100644
--- a/lib/hsts.c
+++ b/lib/hsts.c
@@ -262,6 +262,37 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
}
/*
+ * Send this HSTS entry to the write callback.
+ */
+static CURLcode hsts_push(struct Curl_easy *data,
+ struct curl_index *i,
+ struct stsentry *sts,
+ bool *stop)
+{
+ struct curl_hstsentry e;
+ CURLSTScode sc;
+ struct tm stamp;
+ CURLcode result;
+
+ e.name = (char *)sts->host;
+ e.namelen = strlen(sts->host);
+ e.includeSubDomains = sts->includeSubDomains;
+
+ result = Curl_gmtime(sts->expires, &stamp);
+ if(result)
+ return result;
+
+ msnprintf(e.expire, sizeof(e.expire), "%d%02d%02d %02d:%02d:%02d",
+ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+
+ sc = data->set.hsts_write(data, &e, i,
+ data->set.hsts_write_userp);
+ *stop = (sc != CURLSTS_OK);
+ return sc == CURLSTS_FAIL ? CURLE_BAD_FUNCTION_ARGUMENT : CURLE_OK;
+}
+
+/*
* Write this single hsts entry to a single output line
*/
static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
@@ -280,7 +311,7 @@ static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
/*
- * Curl_https_save() writes the HSTS cache to a file.
+ * Curl_https_save() writes the HSTS cache to file and callback.
*/
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
const char *file)
@@ -302,7 +333,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
if((h->flags & CURLHSTS_READONLYFILE) || !file || !file[0])
/* marked as read-only, no file or zero length file name */
- return CURLE_OK;
+ goto skipsave;
if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
return CURLE_FAILED_INIT;
@@ -333,6 +364,22 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
unlink(tempstore);
}
free(tempstore);
+ skipsave:
+ if(data->set.hsts_write) {
+ /* if there's a write callback */
+ struct curl_index i; /* count */
+ i.total = h->list.size;
+ i.index = 0;
+ for(e = h->list.head; e; e = n) {
+ struct stsentry *sts = e->ptr;
+ bool stop;
+ n = e->next;
+ result = hsts_push(data, &i, sts, &stop);
+ if(result || stop)
+ break;
+ i.index++;
+ }
+ }
return result;
}
@@ -368,6 +415,46 @@ static CURLcode hsts_add(struct hsts *h, char *line)
}
/*
+ * Load HSTS data from callback.
+ *
+ */
+static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
+{
+ /* if the HSTS read callback is set, use it */
+ if(data->set.hsts_read) {
+ CURLSTScode sc;
+ DEBUGASSERT(h);
+ do {
+ char buffer[257];
+ struct curl_hstsentry e;
+ e.name = buffer;
+ e.namelen = sizeof(buffer)-1;
+ e.includeSubDomains = FALSE; /* default */
+ e.expire[0] = 0;
+ e.name[0] = 0; /* just to make it clean */
+ sc = data->set.hsts_read(data, &e, data->set.hsts_read_userp);
+ if(sc == CURLSTS_OK) {
+ time_t expires;
+ CURLcode result;
+ if(!e.name[0])
+ /* bail out if no name was stored */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ if(e.expire[0])
+ expires = Curl_getdate_capped(e.expire);
+ else
+ expires = TIME_T_MAX; /* the end of time */
+ result = hsts_create(h, e.name, e.includeSubDomains, expires);
+ if(result)
+ return result;
+ }
+ else if(sc == CURLSTS_FAIL)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ } while(sc == CURLSTS_OK);
+ }
+ return CURLE_OK;
+}
+
+/*
* Load the HSTS cache from the given file. The text based line-oriented file
* format is documented here:
* https://github.com/curl/curl/wiki/HSTS
@@ -417,14 +504,22 @@ static CURLcode hsts_load(struct hsts *h, const char *file)
}
/*
- * Curl_hsts_load() loads HSTS from file.
+ * Curl_hsts_loadfile() loads HSTS from file
*/
-CURLcode Curl_hsts_load(struct hsts *h, const char *file)
+CURLcode Curl_hsts_loadfile(struct Curl_easy *data,
+ struct hsts *h, const char *file)
{
- CURLcode result;
DEBUGASSERT(h);
- result = hsts_load(h, file);
- return result;
+ (void)data;
+ return hsts_load(h, file);
+}
+
+/*
+ * Curl_hsts_loadcb() loads HSTS from callback
+ */
+CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h)
+{
+ return hsts_pull(data, h);
}
#endif /* CURL_DISABLE_HTTP || USE_HSTS */