diff --git a/bin/tests/system/tcp/ns7/named.dropedns b/bin/tests/system/tcp/ns7/named.dropedns new file mode 100644 index 0000000000..37dd9cf1ea --- /dev/null +++ b/bin/tests/system/tcp/ns7/named.dropedns @@ -0,0 +1 @@ +dropedns diff --git a/bin/tests/system/tcp/tests-tcp.py b/bin/tests/system/tcp/tests-tcp.py index da70b1ef38..e641ad9103 100644 --- a/bin/tests/system/tcp/tests-tcp.py +++ b/bin/tests/system/tcp/tests-tcp.py @@ -27,9 +27,8 @@ import dns.query TIMEOUT = 10 -def create_msg(qname, qtype): - msg = dns.message.make_query(qname, qtype, want_dnssec=True, - use_edns=0, payload=4096) +def create_msg(qname, qtype, edns=-1): + msg = dns.message.make_query(qname, qtype, use_edns=edns) return msg @@ -87,3 +86,36 @@ def test_tcp_garbage_response(named_port): (response, rtime) = dns.query.receive_tcp(sock, timeout()) except ConnectionError as e: raise EOFError from e + + +# Regression test for CVE-2022-0396 +def test_close_wait(named_port): + with create_socket("10.53.0.7", named_port) as sock: + + msg = create_msg("a.example.", "A") + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + (response, rtime) = dns.query.receive_tcp(sock, timeout()) + + msg = dns.message.make_query("a.example.", "A", use_edns=0, + payload=1232) + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + + # Shutdown the socket, but ignore the other side closing the socket + # first because we sent DNS message with EDNS0 + try: + sock.shutdown(socket.SHUT_RDWR) + except ConnectionError: + pass + except OSError: + pass + + # BIND allows one TCP client, the part above sends DNS messaage with EDNS0 + # after the first query. BIND should react adequately because of + # ns7/named.dropedns and close the socket, making room for the next + # request. If it gets stuck in CLOSE_WAIT state, there is no connection + # available for the query below and it will time out. + with create_socket("10.53.0.7", named_port) as sock: + + msg = create_msg("a.example.", "A") + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + (response, rtime) = dns.query.receive_tcp(sock, timeout())