From 3aa2d84880ddd844bc20bf770466e50a250e516d Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Thu, 8 Dec 2022 14:17:24 +0000 Subject: [PATCH] Load and validate the configured TLS transport for forwarders Add support for loading and validating the 'tls' parameter from the forwarders' configuration. This prepares ground for adding support to forward queries to DoT-enabled upstream servers. --- bin/named/server.c | 83 ++++++++++++++++++++++++++++++++++- lib/dns/forward.c | 24 +++++++++- lib/dns/include/dns/forward.h | 1 + 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index a49fbf4bea..cf9fe130e9 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -447,6 +447,9 @@ static isc_result_t configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, cfg_aclconfctx_t *actx); +static const cfg_obj_t * +find_maplist(const cfg_obj_t *config, const char *listname, const char *name); + static isc_result_t add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); @@ -6204,11 +6207,44 @@ cleanup: return (result); } +static isc_result_t +validate_tls(const cfg_obj_t *config, dns_view_t *view, const cfg_obj_t *obj, + isc_log_t *logctx, const char *str, dns_name_t **name) { + dns_fixedname_t fname; + dns_name_t *nm = dns_fixedname_initname(&fname); + isc_result_t result = dns_name_fromstring(nm, str, 0, NULL); + + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + return (result); + } + + if (strcasecmp(str, "ephemeral") != 0) { + const cfg_obj_t *tlsmap = find_maplist(config, "tls", str); + + if (tlsmap == NULL) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "tls '%s' is not defined", str); + return (ISC_R_FAILURE); + } + } + + if (name != NULL && *name == NULL) { + *name = isc_mem_get(view->mctx, sizeof(dns_name_t)); + dns_name_init(*name, NULL); + dns_name_dup(nm, view->mctx, *name); + } + + return (ISC_R_SUCCESS); +} + static isc_result_t configure_forward(const cfg_obj_t *config, dns_view_t *view, const dns_name_t *origin, const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype) { const cfg_obj_t *portobj = NULL; + const cfg_obj_t *tlspobj = NULL; const cfg_obj_t *faddresses = NULL; const cfg_listelt_t *element = NULL; dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none; @@ -6216,6 +6252,8 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_forwarder_t *fwd = NULL; isc_result_t result; in_port_t port; + in_port_t tls_port; + const char *tls = NULL; ISC_LIST_INIT(fwdlist); @@ -6223,6 +6261,7 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, * Determine which port to send forwarded requests to. */ CHECKM(named_config_getport(config, "port", &port), "port"); + CHECKM(named_config_getport(config, "tls-port", &tls_port), "tls-port"); if (forwarders != NULL) { portobj = cfg_tuple_get(forwarders, "port"); @@ -6234,7 +6273,24 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, "port '%u' out of range", val); return (ISC_R_RANGE); } - port = (in_port_t)val; + port = tls_port = (in_port_t)val; + } + } + + /* + * TLS value for forwarded requests. + */ + if (forwarders != NULL) { + tlspobj = cfg_tuple_get(forwarders, "tls"); + if (cfg_obj_isstring(tlspobj)) { + tls = cfg_obj_asstring(tlspobj); + if (tls != NULL) { + result = validate_tls(config, view, tlspobj, + named_g_lctx, tls, NULL); + if (result != ISC_R_SUCCESS) { + return (result); + } + } } } @@ -6247,10 +6303,28 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, element = cfg_list_next(element)) { const cfg_obj_t *forwarder = cfg_listelt_value(element); + const char *cur_tls = NULL; + fwd = isc_mem_get(view->mctx, sizeof(dns_forwarder_t)); + fwd->tlsname = NULL; + cur_tls = cfg_obj_getsockaddrtls(forwarder); + if (cur_tls == NULL) { + cur_tls = tls; + } + if (cur_tls != NULL) { + result = validate_tls(config, view, faddresses, + named_g_lctx, cur_tls, + &fwd->tlsname); + if (result != ISC_R_SUCCESS) { + isc_mem_put(view->mctx, fwd, + sizeof(dns_forwarder_t)); + goto cleanup; + } + } fwd->addr = *cfg_obj_assockaddr(forwarder); if (isc_sockaddr_getport(&fwd->addr) == 0) { - isc_sockaddr_setport(&fwd->addr, port); + isc_sockaddr_setport(&fwd->addr, + cur_tls != NULL ? tls_port : port); } ISC_LINK_INIT(fwd, link); ISC_LIST_APPEND(fwdlist, fwd, link); @@ -6300,6 +6374,11 @@ cleanup: while (!ISC_LIST_EMPTY(fwdlist)) { fwd = ISC_LIST_HEAD(fwdlist); ISC_LIST_UNLINK(fwdlist, fwd, link); + if (fwd->tlsname != NULL) { + dns_name_free(fwd->tlsname, view->mctx); + isc_mem_put(view->mctx, fwd->tlsname, + sizeof(dns_name_t)); + } isc_mem_put(view->mctx, fwd, sizeof(dns_forwarder_t)); } diff --git a/lib/dns/forward.c b/lib/dns/forward.c index 8750569c5d..ef05529d83 100644 --- a/lib/dns/forward.c +++ b/lib/dns/forward.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -84,6 +85,15 @@ dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, const dns_name_t *name, { nfwd = isc_mem_get(fwdtable->mctx, sizeof(*nfwd)); *nfwd = *fwd; + + if (fwd->tlsname != NULL) { + nfwd->tlsname = isc_mem_get(fwdtable->mctx, + sizeof(*nfwd->tlsname)); + dns_name_init(nfwd->tlsname, NULL); + dns_name_dup(fwd->tlsname, fwdtable->mctx, + nfwd->tlsname); + } + ISC_LINK_INIT(nfwd, link); ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link); } @@ -103,6 +113,11 @@ cleanup: while (!ISC_LIST_EMPTY(forwarders->fwdrs)) { fwd = ISC_LIST_HEAD(forwarders->fwdrs); ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link); + if (fwd->tlsname != NULL) { + dns_name_free(fwd->tlsname, fwdtable->mctx); + isc_mem_put(fwdtable->mctx, fwd->tlsname, + sizeof(*fwd->tlsname)); + } isc_mem_put(fwdtable->mctx, fwd, sizeof(*fwd)); } isc_mem_put(fwdtable->mctx, forwarders, sizeof(*forwarders)); @@ -126,8 +141,8 @@ dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, sa = ISC_LIST_NEXT(sa, link)) { fwd = isc_mem_get(fwdtable->mctx, sizeof(*fwd)); - fwd->addr = *sa; - ISC_LINK_INIT(fwd, link); + *fwd = (dns_forwarder_t){ .addr = *sa, + .link = ISC_LINK_INITIALIZER }; ISC_LIST_APPEND(forwarders->fwdrs, fwd, link); } forwarders->fwdpolicy = fwdpolicy; @@ -211,6 +226,11 @@ auto_detach(void *data, void *arg) { while (!ISC_LIST_EMPTY(forwarders->fwdrs)) { fwd = ISC_LIST_HEAD(forwarders->fwdrs); ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link); + if (fwd->tlsname != NULL) { + dns_name_free(fwd->tlsname, fwdtable->mctx); + isc_mem_put(fwdtable->mctx, fwd->tlsname, + sizeof(*fwd->tlsname)); + } isc_mem_put(fwdtable->mctx, fwd, sizeof(*fwd)); } isc_mem_put(fwdtable->mctx, forwarders, sizeof(*forwarders)); diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h index f43fce789d..1733fdb232 100644 --- a/lib/dns/include/dns/forward.h +++ b/lib/dns/include/dns/forward.h @@ -25,6 +25,7 @@ ISC_LANG_BEGINDECLS struct dns_forwarder { isc_sockaddr_t addr; + dns_name_t *tlsname; ISC_LINK(dns_forwarder_t) link; };