diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
commit | 3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch) | |
tree | 2e1c188dd7b8d7475cd163de9ae02c428343669b /bin/named/transportconf.c | |
parent | Initial commit. (diff) | |
download | bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.tar.xz bind9-3b9b6d0b8e7f798023c9d109c490449d528fde80.zip |
Adding upstream version 1:9.18.19.upstream/1%9.18.19upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | bin/named/transportconf.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/bin/named/transportconf.c b/bin/named/transportconf.c new file mode 100644 index 0000000..f24aab1 --- /dev/null +++ b/bin/named/transportconf.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> + +#include <isc/buffer.h> +#include <isc/string.h> +#include <isc/util.h> + +#include <dns/name.h> +#include <dns/transport.h> + +#include <isccfg/cfg.h> + +#include <named/log.h> +#include <named/transportconf.h> + +#define create_name(id, name) \ + isc_buffer_t namesrc, namebuf; \ + char namedata[DNS_NAME_FORMATSIZE + 1]; \ + dns_name_init(name, NULL); \ + isc_buffer_constinit(&namesrc, id, strlen(id)); \ + isc_buffer_add(&namesrc, strlen(id)); \ + isc_buffer_init(&namebuf, namedata, sizeof(namedata)); \ + result = (dns_name_fromtext(name, &namesrc, dns_rootname, \ + DNS_NAME_DOWNCASE, &namebuf)); \ + if (result != ISC_R_SUCCESS) { \ + goto failure; \ + } + +#define parse_transport_option(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + setter(transport, cfg_obj_asstring(obj)); \ + } \ + } + +#define parse_transport_tls_versions(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + { \ + uint32_t tls_protos = 0; \ + const cfg_listelt_t *proto = NULL; \ + INSIST(obj != NULL); \ + for (proto = cfg_list_first(obj); proto != 0; \ + proto = cfg_list_next(proto)) \ + { \ + const cfg_obj_t *tls_proto_obj = \ + cfg_listelt_value(proto); \ + const char *tls_sver = \ + cfg_obj_asstring( \ + tls_proto_obj); \ + const isc_tls_protocol_version_t ver = \ + isc_tls_protocol_name_to_version( \ + tls_sver); \ + INSIST(ver != \ + ISC_TLS_PROTO_VER_UNDEFINED); \ + INSIST(isc_tls_protocol_supported( \ + ver)); \ + tls_protos |= ver; \ + } \ + if (tls_protos != 0) { \ + setter(transport, tls_protos); \ + } \ + } \ + } \ + } + +#define parse_transport_bool_option(map, transport, name, setter) \ + { \ + const cfg_obj_t *obj = NULL; \ + cfg_map_get(map, name, &obj); \ + if (obj != NULL) { \ + setter(transport, cfg_obj_asboolean(obj)); \ + } \ + } + +static isc_result_t +add_doh_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) { + const cfg_obj_t *doh = NULL; + const char *dohid = NULL; + isc_result_t result; + + for (const cfg_listelt_t *element = cfg_list_first(transportlist); + element != NULL; element = cfg_list_next(element)) + { + dns_name_t dohname; + dns_transport_t *transport; + + doh = cfg_listelt_value(element); + dohid = cfg_obj_asstring(cfg_map_getname(doh)); + + create_name(dohid, &dohname); + + 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", + dns_transport_set_certfile); + parse_transport_tls_versions(doh, transport, "protocols", + dns_transport_set_tls_versions); + parse_transport_option(doh, transport, "ciphers", + dns_transport_set_ciphers); + parse_transport_bool_option( + doh, transport, "prefer-server-ciphers", + dns_transport_set_prefer_server_ciphers) + parse_transport_option(doh, transport, "ca-file", + dns_transport_set_cafile); + parse_transport_option(doh, transport, "remote-hostname", + dns_transport_set_remote_hostname); + } + + return (ISC_R_SUCCESS); +failure: + cfg_obj_log(doh, named_g_lctx, ISC_LOG_ERROR, + "configuring DoH '%s': %s", dohid, + isc_result_totext(result)); + + return (result); +} + +static isc_result_t +add_tls_transports(const cfg_obj_t *transportlist, dns_transport_list_t *list) { + const cfg_obj_t *tls = NULL; + const char *tlsid = NULL; + isc_result_t result; + + for (const cfg_listelt_t *element = cfg_list_first(transportlist); + element != NULL; element = cfg_list_next(element)) + { + dns_name_t tlsname; + dns_transport_t *transport; + + tls = cfg_listelt_value(element); + tlsid = cfg_obj_asstring(cfg_map_getname(tls)); + + if (!strcmp(tlsid, "ephemeral")) { + result = ISC_R_UNEXPECTEDTOKEN; + goto failure; + } + + create_name(tlsid, &tlsname); + + 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", + dns_transport_set_certfile); + parse_transport_tls_versions(tls, transport, "protocols", + dns_transport_set_tls_versions); + parse_transport_option(tls, transport, "ciphers", + dns_transport_set_ciphers); + parse_transport_bool_option( + tls, transport, "prefer-server-ciphers", + dns_transport_set_prefer_server_ciphers) + parse_transport_option(tls, transport, "ca-file", + dns_transport_set_cafile); + parse_transport_option(tls, transport, "remote-hostname", + dns_transport_set_remote_hostname); + } + + return (ISC_R_SUCCESS); +failure: + cfg_obj_log(tls, named_g_lctx, ISC_LOG_ERROR, + "configuring tls '%s': %s", tlsid, + isc_result_totext(result)); + + return (result); +} + +#define CHECK(f) \ + if ((result = f) != ISC_R_SUCCESS) { \ + goto failure; \ + } + +static isc_result_t +transport_list_fromconfig(const cfg_obj_t *config, dns_transport_list_t *list) { + const cfg_obj_t *obj = NULL; + isc_result_t result = ISC_R_SUCCESS; + + if (result == ISC_R_SUCCESS && + cfg_map_get(config, "tls", &obj) == ISC_R_SUCCESS) + { + result = add_tls_transports(obj, list); + obj = NULL; + } + + if (result == ISC_R_SUCCESS && + cfg_map_get(config, "doh", &obj) == ISC_R_SUCCESS) + { + result = add_doh_transports(obj, list); + obj = NULL; + } + + return (result); +} + +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); + + transport = dns_transport_new(&tlsname, DNS_TRANSPORT_TLS, list); + dns_transport_set_tlsname(transport, "ephemeral"); + + return; +failure: + RUNTIME_CHECK(result == ISC_R_SUCCESS); +} + +isc_result_t +named_transports_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig, + isc_mem_t *mctx, dns_transport_list_t **listp) { + isc_result_t result; + dns_transport_list_t *list = dns_transport_list_new(mctx); + + REQUIRE(listp != NULL && *listp == NULL); + + transport_list_add_ephemeral(list); + + if (config != NULL) { + result = transport_list_fromconfig(config, list); + if (result != ISC_R_SUCCESS) { + goto failure; + } + } + + if (vconfig != NULL) { + config = cfg_tuple_get(vconfig, "options"); + transport_list_fromconfig(config, list); + } + + *listp = list; + return (ISC_R_SUCCESS); +failure: + dns_transport_list_detach(&list); + return (result); +} |