Note that when you use the multi interface, all easy handles added to the same
multi handle will share PSL cache by default without using this option.
+.IP CURL_LOCK_DATA_HSTS
+The in-memory HSTS cache.
+
+Added in 7.88.0
.SH PROTOCOLS
All
.SH EXAMPLE
CURL_LOCK_DATA_CONNECT 7.10.3
CURL_LOCK_DATA_COOKIE 7.10.3
CURL_LOCK_DATA_DNS 7.10.3
+CURL_LOCK_DATA_HSTS 7.88.0
CURL_LOCK_DATA_NONE 7.10.3
CURL_LOCK_DATA_PSL 7.61.0
CURL_LOCK_DATA_SHARE 7.10.4
CURL_LOCK_DATA_SSL_SESSION,
CURL_LOCK_DATA_CONNECT,
CURL_LOCK_DATA_PSL,
+ CURL_LOCK_DATA_HSTS,
CURL_LOCK_DATA_LAST
} curl_lock_data;
#include "parsedate.h"
#include "fopen.h"
#include "rename.h"
+#include "share.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
return CURLE_OK;
}
+void Curl_hsts_loadfiles(struct Curl_easy *data)
+{
+ struct curl_slist *l = data->set.hstslist;
+ if(l) {
+ Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE);
+
+ while(l) {
+ (void)Curl_hsts_loadfile(data, data->hsts, l->data);
+ l = l->next;
+ }
+ Curl_share_unlock(data, CURL_LOCK_DATA_HSTS);
+ }
+}
+
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
struct hsts *h, const char *file);
CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
struct hsts *h);
+void Curl_hsts_loadfiles(struct Curl_easy *data);
#else
#define Curl_hsts_cleanup(x)
#define Curl_hsts_loadcb(x,y) CURLE_OK
#define Curl_hsts_save(x,y,z)
+#define Curl_hsts_loadfiles(x)
#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
#endif /* HEADER_CURL_HSTS_H */
data->cookies = NULL;
#endif
+#ifndef CURL_DISABLE_HSTS
+ if(data->share->hsts == data->hsts)
+ data->hsts = NULL;
+#endif
+#ifdef USE_SSL
if(data->share->sslsession == data->state.session)
data->state.session = NULL;
-
+#endif
#ifdef USE_LIBPSL
if(data->psl == &data->share->psl)
data->psl = data->multi? &data->multi->psl: NULL;
data->cookies = data->share->cookies;
}
#endif /* CURL_DISABLE_HTTP */
+#ifndef CURL_DISABLE_HSTS
+ if(data->share->hsts) {
+ /* first free the private one if any */
+ Curl_hsts_cleanup(&data->hsts);
+ data->hsts = data->share->hsts;
+ }
+#endif /* CURL_DISABLE_HTTP */
+#ifdef USE_SSL
if(data->share->sslsession) {
data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
data->state.session = data->share->sslsession;
}
+#endif
#ifdef USE_LIBPSL
if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
data->psl = &data->share->psl;
case CURLOPT_HSTSWRITEDATA:
data->set.hsts_write_userp = va_arg(param, void *);
break;
- case CURLOPT_HSTS:
+ case CURLOPT_HSTS: {
+ struct curl_slist *h;
if(!data->hsts) {
data->hsts = Curl_hsts_init();
if(!data->hsts)
return CURLE_OUT_OF_MEMORY;
}
argptr = va_arg(param, char *);
- result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
- if(result)
- return result;
- if(argptr)
- (void)Curl_hsts_loadfile(data, data->hsts, argptr);
+ if(argptr) {
+ result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr);
+ if(result)
+ return result;
+ /* this needs to build a list of file names to read from, so that it can
+ read them later, as we might get a shared HSTS handle to load them
+ into */
+ h = curl_slist_append(data->set.hstslist, argptr);
+ if(!h) {
+ curl_slist_free_all(data->set.hstslist);
+ data->set.hstslist = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ data->set.hstslist = h; /* store the list for later use */
+ }
+ else {
+ /* clear the list of HSTS files */
+ curl_slist_free_all(data->set.hstslist);
+ data->set.hstslist = NULL;
+ if(!data->share || !data->share->hsts)
+ /* throw away the HSTS cache unless shared */
+ Curl_hsts_cleanup(&data->hsts);
+ }
break;
+ }
case CURLOPT_HSTS_CTRL:
arg = va_arg(param, long);
if(arg & CURLHSTS_ENABLE) {
#include "share.h"
#include "psl.h"
#include "vtls/vtls.h"
-#include "curl_memory.h"
+#include "hsts.h"
-/* The last #include file should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
#include "memdebug.h"
struct Curl_share *
#endif
break;
+ case CURL_LOCK_DATA_HSTS:
+#ifndef CURL_DISABLE_HSTS
+ if(!share->hsts) {
+ share->hsts = Curl_hsts_init();
+ if(!share->hsts)
+ res = CURLSHE_NOMEM;
+ }
+#else /* CURL_DISABLE_HSTS */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
if(!share->sslsession) {
#endif
break;
+ case CURL_LOCK_DATA_HSTS:
+#ifndef CURL_DISABLE_HSTS
+ if(share->hsts) {
+ Curl_hsts_cleanup(&share->hsts);
+ }
+#else /* CURL_DISABLE_HSTS */
+ res = CURLSHE_NOT_BUILT_IN;
+#endif
+ break;
+
case CURL_LOCK_DATA_SSL_SESSION:
#ifdef USE_SSL
Curl_safefree(share->sslsession);
Curl_cookie_cleanup(share->cookies);
#endif
+#ifndef CURL_DISABLE_HSTS
+ Curl_hsts_cleanup(&share->hsts);
+#endif
+
#ifdef USE_SSL
if(share->sslsession) {
size_t i;
#ifdef USE_LIBPSL
struct PslCache psl;
#endif
-
+#ifndef CURL_DISABLE_HSTS
+ struct hsts *hsts;
+#endif
+#ifdef USE_SSL
struct Curl_ssl_session *sslsession;
size_t max_ssl_sessions;
long sessionage;
+#endif
};
CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
if(data->state.resolve)
result = Curl_loadhostpairs(data);
+ /* If there is a list of hsts files to read */
+ Curl_hsts_loadfiles(data);
+
if(!result) {
/* Allow data->set.use_port to set which port to use. This needs to be
* disabled for example when we follow Location: headers to URLs using
Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
Curl_altsvc_cleanup(&data->asi);
Curl_hsts_save(data, data->hsts, data->set.str[STRING_HSTS]);
- Curl_hsts_cleanup(&data->hsts);
+#ifndef CURL_DISABLE_HSTS
+ if(!data->share || !data->share->hsts)
+ Curl_hsts_cleanup(&data->hsts);
+ curl_slist_free_all(data->set.hstslist); /* clean up list */
+#endif
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
curl_easy_setopt(COOKIEFILE) calls */
#endif
#ifndef CURL_DISABLE_HSTS
+ struct curl_slist *hstslist; /* list of HSTS files set by
+ curl_easy_setopt(HSTS) calls */
curl_hstsread_callback hsts_read;
void *hsts_read_userp;
curl_hstswrite_callback hsts_write;