From 856c0e78a9041b9c532b56de9ad01acdc50bd140 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 10 Aug 2022 15:24:21 +0200 Subject: [PATCH 1/5] Test checkconf NSEC3 and incompatible algorithm The check code for this already exists, but was untested. --- .../system/checkconf/bad-kasp-nsec3-alg.conf | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf diff --git a/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.conf new file mode 100644 index 0000000000..ff25ecea38 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-nsec3-alg.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. + */ + +dnssec-policy "badnsec3alg" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; + nsec3param iterations 0 optout 0 salt-length 0; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy "badnsec3alg"; +}; From 501dc87d75386d50bb713ae3c23c1122e6a5af57 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 10 Aug 2022 15:29:59 +0200 Subject: [PATCH 2/5] Wait with NSEC3 during a DNSSEC policy change When doing a dnssec-policy reconfiguration from a zone with NSEC only keys to a zone that uses NSEC3, figure out to wait with building the NSEC3 chain. Previously, BIND 9 would attempt to sign such a zone, but failed to do so because the NSEC3 chain conflicted with existing DNSKEY records in the zone that were not compatible with NSEC3. There exists logic for detecting such a case in the functions dnskey_sane() (in lib/dns/zone.c) and check_dnssec() (in lib/ns/update.c). Both functions look very similar so refactor them to use the same code and call the new function (called dns_zone_check_dnskey_nsec3()). Also update the dns_nsec_nseconly() function to take an additional parameter 'diff' that, if provided, will be checked whether an offending NSEC only DNSKEY will be deleted from the zone. If so, this key will not be considered when checking the zone for NSEC only DNSKEYs. This is needed to allow a transition from an NSEC zone with NSEC only DNSKEYs to an NSEC3 zone. --- bin/dnssec/dnssec-signzone.c | 2 +- lib/dns/include/dns/nsec.h | 7 +- lib/dns/include/dns/zone.h | 18 ++++ lib/dns/nsec.c | 34 ++++++- lib/dns/zone.c | 192 +++++++++++++++++++++++------------ lib/ns/update.c | 51 +--------- 6 files changed, 189 insertions(+), 115 deletions(-) diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 889ca79ab5..1780a93ae8 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -3901,7 +3901,7 @@ main(int argc, char *argv[]) { hashlist_init(&hashlist, dns_db_nodecount(gdb, dns_dbtree_main) * 2, hash_length); - result = dns_nsec_nseconly(gdb, gversion, &answer); + result = dns_nsec_nseconly(gdb, gversion, NULL, &answer); if (result == ISC_R_NOTFOUND) { fprintf(stderr, "%s: warning: NSEC3 generation " diff --git a/lib/dns/include/dns/nsec.h b/lib/dns/include/dns/nsec.h index 04029e2ff6..e68ea35ebf 100644 --- a/lib/dns/include/dns/nsec.h +++ b/lib/dns/include/dns/nsec.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -60,11 +61,15 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type); */ isc_result_t -dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, bool *answer); +dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, dns_diff_t *diff, + bool *answer); /* * Report whether the DNSKEY RRset has a NSEC only algorithm. Unknown * algorithms are assumed to support NSEC3. If DNSKEY is not found, * *answer is set to false, and ISC_R_NOTFOUND is returned. + * If 'diff' is provided, check if the NSEC only DNSKEY will be deleted. + * If so, and there are no other NSEC only DNSKEYs that will stay in 'db', + * consider the DNSKEY RRset to have no NSEC only DNSKEYs. * * Requires: * 'answer' to be non NULL. diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index c9a1487928..0f035cf5a8 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -2761,3 +2762,20 @@ dns_zone_gettid(dns_zone_t *zone); * * \return thread id associated with the zone */ + +bool +dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_diff_t *diff, + dst_key_t **keys, unsigned int numkeys); +/**< + * Return whether the zone would enter an inconsistent state where NSEC only + * DNSKEYs are present along NSEC3 chains. + * + * Requires: + * \li 'zone' to be a valid zone. + * \li 'db'is not NULL. + * + * Returns: + * \li 'true' if the check passes, that is the zone remains consistent, + * 'false' if the zone would have NSEC only DNSKEYs and an NSEC3 chain. + */ diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index afbe9c80f9..84c47d6c21 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -247,7 +247,8 @@ dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) { } isc_result_t -dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, bool *answer) { +dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, dns_diff_t *diff, + bool *answer) { dns_dbnode_t *node = NULL; dns_rdataset_t rdataset; dns_rdata_dnskey_t dnskey; @@ -282,8 +283,35 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version, bool *answer) { RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dnskey.algorithm == DST_ALG_RSAMD5 || - dnskey.algorithm == DST_ALG_RSASHA1) { - break; + dnskey.algorithm == DST_ALG_DH || + dnskey.algorithm == DST_ALG_DSA || + dnskey.algorithm == DST_ALG_RSASHA1) + { + bool deleted = false; + if (diff != NULL) { + for (dns_difftuple_t *tuple = + ISC_LIST_HEAD(diff->tuples); + tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) + { + if (tuple->rdata.type != + dns_rdatatype_dnskey || + tuple->op != DNS_DIFFOP_DEL) { + continue; + } + + if (dns_rdata_compare( + &rdata, &tuple->rdata) == 0) + { + deleted = true; + break; + } + } + } + + if (!deleted) { + break; + } } } dns_rdataset_disassociate(&rdataset); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d932b1b841..600fad94e5 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -3726,7 +3726,7 @@ zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) { * latter to exist in the first place. */ dns_db_currentversion(db, &version); - result = dns_nsec_nseconly(db, version, &nseconly); + result = dns_nsec_nseconly(db, version, NULL, &nseconly); nsec3ok = (result == ISC_R_SUCCESS && !nseconly); dns_db_closeversion(db, &version, false); if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) { @@ -3918,7 +3918,7 @@ resume_addnsec3chain(dns_zone_t *zone) { * In order to create NSEC3 chains we need the DNSKEY RRset at zone * apex to exist and contain no keys using NSEC-only algorithms. */ - result = dns_nsec_nseconly(db, version, &nseconly); + result = dns_nsec_nseconly(db, version, NULL, &nseconly); nsec3ok = (result == ISC_R_SUCCESS && !nseconly); /* @@ -8186,7 +8186,7 @@ try_private: goto add; } - result = dns_nsec_nseconly(db, ver, &nseconly); + result = dns_nsec_nseconly(db, ver, diff, &nseconly); nsec3ok = (result == ISC_R_SUCCESS && !nseconly); /* @@ -9508,6 +9508,105 @@ failure: return (result); } +/* + * Prevent the zone entering a inconsistent state where + * NSEC only DNSKEYs are present with NSEC3 chains. + */ +bool +dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db, + dns_dbversion_t *ver, dns_diff_t *diff, + dst_key_t **keys, unsigned int numkeys) { + uint8_t alg; + dns_rdatatype_t privatetype; + ; + bool nseconly = false, nsec3 = false; + isc_result_t result; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(db != NULL); + + privatetype = dns_zone_getprivatetype(zone); + + /* Scan the tuples for an NSEC-only DNSKEY */ + if (diff != NULL) { + for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples); + tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link)) + { + if (nseconly && nsec3) { + break; + } + + if (tuple->op != DNS_DIFFOP_ADD) { + continue; + } + + if (tuple->rdata.type == dns_rdatatype_nsec3param) { + nsec3 = true; + } + + if (tuple->rdata.type != dns_rdatatype_dnskey) { + continue; + } + + alg = tuple->rdata.data[3]; + if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH || + alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1) + { + nseconly = true; + } + } + } + /* Scan the zone keys for an NSEC-only DNSKEY */ + if (keys != NULL && !nseconly) { + for (unsigned int i = 0; i < numkeys; i++) { + alg = dst_key_alg(keys[i]); + if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH || + alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1) + { + nseconly = true; + break; + } + } + } + + /* Check DB for NSEC-only DNSKEY */ + if (!nseconly) { + result = dns_nsec_nseconly(db, ver, diff, &nseconly); + /* + * Adding an NSEC3PARAM record can proceed without a + * DNSKEY (it will trigger a delayed change), so we can + * ignore ISC_R_NOTFOUND here. + */ + if (result == ISC_R_NOTFOUND) { + result = ISC_R_SUCCESS; + } + CHECK(result); + } + + /* Check existing DB for NSEC3 */ + if (!nsec3) { + CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3)); + } + + /* Check kasp for NSEC3PARAM settings */ + if (!nsec3) { + dns_kasp_t *kasp = dns_zone_getkasp(zone); + if (kasp != NULL) { + nsec3 = dns_kasp_nsec3(kasp); + } + } + + /* Refuse to allow NSEC3 with NSEC-only keys */ + if (nseconly && nsec3) { + goto failure; + } + + return (true); + +failure: + return (false); +} + /* * Incrementally sign the zone using the keys requested. * Builds the NSEC chain if required. @@ -9643,6 +9742,15 @@ zone_sign(dns_zone_t *zone) { /* Determine which type of chain to build */ if (use_kasp) { build_nsec3 = dns_kasp_nsec3(kasp); + if (!dns_zone_check_dnskey_nsec3(zone, db, version, NULL, + (dst_key_t **)&zone_keys, + nkeys)) + { + dnssec_log(zone, ISC_LOG_INFO, + "wait building NSEC3 chain until NSEC only " + "DNSKEYs are removed"); + build_nsec3 = false; + } build_nsec = !build_nsec3; } else { CHECK(dns_private_chains(db, version, zone->privatetype, @@ -20506,63 +20614,6 @@ failure: return (result); } -/* - * Prevent the zone entering a inconsistent state where - * NSEC only DNSKEYs are present with NSEC3 chains. - * See update.c:check_dnssec() - */ -static bool -dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, - dns_diff_t *diff) { - isc_result_t result; - dns_difftuple_t *tuple; - bool nseconly = false, nsec3 = false; - dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - - /* Scan the tuples for an NSEC-only DNSKEY */ - for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; - tuple = ISC_LIST_NEXT(tuple, link)) - { - uint8_t alg; - if (tuple->rdata.type != dns_rdatatype_dnskey || - tuple->op != DNS_DIFFOP_ADD) { - continue; - } - - alg = tuple->rdata.data[3]; - if (alg == DST_ALG_RSASHA1) { - nseconly = true; - break; - } - } - - /* Check existing DB for NSEC-only DNSKEY */ - if (!nseconly) { - result = dns_nsec_nseconly(db, ver, &nseconly); - if (result == ISC_R_NOTFOUND) { - result = ISC_R_SUCCESS; - } - CHECK(result); - } - - /* Check existing DB for NSEC3 */ - if (!nsec3) { - CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3)); - } - - /* Refuse to allow NSEC3 with NSEC-only keys */ - if (nseconly && nsec3) { - dnssec_log(zone, ISC_LOG_ERROR, - "NSEC only DNSKEYs and NSEC3 chains not allowed"); - goto failure; - } - - return (true); - -failure: - return (false); -} - static isc_result_t clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { @@ -21558,6 +21609,7 @@ zone_rekey(dns_zone_t *zone) { if (result == ISC_R_SUCCESS) { bool cdsdel = false; bool cdnskeydel = false; + bool sane_diff, sane_dnskey; isc_stdtime_t when; /* @@ -21726,9 +21778,21 @@ zone_rekey(dns_zone_t *zone) { } } - if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) && - dnskey_sane(zone, db, ver, &diff)) - { + /* + * A sane diff is one that is not empty, and that does not + * introduce a zone with NSEC only DNSKEYs along with NSEC3 + * chains. + */ + sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff, + NULL, 0); + sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey; + if (!sane_dnskey) { + dnssec_log(zone, ISC_LOG_ERROR, + "NSEC only DNSKEYs and NSEC3 chains not " + "allowed"); + } + + if (newactive || fullsign || sane_diff) { CHECK(dns_diff_apply(&diff, db, ver)); CHECK(clean_nsec3param(zone, db, ver, &diff)); CHECK(add_signing_records(db, zone->privatetype, ver, @@ -22913,7 +22977,7 @@ rss_post(dns_zone_t *zone, isc_event_t *event) { dns_rdata_init(&rdata); np->data[2] |= DNS_NSEC3FLAG_CREATE; - result = dns_nsec_nseconly(db, newver, &nseconly); + result = dns_nsec_nseconly(db, newver, NULL, &nseconly); if (result == ISC_R_NOTFOUND || nseconly) { np->data[2] |= DNS_NSEC3FLAG_INITIAL; } diff --git a/lib/ns/update.c b/lib/ns/update.c index 28b59a5484..4b32b7508f 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -2096,56 +2096,12 @@ failure: static isc_result_t check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff) { - dns_difftuple_t *tuple; - bool nseconly = false, nsec3 = false; isc_result_t result; unsigned int iterations = 0; dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ - for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; - tuple = ISC_LIST_NEXT(tuple, link)) - { - if (tuple->op != DNS_DIFFOP_ADD) { - continue; - } - - if (tuple->rdata.type == dns_rdatatype_dnskey) { - uint8_t alg; - alg = tuple->rdata.data[3]; - if (alg == DST_ALG_RSASHA1) { - nseconly = true; - break; - } - } else if (tuple->rdata.type == dns_rdatatype_nsec3param) { - nsec3 = true; - break; - } - } - - /* Check existing DB for NSEC-only DNSKEY */ - if (!nseconly) { - result = dns_nsec_nseconly(db, ver, &nseconly); - - /* - * An NSEC3PARAM update can proceed without a DNSKEY (it - * will trigger a delayed change), so we can ignore - * ISC_R_NOTFOUND here. - */ - if (result == ISC_R_NOTFOUND) { - result = ISC_R_SUCCESS; - } - - CHECK(result); - } - - /* Check existing DB for NSEC3 */ - if (!nsec3) { - CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3)); - } - /* Refuse to allow NSEC3 with NSEC-only keys */ - if (nseconly && nsec3) { + if (!dns_zone_check_dnskey_nsec3(zone, db, ver, diff, NULL, 0)) { update_log(client, zone, ISC_LOG_ERROR, "NSEC only DNSKEYs and NSEC3 chains not allowed"); result = DNS_R_REFUSED; @@ -2346,8 +2302,11 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, * supporting an NSEC3 chain, then we set the * INITIAL flag to indicate that these parameters * are to be used later. + * + * Don't provide a 'diff' here because we want to + * know the capability of the current database. */ - result = dns_nsec_nseconly(db, ver, &nseconly); + result = dns_nsec_nseconly(db, ver, NULL, &nseconly); if (result == ISC_R_NOTFOUND || nseconly) { buf[2] |= DNS_NSEC3FLAG_INITIAL; } From 6e534c1cd149422cf57bd7984f8ed0c455663598 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 10 Aug 2022 16:41:30 +0200 Subject: [PATCH 3/5] Add test case for #3486 Add two scenarios where we change the dnssec-policy from using RSASHA1 to something with NSEC3. The first case should work, as the DS is still in hidden state and we can basically do anything with DNSSEC. The second case should fail, because the DS of the predecessor is published and we can't immediately remove the predecessor DNSKEY. So in this case we should keep the NSEC chain for a bit longer. Add two more scenarios where we change the dnssec-policy from using NSEC3 to something NSEC only. Both should work because there are no restrictions on using NSEC when it comes to algorithms, but in the cases where the DS is published we can't bluntly remove the predecessor. Extend the nsec3 system test by also checking the DNSKEY RRset for the expected DNSKEY records. This requires some "kasp system"-style setup for each test (setting key properties and key states). Also move the dnssec-verify check inside the check_nsec/check_nsec3 functions because we will have to do that every time. --- bin/tests/system/nsec3/clean.sh | 5 +- bin/tests/system/nsec3/ns3/named.conf.in | 56 +++++ bin/tests/system/nsec3/ns3/named2.conf.in | 59 +++++ bin/tests/system/nsec3/ns3/setup.sh | 25 ++ bin/tests/system/nsec3/tests.sh | 269 +++++++++++++++++----- 5 files changed, 356 insertions(+), 58 deletions(-) diff --git a/bin/tests/system/nsec3/clean.sh b/bin/tests/system/nsec3/clean.sh index 6383f29bea..d6b11e749b 100644 --- a/bin/tests/system/nsec3/clean.sh +++ b/bin/tests/system/nsec3/clean.sh @@ -13,9 +13,10 @@ set -e -rm -f dig.out.* rndc.signing.* +rm -f dig.out.* rndc.signing.* verify.out.* rm -f ns*/named.conf ns*/named.memstats ns*/named.run* rm -f ns*/*.jnl ns*/*.jbk ns*/managed-keys.bind rm -f ns*/K*.private ns*/K*.key ns*/K*.state rm -f ns*/dsset-* ns*/*.db ns*/*.db.signed - +rm -f ns*/keygen.out.* ns*/settime.out.* +rm -f created.key-* *.created unused.key-* diff --git a/bin/tests/system/nsec3/ns3/named.conf.in b/bin/tests/system/nsec3/ns3/named.conf.in index 36c217ad3c..c94fa5d679 100644 --- a/bin/tests/system/nsec3/ns3/named.conf.in +++ b/bin/tests/system/nsec3/ns3/named.conf.in @@ -18,6 +18,12 @@ dnssec-policy "nsec" { // NSEC will be used; }; +dnssec-policy "rsasha1" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; +}; + dnssec-policy "nsec3" { nsec3param; }; @@ -59,6 +65,56 @@ zone "nsec-to-nsec3.kasp" { dnssec-policy "nsec"; }; +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should work despite the incompatible RSAHSHA1 algorithm, + * because the DS is still in hidden state. + */ +zone "rsasha1-to-nsec3.kasp" { + type primary; + file "rsasha1-to-nsec3.kasp.db"; + inline-signing yes; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should block because RSASHA1 is not compatible with NSEC3, + * and the DS is published. + */ +zone "rsasha1-to-nsec3-wait.kasp" { + type primary; + file "rsasha1-to-nsec3-wait.kasp.db"; + inline-signing yes; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should work despite the incompatible RSAHSHA1 + * algorithm, because the DS is still in hidden state. + */ +zone "nsec3-to-rsasha1.kasp" { + type primary; + file "nsec3-to-rsasha1.kasp.db"; + inline-signing yes; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should also be fine because we are allowed + * to change to NSEC with any algorithm, then we can also publish the new + * DNSKEY and signatures of the RSASHA1 algorithm. + */ +zone "nsec3-to-rsasha1-ds.kasp" { + type primary; + file "nsec3-to-rsasha1-ds.kasp.db"; + inline-signing yes; + dnssec-policy "nsec3"; +}; + + /* These zones use the default NSEC3 settings. */ zone "nsec3.kasp" { type primary; diff --git a/bin/tests/system/nsec3/ns3/named2.conf.in b/bin/tests/system/nsec3/ns3/named2.conf.in index c81cd70049..d9764abcad 100644 --- a/bin/tests/system/nsec3/ns3/named2.conf.in +++ b/bin/tests/system/nsec3/ns3/named2.conf.in @@ -18,6 +18,12 @@ dnssec-policy "nsec" { // NSEC will be used; }; +dnssec-policy "rsasha1" { + keys { + csk lifetime unlimited algorithm rsasha1; + }; +}; + dnssec-policy "nsec3" { nsec3param; }; @@ -60,6 +66,59 @@ zone "nsec-to-nsec3.kasp" { dnssec-policy "nsec3"; }; +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should work despite the incompatible RSAHSHA1 algorithm, + * because the DS is still in hidden state. + */ +zone "rsasha1-to-nsec3.kasp" { + type primary; + file "rsasha1-to-nsec3.kasp.db"; + inline-signing yes; + //dnssec-policy "rsasha1"; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC, but will be reconfigured to use NSEC3. + * This should block because RSASHA1 is not compatible with NSEC3, + * and the DS is published. + */ +zone "rsasha1-to-nsec3-wait.kasp" { + type primary; + file "rsasha1-to-nsec3-wait.kasp.db"; + inline-signing yes; + //dnssec-policy "rsasha1"; + dnssec-policy "nsec3"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should work despite the incompatible RSAHSHA1 + * algorithm, because the DS is still in hidden state. + */ +zone "nsec3-to-rsasha1.kasp" { + type primary; + file "nsec3-to-rsasha1.kasp.db"; + inline-signing yes; + //dnssec-policy "nsec3"; + dnssec-policy "rsasha1"; +}; + +/* + * This zone starts with NSEC3, but will be reconfigured to use NSEC with an + * NSEC only algorithm. This should also be fine because we are allowed + * to change to NSEC with any algorithm, then we can also publish the new + * DNSKEY and signatures of the RSASHA1 algorithm. + */ +zone "nsec3-to-rsasha1-ds.kasp" { + type primary; + file "nsec3-to-rsasha1-ds.kasp.db"; + inline-signing yes; + //dnssec-policy "nsec3"; + dnssec-policy "rsasha1"; +}; + /* These zones use the default NSEC3 settings. */ zone "nsec3.kasp" { type primary; diff --git a/bin/tests/system/nsec3/ns3/setup.sh b/bin/tests/system/nsec3/ns3/setup.sh index cbaf84ce8d..e2478ac3df 100644 --- a/bin/tests/system/nsec3/ns3/setup.sh +++ b/bin/tests/system/nsec3/ns3/setup.sh @@ -30,4 +30,29 @@ do setup "${zn}.kasp" done +if (cd ..; $SHELL ../testcrypto.sh -q RSASHA1) +then + for zn in rsasha1-to-nsec3 rsasha1-to-nsec3-wait nsec3-to-rsasha1 \ + nsec3-to-rsasha1-ds + do + setup "${zn}.kasp" + done + + longago="now-1y" + keytimes="-P ${longago} -A ${longago}" + O="omnipresent" + + zone="rsasha1-to-nsec3-wait.kasp" + CSK=$($KEYGEN -k "rsasha1" -l named.conf $keytimes $zone 2> keygen.out.$zone) + echo_i "Created key file $CSK" + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" > settime.out.$zone 2>&1 + + zone="nsec3-to-rsasha1-ds.kasp" + CSK=$($KEYGEN -k "default" -l named.conf $keytimes $zone 2> keygen.out.$zone) + echo_i "Created key file $CSK" + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" > settime.out.$zone 2>&1 +else + echo_i "skip: skip rsasha1 zones - signing with RSASHA1 not supported" +fi + cp nsec3-fails-to-load.kasp.db.in nsec3-fails-to-load.kasp.db diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh index d9c2b83d17..f5865d5ab1 100644 --- a/bin/tests/system/nsec3/tests.sh +++ b/bin/tests/system/nsec3/tests.sh @@ -36,6 +36,8 @@ rndccmd() { set_zone_policy() { ZONE=$1 POLICY=$2 + NUM_KEYS=$3 + DNSKEY_TTL=$4 } # Set expected NSEC3 parameters: flags ($1), iterations ($2), and # salt length ($3). @@ -47,6 +49,49 @@ set_nsec3param() { SALT="" } +# Set expected default dnssec-policy keys values. +set_key_default_values() { + key_clear $1 + + set_keyrole $1 "csk" + set_keylifetime $1 "0" + set_keyalgorithm $1 "13" "ECDSAP256SHA256" "256" + set_keysigning $1 "yes" + set_zonesigning $1 "yes" + + set_keystate $1 "GOAL" "omnipresent" + set_keystate $1 "STATE_DNSKEY" "rumoured" + set_keystate $1 "STATE_KRRSIG" "rumoured" + set_keystate $1 "STATE_ZRRSIG" "rumoured" + set_keystate $1 "STATE_DS" "hidden" +} + +# Set expected rsasha1 dnssec-policy keys values. +set_key_rsasha1_values() { + key_clear $1 + + set_keyrole $1 "csk" + set_keylifetime $1 "0" + set_keyalgorithm $1 "5" "RSASHA1" "2048" + set_keysigning $1 "yes" + set_zonesigning $1 "yes" + + set_keystate $1 "GOAL" "omnipresent" + set_keystate $1 "STATE_DNSKEY" "rumoured" + set_keystate $1 "STATE_KRRSIG" "rumoured" + set_keystate $1 "STATE_ZRRSIG" "rumoured" + set_keystate $1 "STATE_DS" "hidden" +} + +# Update the key states. +set_key_states() { + set_keystate $1 "GOAL" "$2" + set_keystate $1 "STATE_DNSKEY" "$3" + set_keystate $1 "STATE_KRRSIG" "$4" + set_keystate $1 "STATE_ZRRSIG" "$5" + set_keystate $1 "STATE_DS" "$6" +} + # The apex NSEC3PARAM record indicates that it is signed. _wait_for_nsec3param() { dig_with_opts +noquestion "@${SERVER}" "$ZONE" NSEC3PARAM > "dig.out.test$n.wait" || return 1 @@ -79,24 +124,43 @@ wait_for_zone_is_signed() { status=$((status+ret)) } +# Test: check DNSSEC verify +_check_dnssec_verify() { + dig_with_opts @$SERVER "${ZONE}" AXFR > "dig.out.test$n.axfr.$ZONE" || return 1 + $VERIFY -z -o "$ZONE" "dig.out.test$n.axfr.$ZONE" > "verify.out.test$n.$ZONE" 2>&1 || return 1 + return 0 +} + # Test: check NSEC in answers -_check_nsec_nsec3param() -{ +_check_nsec_nsec3param() { dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1 grep "NSEC3PARAM" "dig.out.test$n.nsec3param.$ZONE" > /dev/null && return 1 return 0 } -_check_nsec_nxdomain() -{ +_check_nsec_nxdomain() { dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1 grep "${ZONE}.*IN.*NSEC.*NS.*SOA.*RRSIG.*NSEC.*DNSKEY" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1 grep "NSEC3" "dig.out.test$n.nxdomain.$ZONE" > /dev/null && return 1 return 0 } -check_nsec() -{ +check_nsec() { + n=$((n+1)) + echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)" + ret=0 + check_keys + retry_quiet 10 _check_apex_dnskey || log_error "bad DNSKEY RRset for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + + n=$((n+1)) + echo_i "verify DNSSEC for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + n=$((n+1)) echo_i "check NSEC3PARAM response for zone ${ZONE} ($n)" ret=0 @@ -113,8 +177,7 @@ check_nsec() } # Test: check NSEC3 parameters in answers -_check_nsec3_nsec3param() -{ +_check_nsec3_nsec3param() { dig_with_opts +noquestion @$SERVER "${ZONE}" NSEC3PARAM > "dig.out.test$n.nsec3param.$ZONE" || return 1 grep "${ZONE}.*0.*IN.*NSEC3PARAM.*1.*0.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nsec3param.$ZONE" > /dev/null || return 1 @@ -124,15 +187,13 @@ _check_nsec3_nsec3param() return 0 } -_check_nsec3_nxdomain() -{ +_check_nsec3_nxdomain() { dig_with_opts @$SERVER "nosuchname.${ZONE}" > "dig.out.test$n.nxdomain.$ZONE" || return 1 grep ".*\.${ZONE}.*IN.*NSEC3.*1.${FLAGS}.*${ITERATIONS}.*${SALT}" "dig.out.test$n.nxdomain.$ZONE" > /dev/null || return 1 return 0 } -check_nsec3() -{ +check_nsec3() { n=$((n+1)) echo_i "check that NSEC3PARAM 1 0 ${ITERATIONS} is published zone ${ZONE} ($n)" ret=0 @@ -146,74 +207,119 @@ check_nsec3() retry_quiet 10 _check_nsec3_nxdomain || log_error "bad NXDOMAIN response for zone ${ZONE}" test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) + + n=$((n+1)) + echo_i "verify DNSSEC for zone ${ZONE} ($n)" + ret=0 + retry_quiet 10 _check_dnssec_verify || log_error "DNSSEC verify failed for zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) } start_time="$(TZ=UTC date +%s)" status=0 n=0 +key_clear "KEY1" +key_clear "KEY2" +key_clear "KEY3" +key_clear "KEY4" + # Zone: nsec-to-nsec3.kasp. -set_zone_policy "nsec-to-nsec3.kasp" "nsec" +set_zone_policy "nsec-to-nsec3.kasp" "nsec" 1 3600 set_server "ns3" "10.53.0.3" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec -dnssec_verify + +if ($SHELL ../testcrypto.sh -q RSASHA1) +then + # Zone: rsasha1-to-nsec3.kasp. + set_zone_policy "rsasha1-to-nsec3.kasp" "rsasha1" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + echo_i "initial check zone ${ZONE}" + check_nsec + + # Zone: rsasha1-to-nsec3-wait.kasp. + set_zone_policy "rsasha1-to-nsec3-wait.kasp" "rsasha1" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + echo_i "initial check zone ${ZONE}" + check_nsec + + # Zone: nsec3-to-rsasha1.kasp. + set_zone_policy "nsec3-to-rsasha1.kasp" "nsec3" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + echo_i "initial check zone ${ZONE}" + check_nsec3 + + # Zone: nsec3-to-rsasha1-ds.kasp. + set_zone_policy "nsec3-to-rsasha1-ds.kasp" "nsec3" 1 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + echo_i "initial check zone ${ZONE}" + check_nsec3 +fi # Zone: nsec3.kasp. -set_zone_policy "nsec3.kasp" "nsec3" +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-dynamic.kasp. -set_zone_policy "nsec3-dynamic.kasp" "nsec3" +set_zone_policy "nsec3-dynamic.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-change.kasp. -set_zone_policy "nsec3-change.kasp" "nsec3" +set_zone_policy "nsec3-change.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-dynamic-change.kasp. -set_zone_policy "nsec3-dynamic-change.kasp" "nsec3" +set_zone_policy "nsec3-dynamic-change.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-to-nsec.kasp. -set_zone_policy "nsec3-to-nsec.kasp" "nsec3" +set_zone_policy "nsec3-to-nsec.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-to-optout.kasp. -set_zone_policy "nsec3-to-optout.kasp" "nsec3" +set_zone_policy "nsec3-to-optout.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-from-optout.kasp. -set_zone_policy "nsec3-from-optout.kasp" "optout" +set_zone_policy "nsec3-from-optout.kasp" "optout" 1 3600 set_nsec3param "1" "0" "0" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Zone: nsec3-other.kasp. -set_zone_policy "nsec3-other.kasp" "nsec3-other" +set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600 set_nsec3param "1" "11" "8" +set_key_default_values "KEY1" echo_i "initial check zone ${ZONE}" check_nsec3 -dnssec_verify # Reconfig named. echo_i "reconfig dnssec-policy to trigger nsec3 rollovers" @@ -221,88 +327,139 @@ copy_setports ns3/named2.conf.in ns3/named.conf rndc_reconfig ns3 10.53.0.3 # Zone: nsec-to-nsec3.kasp. (reconfigured) -set_zone_policy "nsec-to-nsec3.kasp" "nsec3" +set_zone_policy "nsec-to-nsec3.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify + +if ($SHELL ../testcrypto.sh -q RSASHA1) +then + # Zone: rsasha1-to-nsec3.kasp. + set_zone_policy "rsasha1-to-nsec3.kasp" "nsec3" 2 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "hidden" "unretentive" "unretentive" "unretentive" "hidden" + set_keysigning "KEY1" "no" + set_zonesigning "KEY1" "no" + set_key_default_values "KEY2" + echo_i "check zone ${ZONE} after reconfig" + check_nsec3 + + # Zone: rsasha1-to-nsec3-wait.kasp. + set_zone_policy "rsasha1-to-nsec3-wait.kasp" "nsec3" 2 3600 + set_server "ns3" "10.53.0.3" + set_key_rsasha1_values "KEY1" + set_key_states "KEY1" "hidden" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + set_key_default_values "KEY2" + echo_i "check zone ${ZONE} after reconfig" + + ret=0 + wait_for_log 10 "zone $ZONE/IN (signed): wait building NSEC3 chain until NSEC only DNSKEYs are removed" ns3/named.run || ret=1 + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + + check_nsec + + # Zone: nsec3-to-rsasha1.kasp. + set_zone_policy "nsec3-to-rsasha1.kasp" "rsasha1" 2 3600 + set_server "ns3" "10.53.0.3" + set_key_default_values "KEY1" + set_key_states "KEY1" "hidden" "unretentive" "unretentive" "unretentive" "hidden" + set_keysigning "KEY1" "no" + set_zonesigning "KEY1" "no" + set_key_rsasha1_values "KEY2" + echo_i "check zone ${ZONE} after reconfig" + check_nsec + + # Zone: nsec3-to-rsasha1-ds.kasp. + set_zone_policy "nsec3-to-rsasha1-ds.kasp" "rsasha1" 2 3600 + set_server "ns3" "10.53.0.3" + set_key_default_values "KEY1" + set_key_states "KEY1" "hidden" "omnipresent" "omnipresent" "omnipresent" "omnipresent" + set_key_rsasha1_values "KEY2" + echo_i "check zone ${ZONE} after reconfig" + check_nsec + + key_clear "KEY1" + key_clear "KEY2" +fi # Zone: nsec3.kasp. (same) -set_zone_policy "nsec3.kasp" "nsec3" +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify # Zone: nsec3-dyamic.kasp. (same) -set_zone_policy "nsec3-dynamic.kasp" "nsec3" +set_zone_policy "nsec3-dynamic.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify # Zone: nsec3-change.kasp. (reconfigured) -set_zone_policy "nsec3-change.kasp" "nsec3-other" +set_zone_policy "nsec3-change.kasp" "nsec3-other" 1 3600 set_nsec3param "1" "11" "8" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify # Zone: nsec3-dynamic-change.kasp. (reconfigured) -set_zone_policy "nsec3-dynamic-change.kasp" "nsec3-other" +set_zone_policy "nsec3-dynamic-change.kasp" "nsec3-other" 1 3600 set_nsec3param "1" "11" "8" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify # Zone: nsec3-to-nsec.kasp. (reconfigured) -set_zone_policy "nsec3-to-nsec.kasp" "nsec" +set_zone_policy "nsec3-to-nsec.kasp" "nsec" 1 3600 set_nsec3param "1" "11" "8" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec -dnssec_verify # Zone: nsec3-to-optout.kasp. (reconfigured) # DISABLED: # There is a bug in the nsec3param building code that thinks when the # optout bit is changed, the chain already exists. [GL #2216] -#set_zone_policy "nsec3-to-optout.kasp" "optout" +#set_zone_policy "nsec3-to-optout.kasp" "optout" 1 3600 #set_nsec3param "1" "0" "0" +#set_key_default_values "KEY1" #echo_i "check zone ${ZONE} after reconfig" #check_nsec3 -#dnssec_verify # Zone: nsec3-from-optout.kasp. (reconfigured) # DISABLED: # There is a bug in the nsec3param building code that thinks when the # optout bit is changed, the chain already exists. [GL #2216] -#set_zone_policy "nsec3-from-optout.kasp" "nsec3" +#set_zone_policy "nsec3-from-optout.kasp" "nsec3" 1 3600 #set_nsec3param "0" "0" "0" +#set_key_default_values "KEY1" #echo_i "check zone ${ZONE} after reconfig" #check_nsec3 -#dnssec_verify # Zone: nsec3-other.kasp. (same) -set_zone_policy "nsec3-other.kasp" "nsec3-other" +set_zone_policy "nsec3-other.kasp" "nsec3-other" 1 3600 set_nsec3param "1" "11" "8" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reconfig" check_nsec3 -dnssec_verify # Using rndc signing -nsec3param (should fail) -set_zone_policy "nsec3-change.kasp" "nsec3-other" +set_zone_policy "nsec3-change.kasp" "nsec3-other" 1 3600 echo_i "use rndc signing -nsec3param ${ZONE} to change NSEC3 settings" rndccmd $SERVER signing -nsec3param 1 1 12 ffff $ZONE > rndc.signing.test$n.$ZONE || log_error "failed to call rndc signing -nsec3param $ZONE" grep "zone uses dnssec-policy, use rndc dnssec command instead" rndc.signing.test$n.$ZONE > /dev/null || log_error "rndc signing -nsec3param should fail" check_nsec3 -dnssec_verify # Test NSEC3 and NSEC3PARAM is the same after restart -set_zone_policy "nsec3.kasp" "nsec3" +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} before restart" check_nsec3 -dnssec_verify # Restart named, NSEC3 should stay the same. ret=0 @@ -318,22 +475,22 @@ test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) prevsalt="${SALT}" -set_zone_policy "nsec3.kasp" "nsec3" +set_zone_policy "nsec3.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" SALT="${prevsalt}" echo_i "check zone ${ZONE} after restart has salt ${SALT}" check_nsec3 -dnssec_verify # Zone: nsec3-fails-to-load.kasp. (should be fixed after reload) cp ns3/template.db.in ns3/nsec3-fails-to-load.kasp.db rndc_reload ns3 10.53.0.3 -set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" +set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" 1 3600 set_nsec3param "0" "0" "0" +set_key_default_values "KEY1" echo_i "check zone ${ZONE} after reload" check_nsec3 -dnssec_verify echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 From 4f2a15b52ac1096ce59437c35dbebee57655d9ee Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 10 Aug 2022 16:52:53 +0200 Subject: [PATCH 4/5] Add change entry and release note for #3486 News worthy. --- CHANGES | 3 +++ doc/notes/notes-current.rst | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGES b/CHANGES index 726e201b06..27848a6f95 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +5947. [func] Change dnssec-policy to allow graceful transition from + an NSEC only zone to NSEC3. [GL #3486] + 5946. [bug] Fix statistics channel's handling of multiple HTTP requests in a single connection which have non-empty request bodies. [GL #3463] diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index ca4a6b79b6..ad45e432bc 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -38,6 +38,12 @@ Feature Changes - Zones using ``dnssec-policy`` now require dynamic DNS or ``inline-signing`` to be configured explicitly :gl:`#3381`. +- When reconfiguring ``dnssec-policy`` from using NSEC with an NSEC-only DNSKEY + algorithm (e.g. RSASHA1) to a policy that uses NSEC3, BIND will no longer fail + to sign the zone, but keep using NSEC for a little longer until the offending + DNSKEY records have been removed from the zone, then switch to using NSEC3. + :gl:`#3486` + Bug Fixes ~~~~~~~~~ From 1c5bbac5089f5404f648fe7b44b2c21576b21c81 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Fri, 19 Aug 2022 14:42:47 +0200 Subject: [PATCH 5/5] Fix nsec3 system test issues The wait_for_zone_is_signed function was never called, which could lead to test failures due to timing issues (where a zone was not fully signed yet, but the test was trying to verify the zone). Also add two missing set_nsec3param calls to ensure the ITERATIONS value is set for these test cases. --- bin/tests/system/nsec3/tests.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh index f5865d5ab1..1d9adbc3a2 100644 --- a/bin/tests/system/nsec3/tests.sh +++ b/bin/tests/system/nsec3/tests.sh @@ -112,7 +112,7 @@ _wait_for_nsec() { wait_for_zone_is_signed() { n=$((n+1)) ret=0 - echo_i "wait for ${ZONE} to be signed ($n)" + echo_i "wait for ${ZONE} to be signed with $1 ($n)" if [ "$1" = "nsec3" ]; then retry_quiet 10 _wait_for_nsec3param || log_error "wait for ${ZONE} to be signed failed" @@ -146,6 +146,8 @@ _check_nsec_nxdomain() { } check_nsec() { + wait_for_zone_is_signed "nsec" + n=$((n+1)) echo_i "check DNSKEY rrset is signed correctly for zone ${ZONE} ($n)" ret=0 @@ -194,6 +196,8 @@ _check_nsec3_nxdomain() { } check_nsec3() { + wait_for_zone_is_signed "nsec3" + n=$((n+1)) echo_i "check that NSEC3PARAM 1 0 ${ITERATIONS} is published zone ${ZONE} ($n)" ret=0 @@ -363,6 +367,7 @@ then # Zone: nsec3-to-rsasha1.kasp. set_zone_policy "nsec3-to-rsasha1.kasp" "rsasha1" 2 3600 + set_nsec3param "1" "0" "0" set_server "ns3" "10.53.0.3" set_key_default_values "KEY1" set_key_states "KEY1" "hidden" "unretentive" "unretentive" "unretentive" "hidden" @@ -374,6 +379,7 @@ then # Zone: nsec3-to-rsasha1-ds.kasp. set_zone_policy "nsec3-to-rsasha1-ds.kasp" "rsasha1" 2 3600 + set_nsec3param "1" "0" "0" set_server "ns3" "10.53.0.3" set_key_default_values "KEY1" set_key_states "KEY1" "hidden" "omnipresent" "omnipresent" "omnipresent" "omnipresent"