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:
parent
6ba6648935
commit
e77b1275a0
@ -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)
|
||||||
|
144
bin/tests/system/tsig/tests_tsig_hypothesis.py
Normal file
144
bin/tests/system/tsig/tests_tsig_hypothesis.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user