summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vtls/vtls_scache.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/vtls/vtls_scache.c')
-rw-r--r--libs/libcurl/src/vtls/vtls_scache.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/libs/libcurl/src/vtls/vtls_scache.c b/libs/libcurl/src/vtls/vtls_scache.c
index c78ef7e9a8..d06c6cf9f9 100644
--- a/libs/libcurl/src/vtls/vtls_scache.c
+++ b/libs/libcurl/src/vtls/vtls_scache.c
@@ -59,6 +59,9 @@
#include "curl_memory.h"
#include "memdebug.h"
+
+static bool cf_ssl_peer_key_is_global(const char *peer_key);
+
/* a peer+tls-config we cache sessions for */
struct Curl_ssl_scache_peer {
char *ssl_peer_key; /* id for peer + relevant TLS configuration */
@@ -73,6 +76,7 @@ struct Curl_ssl_scache_peer {
size_t max_sessions;
long age; /* just a number, the higher the more recent */
BIT(hmac_set); /* if key_salt and key_hmac are present */
+ BIT(exportable); /* sessions for this peer can be exported */
};
#define CURL_SCACHE_MAGIC 0x000e1551
@@ -104,32 +108,18 @@ static struct Curl_ssl_scache *cf_ssl_scache_get(struct Curl_easy *data)
return scache;
}
-static void cf_ssl_scache_clear_session(struct Curl_ssl_session *s)
-{
- if(s->sdata) {
- free((void *)s->sdata);
- s->sdata = NULL;
- }
- s->sdata_len = 0;
- if(s->quic_tp) {
- free((void *)s->quic_tp);
- s->quic_tp = NULL;
- }
- s->quic_tp_len = 0;
- s->ietf_tls_id = 0;
- s->valid_until = 0;
- Curl_safefree(s->alpn);
-}
-
-static void cf_ssl_scache_sesssion_ldestroy(void *udata, void *s)
+static void cf_ssl_scache_sesssion_ldestroy(void *udata, void *obj)
{
+ struct Curl_ssl_session *s = obj;
(void)udata;
- cf_ssl_scache_clear_session(s);
+ free(CURL_UNCONST(s->sdata));
+ free(CURL_UNCONST(s->quic_tp));
+ free((void *)s->alpn);
free(s);
}
CURLcode
-Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len,
+Curl_ssl_session_create(void *sdata, size_t sdata_len,
int ietf_tls_id, const char *alpn,
curl_off_t valid_until, size_t earlydata_max,
struct Curl_ssl_session **psession)
@@ -140,7 +130,7 @@ Curl_ssl_session_create(unsigned char *sdata, size_t sdata_len,
}
CURLcode
-Curl_ssl_session_create2(unsigned char *sdata, size_t sdata_len,
+Curl_ssl_session_create2(void *sdata, size_t sdata_len,
int ietf_tls_id, const char *alpn,
curl_off_t valid_until, size_t earlydata_max,
unsigned char *quic_tp, size_t quic_tp_len,
@@ -223,6 +213,19 @@ static void cf_ssl_scache_peer_set_obj(struct Curl_ssl_scache_peer *peer,
peer->sobj_free = sobj_free;
}
+static void cf_ssl_cache_peer_update(struct Curl_ssl_scache_peer *peer)
+{
+ /* The sessions of this peer are exportable if
+ * - it has no confidential information
+ * - its peer key is not yet known, because sessions were
+ * imported using only the salt+hmac
+ * - the peer key is global, e.g. carrying no relative paths */
+ peer->exportable = (!peer->clientcert && !peer->srp_username &&
+ !peer->srp_password &&
+ (!peer->ssl_peer_key ||
+ cf_ssl_peer_key_is_global(peer->ssl_peer_key)));
+}
+
static CURLcode
cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer,
const char *ssl_peer_key,
@@ -265,6 +268,8 @@ cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer,
if(!peer->srp_password)
goto out;
}
+
+ cf_ssl_cache_peer_update(peer);
result = CURLE_OK;
out:
if(result)
@@ -372,17 +377,22 @@ void Curl_ssl_scache_unlock(struct Curl_easy *data)
static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
const char *name,
- char *path)
+ char *path,
+ bool *is_local)
{
if(path && path[0]) {
/* We try to add absolute paths, so that the session key can stay
* valid when used in another process with different CWD. However,
* when a path does not exist, this does not work. Then, we add
* the path as is. */
-#ifdef _WIN32
+#ifdef UNDER_CE
+ (void)is_local;
+ return Curl_dyn_addf(buf, ":%s-%s", name, path);
+#elif defined(_WIN32)
char abspath[_MAX_PATH];
if(_fullpath(abspath, path, _MAX_PATH))
return Curl_dyn_addf(buf, ":%s-%s", name, abspath);
+ *is_local = TRUE;
#elif defined(HAVE_REALPATH)
if(path[0] != '/') {
char *abspath = realpath(path, NULL);
@@ -391,6 +401,7 @@ static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf,
(free)(abspath); /* allocated by libc, free without memdebug */
return r;
}
+ *is_local = TRUE;
}
#endif
return Curl_dyn_addf(buf, ":%s-%s", name, path);
@@ -423,6 +434,17 @@ out:
return r;
}
+#define CURL_SSLS_LOCAL_SUFFIX ":L"
+#define CURL_SSLS_GLOBAL_SUFFIX ":G"
+
+static bool cf_ssl_peer_key_is_global(const char *peer_key)
+{
+ size_t len = peer_key ? strlen(peer_key) : 0;
+ return (len > 2) &&
+ (peer_key[len - 1] == 'G') &&
+ (peer_key[len - 2] == ':');
+}
+
CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
const struct ssl_peer *peer,
const char *tls_id,
@@ -431,6 +453,7 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
struct ssl_primary_config *ssl = Curl_ssl_cf_get_primary_config(cf);
struct dynbuf buf;
size_t key_len;
+ bool is_local = FALSE;
CURLcode r;
*ppeer_key = NULL;
@@ -514,16 +537,16 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
goto out;
}
if(ssl->verifypeer) {
- r = cf_ssl_peer_key_add_path(&buf, "CA", ssl->CAfile);
+ r = cf_ssl_peer_key_add_path(&buf, "CA", ssl->CAfile, &is_local);
if(r)
goto out;
- r = cf_ssl_peer_key_add_path(&buf, "CApath", ssl->CApath);
+ r = cf_ssl_peer_key_add_path(&buf, "CApath", ssl->CApath, &is_local);
if(r)
goto out;
- r = cf_ssl_peer_key_add_path(&buf, "CRL", ssl->CRLfile);
+ r = cf_ssl_peer_key_add_path(&buf, "CRL", ssl->CRLfile, &is_local);
if(r)
goto out;
- r = cf_ssl_peer_key_add_path(&buf, "Issuer", ssl->issuercert);
+ r = cf_ssl_peer_key_add_path(&buf, "Issuer", ssl->issuercert, &is_local);
if(r)
goto out;
if(ssl->cert_blob) {
@@ -569,6 +592,11 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf,
if(r)
goto out;
+ r = Curl_dyn_addf(&buf, is_local ?
+ CURL_SSLS_LOCAL_SUFFIX : CURL_SSLS_GLOBAL_SUFFIX);
+ if(r)
+ goto out;
+
*ppeer_key = Curl_dyn_take(&buf, &key_len);
/* we just added printable char, and dynbuf always 0 terminates,
* no need to track length */
@@ -655,6 +683,7 @@ cf_ssl_find_peer_by_key(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+ cf_ssl_cache_peer_update(&scache->peers[i]);
*ppeer = &scache->peers[i];
goto out;
}
@@ -832,10 +861,6 @@ CURLcode Curl_ssl_scache_put(struct Curl_cfilter *cf,
Curl_ssl_session_destroy(s);
return CURLE_OK;
}
- if(!GOOD_SCACHE(scache)) {
- Curl_ssl_session_destroy(s);
- return CURLE_BAD_FUNCTION_ARGUMENT;
- }
Curl_ssl_scache_lock(data);
result = cf_scache_add_session(cf, data, scache, ssl_peer_key, s);
@@ -933,31 +958,29 @@ out:
return result;
}
-bool Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const char *ssl_peer_key,
- void **sobj)
+void *Curl_ssl_scache_get_obj(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const char *ssl_peer_key)
{
struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_ssl_scache_peer *peer = NULL;
CURLcode result;
+ void *sobj;
- *sobj = NULL;
if(!scache)
- return FALSE;
+ return NULL;
result = cf_ssl_find_peer_by_key(data, scache, ssl_peer_key, conn_config,
&peer);
if(result)
- return FALSE;
+ return NULL;
- if(peer)
- *sobj = peer->sobj;
+ sobj = peer ? peer->sobj : NULL;
CURL_TRC_SSLS(data, "%s cached session for '%s'",
- *sobj ? "Found" : "No", ssl_peer_key);
- return !!*sobj;
+ sobj ? "Found" : "No", ssl_peer_key);
+ return sobj;
}
void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf,
@@ -1062,7 +1085,7 @@ out:
CURLcode Curl_ssl_session_import(struct Curl_easy *data,
const char *ssl_peer_key,
const unsigned char *shmac, size_t shmac_len,
- const unsigned char *sdata, size_t sdata_len)
+ const void *sdata, size_t sdata_len)
{
struct Curl_ssl_scache *scache = cf_ssl_scache_get(data);
struct Curl_ssl_scache_peer *peer = NULL;
@@ -1157,8 +1180,8 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data,
peer = &scache->peers[i];
if(!peer->ssl_peer_key && !peer->hmac_set)
continue; /* skip free entry */
- if(peer->clientcert || peer->srp_username || peer->srp_password)
- continue; /* not exporting those */
+ if(!peer->exportable)
+ continue;
Curl_dyn_reset(&hbuf);
cf_scache_peer_remove_expired(peer, now);