From 06cd8b52db32315581a2a8f0b939b4d6415af6da Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 8 Mar 2023 14:56:08 +0100 Subject: [PATCH] Add new 'checkds' configuration option Add a new configuration option to set how the checkds method should work. Acceptable values are 'yes', 'no', and 'explicit'. When set to 'yes', the checkds method is to lookup the parental agents by querying the NS records of the parent zone. When set to 'no', no checkds method is enabled. Users should run the 'rndc checkds' command to signal that DS records are published and withdrawn. When set to 'explicit', the parental agents are explicitly configured with the 'parental-agents' configuration option. --- bin/named/server.c | 4 +++ bin/named/zoneconf.c | 24 ++++++++++++++++++ .../checkconf/bad-checkdstype-level.conf | 25 +++++++++++++++++++ .../system/checkconf/bad-checkdstype.conf | 22 ++++++++++++++++ bin/tests/system/checkconf/good.conf.in | 3 +++ doc/misc/primary.zoneopt | 1 + doc/misc/secondary.zoneopt | 1 + lib/dns/include/dns/types.h | 6 +++++ lib/dns/include/dns/zone.h | 6 +++++ lib/dns/zone.c | 11 ++++++++ lib/isccfg/namedconf.c | 21 ++++++++++++++++ 11 files changed, 124 insertions(+) create mode 100644 bin/tests/system/checkconf/bad-checkdstype-level.conf create mode 100644 bin/tests/system/checkconf/bad-checkdstype.conf diff --git a/bin/named/server.c b/bin/named/server.c index 593163ffe5..8bc4e32db9 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1960,6 +1960,7 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, dns_zone_setqueryonacl(zone, view->queryonacl); } dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */ @@ -3568,6 +3569,7 @@ create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view, dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setautomatic(zone, true); @@ -3668,6 +3670,7 @@ create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view, dns_zone_setstats(zone, named_g_server->zonestats); dns_zone_setdbtype(zone, dbtypec, dbtype); dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setautomatic(zone, true); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); @@ -6933,6 +6936,7 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { dns_acl_detach(&none); dns_zone_setdialup(zone, dns_dialuptype_no); + dns_zone_setcheckdstype(zone, dns_checkdstype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true); dns_zone_setjournalsize(zone, 0); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 9e392eb25a..83850a5675 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -877,6 +877,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const char *filename = NULL; const char *kaspname = NULL; const char *dupcheck; + dns_checkdstype_t checkdstype = dns_checkdstype_explicit; dns_notifytype_t notifytype = dns_notifytype_yes; uint32_t count; unsigned int dbargc; @@ -1227,6 +1228,29 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setkasp(zone, NULL); } + obj = NULL; + result = named_config_get(maps, "checkds", &obj); + if (result == ISC_R_SUCCESS) { + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) { + checkdstype = dns_checkdstype_yes; + } else { + checkdstype = dns_checkdstype_no; + } + } else { + const char *str = cfg_obj_asstring(obj); + if (strcasecmp(str, "explicit") == 0) { + checkdstype = dns_checkdstype_explicit; + } else { + UNREACHABLE(); + } + } + } + if (raw != NULL) { + dns_zone_setcheckdstype(raw, dns_checkdstype_no); + } + dns_zone_setcheckdstype(zone, checkdstype); + obj = NULL; result = named_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); diff --git a/bin/tests/system/checkconf/bad-checkdstype-level.conf b/bin/tests/system/checkconf/bad-checkdstype-level.conf new file mode 100644 index 0000000000..f3bc1ad558 --- /dev/null +++ b/bin/tests/system/checkconf/bad-checkdstype-level.conf @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/* + * checkds only allowed at zone level + */ + +options { + checkds no; +}; + +zone dummy { + type primary; + file "xxxx"; +}; diff --git a/bin/tests/system/checkconf/bad-checkdstype.conf b/bin/tests/system/checkconf/bad-checkdstype.conf new file mode 100644 index 0000000000..56cd367ad3 --- /dev/null +++ b/bin/tests/system/checkconf/bad-checkdstype.conf @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/* + * Bad checkds type + */ + +zone dummy { + type primary; + file "xxxx"; + checkds foobar; +}; diff --git a/bin/tests/system/checkconf/good.conf.in b/bin/tests/system/checkconf/good.conf.in index a510bef0b2..1e2f49f94f 100644 --- a/bin/tests/system/checkconf/good.conf.in +++ b/bin/tests/system/checkconf/good.conf.in @@ -182,6 +182,7 @@ view "third" { view "fourth" { zone "dnssec-test" { type primary; + checkds explicit; file "dnssec-test.db"; inline-signing yes; parental-agents { @@ -202,6 +203,7 @@ view "fourth" { }; zone "dnssec-inherit" { type primary; + checkds no; file "dnssec-inherit.db"; inline-signing yes; }; @@ -212,6 +214,7 @@ view "fourth" { }; zone "dnssec-view1" { type primary; + checkds yes; file "dnssec-view41.db"; inline-signing yes; dnssec-policy "test"; diff --git a/doc/misc/primary.zoneopt b/doc/misc/primary.zoneopt index f0d3a93b75..dd5f8b6572 100644 --- a/doc/misc/primary.zoneopt +++ b/doc/misc/primary.zoneopt @@ -16,6 +16,7 @@ zone [ ] { check-srv-cname ( fail | warn | ignore ); check-svcb ; check-wildcard ; + checkds ( explicit | ); database ; dialup ( notify | notify-passive | passive | refresh | ); dlz ; diff --git a/doc/misc/secondary.zoneopt b/doc/misc/secondary.zoneopt index c4de3866a7..6139782989 100644 --- a/doc/misc/secondary.zoneopt +++ b/doc/misc/secondary.zoneopt @@ -8,6 +8,7 @@ zone [ ] { also-notify [ port ] [ source ( | * ) ] [ source-v6 ( | * ) ] { ( | [ port ] | [ port ] ) [ key ] [ tls ]; ... }; auto-dnssec ( allow | maintain | off ); // deprecated check-names ( fail | warn | ignore ); + checkds ( explicit | ); database ; dialup ( notify | notify-passive | passive | refresh | ); dlz ; diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index 13c65c6920..7109f759a9 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -193,6 +193,12 @@ typedef enum { dns_dbtree_nsec3 = 2 } dns_dbtree_t; +typedef enum { + dns_checkdstype_no = 0, + dns_checkdstype_yes = 1, + dns_checkdstype_explicit = 2 +} dns_checkdstype_t; + typedef enum { dns_notifytype_no = 0, dns_notifytype_yes = 1, diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index aa765ac21e..0394718c23 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -1492,6 +1492,12 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype); * Sets zone notify method to "notifytype" */ +void +dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype); +/*%< + * Sets zone checkds method to "checkdstype" + */ + isc_result_t dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, dns_updatecallback_t callback, void *callback_arg); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 3fd2783009..a131314e85 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -312,6 +312,7 @@ struct dns_zone { dns_remote_t parentals; dns_dnsseckeylist_t checkds_ok; + dns_checkdstype_t checkdstype; dns_remote_t notify; dns_notifytype_t notifytype; @@ -1062,6 +1063,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) { .minrefresh = DNS_ZONE_MINREFRESH, .maxretry = DNS_ZONE_MAXRETRY, .minretry = DNS_ZONE_MINRETRY, + .checkdstype = dns_checkdstype_explicit, .notifytype = dns_notifytype_yes, .zero_no_soa_ttl = true, .check_names = dns_severity_ignore, @@ -1395,6 +1397,15 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) { UNLOCK_ZONE(zone); } +void +dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) { + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + zone->checkdstype = checkdstype; + UNLOCK_ZONE(zone); +} + isc_result_t dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) { isc_result_t result; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 2f0363a3a3..7239e39b16 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -91,6 +91,7 @@ static cfg_type_t cfg_type_bracketed_netaddrlist; static cfg_type_t cfg_type_bracketed_sockaddrnameportlist; static cfg_type_t cfg_type_bracketed_sockaddrtlslist; static cfg_type_t cfg_type_bracketed_http_endpoint_list; +static cfg_type_t cfg_type_checkdstype; static cfg_type_t cfg_type_controls; static cfg_type_t cfg_type_controls_sockaddr; static cfg_type_t cfg_type_destinationlist; @@ -2182,6 +2183,24 @@ static cfg_type_t cfg_type_validityinterval = { cfg_doc_tuple, &cfg_rep_tuple, validityinterval_fields }; +/*% + * Checkds type. + */ +static const char *checkds_enums[] = { "explicit", NULL }; +static isc_result_t +parse_checkds_type(cfg_parser_t *pctx, const cfg_type_t *type, + cfg_obj_t **ret) { + return (cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret)); +} +static void +doc_checkds_type(cfg_printer_t *pctx, const cfg_type_t *type) { + cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean); +} +static cfg_type_t cfg_type_checkdstype = { + "checkdstype", parse_checkds_type, cfg_print_ustring, + doc_checkds_type, &cfg_rep_string, checkds_enums, +}; + /*% * Clauses that can be found in a 'dnssec-policy' statement. */ @@ -2375,6 +2394,8 @@ static cfg_clausedef_t zone_only_clauses[] = { { "check-names", &cfg_type_checkmode, CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_HINT | CFG_ZONE_STUB }, + { "checkds", &cfg_type_checkdstype, + CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY }, { "database", &cfg_type_astring, CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },