Merge branch 'artem-tlsctx-caching' into 'main'

Add TLS context cache

Closes #3067

See merge request isc-projects/bind9!5672
This commit is contained in:
Artem Boldariev 2021-12-29 08:58:10 +00:00
commit 3addc36533
19 changed files with 664 additions and 106 deletions

View file

@ -1,3 +1,9 @@
5784. [func] Implement TLS-contexts reuse. Reusing the
previously created TLS context objects can reduce
initialisation time for some configurations and enables
TLS session resumption for incoming zone transfers over
TLS (XoT). [GL #3067]
5783. [func] named is now able to log TLS pre-master secrets for
debugging purposes. This requires setting the
SSLKEYLOGFILE environment variable appropriately.

View file

@ -20,6 +20,7 @@
#include <isc/magic.h>
#include <isc/quota.h>
#include <isc/sockaddr.h>
#include <isc/tls.h>
#include <isc/types.h>
#include <dns/acl.h>
@ -109,6 +110,9 @@ struct named_server {
dns_dtenv_t *dtenv; /*%< Dnstap environment */
char *lockfile;
isc_tlsctx_cache_t *tlsctx_server_cache;
isc_tlsctx_cache_t *tlsctx_client_cache;
};
#define NAMED_SERVER_MAGIC ISC_MAGIC('S', 'V', 'E', 'R')

View file

@ -403,19 +403,21 @@ named_server_reload(isc_task_t *task, isc_event_t *event);
#ifdef HAVE_LIBNGHTTP2
static isc_result_t
listenelt_http(const cfg_obj_t *http, bool tls,
const ns_listen_tls_params_t *tls_params, in_port_t port,
listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, in_port_t port,
isc_mem_t *mctx, ns_listenelt_t **target);
#endif
static isc_result_t
listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
ns_listenelt_t **target);
isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target);
static isc_result_t
listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
isc_tlsctx_cache_t *tlsctx_cache,
ns_listenlist_t **target);
static isc_result_t
@ -8422,6 +8424,22 @@ load_configuration(const char *filename, named_server_t *server,
*/
CHECK(bind9_check_namedconf(config, false, named_g_lctx, named_g_mctx));
/* Let's recreate the TLS context cache */
if (server->tlsctx_server_cache != NULL) {
isc_tlsctx_cache_detach(&server->tlsctx_server_cache);
}
server->tlsctx_server_cache = isc_tlsctx_cache_new(named_g_mctx);
if (server->tlsctx_client_cache != NULL) {
isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
}
server->tlsctx_client_cache = isc_tlsctx_cache_new(named_g_mctx);
dns_zonemgr_set_tlsctx_cache(server->zonemgr,
server->tlsctx_client_cache);
/*
* Fill in the maps array, used for resolving defaults.
*/
@ -8874,13 +8892,15 @@ load_configuration(const char *filename, named_server_t *server,
if (clistenon != NULL) {
CHECK(listenlist_fromconfig(
clistenon, config, named_g_aclconfctx,
named_g_mctx, AF_INET, &listenon));
named_g_mctx, AF_INET,
server->tlsctx_server_cache, &listenon));
} else {
/*
* Not specified, use default.
*/
CHECK(ns_listenlist_default(named_g_mctx, listen_port,
-1, true, &listenon));
-1, true, AF_INET,
&listenon));
}
if (listenon != NULL) {
ns_interfacemgr_setlistenon4(server->interfacemgr,
@ -8901,13 +8921,15 @@ load_configuration(const char *filename, named_server_t *server,
if (clistenon != NULL) {
CHECK(listenlist_fromconfig(
clistenon, config, named_g_aclconfctx,
named_g_mctx, AF_INET6, &listenon));
named_g_mctx, AF_INET6,
server->tlsctx_server_cache, &listenon));
} else {
/*
* Not specified, use default.
*/
CHECK(ns_listenlist_default(named_g_mctx, listen_port,
-1, true, &listenon));
-1, true, AF_INET6,
&listenon));
}
if (listenon != NULL) {
ns_interfacemgr_setlistenon6(server->interfacemgr,
@ -10167,6 +10189,10 @@ named_server_create(isc_mem_t *mctx, named_server_t **serverp) {
server->dtenv = NULL;
server->magic = NAMED_SERVER_MAGIC;
server->tlsctx_server_cache = NULL;
server->tlsctx_client_cache = NULL;
*serverp = server;
}
@ -10221,6 +10247,14 @@ named_server_destroy(named_server_t **serverp) {
INSIST(ISC_LIST_EMPTY(server->viewlist));
INSIST(ISC_LIST_EMPTY(server->cachelist));
if (server->tlsctx_server_cache != NULL) {
isc_tlsctx_cache_detach(&server->tlsctx_server_cache);
}
if (server->tlsctx_client_cache != NULL) {
isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
}
server->magic = 0;
isc_mem_put(server->mctx, server, sizeof(*server));
*serverp = NULL;
@ -10860,6 +10894,7 @@ named_server_togglequerylog(named_server_t *server, isc_lex_t *lex) {
static isc_result_t
listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
isc_tlsctx_cache_t *tlsctx_cache,
ns_listenlist_t **target) {
isc_result_t result;
const cfg_listelt_t *element;
@ -10878,7 +10913,7 @@ listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
ns_listenelt_t *delt = NULL;
const cfg_obj_t *listener = cfg_listelt_value(element);
result = listenelt_fromconfig(listener, config, actx, mctx,
family, &delt);
family, tlsctx_cache, &delt);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
@ -10925,6 +10960,7 @@ find_maplist(const cfg_obj_t *config, const char *listname, const char *name) {
static isc_result_t
listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
isc_tlsctx_cache_t *tlsctx_cache,
ns_listenelt_t **target) {
isc_result_t result;
const cfg_obj_t *ltup = NULL;
@ -10942,6 +10978,7 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
ns_listenelt_t *delt = NULL;
uint32_t tls_protos = 0;
ns_listen_tls_params_t tls_params = { 0 };
const char *tlsname = NULL;
REQUIRE(target != NULL && *target == NULL);
@ -10950,7 +10987,7 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
tlsobj = cfg_tuple_get(ltup, "tls");
if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) {
const char *tlsname = cfg_obj_asstring(tlsobj);
tlsname = cfg_obj_asstring(tlsobj);
if (strcasecmp(tlsname, "none") == 0) {
no_tls = true;
@ -11033,6 +11070,7 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
}
tls_params = (ns_listen_tls_params_t){
.name = tlsname,
.key = key,
.cert = cert,
.protocols = tls_protos,
@ -11126,14 +11164,15 @@ listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
#ifdef HAVE_LIBNGHTTP2
if (http) {
CHECK(listenelt_http(http_server, do_tls, &tls_params, port,
mctx, &delt));
CHECK(listenelt_http(http_server, family, do_tls, &tls_params,
tlsctx_cache, port, mctx, &delt));
}
#endif /* HAVE_LIBNGHTTP2 */
if (!http) {
CHECK(ns_listenelt_create(mctx, port, dscp, NULL, do_tls,
&tls_params, &delt));
CHECK(ns_listenelt_create(mctx, port, dscp, NULL, family,
do_tls, &tls_params, tlsctx_cache,
&delt));
}
result = cfg_acl_fromconfig2(cfg_tuple_get(listener, "acl"), config,
@ -11151,8 +11190,9 @@ cleanup:
#ifdef HAVE_LIBNGHTTP2
static isc_result_t
listenelt_http(const cfg_obj_t *http, bool tls,
const ns_listen_tls_params_t *tls_params, in_port_t port,
listenelt_http(const cfg_obj_t *http, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, in_port_t port,
isc_mem_t *mctx, ns_listenelt_t **target) {
isc_result_t result = ISC_R_SUCCESS;
ns_listenelt_t *delt = NULL;
@ -11224,9 +11264,9 @@ listenelt_http(const cfg_obj_t *http, bool tls,
quota = isc_mem_get(mctx, sizeof(isc_quota_t));
isc_quota_init(quota, max_clients);
}
result = ns_listenelt_create_http(mctx, port, named_g_dscp, NULL, tls,
tls_params, endpoints, len, quota,
max_streams, &delt);
result = ns_listenelt_create_http(
mctx, port, named_g_dscp, NULL, family, tls, tls_params,
tlsctx_cache, endpoints, len, quota, max_streams, &delt);
if (result != ISC_R_SUCCESS) {
goto error;
}

View file

@ -108,6 +108,7 @@ add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
transport = dns_transport_new(&dohname, DNS_TRANSPORT_HTTP,
list);
dns_transport_set_tlsname(transport, dohid);
parse_transport_option(doh, transport, "key-file",
dns_transport_set_keyfile);
parse_transport_option(doh, transport, "cert-file",
@ -165,6 +166,7 @@ add_tls_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) {
transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS,
list);
dns_transport_set_tlsname(transport, tlsid);
parse_transport_option(tls, transport, "key-file",
dns_transport_set_keyfile);
parse_transport_option(tls, transport, "cert-file",
@ -228,10 +230,12 @@ static void
transport_list_add_ephemeral(dns_transport_list_t *list) {
isc_result_t result;
dns_name_t tlsname;
dns_transport_t *transport;
create_name("ephemeral", &tlsname);
(void)dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, list);
transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, list);
dns_transport_set_tlsname(transport, "ephemeral");
return;
failure:

View file

@ -54,6 +54,8 @@ dns_http_mode_t
dns_transport_get_mode(dns_transport_t *transport);
char *
dns_transport_get_ciphers(dns_transport_t *transport);
char *
dns_transport_get_tlsname(dns_transport_t *transport);
uint32_t
dns_transport_get_tls_versions(const dns_transport_t *transport);
bool
@ -82,6 +84,9 @@ void
dns_transport_set_mode(dns_transport_t *transport, dns_http_mode_t mode);
void
dns_transport_set_ciphers(dns_transport_t *transport, const char *ciphers);
void
dns_transport_set_tlsname(dns_transport_t *transport, const char *tlsname);
void
dns_transport_set_tls_versions(dns_transport_t *transport,
const uint32_t tls_versions);

View file

@ -25,6 +25,7 @@
***/
#include <isc/lang.h>
#include <isc/tls.h>
#include <dns/transport.h>
#include <dns/types.h>
@ -49,7 +50,8 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
dns_tsigkey_t *tsigkey, dns_transport_t *transport,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done,
isc_tlsctx_cache_t *tlsctx_cache, isc_mem_t *mctx,
isc_nm_t *netmgr, dns_xfrindone_t done,
dns_xfrin_ctx_t **xfrp);
/*%<
* Attempt to start an incoming zone transfer of 'zone'

View file

@ -24,6 +24,7 @@
#include <isc/formatcheck.h>
#include <isc/lang.h>
#include <isc/rwlock.h>
#include <isc/tls.h>
#include <dns/catz.h>
#include <dns/master.h>
@ -2068,6 +2069,18 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
*\li 'local' to be a valid sockaddr.
*/
void
dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
isc_tlsctx_cache_t *tlsctx_cache);
/*%<
* Set the TLS client context cache used for zone transfers via
* encrypted transports (e.g. XoT).
*
* Requires:
*\li 'zmgr' is a valid zone manager.
*\li 'tlsctx_cache' is a valid TLS context cache.
*/
void
dns_zone_forcereload(dns_zone_t *zone);
/*%<

View file

@ -44,6 +44,7 @@ struct dns_transport {
isc_mem_t *mctx;
dns_transport_type_t type;
struct {
char *tlsname;
char *certfile;
char *keyfile;
char *cafile;
@ -269,6 +270,22 @@ dns_transport_set_ciphers(dns_transport_t *transport, const char *ciphers) {
}
}
void
dns_transport_set_tlsname(dns_transport_t *transport, const char *tlsname) {
REQUIRE(VALID_TRANSPORT(transport));
REQUIRE(transport->type == DNS_TRANSPORT_TLS ||
transport->type == DNS_TRANSPORT_HTTP);
if (transport->tls.tlsname != NULL) {
isc_mem_free(transport->mctx, transport->tls.tlsname);
}
if (tlsname != NULL) {
transport->tls.tlsname = isc_mem_strdup(transport->mctx,
tlsname);
}
}
char *
dns_transport_get_ciphers(dns_transport_t *transport) {
REQUIRE(VALID_TRANSPORT(transport));
@ -276,6 +293,13 @@ dns_transport_get_ciphers(dns_transport_t *transport) {
return (transport->tls.ciphers);
}
char *
dns_transport_get_tlsname(dns_transport_t *transport) {
REQUIRE(VALID_TRANSPORT(transport));
return (transport->tls.tlsname);
}
void
dns_transport_set_prefer_server_ciphers(dns_transport_t *transport,
const bool prefer) {
@ -330,6 +354,10 @@ transport_destroy(dns_transport_t *transport) {
isc_mem_free(transport->mctx, transport->tls.ciphers);
}
if (transport->tls.tlsname != NULL) {
isc_mem_free(transport->mctx, transport->tls.tlsname);
}
isc_mem_putanddetach(&transport->mctx, transport, sizeof(*transport));
}

View file

@ -163,7 +163,6 @@ struct dns_xfrin_ctx {
unsigned int sincetsig; /*%< recvd since the last TSIG */
dns_transport_t *transport;
isc_tlsctx_t *tlsctx;
dns_xfrindone_t done;
@ -183,6 +182,8 @@ struct dns_xfrin_ctx {
dns_rdata_t firstsoa;
unsigned char *firstsoa_data;
isc_tlsctx_cache_t *tlsctx_cache;
};
#define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
@ -199,7 +200,7 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
dns_tsigkey_t *tsigkey, dns_transport_t *transport,
dns_xfrin_ctx_t **xfrp);
isc_tlsctx_cache_t *tlsctx_cache, dns_xfrin_ctx_t **xfrp);
static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr);
@ -693,7 +694,8 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
dns_tsigkey_t *tsigkey, dns_transport_t *transport,
isc_mem_t *mctx, isc_nm_t *netmgr, dns_xfrindone_t done,
isc_tlsctx_cache_t *tlsctx_cache, isc_mem_t *mctx,
isc_nm_t *netmgr, dns_xfrindone_t done,
dns_xfrin_ctx_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone);
dns_xfrin_ctx_t *xfr = NULL;
@ -712,7 +714,7 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
xfrin_create(mctx, zone, db, netmgr, zonename, dns_zone_getclass(zone),
xfrtype, primaryaddr, sourceaddr, dscp, tsigkey, transport,
&xfr);
tlsctx_cache, &xfr);
if (db != NULL) {
xfr->zone_had_db = true;
@ -860,7 +862,7 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
dns_tsigkey_t *tsigkey, dns_transport_t *transport,
dns_xfrin_ctx_t **xfrp) {
isc_tlsctx_cache_t *tlsctx_cache, dns_xfrin_ctx_t **xfrp) {
dns_xfrin_ctx_t *xfr = NULL;
xfr = isc_mem_get(mctx, sizeof(*xfr));
@ -918,6 +920,8 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2],
sizeof(xfr->qbuffer_data) - 2);
isc_tlsctx_cache_attach(tlsctx_cache, &xfr->tlsctx_cache);
xfr->magic = XFRIN_MAGIC;
*xfrp = xfr;
@ -928,6 +932,7 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
isc_result_t result;
dns_xfrin_ctx_t *connect_xfr = NULL;
dns_transport_type_t transport_type = DNS_TRANSPORT_TCP;
isc_tlsctx_t *tlsctx = NULL, *found = NULL;
(void)isc_refcount_increment0(&xfr->connects);
dns_xfrin_attach(xfr, &connect_xfr);
@ -948,32 +953,79 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
break;
case DNS_TRANSPORT_TLS: {
uint32_t tls_versions;
const char *ciphers;
const char *ciphers = NULL;
bool prefer_server_ciphers;
CHECK(isc_tlsctx_createclient(&xfr->tlsctx));
if (xfr->transport != NULL) {
const uint16_t family = isc_sockaddr_pf(&xfr->primaryaddr) ==
PF_INET6
? AF_INET6
: AF_INET;
const char *tlsname = NULL;
INSIST(xfr->transport != NULL);
tlsname = dns_transport_get_tlsname(xfr->transport);
INSIST(tlsname != NULL && *tlsname != '\0');
/*
* Let's try to re-use the already created context. This way
* we have a chance to resume the TLS session, bypassing the
* full TLS handshake procedure, making establishing
* subsequent TLS connections for XoT faster.
*/
result = isc_tlsctx_cache_find(xfr->tlsctx_cache, tlsname,
isc_tlsctx_cache_tls, family,
&tlsctx);
if (result != ISC_R_SUCCESS) {
/*
* So, no context exists. Let's create one using the
* parameters from the configuration file and try to
* store it for further reuse.
*/
CHECK(isc_tlsctx_createclient(&tlsctx));
tls_versions =
dns_transport_get_tls_versions(xfr->transport);
if (tls_versions != 0) {
isc_tlsctx_set_protocols(xfr->tlsctx,
tls_versions);
isc_tlsctx_set_protocols(tlsctx, tls_versions);
}
ciphers = dns_transport_get_ciphers(xfr->transport);
if (ciphers != NULL) {
isc_tlsctx_set_cipherlist(xfr->tlsctx, ciphers);
isc_tlsctx_set_cipherlist(tlsctx, ciphers);
}
if (dns_transport_get_prefer_server_ciphers(
xfr->transport, &prefer_server_ciphers))
{
isc_tlsctx_prefer_server_ciphers(
xfr->tlsctx, prefer_server_ciphers);
tlsctx, prefer_server_ciphers);
}
isc_tlsctx_enable_dot_client_alpn(tlsctx);
result = isc_tlsctx_cache_add(
xfr->tlsctx_cache, tlsname,
isc_tlsctx_cache_tls, family, tlsctx, &found);
if (result == ISC_R_EXISTS) {
/*
* It seems the entry has just been created
* from within another thread while we were
* initialising ours. Although this is
* unlikely, it could happen after
* startup/re-initialisation. In such a case,
* discard the new context and use the already
* established one from now on.
*
* Such situation will not occur after the
* initial 'warm-up', so it is not critical
* performance-wise.
*/
INSIST(found != NULL);
isc_tlsctx_free(&tlsctx);
tlsctx = found;
} else {
INSIST(result == ISC_R_SUCCESS);
}
}
isc_tlsctx_enable_dot_client_alpn(xfr->tlsctx);
isc_nm_tlsdnsconnect(xfr->netmgr, &xfr->sourceaddr,
&xfr->primaryaddr, xfrin_connect_done,
connect_xfr, 30000, 0, xfr->tlsctx);
connect_xfr, 30000, 0, tlsctx);
} break;
default:
INSIST(0);
@ -983,8 +1035,13 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
return (ISC_R_SUCCESS);
failure:
if (xfr->tlsctx != NULL) {
isc_tlsctx_free(&xfr->tlsctx);
/*
* The 'found' context is being managed by the TLS context cache.
* Thus, we should keep it as it is, as it will get destroyed
* alongside the cache.
*/
if (tlsctx != NULL && found != tlsctx) {
isc_tlsctx_free(&tlsctx);
}
isc_refcount_decrement0(&xfr->connects);
dns_xfrin_detach(&connect_xfr);
@ -1032,10 +1089,6 @@ xfrin_connect_done(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_refcount_decrement0(&xfr->connects);
if (xfr->tlsctx != NULL) {
isc_tlsctx_free(&xfr->tlsctx);
}
if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
@ -1670,6 +1723,10 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
isc_mem_free(xfr->mctx, xfr->firstsoa_data);
}
if (xfr->tlsctx_cache != NULL) {
isc_tlsctx_cache_detach(&xfr->tlsctx_cache);
}
isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
}

View file

@ -35,6 +35,7 @@
#include <isc/taskpool.h>
#include <isc/thread.h>
#include <isc/timer.h>
#include <isc/tls.h>
#include <isc/util.h>
#include <dns/acl.h>
@ -629,6 +630,8 @@ struct dns_zonemgr {
struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
dns_keymgmt_t *keymgmt;
isc_tlsctx_cache_t *tlsctx_cache;
};
/*%
@ -18133,7 +18136,8 @@ got_transfer_quota(isc_task_t *task, isc_event_t *event) {
}
CHECK(dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr, dscp,
zone->tsigkey, zone->transport, zone->mctx,
zone->tsigkey, zone->transport,
zone->zmgr->tlsctx_cache, zone->mctx,
zone->zmgr->netmgr, zone_xfrdone, &zone->xfr));
LOCK_ZONE(zone);
if (xfrtype == dns_rdatatype_axfr) {
@ -18831,6 +18835,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_mutex_init(&zmgr->iolock);
zmgr->tlsctx_cache = NULL;
zmgr->magic = ZONEMGR_MAGIC;
*zmgrp = zmgr;
@ -19188,6 +19194,9 @@ zonemgr_free(dns_zonemgr_t *zmgr) {
zonemgr_keymgmt_destroy(zmgr);
mctx = zmgr->mctx;
if (zmgr->tlsctx_cache != NULL) {
isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
}
isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
isc_mem_detach(&mctx);
}
@ -23627,3 +23636,20 @@ zone_nsecttl(dns_zone_t *zone) {
return (ISC_MIN(zone->minimum, zone->soattl));
}
void
dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
isc_tlsctx_cache_t *tlsctx_cache) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
REQUIRE(tlsctx_cache != NULL);
RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
if (zmgr->tlsctx_cache != NULL) {
isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
}
isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
}

View file

@ -158,7 +158,6 @@ isc_tlsctx_enable_http2client_alpn(isc_tlsctx_t *ctx);
void
isc_tlsctx_enable_http2server_alpn(isc_tlsctx_t *ctx);
/*%<
*
* Enable HTTP/2 Application Layer Protocol Negotation for 'ctx'.
*
* Requires:
@ -178,9 +177,118 @@ isc_tlsctx_enable_dot_client_alpn(isc_tlsctx_t *ctx);
void
isc_tlsctx_enable_dot_server_alpn(isc_tlsctx_t *ctx);
/*%<
*
* Enable DoT Application Layer Protocol Negotation for 'ctx'.
*
* Requires:
*\li 'ctx' is not NULL.
*/
typedef struct isc_tlsctx_cache isc_tlsctx_cache_t;
/*%<
* The TLS context cache is an object which allows retrieving a
* previously created TLS context based on the following tuple:
*
* 1. The name of a TLS entry, as defined in the configuration file;
* 2. A transport type. Currently, only TLS (DoT) and HTTPS (DoH) are
* supported;
* 3. An IP address family (AF_INET or AF_INET6).
*
* There are multiple uses for this object:
*
* First, it allows reuse of client-side contexts during zone transfers.
* That, in turn, allows use of session caches associated with these
* contexts, which enables TLS session resumption, making establishment
* of XoT connections faster and computationally cheaper.
*
* Second, it can be extended to be used as storage for TLS context related
* data, as defined in 'tls' statements in the configuration file (for
* example, CA-bundle intermediate certificate storage, client-side contexts
* with pre-loaded certificates in a case of Mutual TLS, etc). This will
* be used to implement Strict/Mutual TLS.
*
* Third, it avoids creating an excessive number of server-side TLS
* contexts, which might help to reduce the number of contexts
* created during server initialisation and reconfiguration.
*/
typedef enum {
isc_tlsctx_cache_none = 0,
isc_tlsctx_cache_tls,
isc_tlsctx_cache_https,
isc_tlsctx_cache_count
} isc_tlsctx_cache_transport_t;
/*%< TLS context cache transport type values. */
isc_tlsctx_cache_t *
isc_tlsctx_cache_new(isc_mem_t *mctx);
/*%<
* Create a new TLS context cache object.
*
* Requires:
*\li 'mctx' is a valid memory context.
*/
void
isc_tlsctx_cache_attach(isc_tlsctx_cache_t *source,
isc_tlsctx_cache_t **targetp);
/*%<
* Create a reference to the TLS context cache object.
*
* Requires:
*\li 'source' is a valid TLS context cache object;
*\li 'targetp' is a valid pointer to a pointer which must equal NULL.
*/
void
isc_tlsctx_cache_detach(isc_tlsctx_cache_t **pcache);
/*%<
* Remove a reference to the TLS context cache object.
*
* Requires:
*\li 'pcache' is a valid pointer to a pointer which must point to a
* valid TLS context cache object.
*/
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);
/*%<
*
* 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.
*
* Requires:
*\li 'cache' is a valid pointer to a TLS context cache object;
*\li 'name' is a valid pointer to a non-empty string;
*\li 'transport' is a valid transport identifier (currently only
* TLS/DoT and HTTPS/DoH are supported);
*\li 'family' - either 'AF_INET' or 'AF_INET6';
*\li 'ctx' - a valid pointer to a valid TLS context object.
*
* Returns:
*\li #ISC_R_EXISTS - node of the same key already exists;
*\li #ISC_R_SUCCESS - the new entry has been added successfully.
*/
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);
/*%<
* Look up a TLS context in the TLS context cache.
*
* Requires:
*\li 'cache' is a valid pointer to a TLS context cache object;
*\li 'name' is a valid pointer to a non empty string;
*\li 'transport' - a valid transport identifier (currently only
* TLS/DoT and HTTPS/DoH are supported;
*\li 'family' - either 'AF_INET' or 'AF_INET6';
*\li 'pctx' - a valid pointer to a non-NULL pointer.
*
* Returns:
*\li #ISC_R_SUCCESS - the context has been found;
*\li #ISC_R_NOTFOUND - the context has not been found.
*/

View file

@ -2454,7 +2454,6 @@ isc_nm_listenhttp(isc_nm_t *mgr, isc_sockaddr_t *iface, int backlog,
isc_nm_http_endpoints_attach(eps, &sock->h2.listener_endpoints);
if (ctx != NULL) {
isc_tlsctx_enable_http2server_alpn(ctx);
result = isc_nm_listentls(mgr, iface, httplisten_acceptcb, sock,
sizeof(isc_nm_http_session_t),
backlog, quota, ctx, &sock->outer);

View file

@ -494,8 +494,6 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
sock->tid = 0;
sock->fd = -1;
isc_tlsctx_enable_dot_server_alpn(sslctx);
#if !HAVE_SO_REUSEPORT_LB
fd = isc__nm_tlsdns_lb_socket(iface->type.sa.sa_family);
#endif

View file

@ -332,6 +332,7 @@ nm_setup(void **state) {
server_tlsctx = NULL;
isc_tlsctx_createserver(NULL, NULL, &server_tlsctx);
isc_tlsctx_enable_http2server_alpn(server_tlsctx);
client_tlsctx = NULL;
isc_tlsctx_createclient(&client_tlsctx);
isc_tlsctx_enable_http2client_alpn(client_tlsctx);

View file

@ -12,6 +12,7 @@
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#if HAVE_LIBNGHTTP2
#include <nghttp2/nghttp2.h>
#endif /* HAVE_LIBNGHTTP2 */
@ -27,10 +28,14 @@
#include <openssl/rsa.h>
#include <isc/atomic.h>
#include <isc/ht.h>
#include <isc/log.h>
#include <isc/magic.h>
#include <isc/mutex.h>
#include <isc/mutexblock.h>
#include <isc/once.h>
#include <isc/refcount.h>
#include <isc/rwlock.h>
#include <isc/thread.h>
#include <isc/tls.h>
#include <isc/util.h>
@ -885,3 +890,200 @@ isc_tlsctx_enable_dot_server_alpn(isc_tlsctx_t *tls) {
SSL_CTX_set_alpn_select_cb(tls, dot_alpn_select_proto_cb, NULL);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
}
#define TLSCTX_CACHE_MAGIC ISC_MAGIC('T', 'l', 'S', 'c')
#define VALID_TLSCTX_CACHE(t) ISC_MAGIC_VALID(t, TLSCTX_CACHE_MAGIC)
typedef struct isc_tlsctx_cache_entry {
/*
* We need a TLS context entry for each transport on both IPv4 and
* IPv6 in order to avoid cluttering a context-specific
* session-resumption cache.
*/
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
*/
} isc_tlsctx_cache_entry_t;
struct isc_tlsctx_cache {
uint32_t magic;
isc_refcount_t references;
isc_mem_t *mctx;
isc_rwlock_t rwlock;
isc_ht_t *data;
};
isc_tlsctx_cache_t *
isc_tlsctx_cache_new(isc_mem_t *mctx) {
isc_tlsctx_cache_t *nc;
nc = isc_mem_get(mctx, sizeof(*nc));
*nc = (isc_tlsctx_cache_t){ .magic = TLSCTX_CACHE_MAGIC };
isc_refcount_init(&nc->references, 1);
isc_mem_attach(mctx, &nc->mctx);
RUNTIME_CHECK(isc_ht_init(&nc->data, mctx, 5) == ISC_R_SUCCESS);
isc_rwlock_init(&nc->rwlock, 0, 0);
return (nc);
}
void
isc_tlsctx_cache_attach(isc_tlsctx_cache_t *source,
isc_tlsctx_cache_t **targetp) {
REQUIRE(VALID_TLSCTX_CACHE(source));
REQUIRE(targetp != NULL && *targetp == NULL);
isc_refcount_increment(&source->references);
*targetp = source;
}
static void
tlsctx_cache_entry_destroy(isc_mem_t *mctx, isc_tlsctx_cache_entry_t *entry) {
size_t i, k;
for (i = 0; i < (isc_tlsctx_cache_count - 1); i++) {
for (k = 0; k < 2; k++) {
if (entry->ctx[i][k] != NULL) {
isc_tlsctx_free(&entry->ctx[i][k]);
}
}
}
isc_mem_put(mctx, entry, sizeof(*entry));
}
void
isc_tlsctx_cache_detach(isc_tlsctx_cache_t **pcache) {
isc_tlsctx_cache_t *cache;
isc_ht_iter_t *it = NULL;
isc_result_t result;
REQUIRE(pcache != NULL);
cache = *pcache;
REQUIRE(VALID_TLSCTX_CACHE(cache));
if (isc_refcount_decrement(&cache->references) > 1) {
return;
}
RUNTIME_CHECK(isc_ht_iter_create(cache->data, &it) == ISC_R_SUCCESS);
for (result = isc_ht_iter_first(it); result == ISC_R_SUCCESS;
result = isc_ht_iter_delcurrent_next(it))
{
isc_tlsctx_cache_entry_t *entry = NULL;
isc_ht_iter_current(it, (void **)&entry);
tlsctx_cache_entry_destroy(cache->mctx, entry);
}
isc_ht_iter_destroy(&it);
isc_ht_destroy(&cache->data);
isc_rwlock_destroy(&cache->rwlock);
cache->magic = 0;
isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
*pcache = NULL;
}
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_result_t result = ISC_R_FAILURE;
size_t name_len, tr_offset;
isc_tlsctx_cache_entry_t *entry = NULL;
bool ipv6;
REQUIRE(VALID_TLSCTX_CACHE(cache));
REQUIRE(name != NULL && *name != '\0');
REQUIRE(transport > isc_tlsctx_cache_none &&
transport < isc_tlsctx_cache_count);
REQUIRE(family == AF_INET || family == AF_INET6);
REQUIRE(ctx != NULL);
tr_offset = (transport - 1);
ipv6 = (family == AF_INET6);
RWLOCK(&cache->rwlock, isc_rwlocktype_write);
name_len = strlen(name);
result = isc_ht_find(cache->data, (const uint8_t *)name, name_len,
(void **)&entry);
if (result == ISC_R_SUCCESS && entry->ctx[tr_offset][ipv6] != NULL) {
/* The entry exists. */
if (pfound != NULL) {
INSIST(*pfound == NULL);
*pfound = entry->ctx[tr_offset][ipv6];
}
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
* particular transport/IP type combination.
*/
entry->ctx[tr_offset][ipv6] = ctx;
result = ISC_R_SUCCESS;
} else {
/*
* The hash table entry does not exist, let's create one.
*/
INSIST(result != ISC_R_SUCCESS);
entry = isc_mem_get(cache->mctx, sizeof(*entry));
/* Oracle/Red Hat Linux, GCC bug #53119 */
memset(entry, 0, sizeof(*entry));
entry->ctx[tr_offset][ipv6] = ctx;
RUNTIME_CHECK(isc_ht_add(cache->data, (const uint8_t *)name,
name_len,
(void *)entry) == ISC_R_SUCCESS);
result = ISC_R_SUCCESS;
}
RWUNLOCK(&cache->rwlock, isc_rwlocktype_write);
return (result);
}
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) {
isc_result_t result = ISC_R_FAILURE;
size_t tr_offset;
isc_tlsctx_cache_entry_t *entry = NULL;
bool ipv6;
REQUIRE(VALID_TLSCTX_CACHE(cache));
REQUIRE(name != NULL && *name != '\0');
REQUIRE(transport > isc_tlsctx_cache_none &&
transport < isc_tlsctx_cache_count);
REQUIRE(family == AF_INET || family == AF_INET6);
REQUIRE(pctx != NULL && *pctx == NULL);
tr_offset = (transport - 1);
ipv6 = (family == AF_INET6);
RWLOCK(&cache->rwlock, isc_rwlocktype_read);
result = isc_ht_find(cache->data, (const uint8_t *)name, strlen(name),
(void **)&entry);
if (result == ISC_R_SUCCESS && entry->ctx[tr_offset][ipv6] != NULL) {
*pctx = entry->ctx[tr_offset][ipv6];
} else if (result == ISC_R_SUCCESS &&
entry->ctx[tr_offset][ipv6] == NULL) {
result = ISC_R_NOTFOUND;
} else {
INSIST(result != ISC_R_SUCCESS);
}
RWUNLOCK(&cache->rwlock, isc_rwlocktype_read);
return (result);
}

View file

@ -40,15 +40,16 @@ typedef struct ns_listenlist ns_listenlist_t;
struct ns_listenelt {
isc_mem_t *mctx;
in_port_t port;
bool is_http;
isc_dscp_t dscp; /* -1 = not set, 0..63 */
in_port_t port;
bool is_http;
isc_dscp_t dscp; /* -1 = not set, 0..63 */
dns_acl_t *acl;
isc_tlsctx_t *sslctx;
char **http_endpoints;
size_t http_endpoints_number;
isc_quota_t *http_quota;
uint32_t max_concurrent_streams;
isc_tlsctx_t *sslctx;
isc_tlsctx_cache_t *sslctx_cache;
char **http_endpoints;
size_t http_endpoints_number;
isc_quota_t *http_quota;
uint32_t max_concurrent_streams;
ISC_LINK(ns_listenelt_t) link;
};
@ -59,6 +60,7 @@ struct ns_listenlist {
};
typedef struct ns_listen_tls_params {
const char *name;
const char *key;
const char *cert;
uint32_t protocols;
@ -76,24 +78,25 @@ typedef struct ns_listen_tls_params {
isc_result_t
ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
ns_listenelt_t **target);
isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target);
/*%<
* Create a listen-on list element.
*
* Requires:
* \li 'targetp' is a valid pointer to a pointer containing 'NULL';
* \li 'tls_params' is a valid, non-'NULL' pointer if 'tls' equals 'true'.
* \li 'tlsctx_cache' is a valid, non-'NULL' pointer if 'tls' equals 'true'.
*/
isc_result_t
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
char **endpoints, size_t nendpoints,
isc_quota_t *quota, const uint32_t max_streams,
ns_listenelt_t **target);
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
size_t nendpoints, isc_quota_t *quota,
const uint32_t max_streams, ns_listenelt_t **target);
/*%<
* Create a listen-on list element for HTTP(S).
*/
@ -124,7 +127,8 @@ ns_listenlist_detach(ns_listenlist_t **listp);
isc_result_t
ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
bool enabled, ns_listenlist_t **target);
bool enabled, const uint16_t family,
ns_listenlist_t **target);
/*%<
* Create a listen-on list with default contents, matching
* all addresses with port 'port' (if 'enabled' is true),

View file

@ -24,50 +24,92 @@
static void
destroy(ns_listenlist_t *list);
isc_result_t
ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls,
const ns_listen_tls_params_t *tls_params,
ns_listenelt_t **target) {
static isc_result_t
listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
dns_acl_t *acl, const uint16_t family, const bool is_http,
bool tls, const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target) {
ns_listenelt_t *elt = NULL;
isc_result_t result = ISC_R_SUCCESS;
isc_tlsctx_t *sslctx = NULL;
REQUIRE(target != NULL && *target == NULL);
REQUIRE(!tls || tls_params != NULL);
REQUIRE(!tls || (tls_params != NULL && tlsctx_cache != NULL));
if (tls) {
result = isc_tlsctx_createserver(tls_params->key,
tls_params->cert, &sslctx);
const isc_tlsctx_cache_transport_t transport =
is_http ? isc_tlsctx_cache_https : isc_tlsctx_cache_tls;
/*
* Let's try to reuse the existing context from the cache in
* order to avoid excessive TLS contexts creation.
*/
result = isc_tlsctx_cache_find(tlsctx_cache, tls_params->name,
transport, family, &sslctx);
if (result != ISC_R_SUCCESS) {
return (result);
}
/*
* The lookup failed, let's try to create a new context
* and store it within the cache.
*/
INSIST(tls_params->name != NULL &&
*tls_params->name != '\0');
if (tls_params->protocols != 0) {
isc_tlsctx_set_protocols(sslctx, tls_params->protocols);
}
if (tls_params->dhparam_file != NULL) {
if (!isc_tlsctx_load_dhparams(sslctx,
tls_params->dhparam_file))
{
isc_tlsctx_free(&sslctx);
return (ISC_R_FAILURE);
result = isc_tlsctx_createserver(
tls_params->key, tls_params->cert, &sslctx);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
if (tls_params->ciphers != NULL) {
isc_tlsctx_set_cipherlist(sslctx, tls_params->ciphers);
}
if (tls_params->protocols != 0) {
isc_tlsctx_set_protocols(sslctx,
tls_params->protocols);
}
if (tls_params->prefer_server_ciphers_set) {
isc_tlsctx_prefer_server_ciphers(
sslctx, tls_params->prefer_server_ciphers);
}
if (tls_params->dhparam_file != NULL) {
if (!isc_tlsctx_load_dhparams(
sslctx, tls_params->dhparam_file)) {
isc_tlsctx_free(&sslctx);
return (ISC_R_FAILURE);
}
}
if (tls_params->session_tickets_set) {
isc_tlsctx_session_tickets(sslctx,
tls_params->session_tickets);
if (tls_params->ciphers != NULL) {
isc_tlsctx_set_cipherlist(sslctx,
tls_params->ciphers);
}
if (tls_params->prefer_server_ciphers_set) {
isc_tlsctx_prefer_server_ciphers(
sslctx,
tls_params->prefer_server_ciphers);
}
if (tls_params->session_tickets_set) {
isc_tlsctx_session_tickets(
sslctx, tls_params->session_tickets);
}
#ifdef HAVE_LIBNGHTTP2
if (is_http) {
isc_tlsctx_enable_http2server_alpn(sslctx);
}
#endif /* HAVE_LIBNGHTTP2 */
if (!is_http) {
isc_tlsctx_enable_dot_server_alpn(sslctx);
}
/*
* The storing in the cache should not fail because the
* (re)initialisation happens from within a single
* thread.
*/
RUNTIME_CHECK(isc_tlsctx_cache_add(
tlsctx_cache, tls_params->name,
transport, family, sslctx,
NULL) == ISC_R_SUCCESS);
} else {
INSIST(sslctx != NULL);
}
}
@ -79,6 +121,10 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
elt->dscp = dscp;
elt->acl = acl;
elt->sslctx = sslctx;
elt->sslctx_cache = NULL;
if (sslctx != NULL && tlsctx_cache != NULL) {
isc_tlsctx_cache_attach(tlsctx_cache, &elt->sslctx_cache);
}
elt->http_endpoints = NULL;
elt->http_endpoints_number = 0;
elt->http_quota = NULL;
@ -87,21 +133,30 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
return (ISC_R_SUCCESS);
}
isc_result_t
ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
isc_tlsctx_cache_t *tlsctx_cache, ns_listenelt_t **target) {
return listenelt_create(mctx, port, dscp, acl, family, false, tls,
tls_params, tlsctx_cache, target);
}
isc_result_t
ns_listenelt_create_http(isc_mem_t *mctx, in_port_t http_port, isc_dscp_t dscp,
dns_acl_t *acl, bool tls,
dns_acl_t *acl, const uint16_t family, bool tls,
const ns_listen_tls_params_t *tls_params,
char **endpoints, size_t nendpoints,
isc_quota_t *quota, const uint32_t max_streams,
ns_listenelt_t **target) {
isc_tlsctx_cache_t *tlsctx_cache, char **endpoints,
size_t nendpoints, isc_quota_t *quota,
const uint32_t max_streams, ns_listenelt_t **target) {
isc_result_t result;
REQUIRE(target != NULL && *target == NULL);
REQUIRE(endpoints != NULL && *endpoints != NULL);
REQUIRE(nendpoints > 0);
result = ns_listenelt_create(mctx, http_port, dscp, acl, tls,
tls_params, target);
result = listenelt_create(mctx, http_port, dscp, acl, family, true, tls,
tls_params, tlsctx_cache, target);
if (result == ISC_R_SUCCESS) {
(*target)->is_http = true;
(*target)->http_endpoints = endpoints;
@ -123,8 +178,11 @@ ns_listenelt_destroy(ns_listenelt_t *elt) {
if (elt->acl != NULL) {
dns_acl_detach(&elt->acl);
}
if (elt->sslctx != NULL) {
isc_tlsctx_free(&elt->sslctx);
elt->sslctx = NULL; /* this one is going to be destroyed alongside the
sslctx_cache */
if (elt->sslctx_cache != NULL) {
isc_tlsctx_cache_detach(&elt->sslctx_cache);
}
if (elt->http_endpoints != NULL) {
size_t i;
@ -179,7 +237,8 @@ ns_listenlist_detach(ns_listenlist_t **listp) {
isc_result_t
ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
bool enabled, ns_listenlist_t **target) {
bool enabled, const uint16_t family,
ns_listenlist_t **target) {
isc_result_t result;
dns_acl_t *acl = NULL;
ns_listenelt_t *elt = NULL;
@ -195,7 +254,8 @@ ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
goto cleanup;
}
result = ns_listenelt_create(mctx, port, dscp, acl, false, NULL, &elt);
result = ns_listenelt_create(mctx, port, dscp, acl, family, false, NULL,
NULL, &elt);
if (result != ISC_R_SUCCESS) {
goto cleanup_acl;
}

View file

@ -71,7 +71,7 @@ ns_listenlist_default_test(void **state) {
UNUSED(state);
result = ns_listenlist_default(mctx, port, -1, false, &list);
result = ns_listenlist_default(mctx, port, -1, false, AF_INET, &list);
assert_int_equal(result, ISC_R_SUCCESS);
assert_non_null(list);
@ -98,7 +98,7 @@ ns_listenlist_default_test(void **state) {
ns_listenlist_detach(&list);
result = ns_listenlist_default(mctx, port, -1, true, &list);
result = ns_listenlist_default(mctx, port, -1, true, AF_INET, &list);
assert_int_equal(result, ISC_R_SUCCESS);
assert_false(ISC_LIST_EMPTY(list->elts));

View file

@ -11,7 +11,6 @@
/*! \file */
#include "nstest.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
@ -50,6 +49,8 @@
#include <ns/interfacemgr.h>
#include <ns/server.h>
#include "nstest.h"
isc_mem_t *mctx = NULL;
isc_log_t *lctx = NULL;
isc_nm_t *netmgr = NULL;
@ -236,7 +237,7 @@ create_managers(void) {
dispatchmgr, maintask, NULL, ncpus, false,
&interfacemgr));
CHECK(ns_listenlist_default(mctx, port, -1, true, &listenon));
CHECK(ns_listenlist_default(mctx, port, -1, true, AF_INET, &listenon));
ns_interfacemgr_setlistenon4(interfacemgr, listenon);
ns_listenlist_detach(&listenon);