]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add RPZ NSDNAME test
authorColin Vidal <colin@isc.org>
Fri, 27 Mar 2026 12:12:17 +0000 (13:12 +0100)
committerColin Vidal <colin@isc.org>
Mon, 30 Mar 2026 18:41:13 +0000 (20:41 +0200)
Add a simple case (i.e. not relying on zone being generated during the
test) ensuring that RPZ NSDNAME rules are correctly applied using the
parent-centric resolver.

bin/tests/system/rpzrecurse/ans6/ans.py [new file with mode: 0644]
bin/tests/system/rpzrecurse/ns3/policy.db
bin/tests/system/rpzrecurse/ns3/root.db
bin/tests/system/rpzrecurse/tests.sh

diff --git a/bin/tests/system/rpzrecurse/ans6/ans.py b/bin/tests/system/rpzrecurse/ans6/ans.py
new file mode 100644 (file)
index 0000000..f2d8887
--- /dev/null
@@ -0,0 +1,67 @@
+"""
+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 collections.abc import AsyncGenerator
+
+import dns.rcode
+import dns.rdatatype
+import dns.rrset
+
+from isctest.asyncserver import (
+    AsyncDnsServer,
+    DnsResponseSend,
+    QueryContext,
+    ResponseHandler,
+)
+
+
+class ReplyA(ResponseHandler):
+    def match(self, qctx: QueryContext) -> bool:
+        return qctx.qtype == dns.rdatatype.A
+
+    async def get_responses(
+        self, qctx: QueryContext
+    ) -> AsyncGenerator[DnsResponseSend, None]:
+        a_rrset = dns.rrset.from_text(
+            qctx.qname, 300, qctx.qclass, dns.rdatatype.A, "10.53.0.6"
+        )
+        qctx.response.answer.append(a_rrset)
+        yield DnsResponseSend(qctx.response)
+
+
+class DelayNs(ResponseHandler):
+    def match(self, qctx: QueryContext) -> bool:
+        return qctx.qtype == dns.rdatatype.NS
+
+    async def get_responses(
+        self, qctx: QueryContext
+    ) -> AsyncGenerator[DnsResponseSend, None]:
+        ns_rrset = dns.rrset.from_text(
+            "www.bar.",
+            300,
+            qctx.qclass,
+            dns.rdatatype.NS,
+            "ns6.foo.",
+        )
+        qctx.response.answer.append(ns_rrset)
+        yield DnsResponseSend(qctx.response, delay=1)
+
+
+def main() -> None:
+    server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
+    server.install_response_handlers(ReplyA(), DelayNs())
+    server.run()
+
+
+if __name__ == "__main__":
+    main()
index 526d75ccb9b72d77fd92b74485bc4f433a2249cd..99ab7ebe08676984d08eef8127b1becc39793401 100644 (file)
@@ -13,3 +13,6 @@ $TTL 0
 @                      SOA     . . 0 0 0 0 0
 @                      NS      .
 32.100.0.53.10.rpz-nsip        CNAME   .
+
+; Return NXDOMAIN is the NS name of the zone is `ns6.foo.`
+ns6.foo.rpz-nsdname    CNAME   .
index 327be8040405d78afe366e3676931e63904d126e..c493825cb985bee76ca1455274a379e1a735abd0 100644 (file)
@@ -15,3 +15,5 @@ $TTL 0
 ns                     A       10.53.0.3
 foo                    NS      ns5.foo
 ns5.foo                        A       10.53.0.5
+bar                    NS      ns6.foo
+ns6.foo                        A       10.53.0.6
index 113322600dfdcc0f2939541c3c4882cb2a95af4d..5940c88edbc952fc2c15a17d823da61e29af2493 100644 (file)
@@ -436,6 +436,14 @@ grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\
   status=1
 }
 
+t=$((t + 1))
+echo_i "checking NSDNAME policy being blocked' ($t)"
+$DIG $DIGOPTS www.bar. @10.53.0.3 -p ${PORT} >dig.out.${t}
+grep "status: NXDOMAIN" dig.out.${t} >/dev/null || {
+  echo_i "test ${t} failed"
+  status=1
+}
+
 t=$((t + 1))
 echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)"
 add_test_marker 10.53.0.2 10.53.0.3