From d0e413dd5763fbe81ba37abeec650f26a9248feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0pa=C4=8Dek?= Date: Thu, 10 Jul 2025 13:13:02 +0200 Subject: [PATCH] Test dangling CNAMEs come with NXDOMAIN proofs Simplistic test. Ignores the possibility of CNAME chain going through multiple zones and/or wildcard expansions. --- bin/tests/system/nsec3-answer/ns1/root.db.in | 4 +++- bin/tests/system/nsec3-answer/tests_nsec3.py | 24 ++++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bin/tests/system/nsec3-answer/ns1/root.db.in b/bin/tests/system/nsec3-answer/ns1/root.db.in index 295e28c1d9..2171c44239 100644 --- a/bin/tests/system/nsec3-answer/ns1/root.db.in +++ b/bin/tests/system/nsec3-answer/ns1/root.db.in @@ -25,7 +25,9 @@ a. A 10.0.0.1 a.a.a.a. A 10.0.0.3 b. A 10.0.0.2 b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b. A 10.0.0.2 -; cname. CNAME cname.a.a. +cname. CNAME does-not-exist. +cname.cname. CNAME cname. +cname.ent.cname. CNAME cname.cname. d. A 10.0.0.4 dname-nowhere. DNAME does-not-exist. insecure. NS a.root-servers.nil. diff --git a/bin/tests/system/nsec3-answer/tests_nsec3.py b/bin/tests/system/nsec3-answer/tests_nsec3.py index ac3fe44715..f1b0a70154 100755 --- a/bin/tests/system/nsec3-answer/tests_nsec3.py +++ b/bin/tests/system/nsec3-answer/tests_nsec3.py @@ -47,7 +47,7 @@ ZONE = isctest.name.ZoneAnalyzer.read_path( def do_test_query( qname, qtype, server, named_port -) -> Tuple[dns.message.Message, "NSEC3Checker"]: +) -> Tuple[dns.message.QueryMessage, "NSEC3Checker"]: query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) response = isctest.query.tcp(query, server, named_port, timeout=TIMEOUT) isctest.check.is_response_to(response, query) @@ -58,7 +58,11 @@ def do_test_query( @pytest.mark.parametrize( "server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")] ) -@given(qname=sampled_from(sorted(ZONE.reachable))) +@given( + qname=sampled_from( + sorted(ZONE.reachable - ZONE.get_names_with_type(dns.rdatatype.CNAME)) + ) +) def test_nodata(server, qname: dns.name.Name, named_port: int) -> None: """An existing name, no wildcards, but a query type for RRset which does not exist""" response, nsec3check = do_test_query(qname, dns.rdatatype.HINFO, server, named_port) @@ -96,6 +100,22 @@ def test_nxdomain(server, qname: dns.name.Name, named_port: int) -> None: check_nxdomain(qname, nsec3check) +@pytest.mark.parametrize( + "server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")] +) +@given(qname=sampled_from(sorted(ZONE.get_names_with_type(dns.rdatatype.CNAME)))) +def test_cname_nxdomain(server, qname: dns.name.Name, named_port: int) -> None: + """CNAME which terminates by NXDOMAIN, no wildcards involved""" + response, nsec3check = do_test_query(qname, dns.rdatatype.A, server, named_port) + chain = response.resolve_chaining() + assume_nx_and_no_delegation(chain.canonical_name) + + wname = ZONE.source_of_synthesis(chain.canonical_name) + assume(wname not in ZONE.reachable_wildcards) + + check_nxdomain(chain.canonical_name, nsec3check) + + @pytest.mark.parametrize( "server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")] )