[9.20] fix: usr: Fix DNSSEC validation failures for names under an apex DNAME

DNSSEC validation could fail with SERVFAIL for names covered by a DNAME
at the apex of a signed zone, unless the zone's keys were already validated
in the cache. This regression was introduced by the recent fix for resolver
stalls on CNAME responses to DS queries.

Closes #6176

Backport of MR !12353

Merge branch 'backport-6176-validator-apex-dname-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!12356
This commit is contained in:
Ondřej Surý 2026-07-08 13:02:32 +02:00
commit cd006ecf23
2 changed files with 70 additions and 5 deletions

View file

@ -0,0 +1,59 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
from dns import rdatatype
import pytest
import isctest
import isctest.mark
pytestmark = pytest.mark.extra_artifacts(
[
"*/K*",
"*/NSEC*",
"*/dsset-*",
"*/*.bk",
"*/*.conf",
"*/*.db",
"*/*.id",
"*/*.jnl",
"*/*.jbk",
"*/*.key",
"*/*.signed",
"*/settime.out.*",
"ans*/ans.run",
"*/trusted.keys",
"*/*.bad",
"*/*.next",
"*/*.stripped",
"*/*.tmp",
"*/*.stage?",
"*/*.patched",
"*/*.lower",
"*/*.upper",
"*/*.unsplit",
]
)
def test_positive_validation_dname_at_apex():
# an apex DNAME is signed by the DNSKEY living at the DNAME owner
# name itself; fetching that key must not be mistaken for a
# non-advancing alias chain (GL #6176)
msg = isctest.query.create("a.dname-at-apex-nsec3.example", "A")
res = isctest.query.tcp(msg, "10.53.0.4")
isctest.check.noerror(res)
isctest.check.adflag(res)
answers = {(str(rr.name), rr.rdtype) for rr in res.answer}
assert ("dname-at-apex-nsec3.example.", rdatatype.DNAME) in answers
assert ("a.example.", rdatatype.A) in answers

View file

@ -993,12 +993,18 @@ check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
}
/*
* Validating a CNAME/DNAME ("chaining" rdataset): a fetch at
* the alias's own name cannot advance the chain (the type we
* need, e.g. DS/DNSKEY for an insecurity proof, cannot live at
* an alias) and would only self-join the in-flight fetch.
* Validating a chaining CNAME: a fetch at the alias's own
* name cannot advance the chain (no other type can live at
* a CNAME owner, so e.g. the DS/DNSKEY needed for an
* insecurity proof cannot be there) and would only
* self-join the in-flight fetch. A chaining DNAME is
* different: it aliases only the names below its owner, so
* the owner itself may legitimately hold the DNSKEY or DS
* this validation needs (e.g. a DNAME at a zone apex).
*/
if (cur->rdataset != NULL && CHAINING(cur->rdataset)) {
if (cur->rdataset != NULL && CHAINING(cur->rdataset) &&
cur->rdataset->type == dns_rdatatype_cname)
{
validator_log(
val, ISC_LOG_DEBUG(3),
"fetch would not advance the alias chain: "