]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Extend TLS context cache with CA certificates store
authorArtem Boldariev <artem@boldariev.com>
Tue, 18 Jan 2022 16:31:11 +0000 (18:31 +0200)
committerArtem Boldariev <artem@boldariev.com>
Mon, 28 Mar 2022 12:31:22 +0000 (15:31 +0300)
This commit adds support for keeping CA certificates stores associated
with TLS contexts. The intention is to keep one reusable store per a
set of related TLS contexts.

lib/dns/xfrin.c
lib/isc/include/isc/tls.h
lib/isc/tls.c
lib/ns/listenlist.c

index c64b5525c55615ca6ef0ffcb01a53a1dccafeebd..8e2dd17e6421f0c2ef0d69bdb9c56376fd64f3fb 100644 (file)
@@ -973,7 +973,7 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
                 */
                result = isc_tlsctx_cache_find(xfr->tlsctx_cache, tlsname,
                                               isc_tlsctx_cache_tls, family,
-                                              &tlsctx);
+                                              &tlsctx, NULL);
                if (result != ISC_R_SUCCESS) {
                        /*
                         * So, no context exists. Let's create one using the
@@ -1001,7 +1001,8 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
 
                        result = isc_tlsctx_cache_add(
                                xfr->tlsctx_cache, tlsname,
-                               isc_tlsctx_cache_tls, family, tlsctx, &found);
+                               isc_tlsctx_cache_tls, family, tlsctx, NULL,
+                               &found, NULL);
                        if (result == ISC_R_EXISTS) {
                                /*
                                 * It seems the entry has just been created
index 34a3d237567421ba75414e53a5393d8dffc9fb1f..fc75157bbebe1c09aae1369223b04028b4aab04b 100644 (file)
@@ -326,13 +326,18 @@ isc_result_t
 isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
                     const isc_tlsctx_cache_transport_t transport,
                     const uint16_t family, isc_tlsctx_t *ctx,
-                    isc_tlsctx_t **pfound);
+                    isc_tls_cert_store_t *store, isc_tlsctx_t **pfound,
+                    isc_tls_cert_store_t **pfound_store);
 /*%<
  *
  * Add a new TLS context to the TLS context cache. 'pfound' is an
  * optional pointer, which can be used to retrieve an already
  * existing TLS context object in a case it exists.
  *
+ * The passed certificates store object ('store') possession is
+ * transferred to the cache object in a case of success. In some cases
+ * it might be destroyed immediately upon the call completion.
+ *
  * Requires:
  *\li  'cache' is a valid pointer to a TLS context cache object;
  *\li  'name' is a valid pointer to a non-empty string;
@@ -349,7 +354,8 @@ isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
 isc_result_t
 isc_tlsctx_cache_find(isc_tlsctx_cache_t *cache, const char *name,
                      const isc_tlsctx_cache_transport_t transport,
-                     const uint16_t family, isc_tlsctx_t **pctx);
+                     const uint16_t family, isc_tlsctx_t **pctx,
+                     isc_tls_cert_store_t **pstore);
 /*%<
  * Look up a TLS context in the TLS context cache.
  *
index 3cce41f7d02f7862d37301660a6d45e1dc2c69ec..e85f549642f5287eb47d3e35d7eacbe80b9309e1 100644 (file)
@@ -1084,13 +1084,10 @@ typedef struct isc_tlsctx_cache_entry {
         */
        isc_tlsctx_t *ctx[isc_tlsctx_cache_count - 1][2];
        /*
-        * TODO: add a certificate store for an intermediate certificates
-        * from a CA-bundle file. One is enough for all the contexts defined
-        * above. We will need that for validation.
-        *
-        * X509_STORE *ca_bundle_store; // TODO:  define the utilities to
-        * operate on these ones
+        * One certificate store is enough for all the contexts defined
+        * above. We need that for peer validation.
         */
+       isc_tls_cert_store_t *ca_store;
 } isc_tlsctx_cache_entry_t;
 
 struct isc_tlsctx_cache {
@@ -1140,6 +1137,9 @@ tlsctx_cache_entry_destroy(isc_mem_t *mctx, isc_tlsctx_cache_entry_t *entry) {
                        }
                }
        }
+       if (entry->ca_store != NULL) {
+               isc_tls_cert_store_free(&entry->ca_store);
+       }
        isc_mem_put(mctx, entry, sizeof(*entry));
 }
 
@@ -1187,7 +1187,8 @@ isc_result_t
 isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
                     const isc_tlsctx_cache_transport_t transport,
                     const uint16_t family, isc_tlsctx_t *ctx,
-                    isc_tlsctx_t **pfound) {
+                    isc_tls_cert_store_t *store, isc_tlsctx_t **pfound,
+                    isc_tls_cert_store_t **pfound_store) {
        isc_result_t result = ISC_R_FAILURE;
        size_t name_len, tr_offset;
        isc_tlsctx_cache_entry_t *entry = NULL;
@@ -1214,14 +1215,27 @@ isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
                        INSIST(*pfound == NULL);
                        *pfound = entry->ctx[tr_offset][ipv6];
                }
+
+               if (pfound_store != NULL && entry->ca_store != NULL) {
+                       INSIST(*pfound_store == NULL);
+                       *pfound_store = entry->ca_store;
+               }
                result = ISC_R_EXISTS;
        } else if (result == ISC_R_SUCCESS &&
                   entry->ctx[tr_offset][ipv6] == NULL) {
                /*
-                * The hast table entry exists, but is not filled for this
+                * The hash table entry exists, but is not filled for this
                 * particular transport/IP type combination.
                 */
                entry->ctx[tr_offset][ipv6] = ctx;
+               /*
+                * As the passed certificates store object is supposed to be
+                * internally managed by the cache object anyway, we might
+                * destroy the unneeded store object right now.
+                */
+               if (store != NULL && store != entry->ca_store) {
+                       isc_tls_cert_store_free(&store);
+               }
                result = ISC_R_SUCCESS;
        } else {
                /*
@@ -1232,6 +1246,7 @@ isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
                /* Oracle/Red Hat Linux, GCC bug #53119 */
                memset(entry, 0, sizeof(*entry));
                entry->ctx[tr_offset][ipv6] = ctx;
+               entry->ca_store = store;
                RUNTIME_CHECK(isc_ht_add(cache->data, (const uint8_t *)name,
                                         name_len,
                                         (void *)entry) == ISC_R_SUCCESS);
@@ -1246,7 +1261,8 @@ isc_tlsctx_cache_add(isc_tlsctx_cache_t *cache, const char *name,
 isc_result_t
 isc_tlsctx_cache_find(isc_tlsctx_cache_t *cache, const char *name,
                      const isc_tlsctx_cache_transport_t transport,
-                     const uint16_t family, isc_tlsctx_t **pctx) {
+                     const uint16_t family, isc_tlsctx_t **pctx,
+                     isc_tls_cert_store_t **pstore) {
        isc_result_t result = ISC_R_FAILURE;
        size_t tr_offset;
        isc_tlsctx_cache_entry_t *entry = NULL;
@@ -1266,6 +1282,12 @@ isc_tlsctx_cache_find(isc_tlsctx_cache_t *cache, const char *name,
 
        result = isc_ht_find(cache->data, (const uint8_t *)name, strlen(name),
                             (void **)&entry);
+
+       if (result == ISC_R_SUCCESS && pstore != NULL &&
+           entry->ca_store != NULL) {
+               *pstore = entry->ca_store;
+       }
+
        if (result == ISC_R_SUCCESS && entry->ctx[tr_offset][ipv6] != NULL) {
                *pctx = entry->ctx[tr_offset][ipv6];
        } else if (result == ISC_R_SUCCESS &&
index 689e278c45f49ee4f89598d9c718fe114714a237..25017b5c6a17e606b2188142df8aa68f038501a5 100644 (file)
@@ -47,7 +47,8 @@ listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                 * order to avoid excessive TLS contexts creation.
                 */
                result = isc_tlsctx_cache_find(tlsctx_cache, tls_params->name,
-                                              transport, family, &sslctx);
+                                              transport, family, &sslctx,
+                                              NULL);
                if (result != ISC_R_SUCCESS) {
                        /*
                         * The lookup failed, let's try to create a new context
@@ -108,8 +109,8 @@ listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
                         */
                        RUNTIME_CHECK(isc_tlsctx_cache_add(
                                              tlsctx_cache, tls_params->name,
-                                             transport, family, sslctx,
-                                             NULL) == ISC_R_SUCCESS);
+                                             transport, family, sslctx, NULL,
+                                             NULL, NULL) == ISC_R_SUCCESS);
                } else {
                        INSIST(sslctx != NULL);
                }