2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00
bind/bin/named/transportconf.c
Ondřej Surý 42496f3f4a
Use ControlStatementsExceptControlMacros for SpaceBeforeParens
> Put a space before opening parentheses only after control statement
> keywords (for/if/while...) except this option doesn’t apply to ForEach
> and If macros. This is useful in projects where ForEach/If macros are
> treated as function calls instead of control statements.
2025-08-19 07:58:33 +02:00

257 lines
8.1 KiB
C

/*
* 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; \
dns_fixedname_t _fn; \
name = dns_fixedname_initname(&_fn); \
isc_buffer_constinit(&namesrc, id, strlen(id)); \
isc_buffer_add(&namesrc, strlen(id)); \
result = (dns_name_fromtext(name, &namesrc, dns_rootname, \
DNS_NAME_DOWNCASE)); \
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; \
INSIST(obj != NULL); \
CFG_LIST_FOREACH(obj, 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;
CFG_LIST_FOREACH(transportlist, element) {
dns_name_t *dohname = NULL;
dns_transport_t *transport = NULL;
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_option(doh, transport, "cipher-suites",
dns_transport_set_cipher_suites);
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, 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;
CFG_LIST_FOREACH(transportlist, element) {
dns_name_t *tlsname = NULL;
dns_transport_t *transport = NULL;
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_option(tls, transport, "cipher-suites",
dns_transport_set_cipher_suites);
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, 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 = NULL;
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;
}