From 4b3d727d96fc3ee3a0c12c716f14163adfcf1fed Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 24 Oct 2012 15:45:48 -0700 Subject: [PATCH] [master] remove spurious signatures from glue 3404. [bug] dnssec-signzone: When re-signing a zone, remove RRSIG and NSEC records from nodes that used to be in-zone but are now below a zone cut. [RT #31556] --- CHANGES | 4 ++ bin/dnssec/dnssec-signzone.c | 55 ++++++++++++++++++++++--- bin/tests/system/dnssec/clean.sh | 2 +- bin/tests/system/dnssec/tests.sh | 69 ++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index b8e6c3e771..7a5194465a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3404. [bug] dnssec-signzone: When re-signing a zone, remove + RRSIG and NSEC records from nodes that used to be + in-zone but are now below a zone cut. [RT #31556] + 3403. [bug] Silence noisy OpenSSL logging. [RT #31497] 3402. [bug] Correct interface numbers for IPv4 and IPv6 interfaces. diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 720e9a6ce2..4b8a094085 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -1602,7 +1602,9 @@ add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) { * Remove records of the given type and their signatures. */ static void -remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { +remove_records(dns_dbnode_t *node, dns_rdatatype_t which, + isc_boolean_t checknsec) +{ isc_result_t result; dns_rdatatype_t type, covers; dns_rdatasetiter_t *rdsiter = NULL; @@ -1623,10 +1625,12 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { covers = rdataset.covers; dns_rdataset_disassociate(&rdataset); if (type == which || covers == which) { - if (which == dns_rdatatype_nsec && !update_chain) + if (which == dns_rdatatype_nsec && + checknsec && !update_chain) fatal("Zone contains NSEC records. Use -u " "to update to NSEC3."); - if (which == dns_rdatatype_nsec3param && !update_chain) + if (which == dns_rdatatype_nsec3param && + checknsec && !update_chain) fatal("Zone contains NSEC3 chains. Use -u " "to update to NSEC."); result = dns_db_deleterdataset(gdb, node, gversion, @@ -1638,6 +1642,39 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) { dns_rdatasetiter_destroy(&rdsiter); } +/* + * Remove signatures covering the given type (0 == all signatures). + */ +static void +remove_sigs(dns_dbnode_t *node, dns_rdatatype_t which) { + isc_result_t result; + dns_rdatatype_t type, covers; + dns_rdatasetiter_t *rdsiter = NULL; + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter); + check_result(result, "dns_db_allrdatasets()"); + for (result = dns_rdatasetiter_first(rdsiter); + result == ISC_R_SUCCESS; + result = dns_rdatasetiter_next(rdsiter)) { + dns_rdatasetiter_current(rdsiter, &rdataset); + type = rdataset.type; + covers = rdataset.covers; + dns_rdataset_disassociate(&rdataset); + + if (type == dns_rdatatype_rrsig && + (covers == which || which == 0)) + { + result = dns_db_deleterdataset(gdb, node, gversion, + type, covers); + check_result(result, "dns_db_deleterdataset()"); + continue; + } + } + dns_rdatasetiter_destroy(&rdsiter); +} + /*% * Generate NSEC records for the zone and remove NSEC3/NSEC3PARAM records. */ @@ -1714,14 +1751,17 @@ nsecify(void) { } if (dns_name_equal(name, gorigin)) - remove_records(node, dns_rdatatype_nsec3param); + remove_records(node, dns_rdatatype_nsec3param, + ISC_TRUE); if (is_delegation(gdb, gversion, gorigin, name, node, &nsttl)) { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(name, zonecut, NULL); + remove_sigs(node, 0); if (generateds) add_ds(name, node, nsttl); } + result = dns_dbiterator_next(dbiter); nextnode = NULL; while (result == ISC_R_SUCCESS) { @@ -1739,6 +1779,9 @@ nsecify(void) { (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { + remove_sigs(nextnode, 0); + remove_records(nextnode, dns_rdatatype_nsec, + ISC_FALSE); dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; @@ -2130,7 +2173,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, } if (dns_name_equal(name, gorigin)) - remove_records(node, dns_rdatatype_nsec); + remove_records(node, dns_rdatatype_nsec, ISC_TRUE); result = dns_dbiterator_next(dbiter); nextnode = NULL; @@ -2147,6 +2190,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, if (!dns_name_issubdomain(nextname, gorigin) || (zonecut != NULL && dns_name_issubdomain(nextname, zonecut))) { + remove_sigs(nextnode, 0); dns_db_detachnode(gdb, &nextnode); result = dns_dbiterator_next(dbiter); continue; @@ -2156,6 +2200,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations, { zonecut = dns_fixedname_name(&fzonecut); dns_name_copy(nextname, zonecut, NULL); + remove_sigs(nextnode, 0); if (generateds) add_ds(nextname, nextnode, nsttl); if (OPTOUT(nsec3flags) && diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index 8e21caa871..fc853c0e33 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -47,7 +47,7 @@ rm -f ns3/secure.nsec3.example.db rm -f ns3/secure.optout.example.db rm -f */named.secroots rm -f ns1/managed.key.id -rm -f signer/example.db +rm -f signer/*.db rm -f signer/signer.out.* rm -f ns2/algroll.db rm -f ns3/kskonly.example.db diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index e4040ddb74..0de949c3ce 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1123,6 +1123,75 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec) ($n)" +ret=0 +( +cd signer +# remove NSEC-only keys +rm -f Kexample.+005* +cp -f example.db.in example2.db +cat << EOF >> example2.db +sub1.example. IN A 10.53.0.1 +ns.sub2.example. IN A 10.53.0.2 +EOF +echo '$INCLUDE "example2.db.signed"' >> example2.db +touch example2.db.signed +$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null 2>&1 +) || ret=1 +grep "^sub1\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1 +grep "^ns\.sub2\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1 +( +cd signer +cp -f example.db.in example2.db +cat << EOF >> example2.db +sub1.example. IN NS sub1.example. +sub1.example. IN A 10.53.0.1 +sub2.example. IN NS ns.sub2.example. +ns.sub2.example. IN A 10.53.0.2 +EOF +echo '$INCLUDE "example2.db.signed"' >> example2.db +$SIGNER -DS -O full -f example2.db.signed -o example example2.db > /dev/null 2>&1 +) || ret=1 +grep "^sub1\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1 +grep "^ns\.sub2\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking dnssec-signzone purges RRSIGs from formerly-owned glue (nsec3) ($n)" +ret=0 +( +cd signer +rm -f example2.db.signed +cp -f example.db.in example2.db +cat << EOF >> example2.db +sub1.example. IN A 10.53.0.1 +ns.sub2.example. IN A 10.53.0.2 +EOF +echo '$INCLUDE "example2.db.signed"' >> example2.db +touch example2.db.signed +$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null 2>&1 +) || ret=1 +grep "^sub1\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1 +grep "^ns\.sub2\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 || ret=1 +( +cd signer +cp -f example.db.in example2.db +cat << EOF >> example2.db +sub1.example. IN NS sub1.example. +sub1.example. IN A 10.53.0.1 +sub2.example. IN NS ns.sub2.example. +ns.sub2.example. IN A 10.53.0.2 +EOF +echo '$INCLUDE "example2.db.signed"' >> example2.db +$SIGNER -DS -3 feedabee -O full -f example2.db.signed -o example example2.db > /dev/null 2>&1 +) || ret=1 +grep "^sub1\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1 +grep "^ns\.sub2\.example\..*RRSIG[ ]A[ ]" signer/example2.db.signed > /dev/null 2>&1 && ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:checking dnssec-signzone output format ($n)" ret=0 (