]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Test Negative Trust Anchor disclosure via Extended DNS Error 33
authorOndřej Surý <ondrej@sury.org>
Mon, 20 Jul 2026 08:46:09 +0000 (10:46 +0200)
committerOndřej Surý <ondrej@sury.org>
Mon, 20 Jul 2026 10:08:33 +0000 (12:08 +0200)
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
bin/tests/system/nta/tests_nta.py
tests/dns/ede_test.c

index ece8db67295c963984da8a0d98996500823e0f9d..4e083b75cc8a0b3b62c8cbf4fe403b120df07768 100644 (file)
@@ -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
index 4efad9e525f073be89524dd7d15c08d09272830f..0166212ce0d15d5ea6c96005ff10d9637243815c 100644 (file)
@@ -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);
 }