bind9/bin/tests/system/tsig/tests_tsig_hypothesis.py
Nicki Křížek fe55342916 Add nsX fixtures to system tests
Many of our test cases only use a single NamedInstance from the
`servers` fixture. Introduce `nsX` helper fixtures to simplify these
tests and reduce boilterplate code further.

Specifically, the test no longer has to either define its own variable
to extract a single server from the list, or use the longer
servers["nsX"] syntax. While this may seem minor, the amount of times it
is repeated across the tests justifies the change. It also promotes
using more explicit server identification, i.e. `nsX`, rather than
generic `server`. This also improves the clarity of the tests and may be
helpful in traceback during debugging as well.
2025-07-18 14:37:32 +02:00

134 lines
3.3 KiB
Python

#!/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
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
import isctest
from isctest.hypothesis.strategies import dns_names, uint
from hypothesis import assume, example, given
from hypothesis.strategies import binary, booleans, composite, just, sampled_from
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,
ns1,
named_port,
):
alg, mac = alg_and_mac
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