]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Prevent UDPATE deleting keys in dnssec-policy zones 5956-update-keydata 12020/head
authorEvan Hunt <each@isc.org>
Thu, 14 May 2026 03:03:43 +0000 (20:03 -0700)
committerEvan Hunt <each@isc.org>
Thu, 14 May 2026 05:02:52 +0000 (22:02 -0700)
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.

bin/tests/system/nsupdate/tests.sh
lib/ns/update.c

index 7a77faea6beefce4ee8d335bef9672f2b1352bda..bce4b98b810e9c12eb045bf4753a7a5a574f384d 100755 (executable)
@@ -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 <<END >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)"
index 93240ca250c2108d0815de17bd7b8ec51b837889..f2ad9fe3d394cde9061f47d83a77fa7408e32854 100644 (file)
@@ -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];