rdobuilder 8e7af2
From 51e3c4928d4938beb576eff34f3bf97e6e64e6b4 Mon Sep 17 00:00:00 2001
rdobuilder 8e7af2
From: Kelvin J Li <72498127+kelvin-j-li@users.noreply.github.com>
rdobuilder 8e7af2
Date: Mon, 19 Feb 2024 21:42:27 +0800
rdobuilder 8e7af2
Subject: [PATCH] Dnspython 2.6.1 - Address DoS via the Tudoor mechanism
rdobuilder 8e7af2
 (CVE-2023-29483)
rdobuilder 8e7af2
MIME-Version: 1.0
rdobuilder 8e7af2
Content-Type: text/plain; charset=UTF-8
rdobuilder 8e7af2
Content-Transfer-Encoding: 8bit
rdobuilder 8e7af2
rdobuilder 8e7af2
Fix for (CVE-2023-29483) and handling of truncated exceptions in greendns.py provided by Bob Halley from https://github.com/rthalley/eventlet/tree/tudoor
rdobuilder 8e7af2
rdobuilder 8e7af2
Do not eat legitimate Truncated exceptions.
rdobuilder 8e7af2
---------
rdobuilder 8e7af2
Co-authored-by: Bob Halley <halley@play-bow.org>
rdobuilder 8e7af2
Co-authored-by: Hervé Beraud <hberaud@redhat.com>
rdobuilder 8e7af2
---
rdobuilder 8e7af2
 eventlet/support/greendns.py | 56 ++++++++++++++++++++++++------------
rdobuilder 8e7af2
 1 file changed, 38 insertions(+), 18 deletions(-)
rdobuilder 8e7af2
rdobuilder 8e7af2
diff --git a/eventlet/support/greendns.py b/eventlet/support/greendns.py
rdobuilder 8e7af2
index 62621423..365664f2 100644
rdobuilder 8e7af2
--- a/eventlet/support/greendns.py
rdobuilder 8e7af2
+++ b/eventlet/support/greendns.py
rdobuilder 8e7af2
@@ -713,7 +713,7 @@ except TypeError:
rdobuilder 8e7af2
 def udp(q, where, timeout=DNS_QUERY_TIMEOUT, port=53,
rdobuilder 8e7af2
         af=None, source=None, source_port=0, ignore_unexpected=False,
rdobuilder 8e7af2
         one_rr_per_rrset=False, ignore_trailing=False,
rdobuilder 8e7af2
-        raise_on_truncation=False, sock=None):
rdobuilder 8e7af2
+        raise_on_truncation=False, sock=None, ignore_errors=False):
rdobuilder 8e7af2
     """coro friendly replacement for dns.query.udp
rdobuilder 8e7af2
     Return the response obtained after sending a query via UDP.
rdobuilder 8e7af2
 
rdobuilder 8e7af2
@@ -752,7 +752,10 @@ def udp(q, where, timeout=DNS_QUERY_TIMEOUT, port=53,
rdobuilder 8e7af2
     query.  If None, the default, a socket is created.  Note that
rdobuilder 8e7af2
     if a socket is provided, it must be a nonblocking datagram socket,
rdobuilder 8e7af2
     and the source and source_port are ignored.
rdobuilder 8e7af2
-    @type sock: socket.socket | None"""
rdobuilder 8e7af2
+    @type sock: socket.socket | None
rdobuilder 8e7af2
+    @param ignore_errors: if various format errors or response mismatches occur,
rdobuilder 8e7af2
+    continue listening.
rdobuilder 8e7af2
+    @type ignore_errors: bool"""
rdobuilder 8e7af2
 
rdobuilder 8e7af2
     wire = q.to_wire()
rdobuilder 8e7af2
     if af is None:
rdobuilder 8e7af2
@@ -816,26 +819,43 @@ def udp(q, where, timeout=DNS_QUERY_TIMEOUT, port=53,
rdobuilder 8e7af2
                 addr = from_address[0]
rdobuilder 8e7af2
                 addr = dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(addr))
rdobuilder 8e7af2
                 from_address = (addr, from_address[1], from_address[2], from_address[3])
rdobuilder 8e7af2
-            if from_address == destination:
rdobuilder 8e7af2
+            if from_address != destination:
rdobuilder 8e7af2
+                if ignore_unexpected:
rdobuilder 8e7af2
+                    continue
rdobuilder 8e7af2
+                else:
rdobuilder 8e7af2
+                    raise dns.query.UnexpectedSource(
rdobuilder 8e7af2
+                        'got a response from %s instead of %s'
rdobuilder 8e7af2
+                        % (from_address, destination))
rdobuilder 8e7af2
+            try:
rdobuilder 8e7af2
+                if _handle_raise_on_truncation:
rdobuilder 8e7af2
+                    r = dns.message.from_wire(wire,
rdobuilder 8e7af2
+                                              keyring=q.keyring,
rdobuilder 8e7af2
+                                              request_mac=q.mac,
rdobuilder 8e7af2
+                                              one_rr_per_rrset=one_rr_per_rrset,
rdobuilder 8e7af2
+                                              ignore_trailing=ignore_trailing,
rdobuilder 8e7af2
+                                              raise_on_truncation=raise_on_truncation)
rdobuilder 8e7af2
+                else:
rdobuilder 8e7af2
+                    r = dns.message.from_wire(wire,
rdobuilder 8e7af2
+                                              keyring=q.keyring,
rdobuilder 8e7af2
+                                              request_mac=q.mac,
rdobuilder 8e7af2
+                                              one_rr_per_rrset=one_rr_per_rrset,
rdobuilder 8e7af2
+                                              ignore_trailing=ignore_trailing)
rdobuilder 8e7af2
+                if not q.is_response(r):
rdobuilder 8e7af2
+                    raise dns.query.BadResponse()
rdobuilder 8e7af2
                 break
rdobuilder 8e7af2
-            if not ignore_unexpected:
rdobuilder 8e7af2
-                raise dns.query.UnexpectedSource(
rdobuilder 8e7af2
-                    'got a response from %s instead of %s'
rdobuilder 8e7af2
-                    % (from_address, destination))
rdobuilder 8e7af2
+            except dns.message.Truncated as e:
rdobuilder 8e7af2
+                if ignore_errors and not q.is_response(e.message()):
rdobuilder 8e7af2
+                    continue
rdobuilder 8e7af2
+                else:
rdobuilder 8e7af2
+                    raise
rdobuilder 8e7af2
+            except Exception:
rdobuilder 8e7af2
+                if ignore_errors:
rdobuilder 8e7af2
+                    continue
rdobuilder 8e7af2
+                else:
rdobuilder 8e7af2
+                    raise
rdobuilder 8e7af2
     finally:
rdobuilder 8e7af2
         s.close()
rdobuilder 8e7af2
 
rdobuilder 8e7af2
-    if _handle_raise_on_truncation:
rdobuilder 8e7af2
-        r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
rdobuilder 8e7af2
-                                  one_rr_per_rrset=one_rr_per_rrset,
rdobuilder 8e7af2
-                                  ignore_trailing=ignore_trailing,
rdobuilder 8e7af2
-                                  raise_on_truncation=raise_on_truncation)
rdobuilder 8e7af2
-    else:
rdobuilder 8e7af2
-        r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac,
rdobuilder 8e7af2
-                                  one_rr_per_rrset=one_rr_per_rrset,
rdobuilder 8e7af2
-                                  ignore_trailing=ignore_trailing)
rdobuilder 8e7af2
-    if not q.is_response(r):
rdobuilder 8e7af2
-        raise dns.query.BadResponse()
rdobuilder 8e7af2
     return r
rdobuilder 8e7af2
 
rdobuilder 8e7af2
 
rdobuilder 8e7af2
-- 
rdobuilder 8e7af2
2.46.0
rdobuilder 8e7af2