diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 255b9e9364..9da64d7dd3 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -441,10 +441,23 @@ dns_nsec_noexistnodata(dns_rdatatype_t type, const dns_name_t *name, return DNS_R_DNAME; } + if (relation != dns_namereln_subdomain && + dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) + { + /* + * An NSEC with an SOA in the bitmap can only cover + * names that are subdomains of the owner. + */ + (*logit)(arg, ISC_LOG_DEBUG(3), + "ignoring nsec with SOA covering non-subdomain"); + return ISC_R_IGNORE; + } + result = dns_rdata_tostruct(&rdata, &nsec, NULL); if (result != ISC_R_SUCCESS) { return result; } + relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels); if (order == 0) { dns_rdata_freestruct(&nsec); diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 9b5ef3fc51..da41e41981 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -846,6 +846,8 @@ validator_callback_nsec(void *arg) { rdataset->trust == dns_trust_secure && (NEEDNODATA(val) || NEEDNOQNAME(val)) && !FOUNDNODATA(val) && !FOUNDNOQNAME(val) && + dns_name_issubdomain(val->name, + &subvalidator->siginfo->signer) && dns_nsec_noexistnodata(val->type, val->name, subvalidator->name, rdataset, &exists, &data, wild, validator_log, diff --git a/lib/ns/query.c b/lib/ns/query.c index bad57c4ee6..09431d4ce2 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -9959,6 +9959,13 @@ query_coveringnsec(query_ctx_t *qctx) { goto cleanup; } + /* + * The query name can't be above the signer of the NSEC. + */ + if (!dns_name_issubdomain(qctx->client->query.qname, signer)) { + goto cleanup; + } + /* * If NSEC or RRSIG are missing from the type map * reject the NSEC RRset.