]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: add multi->proto_hash, a key-value store for protocol data
authorStefan Eissing <stefan@eissing.org>
Thu, 11 Apr 2024 10:34:40 +0000 (12:34 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 25 May 2024 22:15:01 +0000 (00:15 +0200)
- 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

17 files changed:
lib/hash.c
lib/hash.h
lib/multi.c
lib/multihandle.h
lib/vtls/bearssl.c
lib/vtls/gtls.c
lib/vtls/mbedtls.c
lib/vtls/openssl.c
lib/vtls/rustls.c
lib/vtls/schannel.c
lib/vtls/schannel_int.h
lib/vtls/sectransp.c
lib/vtls/vtls.c
lib/vtls/vtls.h
lib/vtls/vtls_int.h
lib/vtls/wolfssl.c
tests/unit/unit1603.c

index ddbae4d3e1675ea8249312e741eb6eeba1b21805..6c09a090c4b3e5607de7a1ed53e358afb34e6e71 100644 (file)
@@ -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.
  *
index 2bdc2471726d48274bf1ce35754558cdd6b6ad17..1cf787525b075294093a2328e7941febb5d3fb7b 100644 (file)
@@ -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)
index 6bbdfe26721d14d40adddf48f852fd002092b757..2f9c0c70d75877cb5361a957e85dfd2c444c60e7 100644 (file)
@@ -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);
 
index add9a05184a7e4c20180f468095aafc9aa9ed698..418fb7b7d68ffbc300a90023fcfaf5d3cac21ab9 100644 (file)
@@ -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;
index a595f54a9cd3ac65e70972515ce9014418dad0b6..d866e93e3f87e284be7aa117d5608374fc358994 100644 (file)
@@ -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 */
 };
index 5cf3bf9527cc73707a3044c71842516a83aff96d..3862405d53526d13a25771a68ea2dba92552d535 100644 (file)
@@ -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 */
 };
index 875f3319dcf73afadb6e94a2be87f04ebac65bf2..47af728bd022760606fd506d782070f85d0f6b0f 100644 (file)
@@ -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 */
 };
index 33ce0b11d2419aa687db13c35bab82bf6fa8c44f..57962484895aef1231f6d665573856e97914720f 100644 (file)
@@ -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 */
 };
index 8b6588a376611f0918887fbd2f703bd4b418b24f..6fc5cfa430df6af2e64bee3f18963447275ed4b2 100644 (file)
@@ -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 */
 };
index 19cdc4b20b8a4cb7e741e8c53a50f42877d2ab34..b4fb3b7e5b7014702909e7d01764069e67e10929 100644 (file)
@@ -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 */
 };
index 5e233a9d05bf9c72ff9c794ac07444e7095c76d4..af29b67de0088fac6d53955b105341072afd14e9 100644 (file)
@@ -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
index f49db6481cf085f2dfbf0d3145b189c4a8ef8ee9..76b491636d51cf83d8370024624cfab901c6ca48 100644 (file)
@@ -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 */
 };
index 570a10d5ac664f3ec672abbee238b8cadf905220..fcf17b82435e844ac97abb995e512786706e19f7 100644 (file)
@@ -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 */
 };
index c40ff26208c8b1a70bcab6c364ad80320134b1bf..ab667795858309c4d6273a5a0ba38d669652b76d 100644 (file)
@@ -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,
index 5259babb251a5b944839516ded037c1179d4ed53..9ac964d114060d927ac33af6b759c3d09cdc85ed 100644 (file)
@@ -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,
index 2c92f56ea417227bb9dc7501e9ceed6a963ca758..4acd354ffc229d2340bd659658134dc43c99a6b8 100644 (file)
@@ -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 */
 };
index 850ad8569ed56c0b0846d722ad7daec3e4dd041d..44f9b880ad12a3a1a0d9635cd7d1667c8605b423 100644 (file)
@@ -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);