2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +00:00

Add a bad TSIG algorithm hypothesis python test

Co-authored-by: Petr Špaček <pspacek@isc.org>
(cherry picked from commit 96b0621de4b56795646dfa67cb47225216f4cab5)
This commit is contained in:
Nicki Křížek 2025-04-29 21:06:23 -07:00
parent 6ba6648935
commit e77b1275a0
2 changed files with 149 additions and 0 deletions

View File

@ -168,3 +168,8 @@ def _partition_bytes_to_labels(
# NOTE: Some of the remaining bytes will usually not be assigned to any label, but we don't care. # NOTE: Some of the remaining bytes will usually not be assigned to any label, but we don't care.
return draw(permutations(partition)) return draw(permutations(partition))
def uint(byte_size: int):
max_value = 2**byte_size - 1
return integers(min_value=0, max_value=max_value)

View File

@ -0,0 +1,144 @@
#!/usr/bin/python3
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import time
import pytest
pytest.importorskip("dns", minversion="2.7.0") # TSIG parsing without validation
# in FIPs mode md5 fails so we need 4.41.2 or later which does not use md5
try:
import hashlib
hashlib.md5(b"1234")
pytest.importorskip("hypothesis")
except ValueError:
pytest.importorskip("hypothesis", minversion="4.41.2")
import dns.exception
import dns.message
import dns.name
import dns.rdataclass
import dns.rdatatype
import dns.rdtypes.ANY.TSIG
import dns.rrset
import dns.tsig
from hypothesis import assume, example, given
from hypothesis.strategies import binary, booleans, composite, just, sampled_from
import isctest
from isctest.hypothesis.strategies import dns_names, uint
pytestmark = pytest.mark.extra_artifacts(
[
"ans*/ans.run",
"ns1/named-fips.conf",
]
)
@composite
def generate_known_algoritm_and_matching_len_mac(draw):
candidates = tuple(dns.tsig.mac_sizes.items())
alg, mac_size = draw(sampled_from(candidates))
mac = draw(binary(min_size=mac_size, max_size=mac_size))
return alg, mac
@composite
def generate_known_algoritm_and_wrong_len_mac(draw):
candidates = tuple(dns.tsig.mac_sizes.items())
alg, correct_mac_len = draw(sampled_from(candidates))
mac = draw(binary())
assume(len(mac) != correct_mac_len)
return alg, mac
@composite
def generate_unknown_but_likely_algoritm_and_mac(draw):
alg = draw(dns_names(min_labels=2, max_labels=2))
mac = draw(binary())
return alg, mac
@composite
def generate_random_alg_and_mac(draw):
alg = draw(dns_names())
mac = draw(binary())
return alg, mac
@given(
keyname=dns_names(max_labels=3) | dns_names(),
alg_and_mac=generate_known_algoritm_and_matching_len_mac()
| generate_known_algoritm_and_wrong_len_mac()
| generate_unknown_but_likely_algoritm_and_mac()
| generate_random_alg_and_mac(),
time_signed=just(int(time.time())) | uint(48),
fudge=just(300) | uint(16),
mangle_orig_id=booleans(),
error=just(0) | uint(12),
other=just(b"") | binary(),
)
@example(
keyname=dns.name.from_text("."),
alg_and_mac=(dns.name.from_text("."), b""),
time_signed=0,
fudge=300,
mangle_orig_id=False,
error=0,
other=b"",
)
def test_tsig_fuzz_rdata(
keyname,
alg_and_mac,
time_signed,
fudge,
error,
mangle_orig_id,
other,
servers,
named_port,
):
alg, mac = alg_and_mac
ns1 = servers["ns1"]
msg = dns.message.make_query("example.com.", "AXFR")
msg.keyring = False # don't validate received TSIG
tsig_orig_id = msg.id
if mangle_orig_id:
tsig_orig_id = (msg.id - 0xABCD) % 0x10000
tsig = dns.rdtypes.ANY.TSIG.TSIG(
dns.rdataclass.ANY,
dns.rdatatype.TSIG,
alg,
time_signed,
fudge,
mac,
tsig_orig_id,
error,
other,
)
rrs = dns.rrset.from_rdata(keyname, 0, tsig)
msg.additional.append(rrs)
try:
isctest.query.tcp(msg, ns1.ip, named_port)
except dns.tsig.PeerError:
pass # any error from named is fine
except dns.exception.TooBig:
assume(False) # some randomly generated value did not fit into message