diff --git a/bin/tests/system/dnssec/tests_validation.py b/bin/tests/system/dnssec/tests_validation.py new file mode 100644 index 0000000000..c7f1ddca0d --- /dev/null +++ b/bin/tests/system/dnssec/tests_validation.py @@ -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 diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 10108d7501..84fbfd5789 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -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: "