From: Evan Hunt Date: Thu, 14 May 2026 03:03:43 +0000 (-0700) Subject: Prevent UDPATE deleting keys in dnssec-policy zones X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F5956-update-keydata;p=thirdparty%2Fbind9.git Prevent UDPATE deleting keys in dnssec-policy zones In dnssec-policy zones, DNSKEY, CDNSKEY and CDS data at the zone apex should not be deleted by UPDATE. Previously, this was prevented when deleting individual RRs. It is now also prevented when deleting the entire RRset. --- diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 7a77faea6be..bce4b98b810 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -2303,6 +2303,24 @@ retry_quiet 5 has_positive_response multisigner.test CDNSKEY 10.53.0.3 || ret=1 status=1 } +n=$((n + 1)) +ret=0 +echo_i "check that DNSKEY removal in dnssec-policy zone is rejected ($n)" +$DIG $DIGOPTS +tcp +norec multisigner.test DNSKEY @10.53.0.3 >dig.out.pre.test$n || ret=1 +grep "status: NOERROR" dig.out.pre.test$n >/dev/null || ret=1 +grep "ANSWER: 1," dig.out.pre.test$n >/dev/null || ret=1 +$NSUPDATE -d <nsupdate.out.test$n 2>&1 || ret=1 +server 10.53.0.3 ${PORT} +zone multisigner.test +update delete multisigner.test DNSKEY +send +END +retry_quiet 5 has_positive_response multisigner.test DNSKEY 10.53.0.3 || ret=1 +[ $ret = 0 ] || { + echo_i "failed" + status=1 +} + n=$((n + 1)) ret=0 echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)" diff --git a/lib/ns/update.c b/lib/ns/update.c index 93240ca250c..f2ad9fe3d39 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -3044,32 +3044,45 @@ update_action(void *arg) { dns_rdatatype_none, &rdata, &diff)); } - } else if (dns_name_equal(name, zonename) && - (rdata.type == dns_rdatatype_soa || - rdata.type == dns_rdatatype_ns)) - { - update_log(client, zone, LOGLEVEL_PROTOCOL, - "attempt to delete all SOA or NS " - "records ignored"); continue; - } else { - if (isc_log_wouldlog(LOGLEVEL_PROTOCOL)) { - char namestr[DNS_NAME_FORMATSIZE]; - char typestr[DNS_RDATATYPE_FORMATSIZE]; - dns_name_format(name, namestr, - sizeof(namestr)); - dns_rdatatype_format(rdata.type, - typestr, - sizeof(typestr)); + } else if (dns_name_equal(name, zonename)) { + char typestr[DNS_RDATATYPE_FORMATSIZE]; + dns_rdatatype_format(rdata.type, typestr, + sizeof(typestr)); + if (rdata.type == dns_rdatatype_soa || + rdata.type == dns_rdatatype_ns) + { update_log(client, zone, LOGLEVEL_PROTOCOL, - "deleting rrset at '%s' %s", - namestr, typestr); + "attempt to delete all %s " + "records ignored", + typestr); + continue; + } else if (dns_zone_getkasp(zone) != NULL && + dns_rdatatype_iskeymaterial( + rdata.type)) + { + update_log(client, zone, + LOGLEVEL_PROTOCOL, + "attempt to delete %s " + "records in dnssec-policy " + "zone ignored", + typestr); + continue; } - CHECK(delete_if(true_p, db, ver, name, - rdata.type, covers, &rdata, - &diff)); } + if (isc_log_wouldlog(LOGLEVEL_PROTOCOL)) { + char namestr[DNS_NAME_FORMATSIZE]; + char typestr[DNS_RDATATYPE_FORMATSIZE]; + dns_name_format(name, namestr, sizeof(namestr)); + dns_rdatatype_format(rdata.type, typestr, + sizeof(typestr)); + update_log(client, zone, LOGLEVEL_PROTOCOL, + "deleting rrset at '%s' %s", namestr, + typestr); + } + CHECK(delete_if(true_p, db, ver, name, rdata.type, + covers, &rdata, &diff)); } else if (update_class == dns_rdataclass_none) { char namestr[DNS_NAME_FORMATSIZE]; char typestr[DNS_RDATATYPE_FORMATSIZE];