]> 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 10:02:20 +0000 (12:02 +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.

(cherry picked from commit de42425bbd6f51edf2abc0e57d4d3e3dd2e92159)

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

index f3c6c9fec167b056fe81db03c870e0a66274bdc9..94f986c8e7949029e119d637b595177d8f7c4289 100644 (file)
@@ -66,21 +66,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)