hsts: add read/write callbacks

- read/write callback options
- man pages for the 4 new setopts
- test 1915 verifies the callbacks

Closes #5896
上级 7385610d
......@@ -192,7 +192,7 @@ jobs:
- libbrotli-dev
- libzstd-dev
- env:
- T=debug C="--disable-alt-svc"
- T=debug C="--enable-hsts --disable-alt-svc"
- *clang
compiler: clang
addons:
......
......@@ -323,6 +323,14 @@ Enable and configure Alt-Svc: treatment. See \fICURLOPT_ALTSVC_CTRL(3)\fP
Set HSTS cache file. See \fICURLOPT_HSTS(3)\fP
.IP CURLOPT_HSTS_CTRL
Enable HSTS. See \fICURLOPT_HSTS_CTRL(3)\fP
.IP CURLOPT_HSTSREADFUNCTION
Set HSTS read callback. See \fICURLOPT_HSTSREADFUNCTION(3)\fP
.IP CURLOPT_HSTSREADDATA
Pass pointer to the HSTS read callback. See \fICURLOPT_HSTSREADDATA(3)\fP
.IP CURLOPT_HSTSWRITEFUNCTION
Set HSTS write callback. See \fICURLOPT_HSTSWRITEFUNCTION(3)\fP
.IP CURLOPT_HSTSWRITEDATA
Pass pointer to the HSTS write callback. See \fICURLOPT_HSTSWRITEDATA(3)\fP
.IP CURLOPT_HTTPGET
Do an HTTP GET request. See \fICURLOPT_HTTPGET(3)\fP
.IP CURLOPT_REQUEST_TARGET
......
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADDATA 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_HSTSREADDATA \- pointer passed to the HSTS read callback
.SH SYNOPSIS
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADDATA, void *pointer);
.SH EXPERIMENTAL
Warning: this feature is early code and is marked as experimental. It can only
be enabled by explicitly telling configure with \fB--enable-hsts\fP. You are
advised to not ship this in production before the experimental label is
removed.
.SH DESCRIPTION
Data \fIpointer\fP to pass to the HSTS read function. If you use the
\fICURLOPT_HSTSREADFUNCTION(3)\fP option, this is the pointer you'll get as
input in the 3rd argument to the callback.
This option doesn't enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
do that.
.SH DEFAULT
NULL
.SH PROTOCOLS
This feature is only used for HTTP(S) transfer.
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
struct MyData this;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* pass pointer that gets passed in to the
CURLOPT_HSTSREADFUNCTION callback */
curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &this);
curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.74.0
.SH RETURN VALUE
This will return CURLE_OK.
.SH "SEE ALSO"
.BR CURLOPT_HSTSREADFUNCTION "(3), " CURLOPT_HSTSWRITEDATA "(3), "
.BR CURLOPT_HSTSWRITEFUNCTION "(3), "
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSREADFUNCTION 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_HSTSREADFUNCTION \- read callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>
CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *userp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADFUNCTION, hstsread);
.SH EXPERIMENTAL
Warning: this feature is early code and is marked as experimental. It can only
be enabled by explicitly telling configure with \fB--enable-hsts\fP. You are
advised to not ship this in production before the experimental label is
removed.
.SH DESCRIPTION
Pass a pointer to your callback function, as the prototype shows above.
This callback function gets called by libcurl repeatedly when it populates the
in-memory HSTS cache.
Set the \fIuserp\fP argument with the \fICURLOPT_HSTSREADDATA(3)\fP option or
it will be NULL.
When this callback is invoked, the \fIsts\fP pointer points to a populated
struct: Copy the host name to 'name' (no longer than 'namelen' bytes). Make it
null-terminated. Set 'includeSubDomains' to TRUE or FALSE. Set 'expire' to a
date stamp or a zero length string for *forever* (wrong date stamp format
might cause the name to not get accepted)
The callback should return \fICURLSTS_OK\fP if it returns a name and is
prepared to be called again (for another host) or \fICURLSTS_DONE\fP if it has
no entry to return. It can also return \fICURLSTS_FAIL\fP to signal error.
This option doesn't enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
do that.
.SH DEFAULT
NULL - no callback.
.SH PROTOCOLS
This feature is only used for HTTP(S) transfer.
.SH EXAMPLE
.nf
{
/* set HSTS read callback */
curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsread);
/* pass in suitable argument to the callback */
curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &hstspreload[0]);
result = curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.74.0
.SH RETURN VALUE
This will return CURLE_OK.
.SH "SEE ALSO"
.BR CURLOPT_HSTSREADDATA "(3), " CURLOPT_HSTSWRITEFUNCTION "(3), "
.BR CURLOPT_HSTS "(3), " CURLOPT_HSTS_CTRL "(3), "
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEDATA 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_HSTSWRITEDATA \- pointer passed to the HSTS write callback
.SH SYNOPSIS
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEDATA, void *pointer);
.SH EXPERIMENTAL
Warning: this feature is early code and is marked as experimental. It can only
be enabled by explicitly telling configure with \fB--enable-hsts\fP. You are
advised to not ship this in production before the experimental label is
removed.
.SH DESCRIPTION
Data \fIpointer\fP to pass to the HSTS write function. If you use the
\fICURLOPT_HSTSWRITEFUNCTION(3)\fP option, this is the pointer you'll get as
input in the 4th argument to the callback.
This option doesn't enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
do that.
.SH DEFAULT
NULL
.SH PROTOCOLS
This feature is only used for HTTP(S) transfer.
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
struct MyData this;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* pass pointer that gets passed in to the
CURLOPT_HSTSWRITEFUNCTION callback */
curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &this);
curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.74.0
.SH RETURN VALUE
This will return CURLE_OK.
.SH "SEE ALSO"
.BR CURLOPT_HSTSWRITEFUNCTION "(3), " CURLOPT_HSTSREADDATA "(3), "
.BR CURLOPT_HSTSREADFUNCTION "(3), "
.\" **************************************************************************
.\" * _ _ ____ _
.\" * Project ___| | | | _ \| |
.\" * / __| | | | |_) | |
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
.\" * are also available at https://curl.haxx.se/docs/copyright.html.
.\" *
.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
.\" * copies of the Software, and permit persons to whom the Software is
.\" * furnished to do so, under the terms of the COPYING file.
.\" *
.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
.\" * KIND, either express or implied.
.\" *
.\" **************************************************************************
.\"
.TH CURLOPT_HSTSWRITEFUNCTION 3 "14 Sep 2020" "libcurl 7.74.0" "curl_easy_setopt options"
.SH NAME
CURLOPT_HSTSWRITEFUNCTION \- write callback for HSTS hosts
.SH SYNOPSIS
#include <curl/curl.h>
CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *sts,
struct curl_index *count, void *userp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
.SH EXPERIMENTAL
Warning: this feature is early code and is marked as experimental. It can only
be enabled by explicitly telling configure with \fB--enable-hsts\fP. You are
advised to not ship this in production before the experimental label is
removed.
.SH DESCRIPTION
Pass a pointer to your callback function, as the prototype shows above.
This callback function gets called by libcurl repeatedly to allow the
application to store the in-memory HSTS cache when libcurl is about to discard
it.
Set the \fIuserp\fP argument with the \fICURLOPT_HSTSWRITEDATA(3)\fP option or
it will be NULL.
When the callback is invoked, the \fIsts\fP pointer points to a populated
struct: Read the host name to 'name' (it is 'namelen' bytes long and null
terminated. The 'includeSubDomains' field is non-zero if the entry matches
subdomains. The 'expire' string is a date stamp null-terminated string using
the syntax YYYYMMDD HH:MM:SS.
The callback should return \fICURLSTS_OK\fP if it succeeded and is prepared to
be called again (for another host) or \fICURLSTS_DONE\fP if there's nothing
more to do. It can also return \fICURLSTS_FAIL\fP to signal error.
.SH DEFAULT
NULL - no callback.
.SH PROTOCOLS
This feature is only used for HTTP(S) transfer.
.SH EXAMPLE
.nf
{
/* set HSTS read callback */
curl_easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
/* pass in suitable argument to the callback */
curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &hstspreload[0]);
result = curl_easy_perform(curl);
}
.fi
.SH AVAILABILITY
Added in 7.74.0
.SH RETURN VALUE
This will return CURLE_OK.
.SH "SEE ALSO"
.BR CURLOPT_HSTSWRITEDATA "(3), " CURLOPT_HSTSWRITEFUNCTION "(3), "
.BR CURLOPT_HSTS "(3), " CURLOPT_HSTS_CTRL "(3), "
......@@ -67,6 +67,9 @@ transfer to become paused. See \fIcurl_easy_pause(3)\fP for further details.
Set this option to NULL to get the internal default function used instead of
your callback. The internal default function will write the data to the FILE *
given with \fICURLOPT_WRITEDATA(3)\fP.
This option doesn't enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
do that.
.SH DEFAULT
libcurl will use 'fwrite' as a callback by default.
.SH PROTOCOLS
......
......@@ -181,6 +181,10 @@ man_MANS = \
CURLOPT_HEADERFUNCTION.3 \
CURLOPT_HEADEROPT.3 \
CURLOPT_HSTS.3 \
CURLOPT_HSTSREADDATA.3 \
CURLOPT_HSTSREADFUNCTION.3 \
CURLOPT_HSTSWRITEDATA.3 \
CURLOPT_HSTSWRITEFUNCTION.3 \
CURLOPT_HSTS_CTRL.3 \
CURLOPT_HTTP09_ALLOWED.3 \
CURLOPT_HTTP200ALIASES.3 \
......
......@@ -447,6 +447,10 @@ CURLOPT_HEADERFUNCTION 7.7.2
CURLOPT_HEADEROPT 7.37.0
CURLOPT_HSTS 7.74.0
CURLOPT_HSTS_CTRL 7.74.0
CURLOPT_HSTSREADDATA 7.74.0
CURLOPT_HSTSREADFUNCTION 7.74.0
CURLOPT_HSTSWRITEDATA 7.74.0
CURLOPT_HSTSWRITEFUNCTION 7.74.0
CURLOPT_HTTP09_ALLOWED 7.64.0
CURLOPT_HTTP200ALIASES 7.10.3
CURLOPT_HTTPAUTH 7.10.6
......@@ -812,6 +816,9 @@ CURLSSLSET_NO_BACKENDS 7.56.0
CURLSSLSET_OK 7.56.0
CURLSSLSET_TOO_LATE 7.56.0
CURLSSLSET_UNKNOWN_BACKEND 7.56.0
CURLSTS_DONE 7.74.0
CURLSTS_FAIL 7.74.0
CURLSTS_OK 7.74.0
CURLUE_BAD_HANDLE 7.62.0
CURLUE_BAD_PARTPOINTER 7.62.0
CURLUE_BAD_PORT_NUMBER 7.62.0
......
......@@ -954,6 +954,33 @@ typedef enum {
#define CURLALTSVC_H2 (1<<4)
#define CURLALTSVC_H3 (1<<5)
struct curl_hstsentry {
char *name;
size_t namelen;
unsigned int includeSubDomains:1;
char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
};
struct curl_index {
size_t index; /* the provided entry's "index" or count */
size_t total; /* total number of entries to save */
};
typedef enum {
CURLSTS_OK,
CURLSTS_DONE,
CURLSTS_FAIL
} CURLSTScode;
typedef CURLSTScode (*curl_hstsread_callback)(CURL *easy,
struct curl_hstsentry *e,
void *userp);
typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
struct curl_hstsentry *e,
struct curl_index *i,
void *userp);
/* CURLHSTS_* are bits for the CURLOPT_HSTS option */
#define CURLHSTS_ENABLE (long)(1<<0)
#define CURLHSTS_READONLYFILE (long)(1<<1)
......@@ -2038,6 +2065,14 @@ typedef enum {
/* HSTS file name */
CURLOPT(CURLOPT_HSTS, CURLOPTTYPE_STRINGPOINT, 300),
/* HSTS read callback */
CURLOPT(CURLOPT_HSTSREADFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 301),
CURLOPT(CURLOPT_HSTSREADDATA, CURLOPTTYPE_CBPOINT, 302),
/* HSTS write callback */
CURLOPT(CURLOPT_HSTSWRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 303),
CURLOPT(CURLOPT_HSTSWRITEDATA, CURLOPTTYPE_CBPOINT, 304),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
......
......@@ -273,6 +273,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_HSTS || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
......@@ -356,6 +357,8 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
(option) == CURLOPT_HSTSREADDATA || \
(option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
......
......@@ -22,7 +22,7 @@
#include "curl_setup.h"
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC)) || \
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \
defined(USE_HSTS)
#include "curl_get_line.h"
......
......@@ -888,7 +888,9 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
if(!outcurl->hsts)
goto fail;
if(outcurl->set.str[STRING_HSTS])
(void)Curl_hsts_load(outcurl->hsts, outcurl->set.str[STRING_HSTS]);
(void)Curl_hsts_loadfile(outcurl,
outcurl->hsts, outcurl->set.str[STRING_HSTS]);
(void)Curl_hsts_loadcb(outcurl, outcurl->hsts);
}
#endif
/* Clone the resolver handle, if present, for the new handle */
......
......@@ -116,6 +116,10 @@ struct curl_easyoption Curl_easyopts[] = {
{"HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0},
{"HEADEROPT", CURLOPT_HEADEROPT, CURLOT_VALUES, 0},
{"HSTS", CURLOPT_HSTS, CURLOT_STRING, 0},
{"HSTSREADDATA", CURLOPT_HSTSREADDATA, CURLOT_CBPTR, 0},
{"HSTSREADFUNCTION", CURLOPT_HSTSREADFUNCTION, CURLOT_FUNCTION, 0},
{"HSTSWRITEDATA", CURLOPT_HSTSWRITEDATA, CURLOT_CBPTR, 0},
{"HSTSWRITEFUNCTION", CURLOPT_HSTSWRITEFUNCTION, CURLOT_FUNCTION, 0},
{"HSTS_CTRL", CURLOPT_HSTS_CTRL, CURLOT_LONG, 0},
{"HTTP09_ALLOWED", CURLOPT_HTTP09_ALLOWED, CURLOT_LONG, 0},
{"HTTP200ALIASES", CURLOPT_HTTP200ALIASES, CURLOT_SLIST, 0},
......@@ -344,6 +348,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
return (CURLOPT_LASTENTRY != (300 + 1));
return (CURLOPT_LASTENTRY != (304 + 1));
}
#endif
......@@ -261,6 +261,37 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
return NULL; /* no match */
}
/*
* 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
*/
......@@ -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;
}
......@@ -367,6 +414,46 @@ static CURLcode hsts_add(struct hsts *h, char *line)
return CURLE_OK;
}
/*
* 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:
......@@ -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 */
......@@ -53,8 +53,13 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
bool subdomain);
CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
const char *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 Curl_hsts_loadcb(struct Curl_easy *data,
struct hsts *h);
#else
#define Curl_hsts_cleanup(x)
#define Curl_hsts_loadcb(x,y)
#define Curl_hsts_save(x,y,z)
#endif /* CURL_DISABLE_HTTP || USE_HSTS */
#endif /* HEADER_CURL_HSTS_H */
......@@ -2841,6 +2841,18 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#endif
break;
#ifdef USE_HSTS
case CURLOPT_HSTSREADFUNCTION:
data->set.hsts_read = va_arg(param, curl_hstsread_callback);
break;