1#!/usr/bin/python3
2
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# SPDX-License-Identifier: MPL-2.0
6#
7# This Source Code Form is subject to the terms of the Mozilla Public
8# License, v. 2.0.  If a copy of the MPL was not distributed with this
9# file, you can obtain one at https://mozilla.org/MPL/2.0/.
10#
11# See the COPYRIGHT file distributed with this work for additional
12# information regarding copyright ownership.
13
14import socket
15import time
16
17import pytest
18
19pytest.importorskip("dns")
20import dns.message
21import dns.query
22import dns.rcode
23
24
25def test_cve_2023_3341(named_port, control_port):
26    depth = 4500
27    # Should not be more than isccc_ccmsg_setmaxsize(&conn->ccmsg, 32768)
28    total_len = 10 + (depth * 7) - 6
29
30    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
31        data = b"".join(
32            [
33                total_len.to_bytes(4, "big"),  # <total lenght>
34                b"\x00\x00\x00\x01",  # <version>
35                b"\x01\x41",  # <size><name>
36            ]
37        )
38
39        for i in range(depth, 0, -1):
40            l = (i - 1) * 7
41            t = b"".join(
42                [
43                    b"\x02",  # ISCCC_CCMSGTYPE_TABLE
44                    l.to_bytes(4, "big"),  # <size>
45                    b"\x01\x41",  # <size><name>
46                ]
47            )
48            data = b"".join([data, t])
49
50        s.connect(("10.53.0.2", control_port))
51        s.sendall(data)
52
53    # Wait for named to (possibly) crash
54    time.sleep(10)
55    msg = dns.message.make_query("version.bind", "TXT", "CH")
56    ans = dns.query.udp(msg, "10.53.0.2", timeout=10, port=named_port)
57    assert ans.rcode() == dns.rcode.NOERROR
58