328 lines
10 KiB
Diff
328 lines
10 KiB
Diff
|
|
From 076a2f629119222aeeb50f5a03bf9f9052fabb9a Mon Sep 17 00:00:00 2001
|
||
|
|
From: Daniel Stenberg <daniel@haxx.se>
|
||
|
|
Date: Tue, 27 Dec 2022 11:50:20 +0100
|
||
|
|
Subject: [PATCH] share: add sharing of HSTS cache among handles
|
||
|
|
|
||
|
|
Closes #10138
|
||
|
|
|
||
|
|
Conflict: Context adaptation
|
||
|
|
Reference: https://github.com/curl/curl/commit/076a2f629119222aeeb50f5a03bf9f9052fabb9a
|
||
|
|
---
|
||
|
|
docs/libcurl/opts/CURLSHOPT_SHARE.3 | 4 +++
|
||
|
|
docs/libcurl/symbols-in-versions | 1 +
|
||
|
|
include/curl/curl.h | 1 +
|
||
|
|
lib/hsts.c | 15 +++++++++
|
||
|
|
lib/hsts.h | 2 ++
|
||
|
|
lib/setopt.c | 48 ++++++++++++++++++++++++-----
|
||
|
|
lib/share.c | 32 +++++++++++++++++--
|
||
|
|
lib/share.h | 6 +++-
|
||
|
|
lib/transfer.c | 3 ++
|
||
|
|
lib/url.c | 6 +++-
|
||
|
|
lib/urldata.h | 2 ++
|
||
|
|
11 files changed, 109 insertions(+), 11 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/docs/libcurl/opts/CURLSHOPT_SHARE.3 b/docs/libcurl/opts/CURLSHOPT_SHARE.3
|
||
|
|
index b30cc0f..e7663d1 100644
|
||
|
|
--- a/docs/libcurl/opts/CURLSHOPT_SHARE.3
|
||
|
|
+++ b/docs/libcurl/opts/CURLSHOPT_SHARE.3
|
||
|
|
@@ -79,6 +79,10 @@ Added in 7.61.0.
|
||
|
|
|
||
|
|
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
|
||
|
|
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
|
||
|
|
index d809940..9558319 100644
|
||
|
|
--- a/docs/libcurl/symbols-in-versions
|
||
|
|
+++ b/docs/libcurl/symbols-in-versions
|
||
|
|
@@ -71,6 +71,7 @@ CURL_LOCK_ACCESS_SINGLE 7.10.3
|
||
|
|
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
|
||
|
|
diff --git a/include/curl/curl.h b/include/curl/curl.h
|
||
|
|
index e28dd0b..0c50ed7 100644
|
||
|
|
--- a/include/curl/curl.h
|
||
|
|
+++ b/include/curl/curl.h
|
||
|
|
@@ -2885,6 +2885,7 @@ typedef enum {
|
||
|
|
CURL_LOCK_DATA_SSL_SESSION,
|
||
|
|
CURL_LOCK_DATA_CONNECT,
|
||
|
|
CURL_LOCK_DATA_PSL,
|
||
|
|
+ CURL_LOCK_DATA_HSTS,
|
||
|
|
CURL_LOCK_DATA_LAST
|
||
|
|
} curl_lock_data;
|
||
|
|
|
||
|
|
diff --git a/lib/hsts.c b/lib/hsts.c
|
||
|
|
index e3b686e..628d03e 100644
|
||
|
|
--- a/lib/hsts.c
|
||
|
|
+++ b/lib/hsts.c
|
||
|
|
@@ -39,6 +39,7 @@
|
||
|
|
#include "parsedate.h"
|
||
|
|
#include "fopen.h"
|
||
|
|
#include "rename.h"
|
||
|
|
+#include "share.h"
|
||
|
|
#include "strtoofft.h"
|
||
|
|
|
||
|
|
/* The last 3 #include files should be in this order */
|
||
|
|
@@ -552,4 +553,18 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *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 */
|
||
|
|
diff --git a/lib/hsts.h b/lib/hsts.h
|
||
|
|
index 0e36a77..3da7574 100644
|
||
|
|
--- a/lib/hsts.h
|
||
|
|
+++ b/lib/hsts.h
|
||
|
|
@@ -59,9 +59,11 @@ 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);
|
||
|
|
+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 */
|
||
|
|
diff --git a/lib/setopt.c b/lib/setopt.c
|
||
|
|
index 5b59754..f7029be 100644
|
||
|
|
--- a/lib/setopt.c
|
||
|
|
+++ b/lib/setopt.c
|
||
|
|
@@ -2251,9 +2251,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||
|
|
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;
|
||
|
|
@@ -2287,10 +2292,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||
|
|
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;
|
||
|
|
@@ -3040,19 +3054,39 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
||
|
|
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) {
|
||
|
|
diff --git a/lib/share.c b/lib/share.c
|
||
|
|
index 1a083e7..69ee00b 100644
|
||
|
|
--- a/lib/share.c
|
||
|
|
+++ b/lib/share.c
|
||
|
|
@@ -29,9 +29,11 @@
|
||
|
|
#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 *
|
||
|
|
@@ -89,6 +91,18 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
|
||
|
|
#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) {
|
||
|
|
@@ -141,6 +155,16 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
|
||
|
|
#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);
|
||
|
|
@@ -207,6 +231,10 @@ curl_share_cleanup(struct Curl_share *share)
|
||
|
|
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;
|
||
|
|
diff --git a/lib/share.h b/lib/share.h
|
||
|
|
index 32be416..2449730 100644
|
||
|
|
--- a/lib/share.h
|
||
|
|
+++ b/lib/share.h
|
||
|
|
@@ -59,10 +59,14 @@ struct Curl_share {
|
||
|
|
#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,
|
||
|
|
diff --git a/lib/transfer.c b/lib/transfer.c
|
||
|
|
index 441da73..4ab72f4 100644
|
||
|
|
--- a/lib/transfer.c
|
||
|
|
+++ b/lib/transfer.c
|
||
|
|
@@ -1470,6 +1470,9 @@ CURLcode Curl_pretransfer(struct Curl_easy *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
|
||
|
|
diff --git a/lib/url.c b/lib/url.c
|
||
|
|
index be5ffca..45cc596 100644
|
||
|
|
--- a/lib/url.c
|
||
|
|
+++ b/lib/url.c
|
||
|
|
@@ -445,7 +445,11 @@ CURLcode Curl_close(struct Curl_easy **datap)
|
||
|
|
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
|
||
|
|
diff --git a/lib/urldata.h b/lib/urldata.h
|
||
|
|
index 1d430b5..8246ee8 100644
|
||
|
|
--- a/lib/urldata.h
|
||
|
|
+++ b/lib/urldata.h
|
||
|
|
@@ -1700,6 +1700,8 @@ struct UserDefined {
|
||
|
|
|
||
|
|
void *seek_client; /* pointer to pass to the seek callback */
|
||
|
|
#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;
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|