From: Ondřej Surý Date: Mon, 20 Jul 2026 08:46:09 +0000 (+0200) Subject: Test Negative Trust Anchor disclosure via Extended DNS Error 33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06ab690435c96010868390eee48f7a06ed4f4ddc;p=thirdparty%2Fbind9.git Test Negative Trust Anchor disclosure via Extended DNS Error 33 Extend the EDE unit test to cover the newly registered code 33 and to verify it does not collide with lower codes in the used-code bitmap. Add a resolver system test: a name whose validation is suppressed by a Negative Trust Anchor is answered with EDE 33 present, while the same name without an NTA still fails validation and carries no such error. Assisted-by: Claude:claude-opus-4-8 --- diff --git a/bin/tests/system/nta/tests_nta.py b/bin/tests/system/nta/tests_nta.py index ece8db67295..4e083b75cc8 100644 --- a/bin/tests/system/nta/tests_nta.py +++ b/bin/tests/system/nta/tests_nta.py @@ -14,13 +14,25 @@ from re import compile as Re import os import time +import dns.edns + import isctest +# Extended DNS Error INFO-CODE disclosing that a Negative Trust Anchor was +# applied to a response (draft-farrokhi-dnsop-ede-nta). +NTA_EDE_CODE = 33 + def active(blob): return len([x for x in blob.splitlines() if " expiry" in x]) +def has_ede(res, code): + return any( + opt.otype == dns.edns.OptionType.EDE and opt.code == code for opt in res.options + ) + + # global start-time variable # pylint: disable=global-statement START = 0 @@ -418,3 +430,31 @@ def test_nta_forward(servers): isctest.check.servfail(res) isctest.check.empty_answer(res) isctest.check.noadflag(res) + + +def test_nta_ede(servers): + # A response whose DNSSEC validation was suppressed by a Negative Trust + # Anchor must disclose that via EDE code 33 (draft-farrokhi-dnsop-ede-nta). + ns9 = servers["ns9"] + + m = isctest.query.create("badds.example", "SOA") + + # Without an NTA, validation fails: SERVFAIL and no NTA EDE. + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.servfail(res) + assert not has_ede(res, NTA_EDE_CODE), res + + # With an NTA in place, the answer is returned (AD=0) and carries EDE 33. + ns9.rndc("nta badds.example") + try: + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.noerror(res) + isctest.check.noadflag(res) + isctest.check.ede(res, NTA_EDE_CODE) + finally: + ns9.rndc("nta -remove badds.example") + + # Once the NTA is gone, the disclosure stops too. + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.servfail(res) + assert not has_ede(res, NTA_EDE_CODE), res diff --git a/tests/dns/ede_test.c b/tests/dns/ede_test.c index 4efad9e525f..0166212ce0d 100644 --- a/tests/dns/ede_test.c +++ b/tests/dns/ede_test.c @@ -148,12 +148,22 @@ ISC_RUN_TEST_IMPL(dns_ede_test_infocode_range) { dns_ede_init(isc_g_mctx, &edectx); dns_ede_add(&edectx, 1, NULL); - expect_assert_failure(dns_ede_add(&edectx, 32, NULL)); + + /* + * DNS_EDE_NTA (33) is the highest defined INFO-CODE. Adding it must + * succeed and must not collide with the previously added code 1 in + * the "already used" bitmap (which requires more than 32 bits). + */ + dns_ede_add(&edectx, DNS_EDE_NTA, NULL); + + /* Codes at or beyond DNS_EDE_MAX_CODE are rejected. */ + expect_assert_failure(dns_ede_add(&edectx, DNS_EDE_MAX_CODE, NULL)); const ede_test_expected_t expected[] = { { .code = 1, .txt = NULL }, + { .code = DNS_EDE_NTA, .txt = NULL }, }; - dns_ede_test_equals(expected, 1, &edectx); + dns_ede_test_equals(expected, 2, &edectx); dns_ede_reset(&edectx); }