]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Refactor the fwdfirst ans3 response server 12527/head
authorŠtěpán Balážik <stepan@isc.org>
Thu, 23 Jul 2026 11:02:39 +0000 (13:02 +0200)
committerŠtěpán Balážik <stepan@isc.org>
Wed, 12 Aug 2026 15:31:31 +0000 (15:31 +0000)
Serve the forged answer with a declarative QnameQtypeHandler scoped to
the victim query instead of an imperative handler that poisoned every A
query.  ns.fwd.hack is reached only if the resolver wrongly follows the
poison referral, and the victim name is the query the test inspects.

Assisted-by: Claude:claude-fable-5
bin/tests/system/fwdfirst/ans3/ans.py

index 8a7ecf8a4deaabff9865eb90099facbf182c65ce..390278fbbe7928cfb8acb3a4ec233333d1cd5f9f 100644 (file)
@@ -11,38 +11,32 @@ See the COPYRIGHT file distributed with this work for additional
 information regarding copyright ownership.
 """
 
-from collections.abc import AsyncGenerator
-
 import dns.rcode
+import dns.rdataclass
 import dns.rdatatype
 import dns.rrset
 
-from isctest.asyncserver import (
-    AsyncDnsServer,
-    DnsResponseSend,
-    QueryContext,
-    ResponseAction,
-    ResponseHandler,
-)
+from isctest.asyncserver import AsyncDnsServer, QnameQtypeHandler, StaticResponseHandler
+
+VICTIM = "victim.sibling.hack."
+POISON_ADDRESS = "6.6.6.6"
+
 
+def a(name: str) -> dns.rrset.RRset:
+    return dns.rrset.from_text(
+        name, 300, dns.rdataclass.IN, dns.rdatatype.A, POISON_ADDRESS
+    )
 
-class AttackerAuthority(ResponseHandler):
-    async def get_responses(
-        self, qctx: QueryContext
-    ) -> AsyncGenerator[ResponseAction, None]:
-        if qctx.qtype == dns.rdatatype.A:
-            qctx.response.answer.append(
-                dns.rrset.from_text(
-                    qctx.qname, 300, qctx.qclass, dns.rdatatype.A, "6.6.6.6"
-                )
-            )
 
-        yield DnsResponseSend(qctx.response)
+class PoisonedAHandler(QnameQtypeHandler, StaticResponseHandler):
+    qnames = [VICTIM]
+    qtypes = [dns.rdatatype.A]
+    answer = [a(VICTIM)]
 
 
 def main() -> None:
     server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)
-    server.install_response_handler(AttackerAuthority())
+    server.install_response_handler(PoisonedAHandler())
     server.run()