]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix flawed response logic for COOKIE-less queries
authorMichał Kępień <michal@isc.org>
Thu, 21 May 2026 09:52:56 +0000 (11:52 +0200)
committerMichał Kępień <michal@isc.org>
Thu, 21 May 2026 09:52:56 +0000 (11:52 +0200)
The "yield" keyword does not cause a function to return.  By design,
get_responses() may yield multiple DNS responses in a single call.  As
currently implemented, CookieHandler.get_responses() sends two responses
to each client query that does not contain a COOKIE option.  Make the
logic in that method consistent with code comments by only sending one
response to every query - either SERVFAIL or BADCOOKIE, never both.

bin/tests/system/resend_loop/ans3/ans.py

index 69ea0be6c76e93f9a4c359061f2629c2f00e1669..47275bf3777794e6a42d2d904c9494f2733a249e 100644 (file)
@@ -73,21 +73,17 @@ class CookieHandler(DomainHandler):
     async def get_responses(
         self, qctx: QueryContext
     ) -> AsyncGenerator[DnsResponseSend, None]:
-
-        # Check for client cookie
-        cookie = _get_cookie(qctx)
-
-        # If missing cookie entirely, just return SERVFAIL
-        if cookie is None:
+        if cookie := _get_cookie(qctx):
+            # If there is a client cookie, mock BADCOOKIE to trigger
+            # the resend loop logic.
+            qctx.response.use_edns(options=[cookie])
+            qctx.response.set_rcode(dns.rcode.BADCOOKIE)
+            yield DnsResponseSend(qctx.response)
+        else:
+            # If missing cookie entirely, just return SERVFAIL
             qctx.response.set_rcode(dns.rcode.SERVFAIL)
             yield DnsResponseSend(qctx.response)
 
-        # If there is a client cookie, mock BADCOOKIE to trigger
-        # the resend loop logic.
-        qctx.response.use_edns(options=[cookie])
-        qctx.response.set_rcode(dns.rcode.BADCOOKIE)
-        yield DnsResponseSend(qctx.response)
-
 
 def resend_server() -> AsyncDnsServer:
     server = AsyncDnsServer(default_aa=True, default_rcode=dns.rcode.NOERROR)