]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not cache minimal NSEC records (NSEC + RRSIG only)
authorMark Andrews <marka@isc.org>
Tue, 19 Oct 2021 03:40:27 +0000 (14:40 +1100)
committerPetr Špaček <pspacek@isc.org>
Thu, 2 Dec 2021 13:18:41 +0000 (14:18 +0100)
these are not useful for dnssec synthesis as they can result in
false NODATA responses and just consume cache memory

lib/dns/resolver.c

index b559c2397b51c3b5dafcaf90fe7dc75c9ee4a7dc..04d57b7c3a584200115ecdb8af4bad48f8ff505f 100644 (file)
@@ -5141,6 +5141,47 @@ unlock:
        }
 }
 
+/*
+ * typemap with just RRSIG(46) and NSEC(47) bits set.
+ *
+ * Bitmap calculation from dns_nsec_setbit:
+ *
+ *                                     46      47
+ *     shift = 7 - (type % 8);         0       1
+ *     mask = 1 << shift;              0x02    0x01
+ *     array[type / 8] |= mask;
+ *
+ * Window (0), bitmap length (6), and bitmap.
+ */
+static const unsigned char minimal_typemap[] = { 0, 6, 0, 0, 0, 0, 0, 0x03 };
+
+static bool
+is_minimal_nsec(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_rdata_nsec_t nsec;
+               dns_rdataset_current(&rdataset, &rdata);
+               result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               if (nsec.len == sizeof(minimal_typemap) &&
+                   memcmp(nsec.typebits, minimal_typemap, nsec.len) == 0)
+               {
+                       dns_rdataset_disassociate(&rdataset);
+                       return (true);
+               }
+       }
+       dns_rdataset_disassociate(&rdataset);
+       return (false);
+}
+
 /*
  * The validator has finished.
  */
@@ -5530,6 +5571,10 @@ answer_response:
                            sigrdataset->trust != dns_trust_secure) {
                                continue;
                        }
+                       if (rdataset->type == dns_rdatatype_nsec &&
+                           is_minimal_nsec(rdataset)) {
+                               continue;
+                       }
                        result = dns_db_findnode(fctx->cache, name, true,
                                                 &nsnode);
                        if (result != ISC_R_SUCCESS) {