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.
This commit is contained in:
Artem Boldariev
2022-01-18 18:31:11 +02:00
parent c49a81e27d
commit 71cf8fa5ac
4 changed files with 46 additions and 16 deletions

View 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

View 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.
*

View 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 &&

View 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);
}