]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Check that SOA and DNSKEY are consistent in NSEC typemaps
authorMark Andrews <marka@isc.org>
Tue, 30 Nov 2021 22:58:46 +0000 (09:58 +1100)
committerPetr Špaček <pspacek@isc.org>
Thu, 2 Dec 2021 13:24:37 +0000 (14:24 +0100)
If there is a SOA record present then there should also be a
DNSKEY record present as the DNSKEY is supposed to live at the
zone apex like the SOA.

lib/dns/resolver.c

index f98295bf1235594f11735e01174ef176b3f1d72a..8a17782c99a56cb3669d6b60c9f7beb1b1d3667e 100644 (file)
@@ -5182,6 +5182,34 @@ is_minimal_nsec(dns_rdataset_t *nsecset) {
        return (false);
 }
 
+/*
+ * If there is a SOA record in the type map then there must be a DNSKEY.
+ */
+static bool
+check_soa_and_dnskey(dns_rdataset_t *nsecset) {
+       dns_rdataset_t rdataset;
+       isc_result_t result;
+
+       dns_rdataset_init(&rdataset);
+       dns_rdataset_clone(nsecset, &rdataset);
+
+       for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&rdataset))
+       {
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdataset_current(&rdataset, &rdata);
+               if (dns_nsec_typepresent(&rdata, dns_rdatatype_soa) &&
+                   (!dns_nsec_typepresent(&rdata, dns_rdatatype_dnskey) ||
+                    !dns_nsec_typepresent(&rdata, dns_rdatatype_ns)))
+               {
+                       dns_rdataset_disassociate(&rdataset);
+                       return (false);
+               }
+       }
+       dns_rdataset_disassociate(&rdataset);
+       return (true);
+}
+
 /*
  * The validator has finished.
  */
@@ -5591,6 +5619,14 @@ answer_response:
                        {
                                continue;
                        }
+
+                       /*
+                        * Check SOA and DNSKEY consistency.
+                        */
+                       if (rdataset->type == dns_rdatatype_nsec &&
+                           !check_soa_and_dnskey(rdataset)) {
+                               continue;
+                       }
                        result = dns_db_findnode(fctx->cache, name, true,
                                                 &nsnode);
                        if (result != ISC_R_SUCCESS) {