]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Reject out-of-zone NSEC next owner names
authorAydın Mercan <aydin@isc.org>
Thu, 7 May 2026 15:59:20 +0000 (18:59 +0300)
committerMichał Kępień <michal@isc.org>
Fri, 10 Jul 2026 07:26:46 +0000 (09:26 +0200)
When verifying DNSSEC records, make sure that a next owner name of
an NSEC record is a subdomain of the signer field.

This follows the specification RFC 4034, section 4.1.1:

 Owner names of RRsets for which the given zone is not authoritative
 (such as glue records) MUST NOT be listed in the Next Domain Name
 unless at least one authoritative RRset exists at the same owner
 name.

While the above paragraph is intended for glue records, it also
applies to out-of-zone data.

lib/dns/dnssec.c
lib/dns/include/dns/dnssec.h

index f7aae5126c3e0edc63d7d18239f88b01508783ee..5b7cded2d7df00ff140c8275730616ff83ce74cf 100644 (file)
@@ -345,8 +345,10 @@ isc_result_t
 dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
                  bool ignoretime, isc_mem_t *mctx, dns_rdata_t *sigrdata,
                  dns_name_t *wild, dns_name_t *wildsigner) {
+       dns_rdata_nsec_t nsec;
        dns_rdata_rrsig_t sig;
        dns_fixedname_t fnewname;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
        isc_region_t r;
        isc_buffer_t envbuf;
        dns_rdata_t *rdatas;
@@ -449,6 +451,17 @@ dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
                }
                break;
        }
+       /*
+        * Check for out of zone NSEC entries.
+        */
+       if (set->type == dns_rdatatype_nsec) {
+               RETERR(dns_rdataset_first(set));
+               dns_rdataset_current(set, &rdata);
+               RETERR(dns_rdata_tostruct(&rdata, &nsec, NULL));
+               if (!dns_name_issubdomain(&nsec.next, &sig.signer)) {
+                       return DNS_R_NOVALIDNSEC;
+               }
+       }
 
 again:
        result = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false,
index be79431b1c43e8ee12d10157f62a8e5c54f6fba2..ac1a6d01c9dda666a9cb09197d24b67d8e2d71f0 100644 (file)
@@ -149,6 +149,9 @@ dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
  *     this record, as this requires a resolver or database.
  *     If 'ignoretime' is true, temporal validity will not be checked.
  *
+ *     If 'set' is of type NSEC, this function also verifies that the
+ *     Next Name is a subdomain of the Signer's Name from 'sigrdata'.
+ *
  *     'maxbits' specifies the maximum number of rsa exponent bits accepted.
  *
  *     Requires:
@@ -173,6 +176,9 @@ dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
  *\li          #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either
  *                     it is not a zone key or its flags prevent
  *                     authentication)
+ *
+ *\li          #DNS_R_NOVALIDNSEC - the NSEC rdata is not valid
+ *\li          #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data
  *\li          DST_R_*
  */