From: Artem Boldariev Date: Tue, 18 Jan 2022 16:31:11 +0000 (+0200) Subject: Extend TLS context cache with CA certificates store X-Git-Tag: v9.19.0~41^2~9 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=71cf8fa5acef38ad5ac7d3e88664a95a510c6b39;p=thirdparty%2Fbind9.git Extend TLS context cache with CA certificates store 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. --- diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index c64b5525c55..8e2dd17e642 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -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 diff --git a/lib/isc/include/isc/tls.h b/lib/isc/include/isc/tls.h index 34a3d237567..fc75157bbeb 100644 --- a/lib/isc/include/isc/tls.h +++ b/lib/isc/include/isc/tls.h @@ -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. * diff --git a/lib/isc/tls.c b/lib/isc/tls.c index 3cce41f7d02..e85f549642f 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -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 && diff --git a/lib/ns/listenlist.c b/lib/ns/listenlist.c index 689e278c45f..25017b5c6a1 100644 --- a/lib/ns/listenlist.c +++ b/lib/ns/listenlist.c @@ -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); }