From: Aydın Mercan Date: Thu, 7 May 2026 15:59:20 +0000 (+0300) Subject: Reject out-of-zone NSEC next owner names X-Git-Tag: v9.21.24~4^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4065512d25b71605b9502bb69dfb903776d35aa9;p=thirdparty%2Fbind9.git Reject out-of-zone NSEC next owner names 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. --- diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index f7aae5126c3..5b7cded2d7d 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -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, diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h index be79431b1c4..ac1a6d01c9d 100644 --- a/lib/dns/include/dns/dnssec.h +++ b/lib/dns/include/dns/dnssec.h @@ -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_* */