mirror of
https://github.com/curl/curl.git
synced 2026-04-15 00:41:41 +03:00
multi: add multi->proto_hash, a key-value store for protocol data
- add `Curl_hash_add2()` that passes a destructor function for the element added. Call element destructor instead of hash destructor if present. - multi: add `proto_hash` for protocol related information, remove `struct multi_ssl_backend_data`. - openssl: use multi->proto_hash to keep x509 shared store - schannel: use multi->proto_hash to keep x509 shared store - vtls: remove Curl_free_multi_ssl_backend_data() and its equivalents in the TLS backends Closes #13345
This commit is contained in:
parent
74e0bb1e7a
commit
e101a7a8b0
17 changed files with 191 additions and 132 deletions
37
lib/hash.c
37
lib/hash.c
|
|
@ -40,7 +40,10 @@ hash_element_dtor(void *user, void *element)
|
|||
struct Curl_hash_element *e = (struct Curl_hash_element *) element;
|
||||
|
||||
if(e->ptr) {
|
||||
h->dtor(e->ptr);
|
||||
if(e->dtor)
|
||||
e->dtor(e->key, e->key_len, e->ptr);
|
||||
else
|
||||
h->dtor(e->ptr);
|
||||
e->ptr = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +80,8 @@ Curl_hash_init(struct Curl_hash *h,
|
|||
}
|
||||
|
||||
static struct Curl_hash_element *
|
||||
mk_hash_element(const void *key, size_t key_len, const void *p)
|
||||
mk_hash_element(const void *key, size_t key_len, const void *p,
|
||||
Curl_hash_elem_dtor dtor)
|
||||
{
|
||||
/* allocate the struct plus memory after it to store the key */
|
||||
struct Curl_hash_element *he = malloc(sizeof(struct Curl_hash_element) +
|
||||
|
|
@ -87,22 +91,15 @@ mk_hash_element(const void *key, size_t key_len, const void *p)
|
|||
memcpy(he->key, key, key_len);
|
||||
he->key_len = key_len;
|
||||
he->ptr = (void *) p;
|
||||
he->dtor = dtor;
|
||||
}
|
||||
return he;
|
||||
}
|
||||
|
||||
#define FETCH_LIST(x,y,z) &x->table[x->hash_func(y, z, x->slots)]
|
||||
|
||||
/* Insert the data in the hash. If there already was a match in the hash, that
|
||||
* data is replaced. This function also "lazily" allocates the table if
|
||||
* needed, as it isn't done in the _init function (anymore).
|
||||
*
|
||||
* @unittest: 1305
|
||||
* @unittest: 1602
|
||||
* @unittest: 1603
|
||||
*/
|
||||
void *
|
||||
Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
||||
void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
Curl_hash_elem_dtor dtor)
|
||||
{
|
||||
struct Curl_hash_element *he;
|
||||
struct Curl_llist_element *le;
|
||||
|
|
@ -130,7 +127,7 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
|||
}
|
||||
}
|
||||
|
||||
he = mk_hash_element(key, key_len, p);
|
||||
he = mk_hash_element(key, key_len, p, dtor);
|
||||
if(he) {
|
||||
Curl_llist_append(l, he, &he->list);
|
||||
++h->size;
|
||||
|
|
@ -140,6 +137,20 @@ Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
|||
return NULL; /* failure */
|
||||
}
|
||||
|
||||
/* Insert the data in the hash. If there already was a match in the hash, that
|
||||
* data is replaced. This function also "lazily" allocates the table if
|
||||
* needed, as it isn't done in the _init function (anymore).
|
||||
*
|
||||
* @unittest: 1305
|
||||
* @unittest: 1602
|
||||
* @unittest: 1603
|
||||
*/
|
||||
void *
|
||||
Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p)
|
||||
{
|
||||
return Curl_hash_add2(h, key, key_len, p, NULL);
|
||||
}
|
||||
|
||||
/* Remove the identified hash entry.
|
||||
* Returns non-zero on failure.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -58,9 +58,12 @@ struct Curl_hash {
|
|||
size_t size;
|
||||
};
|
||||
|
||||
typedef void (*Curl_hash_elem_dtor)(void *key, size_t key_len, void *p);
|
||||
|
||||
struct Curl_hash_element {
|
||||
struct Curl_llist_element list;
|
||||
void *ptr;
|
||||
Curl_hash_elem_dtor dtor;
|
||||
size_t key_len;
|
||||
char key[1]; /* allocated memory following the struct */
|
||||
};
|
||||
|
|
@ -78,6 +81,8 @@ void Curl_hash_init(struct Curl_hash *h,
|
|||
Curl_hash_dtor dtor);
|
||||
|
||||
void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p);
|
||||
void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p,
|
||||
Curl_hash_elem_dtor dtor);
|
||||
int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len);
|
||||
void *Curl_hash_pick(struct Curl_hash *, void *key, size_t key_len);
|
||||
#define Curl_hash_count(h) ((h)->size)
|
||||
|
|
|
|||
20
lib/multi.c
20
lib/multi.c
|
|
@ -370,6 +370,17 @@ static void sh_init(struct Curl_hash *hash, size_t hashsize)
|
|||
sh_freeentry);
|
||||
}
|
||||
|
||||
/* multi->proto_hash destructor. Should never be called as elements
|
||||
* MUST be added with their own destructor */
|
||||
static void ph_freeentry(void *p)
|
||||
{
|
||||
(void)p;
|
||||
/* Will always be FALSE. Cannot use a 0 assert here since compilers
|
||||
* are not in agreement if they then want a NORETURN attribute or
|
||||
* not. *sigh* */
|
||||
DEBUGASSERT(p == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* multi_addmsg()
|
||||
*
|
||||
|
|
@ -396,6 +407,9 @@ struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
|
|||
|
||||
sh_init(&multi->sockhash, hashsize);
|
||||
|
||||
Curl_hash_init(&multi->proto_hash, 23,
|
||||
Curl_hash_str, Curl_str_key_compare, ph_freeentry);
|
||||
|
||||
if(Curl_conncache_init(&multi->conn_cache, chashsize))
|
||||
goto error;
|
||||
|
||||
|
|
@ -431,6 +445,7 @@ struct Curl_multi *Curl_multi_handle(size_t hashsize, /* socket hash */
|
|||
error:
|
||||
|
||||
sockhash_destroy(&multi->sockhash);
|
||||
Curl_hash_destroy(&multi->proto_hash);
|
||||
Curl_hash_destroy(&multi->hostcache);
|
||||
Curl_conncache_destroy(&multi->conn_cache);
|
||||
free(multi);
|
||||
|
|
@ -2856,6 +2871,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
|
|||
Curl_conncache_close_all_connections(&multi->conn_cache);
|
||||
|
||||
sockhash_destroy(&multi->sockhash);
|
||||
Curl_hash_destroy(&multi->proto_hash);
|
||||
Curl_conncache_destroy(&multi->conn_cache);
|
||||
Curl_hash_destroy(&multi->hostcache);
|
||||
Curl_psl_destroy(&multi->psl);
|
||||
|
|
@ -2869,10 +2885,6 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
|
||||
#endif
|
||||
|
||||
multi_xfer_bufs_free(multi);
|
||||
free(multi);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,10 +80,6 @@ typedef enum {
|
|||
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
|
||||
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
|
||||
|
||||
/* Curl_multi SSL backend-specific data; declared differently by each SSL
|
||||
backend */
|
||||
struct multi_ssl_backend_data;
|
||||
|
||||
/* This is the struct known as CURLM on the outside */
|
||||
struct Curl_multi {
|
||||
/* First a simple identifier to easier detect if a user mix up
|
||||
|
|
@ -132,14 +128,17 @@ struct Curl_multi {
|
|||
char *xfer_ulbuf; /* the actual buffer */
|
||||
size_t xfer_ulbuf_len; /* the allocated length */
|
||||
|
||||
#if defined(USE_SSL)
|
||||
struct multi_ssl_backend_data *ssl_backend_data;
|
||||
#endif
|
||||
|
||||
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
|
||||
the pluralis form, there can be more than one easy handle waiting on the
|
||||
same actual socket) */
|
||||
struct Curl_hash sockhash;
|
||||
/* `proto_hash` is a general key-value store for protocol implementations
|
||||
* with the lifetime of the multi handle. The number of elements kept here
|
||||
* should be in the order of supported protocols (and sub-protocols like
|
||||
* TLS), *not* in the order of connections or current transfers!
|
||||
* Elements need to be added with their own destructor to be invoked when
|
||||
* the multi handle is cleaned up (see Curl_hash_add2()).*/
|
||||
struct Curl_hash proto_hash;
|
||||
|
||||
/* Shared connection cache (bundles)*/
|
||||
struct conncache conn_cache;
|
||||
|
|
|
|||
|
|
@ -1130,7 +1130,6 @@ const struct Curl_ssl Curl_ssl_bearssl = {
|
|||
bearssl_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
bearssl_recv, /* recv decrypted data */
|
||||
bearssl_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1856,7 +1856,6 @@ const struct Curl_ssl Curl_ssl_gnutls = {
|
|||
gtls_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
gtls_recv, /* recv decrypted data */
|
||||
gtls_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1515,7 +1515,6 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
|
|||
mbedtls_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
mbed_recv, /* recv decrypted data */
|
||||
mbed_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -307,14 +307,6 @@ typedef unsigned long sslerr_t;
|
|||
#define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
|
||||
#endif /* !LIBRESSL_VERSION_NUMBER */
|
||||
|
||||
#if defined(HAVE_SSL_X509_STORE_SHARE)
|
||||
struct multi_ssl_backend_data {
|
||||
char *CAfile; /* CAfile path used to generate X509 store */
|
||||
X509_STORE *store; /* cached X509 store or NULL if none */
|
||||
struct curltime time; /* when the cached store was created */
|
||||
};
|
||||
#endif /* HAVE_SSL_X509_STORE_SHARE */
|
||||
|
||||
#define push_certinfo(_label, _num) \
|
||||
do { \
|
||||
long info_len = BIO_get_mem_data(mem, &ptr); \
|
||||
|
|
@ -3355,8 +3347,33 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
#if defined(HAVE_SSL_X509_STORE_SHARE)
|
||||
static bool cached_x509_store_expired(const struct Curl_easy *data,
|
||||
const struct multi_ssl_backend_data *mb)
|
||||
|
||||
/* key to use at `multi->proto_hash` */
|
||||
#define MPROTO_OSSL_X509_KEY "tls:ossl:x509:share"
|
||||
|
||||
struct ossl_x509_share {
|
||||
char *CAfile; /* CAfile path used to generate X509 store */
|
||||
X509_STORE *store; /* cached X509 store or NULL if none */
|
||||
struct curltime time; /* when the cached store was created */
|
||||
};
|
||||
|
||||
static void oss_x509_share_free(void *key, size_t key_len, void *p)
|
||||
{
|
||||
struct ossl_x509_share *share = p;
|
||||
DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY)-1));
|
||||
DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len));
|
||||
(void)key;
|
||||
(void)key_len;
|
||||
if(share->store) {
|
||||
X509_STORE_free(share->store);
|
||||
}
|
||||
free(share->CAfile);
|
||||
free(share);
|
||||
}
|
||||
|
||||
static bool
|
||||
cached_x509_store_expired(const struct Curl_easy *data,
|
||||
const struct ossl_x509_share *mb)
|
||||
{
|
||||
const struct ssl_general_config *cfg = &data->set.general_ssl;
|
||||
struct curltime now = Curl_now();
|
||||
|
|
@ -3369,9 +3386,9 @@ static bool cached_x509_store_expired(const struct Curl_easy *data,
|
|||
return elapsed_ms >= timeout_ms;
|
||||
}
|
||||
|
||||
static bool cached_x509_store_different(
|
||||
struct Curl_cfilter *cf,
|
||||
const struct multi_ssl_backend_data *mb)
|
||||
static bool
|
||||
cached_x509_store_different(struct Curl_cfilter *cf,
|
||||
const struct ossl_x509_share *mb)
|
||||
{
|
||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
if(!mb->CAfile || !conn_config->CAfile)
|
||||
|
|
@ -3384,15 +3401,17 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
|
|||
const struct Curl_easy *data)
|
||||
{
|
||||
struct Curl_multi *multi = data->multi;
|
||||
struct ossl_x509_share *share;
|
||||
X509_STORE *store = NULL;
|
||||
|
||||
DEBUGASSERT(multi);
|
||||
if(multi &&
|
||||
multi->ssl_backend_data &&
|
||||
multi->ssl_backend_data->store &&
|
||||
!cached_x509_store_expired(data, multi->ssl_backend_data) &&
|
||||
!cached_x509_store_different(cf, multi->ssl_backend_data)) {
|
||||
store = multi->ssl_backend_data->store;
|
||||
share = multi? Curl_hash_pick(&multi->proto_hash,
|
||||
(void *)MPROTO_OSSL_X509_KEY,
|
||||
sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL;
|
||||
if(share && share->store &&
|
||||
!cached_x509_store_expired(data, share) &&
|
||||
!cached_x509_store_different(cf, share)) {
|
||||
store = share->store;
|
||||
}
|
||||
|
||||
return store;
|
||||
|
|
@ -3404,20 +3423,28 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
|
|||
{
|
||||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct Curl_multi *multi = data->multi;
|
||||
struct multi_ssl_backend_data *mbackend;
|
||||
struct ossl_x509_share *share;
|
||||
|
||||
DEBUGASSERT(multi);
|
||||
if(!multi)
|
||||
return;
|
||||
share = Curl_hash_pick(&multi->proto_hash,
|
||||
(void *)MPROTO_OSSL_X509_KEY,
|
||||
sizeof(MPROTO_OSSL_X509_KEY)-1);
|
||||
|
||||
if(!multi->ssl_backend_data) {
|
||||
multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data));
|
||||
if(!multi->ssl_backend_data)
|
||||
if(!share) {
|
||||
share = calloc(1, sizeof(*share));
|
||||
if(!share)
|
||||
return;
|
||||
if(!Curl_hash_add2(&multi->proto_hash,
|
||||
(void *)MPROTO_OSSL_X509_KEY,
|
||||
sizeof(MPROTO_OSSL_X509_KEY)-1,
|
||||
share, oss_x509_share_free)) {
|
||||
free(share);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mbackend = multi->ssl_backend_data;
|
||||
|
||||
if(X509_STORE_up_ref(store)) {
|
||||
char *CAfile = NULL;
|
||||
|
||||
|
|
@ -3429,14 +3456,14 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
|
||||
if(mbackend->store) {
|
||||
X509_STORE_free(mbackend->store);
|
||||
free(mbackend->CAfile);
|
||||
if(share->store) {
|
||||
X509_STORE_free(share->store);
|
||||
free(share->CAfile);
|
||||
}
|
||||
|
||||
mbackend->time = Curl_now();
|
||||
mbackend->store = store;
|
||||
mbackend->CAfile = CAfile;
|
||||
share->time = Curl_now();
|
||||
share->store = store;
|
||||
share->CAfile = CAfile;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5233,20 +5260,6 @@ static void *ossl_get_internals(struct ssl_connect_data *connssl,
|
|||
(void *)octx->ssl_ctx : (void *)octx->ssl;
|
||||
}
|
||||
|
||||
static void ossl_free_multi_ssl_backend_data(
|
||||
struct multi_ssl_backend_data *mbackend)
|
||||
{
|
||||
#if defined(HAVE_SSL_X509_STORE_SHARE)
|
||||
if(mbackend->store) {
|
||||
X509_STORE_free(mbackend->store);
|
||||
}
|
||||
free(mbackend->CAfile);
|
||||
free(mbackend);
|
||||
#else /* HAVE_SSL_X509_STORE_SHARE */
|
||||
(void)mbackend;
|
||||
#endif /* HAVE_SSL_X509_STORE_SHARE */
|
||||
}
|
||||
|
||||
const struct Curl_ssl Curl_ssl_openssl = {
|
||||
{ CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
|
||||
|
||||
|
|
@ -5290,7 +5303,6 @@ const struct Curl_ssl Curl_ssl_openssl = {
|
|||
#endif
|
||||
NULL, /* use of data in this connection */
|
||||
NULL, /* remote of data from this connection */
|
||||
ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
|
||||
ossl_recv, /* recv decrypted data */
|
||||
ossl_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -783,7 +783,6 @@ const struct Curl_ssl Curl_ssl_rustls = {
|
|||
NULL, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
cr_recv, /* recv decrypted data */
|
||||
cr_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2752,7 +2752,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
|
|||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct Curl_multi *multi = data->multi;
|
||||
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
|
||||
struct schannel_multi_ssl_backend_data *mbackend;
|
||||
struct schannel_cert_share *share;
|
||||
const struct ssl_general_config *cfg = &data->set.general_ssl;
|
||||
timediff_t timeout_ms;
|
||||
timediff_t elapsed_ms;
|
||||
|
|
@ -2761,12 +2761,14 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
|
|||
|
||||
DEBUGASSERT(multi);
|
||||
|
||||
if(!multi || !multi->ssl_backend_data) {
|
||||
if(!multi) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
|
||||
if(!mbackend->cert_store) {
|
||||
share = Curl_hash_pick(&multi->proto_hash,
|
||||
(void *)MPROTO_SCHANNEL_CERT_SHARE_KEY,
|
||||
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1);
|
||||
if(!share || !share->cert_store) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2781,37 +2783,52 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
|
|||
timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
|
||||
if(timeout_ms >= 0) {
|
||||
now = Curl_now();
|
||||
elapsed_ms = Curl_timediff(now, mbackend->time);
|
||||
elapsed_ms = Curl_timediff(now, share->time);
|
||||
if(elapsed_ms >= timeout_ms) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(ca_info_blob) {
|
||||
if(!mbackend->CAinfo_blob_digest) {
|
||||
if(!share->CAinfo_blob_digest) {
|
||||
return NULL;
|
||||
}
|
||||
if(mbackend->CAinfo_blob_size != ca_info_blob->len) {
|
||||
if(share->CAinfo_blob_size != ca_info_blob->len) {
|
||||
return NULL;
|
||||
}
|
||||
schannel_sha256sum((const unsigned char *)ca_info_blob->data,
|
||||
ca_info_blob->len,
|
||||
info_blob_digest,
|
||||
CURL_SHA256_DIGEST_LENGTH);
|
||||
if(memcmp(mbackend->CAinfo_blob_digest,
|
||||
if(memcmp(share->CAinfo_blob_digest,
|
||||
info_blob_digest,
|
||||
CURL_SHA256_DIGEST_LENGTH)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!conn_config->CAfile || !mbackend->CAfile ||
|
||||
strcmp(mbackend->CAfile, conn_config->CAfile)) {
|
||||
if(!conn_config->CAfile || !share->CAfile ||
|
||||
strcmp(share->CAfile, conn_config->CAfile)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return mbackend->cert_store;
|
||||
return share->cert_store;
|
||||
}
|
||||
|
||||
static void schannel_cert_share_free(void *key, size_t key_len, void *p)
|
||||
{
|
||||
struct schannel_cert_share *share = p;
|
||||
DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1));
|
||||
DEBUGASSERT(!memcmp(MPROTO_SCHANNEL_CERT_SHARE_KEY, key, key_len));
|
||||
(void)key;
|
||||
(void)key_len;
|
||||
if(share->cert_store) {
|
||||
CertCloseStore(share->cert_store, 0);
|
||||
}
|
||||
free(share->CAinfo_blob_digest);
|
||||
free(share->CAfile);
|
||||
free(share);
|
||||
}
|
||||
|
||||
bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
|
||||
|
|
@ -2821,7 +2838,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
|
|||
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
|
||||
struct Curl_multi *multi = data->multi;
|
||||
const struct curl_blob *ca_info_blob = conn_config->ca_info_blob;
|
||||
struct schannel_multi_ssl_backend_data *mbackend;
|
||||
struct schannel_cert_share *share;
|
||||
unsigned char *CAinfo_blob_digest = NULL;
|
||||
size_t CAinfo_blob_size = 0;
|
||||
char *CAfile = NULL;
|
||||
|
|
@ -2832,17 +2849,23 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!multi->ssl_backend_data) {
|
||||
multi->ssl_backend_data =
|
||||
calloc(1, sizeof(struct schannel_multi_ssl_backend_data));
|
||||
if(!multi->ssl_backend_data) {
|
||||
share = Curl_hash_pick(&multi->proto_hash,
|
||||
(void *)MPROTO_SCHANNEL_CERT_SHARE_KEY,
|
||||
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1);
|
||||
if(!share) {
|
||||
share = calloc(1, sizeof(*share));
|
||||
if(!share) {
|
||||
return false;
|
||||
}
|
||||
if(!Curl_hash_add2(&multi->proto_hash,
|
||||
(void *)MPROTO_SCHANNEL_CERT_SHARE_KEY,
|
||||
sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1,
|
||||
share, schannel_cert_share_free)) {
|
||||
free(share);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mbackend = (struct schannel_multi_ssl_backend_data *)multi->ssl_backend_data;
|
||||
|
||||
|
||||
if(ca_info_blob) {
|
||||
CAinfo_blob_digest = malloc(CURL_SHA256_DIGEST_LENGTH);
|
||||
if(!CAinfo_blob_digest) {
|
||||
|
|
@ -2864,33 +2887,20 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
/* free old cache data */
|
||||
if(mbackend->cert_store) {
|
||||
CertCloseStore(mbackend->cert_store, 0);
|
||||
if(share->cert_store) {
|
||||
CertCloseStore(share->cert_store, 0);
|
||||
}
|
||||
free(mbackend->CAinfo_blob_digest);
|
||||
free(mbackend->CAfile);
|
||||
free(share->CAinfo_blob_digest);
|
||||
free(share->CAfile);
|
||||
|
||||
mbackend->time = Curl_now();
|
||||
mbackend->cert_store = cert_store;
|
||||
mbackend->CAinfo_blob_digest = CAinfo_blob_digest;
|
||||
mbackend->CAinfo_blob_size = CAinfo_blob_size;
|
||||
mbackend->CAfile = CAfile;
|
||||
share->time = Curl_now();
|
||||
share->cert_store = cert_store;
|
||||
share->CAinfo_blob_digest = CAinfo_blob_digest;
|
||||
share->CAinfo_blob_size = CAinfo_blob_size;
|
||||
share->CAfile = CAfile;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void schannel_free_multi_ssl_backend_data(
|
||||
struct multi_ssl_backend_data *msbd)
|
||||
{
|
||||
struct schannel_multi_ssl_backend_data *mbackend =
|
||||
(struct schannel_multi_ssl_backend_data*)msbd;
|
||||
if(mbackend->cert_store) {
|
||||
CertCloseStore(mbackend->cert_store, 0);
|
||||
}
|
||||
free(mbackend->CAinfo_blob_digest);
|
||||
free(mbackend->CAfile);
|
||||
free(mbackend);
|
||||
}
|
||||
|
||||
const struct Curl_ssl Curl_ssl_schannel = {
|
||||
{ CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
|
||||
|
||||
|
|
@ -2925,7 +2935,6 @@ const struct Curl_ssl Curl_ssl_schannel = {
|
|||
schannel_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
schannel_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
|
||||
schannel_recv, /* recv decrypted data */
|
||||
schannel_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -159,7 +159,10 @@ struct schannel_ssl_backend_data {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct schannel_multi_ssl_backend_data {
|
||||
/* key to use at `multi->proto_hash` */
|
||||
#define MPROTO_SCHANNEL_CERT_SHARE_KEY "tls:schannel:cert:share"
|
||||
|
||||
struct schannel_cert_share {
|
||||
unsigned char *CAinfo_blob_digest; /* CA info blob digest */
|
||||
size_t CAinfo_blob_size; /* CA info blob size */
|
||||
char *CAfile; /* CAfile path used to generate
|
||||
|
|
|
|||
|
|
@ -3476,7 +3476,6 @@ const struct Curl_ssl Curl_ssl_sectransp = {
|
|||
sectransp_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
sectransp_recv, /* recv decrypted data */
|
||||
sectransp_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -753,12 +753,6 @@ out:
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
|
||||
{
|
||||
if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
|
||||
Curl_ssl->free_multi_ssl_backend_data(mbackend);
|
||||
}
|
||||
|
||||
void Curl_ssl_close_all(struct Curl_easy *data)
|
||||
{
|
||||
/* kill the session ID cache if not shared */
|
||||
|
|
@ -1339,7 +1333,6 @@ static const struct Curl_ssl Curl_ssl_multi = {
|
|||
NULL, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
multissl_recv_plain, /* recv decrypted data */
|
||||
multissl_send_plain, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ struct Curl_ssl_session;
|
|||
|
||||
/* Curl_multi SSL backend-specific data; declared differently by each SSL
|
||||
backend */
|
||||
struct multi_ssl_backend_data;
|
||||
struct Curl_cfilter;
|
||||
|
||||
CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
|
||||
|
|
@ -181,8 +180,6 @@ bool Curl_ssl_cert_status_request(void);
|
|||
|
||||
bool Curl_ssl_false_start(struct Curl_easy *data);
|
||||
|
||||
void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend);
|
||||
|
||||
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
|
||||
|
||||
CURLcode Curl_ssl_cfilter_add(struct Curl_easy *data,
|
||||
|
|
|
|||
|
|
@ -135,8 +135,6 @@ struct Curl_ssl {
|
|||
bool (*attach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
|
||||
void (*detach_data)(struct Curl_cfilter *cf, struct Curl_easy *data);
|
||||
|
||||
void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
|
||||
|
||||
ssize_t (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *code);
|
||||
ssize_t (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,6 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
|
|||
wolfssl_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
wolfssl_recv, /* recv decrypted data */
|
||||
wolfssl_send, /* send data to encrypt */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,6 +39,16 @@ static void mydtor(void *p)
|
|||
(void)p; /* unused */
|
||||
}
|
||||
|
||||
static size_t elem_dtor_calls;
|
||||
|
||||
static void my_elem_dtor(void *key, size_t key_len, void *p)
|
||||
{
|
||||
(void)p; /* unused */
|
||||
(void)key; /* unused */
|
||||
(void)key_len; /* unused */
|
||||
++elem_dtor_calls;
|
||||
}
|
||||
|
||||
static CURLcode unit_setup(void)
|
||||
{
|
||||
Curl_hash_init(&hash_static, slots, Curl_hash_str,
|
||||
|
|
@ -147,6 +157,22 @@ UNITTEST_START
|
|||
nodep = Curl_hash_pick(&hash_static, &key3, strlen(key3));
|
||||
fail_unless(nodep == key3, "hash retrieval failed");
|
||||
|
||||
/* Add element with own destructor */
|
||||
nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1,
|
||||
my_elem_dtor);
|
||||
fail_unless(nodep, "add2 insertion into hash failed");
|
||||
fail_unless(elem_dtor_calls == 0, "element destructor count should be 0");
|
||||
/* Add it again, should invoke destructor on first */
|
||||
nodep = Curl_hash_add2(&hash_static, &key1, strlen(key1), &key1,
|
||||
my_elem_dtor);
|
||||
fail_unless(nodep, "add2 again, insertion into hash failed");
|
||||
fail_unless(elem_dtor_calls == 1, "element destructor count should be 1");
|
||||
/* remove, should invoke destructor */
|
||||
rc = Curl_hash_delete(&hash_static, &key1, strlen(key1));
|
||||
fail_unless(rc == 0, "hash delete failed");
|
||||
fail_unless(elem_dtor_calls == 2, "element destructor count should be 1");
|
||||
|
||||
|
||||
/* Clean up */
|
||||
Curl_hash_clean(&hash_static);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue