From 9cab1eafee7956a2e54ccd2f721f46cec977ad84 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 12 Dec 2023 13:47:30 +1100 Subject: [PATCH 01/15] Test dnssec-policy dnskey-ttl behaviour If the dnskey-ttl in the dnssec-policy doesn't match the DNSKEY's ttl then the DNSKEY, CDNSKEY and CDS rrset should be updated by named to reflect the expressed policy. Check that named does this by creating a zone with a TTL that does not match the policy's TTL and check that it is correctly updated. (cherry picked from commit f894bf661f88a273a1a4cc6bd67b839f04b6d531) --- bin/tests/system/kasp.sh | 5 ++- bin/tests/system/kasp/ns3/named-fips.conf.in | 10 +++++ bin/tests/system/kasp/ns3/setup.sh | 8 ++++ bin/tests/system/kasp/tests.sh | 42 ++++++++++++++++++++ bin/tests/system/nsec3/tests.sh | 1 + 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/bin/tests/system/kasp.sh b/bin/tests/system/kasp.sh index 26487cdbc8..d1bf51a79a 100644 --- a/bin/tests/system/kasp.sh +++ b/bin/tests/system/kasp.sh @@ -213,6 +213,7 @@ set_policy() { POLICY=$1 NUM_KEYS=$2 DNSKEY_TTL=$3 + KEYFILE_TTL=${4:-$3} CDS_DELETE="no" } # By default policies are considered to be secure. @@ -329,7 +330,7 @@ check_key() { _alg_numpad=$(printf "%03d" "$_alg_num") _alg_string=$(key_get "$1" ALG_STR) _length=$(key_get "$1" "ALG_LEN") - _dnskey_ttl="$DNSKEY_TTL" + _dnskey_ttl="$KEYFILE_TTL" _lifetime=$(key_get "$1" LIFETIME) _legacy=$(key_get "$1" LEGACY) _private=$(key_get "$1" PRIVATE) @@ -1055,7 +1056,7 @@ _find_dnskey() { _flags="$(key_get $1 FLAGS)" _key_file="$(key_get $1 BASEFILE).key" - awk '$1 == "'"$_owner"'" && $2 == "'"$DNSKEY_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' <"$_key_file" + awk '$1 == "'"$_owner"'" && $2 == "'"$KEYFILE_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' <"$_key_file" } # Test DNSKEY query. diff --git a/bin/tests/system/kasp/ns3/named-fips.conf.in b/bin/tests/system/kasp/ns3/named-fips.conf.in index 8debcd2b51..54ce749d8e 100644 --- a/bin/tests/system/kasp/ns3/named-fips.conf.in +++ b/bin/tests/system/kasp/ns3/named-fips.conf.in @@ -287,6 +287,16 @@ zone "expired-sigs.autosign" { dnssec-policy "autosign"; }; +/* + * Zone that has DNSKEY TTL mismatch with the dnssec-policy. + */ +zone "dnskey-ttl-mismatch.autosign" { + type primary; + file "dnskey-ttl-mismatch.autosign.db"; + inline-signing yes; + dnssec-policy "autosign"; +}; + /* * Zone that has valid, fresh signatures. */ diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index 41cf379734..3ab2f0da2f 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -198,6 +198,14 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" cp $infile $zonefile $SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +# The DNSKEY's TTLs do not match the policy. +setup dnskey-ttl-mismatch.autosign +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 $zsktimes $zone 2>keygen.out.$zone.2) +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +cp $infile $zonefile +$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + # These signatures are still good, and can be reused. setup fresh-sigs.autosign T="now-6mo" diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 611c7177aa..c3153f8744 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -1375,6 +1375,48 @@ check_rrsig_refresh() { check_rrsig_refresh +# +# Zone: dnskey-ttl-mismatch.autosign +# +set_zone "dnskey-ttl-mismatch.autosign" +set_policy "autosign" "2" "300" "30" +set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "63072000" +set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY1" "yes" +set_zonesigning "KEY1" "no" + +key_clear "KEY2" +set_keyrole "KEY2" "zsk" +set_keylifetime "KEY2" "31536000" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" + +# Both KSK and ZSK stay OMNIPRESENT. +set_keystate "KEY1" "GOAL" "omnipresent" +set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" +set_keystate "KEY1" "STATE_DS" "omnipresent" + +set_keystate "KEY2" "GOAL" "omnipresent" +set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" +set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" +# Expect only two keys. +key_clear "KEY3" +key_clear "KEY4" + +check_keys +check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" +set_keytimes_autosign_policy +check_keytimes +check_apex +check_subdomain +dnssec_verify + # # Zone: fresh-sigs.autosign. # diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh index fc864a437b..7a82ffc932 100644 --- a/bin/tests/system/nsec3/tests.sh +++ b/bin/tests/system/nsec3/tests.sh @@ -40,6 +40,7 @@ set_zone_policy() { POLICY=$2 NUM_KEYS=$3 DNSKEY_TTL=$4 + KEYFILE_TTL=${5:-$4} } # Set expected NSEC3 parameters: flags ($1), iterations ($2), and # salt length ($3). From 3a0b3e92bd3479cebe7b056a7f5de84a767e76c8 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 12 Dec 2023 13:47:30 +1100 Subject: [PATCH 02/15] Update the DNSKEY, CDNSKEY and CDS TTLs to match dnskey-ttl If the TTLs of the DNSKEY, CDNSKEY and CDS do not match the dnskey-ttl update them by removing all records and re-adding them with the correct TTL. (cherry picked from commit dcb7799061a7dc93d345b343145f94405d37f32b) --- lib/dns/zone.c | 113 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 8 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 729adcb6e4..990c6f876b 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -21437,6 +21437,55 @@ zone_checkds(dns_zone_t *zone) { } } +static isc_result_t +update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl, + dns_diff_t *diff) { + isc_result_t result; + + /* + * Delete everything using the existing TTL. + */ + for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_difftuple_t *tuple = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(rdataset, &rdata); + result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name, + rdataset->ttl, &rdata, &tuple); + if (result != ISC_R_SUCCESS) { + return (result); + } + dns_diff_appendminimal(diff, &tuple); + } + if (result != ISC_R_NOMORE) { + return (result); + } + + /* + * Add everything using the new TTL. + */ + for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) + { + dns_difftuple_t *tuple = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(rdataset, &rdata); + result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, + ttl, &rdata, &tuple); + if (result != ISC_R_SUCCESS) { + return (result); + } + dns_diff_appendminimal(diff, &tuple); + } + if (result != ISC_R_NOMORE) { + return (result); + } + return (ISC_R_SUCCESS); +} + static void zone_rekey(dns_zone_t *zone) { isc_result_t result; @@ -21494,11 +21543,39 @@ zone_rekey(dns_zone_t *zone) { ttl = soaset.ttl; dns_rdataset_disassociate(&soaset); + /* + * Only update DNSKEY TTL if we have a policy. + */ + if (kasp != NULL) { + ttl = dns_kasp_dnskeyttl(kasp); + } + /* Get the DNSKEY rdataset */ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, dns_rdatatype_none, 0, &keyset, &keysigs); if (result == ISC_R_SUCCESS) { - ttl = keyset.ttl; + /* + * If we don't have a policy then use the DNSKEY ttl + * if it exists. Otherwise update the DNSKEY ttl if + * needed. + */ + if (kasp == NULL) { + ttl = keyset.ttl; + } else if (ttl != keyset.ttl) { + result = update_ttl(&keyset, &zone->origin, ttl, &diff); + if (result != ISC_R_SUCCESS) { + dnssec_log(zone, ISC_LOG_ERROR, + "Updating DNSKEY TTL from %u to %u " + "failed: %s", + keyset.ttl, ttl, + isc_result_totext(result)); + goto failure; + } + dnssec_log(zone, ISC_LOG_INFO, + "Updating DNSKEY TTL from %u to %u", + keyset.ttl, ttl); + keyset.ttl = ttl; + } dns_zone_lock_keyfiles(zone); @@ -21520,6 +21597,18 @@ zone_rekey(dns_zone_t *zone) { dns_rdatatype_none, 0, &cdsset, NULL); if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) { dns_rdataset_disassociate(&cdsset); + } else if (result == ISC_R_SUCCESS && kasp != NULL && ttl != cdsset.ttl) + { + result = update_ttl(&cdsset, &zone->origin, ttl, &diff); + if (result != ISC_R_SUCCESS) { + dnssec_log(zone, ISC_LOG_ERROR, + "Updating CDS TTL from %u to %u failed: %s", + cdsset.ttl, ttl, isc_result_totext(result)); + goto failure; + } + dnssec_log(zone, ISC_LOG_INFO, "Updating CDS TTL from %u to %u", + cdsset.ttl, ttl); + cdsset.ttl = ttl; } /* Get the CDNSKEY rdataset */ @@ -21527,6 +21616,21 @@ zone_rekey(dns_zone_t *zone) { dns_rdatatype_none, 0, &cdnskeyset, NULL); if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) { dns_rdataset_disassociate(&cdnskeyset); + } else if (result == ISC_R_SUCCESS && kasp != NULL && + ttl != cdnskeyset.ttl) + { + result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff); + if (result != ISC_R_SUCCESS) { + dnssec_log( + zone, ISC_LOG_ERROR, + "Updating CDNSKEY TTL from %u to %u failed: %s", + cdnskeyset.ttl, ttl, isc_result_totext(result)); + goto failure; + } + dnssec_log(zone, ISC_LOG_INFO, + "Updating CDNSKEY TTL from %u to %u", cdnskeyset.ttl, + ttl); + cdnskeyset.ttl = ttl; } /* @@ -21659,13 +21763,6 @@ zone_rekey(dns_zone_t *zone) { } } - /* - * Only update DNSKEY TTL if we have a policy. - */ - if (kasp != NULL) { - ttl = dns_kasp_dnskeyttl(kasp); - } - result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys, &zone->origin, ttl, &diff, mctx, dnssec_report); From 5bea0d35888b61b02976b0821c5d860929dba537 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 12 Dec 2023 13:51:19 +1100 Subject: [PATCH 03/15] Use the current CDS and CDNSKEY TTLs When adding new CDS and CDNSKEY records use the existing RRset TTL if they already exist. (cherry picked from commit 21be35c54e1329556062cd772860e730bb37e1de) --- lib/dns/dnssec.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 5678c05cbd..7384c65e1b 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1983,6 +1983,19 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, unsigned char keybuf[DST_KEY_MAXSIZE]; isc_result_t result; dns_dnsseckey_t *key; + dns_ttl_t cdsttl = ttl; + dns_ttl_t cdnskeyttl = ttl; + + REQUIRE(keys != NULL); + REQUIRE(rmkeys != NULL); + + if (dns_rdataset_isassociated(cds)) { + cdsttl = cds->ttl; + } + + if (dns_rdataset_isassociated(cdnskey)) { + cdnskeyttl = cdnskey->ttl; + } for (key = ISC_LIST_HEAD(*keys); key != NULL; key = ISC_LIST_NEXT(key, link)) @@ -2030,7 +2043,7 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, "CDS for key %s is now published", keystr); RETERR(addrdata(&cdnskeyrdata, diff, origin, - ttl, mctx)); + cdnskeyttl, mctx)); } /* Only publish SHA-256 (SHA-1 is deprecated) */ if (!dns_rdataset_isassociated(cds) || @@ -2041,8 +2054,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, "CDNSKEY for key %s is now published", keystr); - RETERR(addrdata(&cds_sha256, diff, origin, ttl, - mctx)); + RETERR(addrdata(&cds_sha256, diff, origin, + cdsttl, mctx)); } } From c1d1f35f13d228fd592c724fc48f7c5876cf0db5 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 14 Dec 2023 15:02:22 +1100 Subject: [PATCH 04/15] sync_secure_db failed to handle some TTL changes If the DNSKEY, CDNSKEY or CDS RRset had different TTLs then the filtering of these RRset resulted in dns_diff_apply failing with "not exact". Identify tuple pairs that are just TTL changes and allow them through the filter. (cherry picked from commit d601a90ea3516aee8be2ddcce5571b4faf66ec22) --- lib/dns/zone.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 2 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 990c6f876b..f010d4fd1b 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -16423,6 +16423,79 @@ failure: return (result); } +#if 0 +/* + * Filter the key material preserving TTL changes. If kasp in effect honour the + * existing ttl. The lists returned by sync_secure_db/dns_db_diffx should be + * DNSSEC RRset order so we can process 'del' and 'add' in parallel rather than + * searching for TTL only changes first and processing them, then checking the + * 'in use' status on a subsequent pass. + */ + +static void +filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del, + dns_difftuplelist_t *add, bool kasp, dns_ttl_t ttl) { + dns_difftuple_t *deltuple = ISC_LIST_HEAD(*del); + dns_difftuple_t *addtuple = ISC_LIST_HEAD(*add); + isc_result_t result; + + while (deltuple != NULL || addtuple != NULL) { + dns_difftuple_t *delnext = NULL, *addnext = NULL; + bool inuse = false; + if (deltuple != NULL) { + delnext = ISC_LIST_NEXT(deltuple, link); + } + if (addtuple != NULL) { + addnext = ISC_LIST_NEXT(addtuple, link); + } + if (deltuple != NULL && addtuple != NULL) { + int n = dns_rdata_compare(&deltuple->rdata, + &addtuple->rdata); + if (n == 0) { + /* + * If the rdata is equal then the only + * difference will be a TTL change. + */ + if (kasp) { + /* TTL is managed by dnssec-policy */ + ISC_LIST_UNLINK(*del, deltuple, link); + dns_difftuple_free(&deltuple); + ISC_LIST_UNLINK(*add, addtuple, link); + dns_difftuple_free(&addtuple); + } + deltuple = delnext; + addtuple = addnext; + continue; + } + if (n < 0) { + goto checkdel; + } + goto checkadd; + } else if (deltuple != NULL) { + checkdel: + result = dns_zone_dnskey_inuse(zone, &deltuple->rdata, + &inuse); + if (result == ISC_R_SUCCESS && inuse) { + ISC_LIST_UNLINK(*del, deltuple, link); + dns_difftuple_free(&deltuple); + } + deltuple = delnext; + } else { + checkadd: + result = dns_zone_dnskey_inuse(zone, &addtuple->rdata, + &inuse); + if (result == ISC_R_SUCCESS && inuse) { + ISC_LIST_UNLINK(*add, addtuple, link); + dns_difftuple_free(&addtuple); + } else if (kasp) { + addtuple->ttl = ttl; + } + addtuple = addnext; + } + } +} +#endif + static isc_result_t sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_dbversion_t *secver, dns_difftuple_t **soatuple, @@ -16433,6 +16506,18 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_difftuple_t *tuple = NULL, *next; dns_difftuple_t *oldtuple = NULL, *newtuple = NULL; dns_rdata_soa_t oldsoa, newsoa; + dns_difftuplelist_t add = ISC_LIST_INITIALIZER; + dns_difftuplelist_t del = ISC_LIST_INITIALIZER; + dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER; + dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER; + dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER; + dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER; + dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER; + dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER; +#if 0 + dns_kasp_t *kasp = NULL; + dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0; +#endif REQUIRE(DNS_ZONE_VALID(seczone)); REQUIRE(soatuple != NULL && *soatuple == NULL); @@ -16451,8 +16536,57 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, return (result); } +#if 0 + /* + * If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS + * TTLs. + */ + kasp = seczone->kasp; + if (kasp != NULL) { + dns_rdataset_t rdataset; + dns_dbnode_t *node = NULL; + dns_ttl_t ttl = dns_kasp_dnskeyttl(kasp); + + dns_rdataset_init(&rdataset); + + result = dns_db_getoriginnode(secdb, &node); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_db_findrdataset( + secdb, node, secver, dns_rdatatype_dnskey, + dns_rdatatype_none, 0, &rdataset, NULL); + keyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl; + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + + result = dns_db_findrdataset( + secdb, node, secver, dns_rdatatype_cdnskey, + dns_rdatatype_none, 0, &rdataset, NULL); + ckeyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl; + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + + result = dns_db_findrdataset( + secdb, node, secver, dns_rdatatype_cds, + dns_rdatatype_none, 0, &rdataset, NULL); + cdsttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl; + if (dns_rdataset_isassociated(&rdataset)) { + dns_rdataset_disassociate(&rdataset); + } + dns_db_detachnode(secdb, &node); + } +#endif + for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) { + dns_difftuplelist_t *al = &add, *dl = &del; + next = ISC_LIST_NEXT(tuple, link); + + /* + * Skip DNSSEC records that BIND maintains with inline-signing. + */ if (tuple->rdata.type == dns_rdatatype_nsec || tuple->rdata.type == dns_rdatatype_rrsig || tuple->rdata.type == dns_rdatatype_dnskey || @@ -16463,6 +16597,34 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_difftuple_free(&tuple); continue; } + +#if 0 + /* + * Apex DNSKEY, CDNSKEY and CDS need special processing so + * split them out. + */ + if (dns_rdatatype_iskeymaterial(tuple->rdata.type) && + dns_name_equal(&tuple->name, &seczone->origin)) + { + switch (tuple->rdata.type) { + case dns_rdatatype_dnskey: + al = &keyadd; + dl = &keydel; + break; + case dns_rdatatype_cdnskey: + al = &ckeyadd; + dl = &ckeydel; + break; + case dns_rdatatype_cds: + al = &cdsadd; + dl = &cdsdel; + break; + default: + UNREACHABLE(); + } + } +#endif + if (tuple->rdata.type == dns_rdatatype_soa) { if (tuple->op == DNS_DIFFOP_DEL) { INSIST(oldtuple == NULL); @@ -16473,6 +16635,23 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, newtuple = tuple; } } + + /* + * Split into deletions and additions. + */ + ISC_LIST_UNLINK(diff->tuples, tuple, link); + switch (tuple->op) { + case DNS_DIFFOP_DEL: + case DNS_DIFFOP_DELRESIGN: + ISC_LIST_APPEND(*dl, tuple, link); + break; + case DNS_DIFFOP_ADD: + case DNS_DIFFOP_ADDRESIGN: + ISC_LIST_APPEND(*al, tuple, link); + break; + default: + UNREACHABLE(); + } } if (oldtuple != NULL && newtuple != NULL) { @@ -16494,13 +16673,34 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_name_equal(&oldsoa.origin, &newsoa.origin) && dns_name_equal(&oldsoa.contact, &newsoa.contact)) { - ISC_LIST_UNLINK(diff->tuples, oldtuple, link); + ISC_LIST_UNLINK(del, oldtuple, link); dns_difftuple_free(&oldtuple); - ISC_LIST_UNLINK(diff->tuples, newtuple, link); + ISC_LIST_UNLINK(add, newtuple, link); dns_difftuple_free(&newtuple); } } +#if 0 + /* + * Filter out keys we manage but still allow TTL changes. + */ + filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl); + filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl); + filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl); +#endif + + /* + * Rebuild the diff now that we have filtered it + */ + ISC_LIST_APPENDLIST(diff->tuples, del, link); + ISC_LIST_APPENDLIST(diff->tuples, keydel, link); + ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link); + ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link); + ISC_LIST_APPENDLIST(diff->tuples, add, link); + ISC_LIST_APPENDLIST(diff->tuples, keyadd, link); + ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link); + ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link); + if (ISC_LIST_EMPTY(diff->tuples)) { return (DNS_R_UNCHANGED); } From 59067fc568431887cb20653909ea6ac5e496e0a6 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 19 Dec 2023 15:58:49 +1100 Subject: [PATCH 05/15] Only create private records for DNSKEYs that have changed We don't need to create private records for DNSKEY records that have only had their TTL's changed. (cherry picked from commit 27e74b2e4b567bf9da9bad0818d94de9db2a8929) --- lib/dns/zone.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f010d4fd1b..02e3890c6f 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -20582,7 +20582,8 @@ failure: static isc_result_t add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) { - dns_difftuple_t *tuple, *newtuple = NULL; + dns_difftuple_t *tuple = NULL, *newtuple = NULL, *next = NULL; + dns_difftuple_t *addtuple = NULL, *deltuple = NULL; dns_rdata_dnskey_t dnskey; dns_rdata_t rdata = DNS_RDATA_INIT; bool flag; @@ -20591,11 +20592,20 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, uint16_t keyid; unsigned char buf[5]; dns_name_t *name = dns_db_origin(db); + dns_difftuplelist_t add = ISC_LIST_INITIALIZER; + dns_difftuplelist_t del = ISC_LIST_INITIALIZER; + dns_difftuplelist_t tuples = ISC_LIST_INITIALIZER; + /* + * Move non DNSKEY and not DNSSEC DNSKEY records to tuples + * and sort the remaining DNSKEY records to add and del. + */ for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; - tuple = ISC_LIST_NEXT(tuple, link)) + tuple = ISC_LIST_HEAD(diff->tuples)) { if (tuple->rdata.type != dns_rdatatype_dnskey) { + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_APPEND(tuples, tuple, link); continue; } @@ -20604,9 +20614,65 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK | DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE) { + ISC_LIST_UNLINK(diff->tuples, tuple, link); + ISC_LIST_APPEND(tuples, tuple, link); continue; } + ISC_LIST_UNLINK(diff->tuples, tuple, link); + switch (tuple->op) { + case DNS_DIFFOP_DEL: + case DNS_DIFFOP_DELRESIGN: + ISC_LIST_APPEND(del, tuple, link); + break; + case DNS_DIFFOP_ADD: + case DNS_DIFFOP_ADDRESIGN: + ISC_LIST_APPEND(add, tuple, link); + break; + default: + UNREACHABLE(); + } + } + + /* + * Put the tuples that don't need more processing back onto + * diff->tuples. + */ + ISC_LIST_APPENDLIST(diff->tuples, tuples, link); + + /* + * Filter out DNSKEY TTL changes and put them back onto diff->tuples. + */ + for (deltuple = ISC_LIST_HEAD(del); deltuple != NULL; deltuple = next) { + next = ISC_LIST_NEXT(deltuple, link); + for (addtuple = ISC_LIST_HEAD(add); addtuple != NULL; + addtuple = ISC_LIST_NEXT(addtuple, link)) + { + int n = dns_rdata_compare(&deltuple->rdata, + &addtuple->rdata); + if (n == 0) { + ISC_LIST_UNLINK(del, deltuple, link); + ISC_LIST_APPEND(diff->tuples, deltuple, link); + ISC_LIST_UNLINK(add, addtuple, link); + ISC_LIST_APPEND(diff->tuples, addtuple, link); + break; + } + } + } + + /* + * Combine any remaining DNSKEY changes together. + */ + ISC_LIST_APPENDLIST(tuples, add, link); + ISC_LIST_APPENDLIST(tuples, del, link); + + /* + * Add private records for keys that have been removed + * or added. + */ + for (tuple = ISC_LIST_HEAD(tuples); tuple != NULL; + tuple = ISC_LIST_NEXT(tuple, link)) + { dns_rdata_toregion(&tuple->rdata, &r); keyid = dst_region_computeid(&r); @@ -20646,7 +20712,15 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, INSIST(newtuple == NULL); } } + failure: + /* + * Put the DNSKEY changes we cared about back on diff->tuples. + */ + ISC_LIST_APPENDLIST(diff->tuples, tuples, link); + INSIST(ISC_LIST_EMPTY(add)); + INSIST(ISC_LIST_EMPTY(del)); + INSIST(ISC_LIST_EMPTY(tuples)); return (result); } From 2a6ee4a9a0a1d1907e0407d7f67728c27786739a Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Fri, 22 Dec 2023 15:08:45 +0100 Subject: [PATCH 06/15] Write new DNSKEY TTL to key file When the current DNSKEY TTL does not match the one from the policy, write the new TTL to disk. (cherry picked from commit b770740b44f7b91ea2a2d6714075547fe836b16f) --- bin/tests/system/kasp.sh | 2 +- bin/tests/system/kasp/tests.sh | 10 +++++----- bin/tests/system/nsec3/tests.sh | 2 +- lib/dns/keymgr.c | 9 +++++++-- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bin/tests/system/kasp.sh b/bin/tests/system/kasp.sh index d1bf51a79a..60d77335ec 100644 --- a/bin/tests/system/kasp.sh +++ b/bin/tests/system/kasp.sh @@ -213,7 +213,7 @@ set_policy() { POLICY=$1 NUM_KEYS=$2 DNSKEY_TTL=$3 - KEYFILE_TTL=${4:-$3} + KEYFILE_TTL=$3 CDS_DELETE="no" } # By default policies are considered to be secure. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index c3153f8744..c16f3cd542 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -1379,7 +1379,7 @@ check_rrsig_refresh # Zone: dnskey-ttl-mismatch.autosign # set_zone "dnskey-ttl-mismatch.autosign" -set_policy "autosign" "2" "300" "30" +set_policy "autosign" "2" "300" set_server "ns3" "10.53.0.3" # Key properties. key_clear "KEY1" @@ -4012,7 +4012,7 @@ dnssec_verify # Zone: step1.going-insecure.kasp # set_zone "step1.going-insecure.kasp" -set_policy "insecure" "2" "7200" +set_policy "insecure" "2" "3600" set_server "ns6" "10.53.0.6" # Expect a CDS/CDNSKEY Delete Record. set_cdsdelete @@ -4049,7 +4049,7 @@ check_next_key_event 93600 # Zone: step2.going-insecure.kasp # set_zone "step2.going-insecure.kasp" -set_policy "insecure" "2" "7200" +set_policy "insecure" "2" "3600" set_server "ns6" "10.53.0.6" # The DS is long enough removed from the zone to be considered HIDDEN. @@ -4079,7 +4079,7 @@ check_next_key_event 7500 # set_zone "step1.going-insecure-dynamic.kasp" set_dynamic -set_policy "insecure" "2" "7200" +set_policy "insecure" "2" "3600" set_server "ns6" "10.53.0.6" # Expect a CDS/CDNSKEY Delete Record. set_cdsdelete @@ -4117,7 +4117,7 @@ check_next_key_event 93600 # set_zone "step2.going-insecure-dynamic.kasp" set_dynamic -set_policy "insecure" "2" "7200" +set_policy "insecure" "2" "3600" set_server "ns6" "10.53.0.6" # The DS is long enough removed from the zone to be considered HIDDEN. diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh index 7a82ffc932..6cb28583c6 100644 --- a/bin/tests/system/nsec3/tests.sh +++ b/bin/tests/system/nsec3/tests.sh @@ -40,7 +40,7 @@ set_zone_policy() { POLICY=$2 NUM_KEYS=$3 DNSKEY_TTL=$4 - KEYFILE_TTL=${5:-$4} + KEYFILE_TTL=$4 } # Set expected NSEC3 parameters: flags ($1), iterations ($2), and # salt length ($3). diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index 106b376ef0..34fa1dd0cc 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -2218,11 +2218,16 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; dkey = ISC_LIST_NEXT(dkey, link)) { - if (dst_key_ismodified(dkey->key) && !dkey->purge) { + bool modified = dst_key_ismodified(dkey->key); + if (dst_key_getttl(dkey->key) != dns_kasp_dnskeyttl(kasp)) { + dst_key_setttl(dkey->key, dns_kasp_dnskeyttl(kasp)); + modified = true; + } + if (modified && !dkey->purge) { dns_dnssec_get_hints(dkey, now); RETERR(dst_key_tofile(dkey->key, options, directory)); - dst_key_setmodified(dkey->key, false); } + dst_key_setmodified(dkey->key, false); } result = ISC_R_SUCCESS; From e30652e33adefce691ccc70e204080fd7ed2eb3d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 12 Dec 2023 16:20:53 +1100 Subject: [PATCH 07/15] Make $TTL match dnskey-ttl (cherry picked from commit 16a720357b9195367f19ea6e8327530a12872088) --- bin/tests/system/autosign/ns3/nozsk.example.db.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/tests/system/autosign/ns3/nozsk.example.db.in b/bin/tests/system/autosign/ns3/nozsk.example.db.in index 1376922f0a..5d244c3fc6 100644 --- a/bin/tests/system/autosign/ns3/nozsk.example.db.in +++ b/bin/tests/system/autosign/ns3/nozsk.example.db.in @@ -9,7 +9,7 @@ ; See the COPYRIGHT file distributed with this work for additional ; information regarding copyright ownership. -$TTL 300 ; 5 minutes +$TTL 3600 ; 1 hour @ IN SOA mname1. . ( 1 ; serial 20 ; refresh (20 seconds) From e5bfe1e540c506b6ada447973c130901a5d4d07e Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 13 Dec 2023 01:05:54 +1100 Subject: [PATCH 08/15] Set the DNSKEY TTLs to match the dnssec policy This prevents the DNSKEY records being updated and the statistics not matching as a consequence (cherry picked from commit 882b1a444963e74ce779a9b7528dc62cf50564ad) --- bin/tests/system/statschannel/ns2/sign.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/tests/system/statschannel/ns2/sign.sh b/bin/tests/system/statschannel/ns2/sign.sh index 5a507daa63..d2da0128fe 100644 --- a/bin/tests/system/statschannel/ns2/sign.sh +++ b/bin/tests/system/statschannel/ns2/sign.sh @@ -19,8 +19,8 @@ set -e zone=dnssec. infile=dnssec.db.in zonefile=dnssec.db.signed -ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") -zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" "$zone") # Sign deliberately with a very short expiration date. "$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1 keyfile_to_key_id "$ksk" >dnssec.ksk.id @@ -29,12 +29,12 @@ keyfile_to_key_id "$zsk" >dnssec.zsk.id zone=manykeys. infile=manykeys.db.in zonefile=manykeys.db.signed -ksk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 -f KSK "$zone") -zsk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 "$zone") -ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 -f KSK "$zone") -zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 "$zone") -ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 -f KSK "$zone") -zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 "$zone") +ksk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 -f KSK "$zone") +zsk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 "$zone") +ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 -f KSK "$zone") +zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 "$zone") +ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 -f KSK "$zone") +zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 "$zone") # Sign deliberately with a very short expiration date. "$SIGNER" -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1 keyfile_to_key_id "$ksk8" >manykeys.ksk8.id From e51f317622e7136877875e5f88fab43c1df7b1e1 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 19 Dec 2023 19:01:22 +1100 Subject: [PATCH 09/15] Add CHANGES note for [GL #4466] (cherry picked from commit 531420bac08c2be902c3134f38b665b2db5e261a) --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index d9a0c0e083..45bbc7a4be 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,11 @@ 'host -C' commands when one of the name servers returns SERVFAIL. [GL #4508] +6313. [bug] When dnssec-policy is in effect the DNSKEY's TTLs in + the zone where not being updated to match the policy. + This lead to failures when DNSKEYs where updated as the + TTLs mismatched. [GL #4466] + 6312. [bug] Conversion from NSEC3 signed to NSEC signed could temporarily put the zone into a state where it was treated as unsigned until the NSEC chain was built. From 2268ee2955bcb465cb0d6767b2699a23b1fdc0e4 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 4 Jan 2024 14:23:24 +1100 Subject: [PATCH 10/15] Update expected DNSKEY TTL to match dnssec-policy csk.kasp and csk-nosep.kasp use the default policy which has a 3600 second dnskey-ttl. --- bin/tests/system/keymgr2kasp/tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/tests/system/keymgr2kasp/tests.sh b/bin/tests/system/keymgr2kasp/tests.sh index 57c1445f19..e1ca49d2f7 100644 --- a/bin/tests/system/keymgr2kasp/tests.sh +++ b/bin/tests/system/keymgr2kasp/tests.sh @@ -499,7 +499,7 @@ status=$((status + ret)) # Testing a good migration (CSK). # set_zone "csk.kasp" -set_policy "default" "1" "7200" +set_policy "default" "1" "3600" set_server "ns3" "10.53.0.3" key_clear "KEY1" @@ -549,7 +549,7 @@ status=$((status + ret)) # Testing a good migration (CSK, no SEP). # set_zone "csk-nosep.kasp" -set_policy "default" "1" "7200" +set_policy "default" "1" "3600" set_server "ns3" "10.53.0.3" key_clear "KEY1" From 74109dfea6f3ec10c4b762e5713ae40ed8bc3d90 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Fri, 3 Mar 2023 14:15:59 +0100 Subject: [PATCH 11/15] Make make_dnskey() a public funcion It can be used to compare DNSKEY, CDNSKEY, and CDS records with signing keys. (cherry picked from commit 81cb18b8a230441d0b5fe5e34bad728cad4e4e9b) --- lib/dns/dnssec.c | 18 +++++++++--------- lib/dns/include/dns/dnssec.h | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index 7384c65e1b..88b4ebd9e2 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1846,9 +1846,9 @@ failure: return (result); } -static isc_result_t -make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, - dns_rdata_t *target) { +isc_result_t +dns_dnssec_make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, + dns_rdata_t *target) { isc_result_t result; isc_buffer_t b; isc_region_t r; @@ -1904,7 +1904,7 @@ publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin, dns_rdata_t dnskey = DNS_RDATA_INIT; dns_rdata_reset(&dnskey); - RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); + RETERR(dns_dnssec_make_dnskey(key->key, buf, sizeof(buf), &dnskey)); dst_key_format(key->key, keystr, sizeof(keystr)); report("Fetching %s (%s) from key %s.", keystr, @@ -1944,7 +1944,7 @@ remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin, report("Removing %s key %s/%d/%s from DNSKEY RRset.", reason, namebuf, dst_key_id(key->key), alg); - RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); + RETERR(dns_dnssec_make_dnskey(key->key, buf, sizeof(buf), &dnskey)); result = delrdata(&dnskey, diff, origin, ttl, mctx); failure: @@ -2005,8 +2005,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT; dns_name_t *origin = dst_key_name(key->key); - RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf), - &cdnskeyrdata)); + RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf), + &cdnskeyrdata)); /* * We construct the SHA-1 version of the record so we can @@ -2127,8 +2127,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys, char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key->key, keystr, sizeof(keystr)); - RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf), - &cdnskeyrdata)); + RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf), + &cdnskeyrdata)); if (dns_rdataset_isassociated(cds)) { RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata, diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h index 6add7d50d1..cb8fd9dc20 100644 --- a/lib/dns/include/dns/dnssec.h +++ b/lib/dns/include/dns/dnssec.h @@ -95,6 +95,23 @@ dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata, *\li various errors from dns_name_totext */ +isc_result_t +dns_dnssec_make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, + dns_rdata_t *target); +/*%< + * Convert a DST key into a DNS record. + * + * Requires: + *\li 'key' is not NULL + *\li 'buf' is not NULL + *\li 'bufsize' equals DST_KEY_MAXSIZE + *\li 'target' is not NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li various errors from dst_key_todns + */ + isc_result_t dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, isc_stdtime_t *inception, isc_stdtime_t *expire, From 0d36d9879193caf985ced4985313e228cf829da5 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 15 Mar 2023 11:51:33 +0100 Subject: [PATCH 12/15] Add new dns_rdatatype_iskeymaterial() function The following code block repeats quite often: if (rdata.type == dns_rdatatype_dnskey || rdata.type == dns_rdatatype_cdnskey || rdata.type == dns_rdatatype_cds) Introduce a new function to reduce the repetition. (cherry picked from commit ef58f2444f4bc76891f89ad3344348232994a4df) --- lib/dns/include/dns/rdata.h | 7 +++++++ lib/dns/rdata.c | 6 ++++++ lib/dns/update.c | 15 +++------------ lib/dns/zone.c | 27 ++++++--------------------- lib/ns/query.c | 4 +--- lib/ns/update.c | 23 +++++++++++++++++++++++ 6 files changed, 46 insertions(+), 36 deletions(-) diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 257a22c9fd..51dc0804b8 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -572,6 +572,13 @@ dns_rdatatype_isdnssec(dns_rdatatype_t type); * \li 'type' is a valid rdata type. */ +bool +dns_rdatatype_iskeymaterial(dns_rdatatype_t type); +/*%< + * Return true iff the rdata type 'type' is a DNSSEC key + * related type, like DNSKEY, CDNSKEY, or CDS. + */ + bool dns_rdatatype_iszonecutauth(dns_rdatatype_t type); /*%< diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 592b9746da..227dfbc795 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -2262,6 +2262,12 @@ dns_rdatatype_isdnssec(dns_rdatatype_t type) { return (false); } +bool +dns_rdatatype_iskeymaterial(dns_rdatatype_t type) { + return (type == dns_rdatatype_dnskey || type == dns_rdatatype_cdnskey || + type == dns_rdatatype_cds); +} + bool dns_rdatatype_iszonecutauth(dns_rdatatype_t type) { if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH) != diff --git a/lib/dns/update.c b/lib/dns/update.c index c3f162ad10..a94d35276e 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1205,10 +1205,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, } } - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || - type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { /* * DNSKEY RRset is signed with KSK. * CDS and CDNSKEY RRsets too (RFC 7344, 4.1). @@ -1242,10 +1239,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, /* * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1). */ - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || - type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { if (!KSK(keys[i]) && keyset_kskonly) { continue; } @@ -1675,10 +1669,7 @@ next_state: &flag)); if (flag) { isc_stdtime_t exp; - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || - type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { exp = state->keyexpire; } else if (type == dns_rdatatype_soa) { exp = state->soaexpire; diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 02e3890c6f..8897a46123 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -6777,9 +6777,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = dns_rdata_tostruct(&rdata, &rrsig, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds && - type != dns_rdatatype_cdnskey) - { + if (!dns_rdatatype_iskeymaterial(type)) { bool warn = false, deleted = false; if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) { result = update_one_rr(db, ver, zonediff->diff, @@ -7097,10 +7095,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, both = have_ksk && have_zsk; } - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || - type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { /* * DNSKEY RRset is signed with KSK. * CDS and CDNSKEY RRsets too (RFC 7344, 4.1). @@ -7140,10 +7135,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone, /* * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1). */ - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || - type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { if (!KSK(keys[i]) && keyset_kskonly) { continue; } @@ -7545,9 +7537,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node, } KASP_UNLOCK(kasp); - if (type == dns_rdatatype_dnskey || - type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(type)) { /* * CDS and CDNSKEY are signed with KSK like DNSKEY. * (RFC 7344, section 4.1 specifies that they must @@ -7723,10 +7713,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name, { goto next_rdataset; } - if (rdataset.type == dns_rdatatype_dnskey || - rdataset.type == dns_rdatatype_cdnskey || - rdataset.type == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(rdataset.type)) { /* * CDS and CDNSKEY are signed with KSK like DNSKEY. * (RFC 7344, section 4.1 specifies that they must @@ -8324,9 +8311,7 @@ dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version, isc_stdtime_t exp = expire; if (keyexpire != 0 && - (tuple->rdata.type == dns_rdatatype_dnskey || - tuple->rdata.type == dns_rdatatype_cdnskey || - tuple->rdata.type == dns_rdatatype_cds)) + dns_rdatatype_iskeymaterial(tuple->rdata.type)) { exp = keyexpire; } diff --git a/lib/ns/query.c b/lib/ns/query.c index c1e91484cf..7c98d1ab47 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -12352,9 +12352,7 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) { /* * Turn on minimal response for (C)DNSKEY and (C)DS queries. */ - if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds || - qtype == dns_rdatatype_cdnskey || qtype == dns_rdatatype_cds) - { + if (dns_rdatatype_iskeymaterial(qtype) || qtype == dns_rdatatype_ds) { client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | NS_QUERYATTR_NOADDITIONAL); } else if (qtype == dns_rdatatype_ns) { diff --git a/lib/ns/update.c b/lib/ns/update.c index 983ca84e26..dfba72db5e 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -3390,6 +3390,29 @@ update_action(isc_task_t *task, isc_event_t *event) { continue; } } +#if 0 + /* + * Don't remove DNSKEY, CDNSKEY, CDS records + * that are in use (under our control). + */ + if (dns_rdatatype_iskeymaterial(rdata.type)) { + isc_result_t r; + bool inuse = false; + r = dns_zone_dnskey_inuse(zone, &rdata, + &inuse); + if (r != ISC_R_SUCCESS) { + FAIL(r); + } + if (inuse) { + update_log(client, zone, + LOGLEVEL_PROTOCOL, + "attempt to " + "delete in use " + "DNSKEY ignored"); + continue; + } + } +#endif } dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdata.type, typestr, From 88734ac7cffb4273f074e0a94b8ab5fd95dd3bd6 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Fri, 3 Mar 2023 14:19:14 +0100 Subject: [PATCH 13/15] Add function to check if a DNSKEY record is in use Add a function that checks whether a DNSKEY, CDNSKEY, or CDS record belongs to a key that is being used for signing. (cherry picked from commit 3b6e9a5fa77c9655faa1bc94abc520f40dd65bf2) --- lib/dns/include/dns/zone.h | 18 ++++ lib/dns/zone.c | 180 +++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 10ed86c4e3..597265393c 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -392,6 +392,24 @@ dns_zone_unlock_keyfiles(dns_zone_t *zone); *\li 'zone' to be a valid zone. */ +isc_result_t +dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse); +/*%< + * Check if the DNSKEY record 'rdata' is used by 'zone' for zone signing. + * Store the result in 'inuse'. + * + * Require: + *\li 'zone' to be a valid zone. + *\li 'rdata' to represent a DNSKEY, CDNSKEY, or CDS record. + * + * Returns: + *\li #ISC_R_SUCCESS + *\li Any error result from dns_dnssec_keyfromrdata, dns_rdata_tostruct, + * dns_dnssec_make_dnskey, dns_ds_buildrdata, or + * dns_dnssec_findmatchingkeys. + * + */ + isc_result_t dns_zone_load(dns_zone_t *zone, bool newonly); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 8897a46123..a7ac53bc01 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -16329,6 +16329,186 @@ update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { dns_zone_log(zone, level, "%s", message); } +static isc_result_t +dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, isc_mem_t *mctx, + dns_dnsseckeylist_t *keylist, bool *inuse) { + isc_result_t result; + dst_key_t *dstkey = NULL; + + result = dns_dnssec_keyfromrdata(dns_zone_getorigin(zone), rdata, mctx, + &dstkey); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_dnssec_keyfromrdata() failed: %s", + isc_result_totext(result)); + return (result); + } + + for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL; + k = ISC_LIST_NEXT(k, link)) + { + if (dst_key_pubcompare(k->key, dstkey, false)) { + *inuse = true; + break; + } + } + + dst_key_free(&dstkey); + return (ISC_R_SUCCESS); +} + +static isc_result_t +cdnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, + dns_dnsseckeylist_t *keylist, bool *inuse) { + isc_result_t result; + dns_rdata_cdnskey_t cdnskey; + + result = dns_rdata_tostruct(rdata, &cdnskey, NULL); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_rdata_tostruct(cdnskey) failed: %s", + isc_result_totext(result)); + return (result); + } + + for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL; + k = ISC_LIST_NEXT(k, link)) + { + dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT; + unsigned char keybuf[DST_KEY_MAXSIZE]; + + result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf), + &cdnskeyrdata); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_dnssec_make_dnskey() failed: %s", + isc_result_totext(result)); + return (result); + } + + cdnskeyrdata.type = dns_rdatatype_cdnskey; + if (dns_rdata_compare(rdata, &cdnskeyrdata) == 0) { + *inuse = true; + break; + } + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist, + bool *inuse) { + isc_result_t result; + dns_rdata_ds_t cds; + + result = dns_rdata_tostruct(rdata, &cds, NULL); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_rdata_tostruct(cds) failed: %s", + isc_result_totext(result)); + return (result); + } + + for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL; + k = ISC_LIST_NEXT(k, link)) + { + dns_rdata_t dnskey = DNS_RDATA_INIT; + dns_rdata_t cdsrdata = DNS_RDATA_INIT; + unsigned char keybuf[DST_KEY_MAXSIZE]; + unsigned char cdsbuf[DNS_DS_BUFFERSIZE]; + + if (dst_key_id(k->key) != cds.key_tag || + dst_key_alg(k->key) != cds.algorithm) + { + continue; + } + result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf), + &dnskey); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_dnssec_make_dnskey() failed: %s", + isc_result_totext(result)); + return (result); + } + result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey, + cds.digest_type, cdsbuf, &cdsrdata); + if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_ds_buildrdata(keytag=%d, algo=%d, " + "digest=%d) failed: %s", + cds.key_tag, cds.algorithm, + cds.digest_type, + isc_result_totext(result)); + return (result); + } + + cdsrdata.type = dns_rdatatype_cds; + if (dns_rdata_compare(rdata, &cdsrdata) == 0) { + *inuse = true; + break; + } + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) { + dns_dnsseckeylist_t keylist; + dns_dnsseckey_t *key = NULL; + isc_result_t result = ISC_R_SUCCESS; + isc_stdtime_t now = 0; + isc_mem_t *mctx; + + REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(dns_rdatatype_iskeymaterial(rdata->type)); + + mctx = zone->mctx; + + isc_stdtime_get(&now); + + ISC_LIST_INIT(keylist); + + *inuse = false; + + dns_zone_lock_keyfiles(zone); + result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), + dns_zone_getkeydirectory(zone), + now, mctx, &keylist); + dns_zone_unlock_keyfiles(zone); + if (result == ISC_R_NOTFOUND) { + return (ISC_R_SUCCESS); + } else if (result != ISC_R_SUCCESS) { + dns_zone_log(zone, ISC_LOG_ERROR, + "dns_dnssec_findmatchingkeys() failed: %s", + isc_result_totext(result)); + return (result); + } + + switch (rdata->type) { + case dns_rdatatype_dnskey: + result = dnskey_inuse(zone, rdata, mctx, &keylist, inuse); + break; + case dns_rdatatype_cdnskey: + result = cdnskey_inuse(zone, rdata, &keylist, inuse); + break; + case dns_rdatatype_cds: + result = cds_inuse(zone, rdata, &keylist, inuse); + break; + default: + UNREACHABLE(); + break; + } + + while (!ISC_LIST_EMPTY(keylist)) { + key = ISC_LIST_HEAD(keylist); + ISC_LIST_UNLINK(keylist, key, link); + dns_dnsseckey_destroy(mctx, &key); + } + return (result); +} + static isc_result_t sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal, uint32_t start, uint32_t end, dns_difftuple_t **soatuplep, From 4efcfa8f1c2ddf6d48e229a88fae7c82a7fc4ab6 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 4 Jan 2024 16:27:56 +1100 Subject: [PATCH 14/15] Apply filters to CDS and CDNSKEY records --- lib/dns/zone.c | 10 ---------- lib/ns/update.c | 2 -- 2 files changed, 12 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a7ac53bc01..43deabfae7 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -16588,7 +16588,6 @@ failure: return (result); } -#if 0 /* * Filter the key material preserving TTL changes. If kasp in effect honour the * existing ttl. The lists returned by sync_secure_db/dns_db_diffx should be @@ -16659,7 +16658,6 @@ filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del, } } } -#endif static isc_result_t sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, @@ -16679,10 +16677,8 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER; dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER; dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER; -#if 0 dns_kasp_t *kasp = NULL; dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0; -#endif REQUIRE(DNS_ZONE_VALID(seczone)); REQUIRE(soatuple != NULL && *soatuple == NULL); @@ -16701,7 +16697,6 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, return (result); } -#if 0 /* * If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS * TTLs. @@ -16742,7 +16737,6 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, } dns_db_detachnode(secdb, &node); } -#endif for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) { dns_difftuplelist_t *al = &add, *dl = &del; @@ -16763,7 +16757,6 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, continue; } -#if 0 /* * Apex DNSKEY, CDNSKEY and CDS need special processing so * split them out. @@ -16788,7 +16781,6 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, UNREACHABLE(); } } -#endif if (tuple->rdata.type == dns_rdatatype_soa) { if (tuple->op == DNS_DIFFOP_DEL) { @@ -16845,14 +16837,12 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, } } -#if 0 /* * Filter out keys we manage but still allow TTL changes. */ filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl); filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl); filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl); -#endif /* * Rebuild the diff now that we have filtered it diff --git a/lib/ns/update.c b/lib/ns/update.c index dfba72db5e..d404dfa786 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -3390,7 +3390,6 @@ update_action(isc_task_t *task, isc_event_t *event) { continue; } } -#if 0 /* * Don't remove DNSKEY, CDNSKEY, CDS records * that are in use (under our control). @@ -3412,7 +3411,6 @@ update_action(isc_task_t *task, isc_event_t *event) { continue; } } -#endif } dns_name_format(name, namestr, sizeof(namestr)); dns_rdatatype_format(rdata.type, typestr, From ecd5459a4d6bae9a4ba817d2aab44a3241c04c34 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 5 Jan 2024 10:36:53 +1100 Subject: [PATCH 15/15] Silence potential unreachable message --- lib/dns/zone.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 43deabfae7..712cb2c023 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -16671,14 +16671,20 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_rdata_soa_t oldsoa, newsoa; dns_difftuplelist_t add = ISC_LIST_INITIALIZER; dns_difftuplelist_t del = ISC_LIST_INITIALIZER; +#if 0 dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER; dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER; +#endif dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER; dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER; dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER; dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER; dns_kasp_t *kasp = NULL; - dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0; +#if 0 + dns_ttl_t keyttl = 0; +#endif + dns_ttl_t ckeyttl = 0; + dns_ttl_t cdsttl = 0; REQUIRE(DNS_ZONE_VALID(seczone)); REQUIRE(soatuple != NULL && *soatuple == NULL); @@ -16712,6 +16718,7 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, result = dns_db_getoriginnode(secdb, &node); RUNTIME_CHECK(result == ISC_R_SUCCESS); +#if 0 result = dns_db_findrdataset( secdb, node, secver, dns_rdatatype_dnskey, dns_rdatatype_none, 0, &rdataset, NULL); @@ -16719,6 +16726,7 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, if (dns_rdataset_isassociated(&rdataset)) { dns_rdataset_disassociate(&rdataset); } +#endif result = dns_db_findrdataset( secdb, node, secver, dns_rdatatype_cdnskey, @@ -16748,6 +16756,7 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, */ if (tuple->rdata.type == dns_rdatatype_nsec || tuple->rdata.type == dns_rdatatype_rrsig || + /* if dnskey is removed adjust switch below */ tuple->rdata.type == dns_rdatatype_dnskey || tuple->rdata.type == dns_rdatatype_nsec3 || tuple->rdata.type == dns_rdatatype_nsec3param) @@ -16765,10 +16774,12 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_name_equal(&tuple->name, &seczone->origin)) { switch (tuple->rdata.type) { +#if 0 case dns_rdatatype_dnskey: al = &keyadd; dl = &keydel; break; +#endif case dns_rdatatype_cdnskey: al = &ckeyadd; dl = &ckeydel; @@ -16840,7 +16851,9 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, /* * Filter out keys we manage but still allow TTL changes. */ +#if 0 filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl); +#endif filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl); filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl); @@ -16848,11 +16861,15 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, * Rebuild the diff now that we have filtered it */ ISC_LIST_APPENDLIST(diff->tuples, del, link); +#if 0 ISC_LIST_APPENDLIST(diff->tuples, keydel, link); +#endif ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link); ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link); ISC_LIST_APPENDLIST(diff->tuples, add, link); +#if 0 ISC_LIST_APPENDLIST(diff->tuples, keyadd, link); +#endif ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link); ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link);