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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user