13117 Commits

Author SHA1 Message Date
Štěpán Balážik
46ecbbed0a Use isctest.asyncserver in the "ixfr" system test
Replace the usage of the `bin/tests/system/ans.pl` server with an
instance of ControllableAsyncServer.
2026-01-14 12:29:59 +01:00
Štěpán Balážik
2302fe1235 Add SwitchControlCommand for ControllableAsyncServer
To provide feature parity with `bin/tests/system/ans.pl` add a control
command to allow easy switching between different sequences of
ResponseHandlers.
2026-01-14 12:29:59 +01:00
Štěpán Balážik
7e587201a4 Use variadic positional parameters for plural install_* methods
It saves an indent and brackets on the call sites.

Also sort the handlers alphabetically where their order doesn't matter
and split the fallback handlers into a separate call to signify that
their position in the end matters.
2026-01-14 12:29:59 +01:00
Aram Sargsyan
4e9d97b4f7 Test that catalog zones' entry names are case-insensitive 2026-01-12 12:58:57 +00:00
Aram Sargsyan
6d0e6454ac Test that catalog zone names are case-insensitive
Change one of the existing catalog zone names to test that
catalog zones are now case-insensitive.
2026-01-12 12:58:57 +00:00
Nicki Křížek
9b63187a99 Renumber ans7->ans6 and ans8->ans7 in digdelv test
Since there was no 10.53.0.6 server in the test, renumber the remaining
ones so that there's no gap in the server names.

This commit simply moves the ans.py files without any changes and
renumbers the IP addresses in tests.
2026-01-12 11:09:14 +01:00
Nicki Křížek
6c69abf783 Add dnspython>=2.0.0 requirement for digdelv
Now that the test uses AsyncDnsServer, require the appropriate dnspython
version for the test.
2026-01-12 11:08:31 +01:00
Nicki Křížek
0b7a089c7f Replace digdelv/ans8 with AsyncDnsServer
Previously, the ans8 server had different response modes that applied to
all queries. Replace it with AsyncDnsServer that has serves the different
response modes under different domains without the need to change the
server behaviour at runtime.

Add the new queries that require an ns3 fallback to the ns3/example.db
zone.
2026-01-12 11:08:26 +01:00
Nicki Křížek
575f0e3916 Replace digdelv/ans5 with ControllableAsyncDnsServer
The server has three modes of operation - either no response, a partial
AXFR or a complete AXFR. To test the fallback behaviour of dig, these
actions are be combined in a specific sequences. To set up the desired
server behaviour, use the _control queries for the server.
2026-01-12 11:08:26 +01:00
Nicki Křížek
20887ff80f Rename ResponseDropAndCloseConnection action
The action can be used to close the connection even after some response
was sent, depending on the ordering of actions in the handler that uses
it. Rename it to CloseConnection to use a more fitting name.
2026-01-12 11:08:26 +01:00
Nicki Křížek
c50a7d2de1 Replace digdelv/ans7 with AsyncDnsServer
ans7 server always replies with an UPDATE opcode in the message.
2026-01-12 11:08:22 +01:00
Nicki Křížek
648f2534b1 Replace digdelv/ans4 with AsyncDnsServer
Configure the AsyncDnsServer to ignore all queries to ensure the same
behaviour as with "//" command for ans.pl.
2026-01-12 11:05:48 +01:00
Nicki Křížek
3a6b977a92 Remove unused digdelv/ans6 server
This server receives no queries during the test and doesn't affect the
test outcome.
2026-01-12 11:05:48 +01:00
Štěpán Balážik
1fc206556b Avoid sending manually created responses in asyncserver
If at all possible, all the responses should be created by
AsyncDnsServer's internal methods. To ensure this, mark them with a
magic attribute and check it on send and crash the server if a manually
created response is detected.

Fix the qmin test server which uses `make_response`.
2026-01-09 14:22:16 +00:00
Colin Vidal
e0d7bddc6c simplify usage of dns_view_findzonecut()
As `dns_view_findzonecut()` only returns either ISC_R_SUCCESS or
DNS_R_NXDOMAIN, and since it automatically disassociates the rdatasets
in case of failure, some call sites are simplified.
2026-01-08 20:26:32 +01:00
Alessio Podda
78588981df Remove rrset-order cyclic from the default config, with shim
Currently we add an rrset-order cyclic statement to the default config.
Since the rrset-order allows matching a subset of all names, it must
be implemented with a string comparison against a wildcard, and since
the statement applies per rrset, this can result in millions of
comparisons per second on a busy authoritative server.

This commit removes rrset-order from the default config, but adds back
a code shim in query_setorder to preserve the previous behaviour.
2026-01-08 14:43:04 +01:00
Colin Vidal
588de09145 add strict bound check tests
Add checkconf system test covering the strict boundary checks for
`edns-version`, `edns-udp-size`, `max-udp-size`, `no-cookie-udp-size`
and `padding`.
2026-01-07 07:01:59 +00:00
Colin Vidal
a67487a4ad remove implicit bounds fixes in server config
Now that the configuration options `edns-version`, `edns-udp-size`,
`max-udp-size`, `no-cookie-udp-size` and `padding` have strict boundaries
(configuration failing if they are not respected), remove configuration
loading code which implicitely raises or lowers them.
2026-01-07 07:01:59 +00:00
Michal Nowak
b4c0408d81 Add ans10 blackhole server to xfer system test
On FreeBSD 15.0, sending requests to non-existent address produces
unexpected results. Add a blackhole server instead.
2026-01-06 21:17:48 +01:00
Nicki Křížek
0ddfa108a7 Test zone with truncated revoked DNSKEY
Ensure that named can handle a situation where the zone is signed with a
truncated, self-signed revoked DNSKEY. The signatures are inevitably
bogus and a SERVFAIL is expected. However, prior to CVE-2025-8677 fix,
this could trigger an assertion failure.
2026-01-05 14:04:58 +01:00
Nicki Křížek
1a2e46d364 Test that DNSSEC validation is aborted on malformed DNSKEY
Create a signed zone file that contains malformed ZSKs with colliding
key tags. The ZSKs don't represent valid ECDSA keys and will cause a
crypto failure when attempting to use them. Sign the zone with KSK, with
the exception of one record which is "signed" with the invalid ZSKs.

Check that the resolver aborts the DNSSEC verification after
encountering the first crypto failure, indicating malformed DNSKEY.
2026-01-05 14:04:58 +01:00
Štěpán Balážik
dc58c73264 Set default_aa on AsyncDnsServer to False by default
In 6e684d44 I mistakenly set the default for `default_aa` for
`AsyncDnsServer()` to `True` and then explicitly set it to True in
cases where all the `ResponseHandlers` said
`yield DnsResponseSend(..., authoritative=True)` as if the default was
`False`.

Also the rest of `AsyncDnsServer` code (namely `_prepare_responses`)
reads like `default_aa` is `False` by default.

This accidentally changed the behavior of servers which don't set the
`default_aa` and where AA is not set from the zone data
(e.g. `dispatch/ans3`).
2026-01-05 13:27:57 +01:00
Matthijs Mekking
17f93fff78 Fix Coverity issue 640332/640331
The `notifytype = cfg_obj_asboolean(obj);` was left in place
erroneously in commit 52c940551d.

See https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/11384#note_628991
for background discussion.
2026-01-02 08:12:01 +00:00
Matthijs Mekking
22c02a4df9 Wait for "sending notifies" for step3.zsk-prepub
Commit c17ac42608 changed some tests to
wait for "zone_needdump" messages instead of "sending notifies", because
notifies are rate limited and "zone_needdump" happen on every change.

However, inspecting the logs, the "zone_needdump" changes happen more
than once (likely because the re-signing is done in batches):

    received control channel command 'sign step3.zsk-prepub.manual'
    zone_journal: zone step3.zsk-prepub.manual/IN (signed): enter
    zone_needdump: zone step3.zsk-prepub.manual/IN (signed): enter
    zone_journal: zone step3.zsk-prepub.manual/IN (signed): enter
    zone_needdump: zone step3.zsk-prepub.manual/IN (signed): enter
    zone_journal: zone step3.zsk-prepub.manual/IN (signed): enter
    zone_needdump: zone step3.zsk-prepub.manual/IN (signed): enter
    zone step3.zsk-prepub.manual/IN (signed): sending notifies

This means we are running the rollover step checks too fast in some
test runs.

Revert the wait for log change for the rollover-zsk-prepub test.
2025-12-31 11:40:42 +01:00
Matthijs Mekking
52c940551d Change notify-cds option to notify-cfg CDS
Change the notify configuration to be more flexible for other types
of generalized DNS notifications.

Also allow for notify-cfg SOA.
2025-12-29 10:06:16 +01:00
Matthijs Mekking
7fd1eccb6e Change zone set/get options related to notify
Add a type to all dns_zone_(get|set) functions that apply to sending
notifies, so the options can be set and retrieved separately per type.

This affects dns_zone_setnotifydefer, dns_zone_getnotifydefer,
dns_zone_setnotifydelay, dns_zone_getnotifydelay,
dns_zone_setnotifysrc4, and dns_zone_setnotifysrc6.

The functions dns_zone_getnotifysrc4 and dns_zone_getnotifysrc6 are
unused and can be removed.
2025-12-29 09:43:04 +01:00
Matthijs Mekking
3f52303ef7 Clarify rndc sign
It was not explicitly clear that 'rndc sign' replaces signatures of
inactive keys and updates signatures that are not so fresh.
2025-12-22 13:33:48 +00:00
Petr Špaček
e223ee7097 Test that spoofed DNAME is not accepted via spoofable transport
A single spoofed DNAME answer can impact many names, and because of the
nature of DNAME, the attacker can use randomized query names to get
unlimited number of tries to spoof the answer.  To limit impact, we
should not be accepting DNAME over insecure transport, like UDP without
cookies etc.

In short, the attacker tries to spoof at least one answer that has the
following form:

    opcode QUERY
    rcode NOERROR
    flags QR AA
    ;QUESTION
    trigger$RANDOM.test. IN A
    ;ANSWER
    trigger$RANDOM.test. 3600 IN CNAME trigger$RANDOM.attacker.net.
    test. 3600 IN DNAME attacker.net.
    ;AUTHORITY
    ;ADDITIONAL

This has been discovered internally.

Co-authored-by: Michał Kępień <michal@isc.org>
2025-12-22 11:58:39 +01:00
Petr Špaček
b5dc46fe6e Test that fake child delegation cannot overwrite parent's glue RR
In short, the attacker tries to spoof at least one answer that has the
following form:

    rcode NOERROR
    flags QR
    ;QUESTION
    trigger$RANDOM.victim. IN TXT
    ;ANSWER
    ;AUTHORITY
    trigger$RANDOM.victim. 3600 IN NS ns.victim.
    ;ADDITIONAL
    ns.victim. 3600 IN A 10.53.0.3

This attack was originally reported as "test case 2".

Co-authored-by: Michał Kępień <michal@isc.org>
2025-12-22 11:58:39 +01:00
Petr Špaček
658d2e9f8e Test that unsolicited NS in positive answer cannot overwrite current NS
Before the fixes for CVE-2025-40778, an unsolicited in-bailiwick NS
record was accepted from a (spoofed) answer, enabling a single spoofed A
query/response to redirect traffic for a whole delegation.

In short, the attacker tries to spoof at least one answer that has the
following form:

    rcode NOERROR
    flags QR AA
    ;QUESTION
    trigger$RANDOM.victim. IN TXT
    ;ANSWER
    trigger$RANDOM.victim. 3600 IN TXT "spoofed answer with extra NS"
    ;AUTHORITY
    victim. 3600 IN NS ns.attacker.
    ;ADDITIONAL

This attack was originally reported as "test case 1".

Co-authored-by: Michał Kępień <michal@isc.org>
2025-12-22 11:58:39 +01:00
Petr Špaček
26eed16d61 Test that positive answer cannot overwrite sibling NS RRs
Before the fixes for CVE-2025-40778, a positive answer was allowed to
overwrite sibling NS RRs.  The answer had to be a positive AA=1 answer
with a fake NS along with it.  This combination of conditions avoided
the code path with "unrelated <RRTYPE>" detection logic.

If it were some other answer, named from the main branch would detect
the attempt and log:

    DNS format error from 10.53.0.1#16386 resolving trigger/A for <unknown>: unrelated NS victim in trigger authority section

In short, the attacker tries to spoof at least one answer that has the
following form:

    opcode QUERY
    rcode NOERROR
    flags QR AA
    ;QUESTION
    trigger$RANDOM. IN A
    ;ANSWER
    trigger$RANDOM. 3600 IN A 10.53.0.3
    ;AUTHORITY
    victim. 3600 IN NS ns.attacker.
    ;ADDITIONAL
    ns.attacker. 3600 IN A 10.53.0.3

This attack was originally reported as "test case 1c".

Co-authored-by: Michał Kępień <michal@isc.org>
2025-12-22 11:58:39 +01:00
Petr Špaček
607974b1bc Add a common base for CVE-2025-40778 tests
Add the zone files, configuration, and code that will be reused by all
tests related to CVE-2025-40778.

Co-authored-by: Michał Kępień <michal@isc.org>
2025-12-22 11:58:39 +01:00
Michał Kępień
440e510f75 Add a reusable, bare-bones AsyncDnsServer
Add bin/tests/system/ans.py, a bare-bones DNS server that can be used in
system tests instead of full-blown named instances when a server is only
required to return zone-based data.  Where applicable, this reduces load
on the test host and the amount of generated logs.
2025-12-22 11:58:39 +01:00
Matthijs Mekking
f6749a432b Add isctest.kasp.SettimeOptions
This Class sets settime parameters and these can be called with key.settime()
that runs dnssec-settime on the given key with the given parameters.
2025-12-22 09:04:46 +00:00
Michał Kępień
1acde358ea Prevent garbage-collecting ignored TCP connections
Due to the way various asyncio-related objects (tasks, streams,
transports, selectors) are referencing each other, pausing reads for a
TCP transport (which in practice means removing the client socket from
the set of descriptors monitored by a selector) can cause the client
task (AsyncDnsServer._handle_tcp()) to be prematurely garbage-collected,
causing asyncio code to raise a "Task was destroyed but it is pending!"
exception.  Who knew that solutions as elegant as the one introduced by
e407888507 could cause unexpected trouble?

Fix by making a horrible hack even more horrible, specifically by
keeping a reference to each incoming TCP connection to protect its
related asyncio objects from getting garbage-collected.  This prevents
AsyncDnsServer from closing any of the ignored TCP connections
indefinitely, which is obviously a pretty brain-dead idea for a
production-grade DNS server, but AsyncDnsServer was never meant to be
one and this hack reliably solves the problem at hand.

Only apply this change for the IgnoreAllConnections handler as the
ConnectionReset handler triggers a connection reset immediately after
pausing reads for an incoming TCP connection.

As pointed out in e407888507, the proper
solution would require implementing a custom asyncio transport from
scratch and that is still deemed to be too much work for the purpose at
hand.  Let's see how much longer we can limp along with the existing
approach.
2025-12-21 06:25:56 +01:00
Michał Kępień
0ec94e501a Make exception/signal handlers idempotent
Calling asyncio.Future.set_exception() or asyncio.Future.set_result()
more than once for a given Future object raises an
asyncio.InvalidStateError exception.

In the case of AsyncServer:

  - it is enough to capture the first exception raised by higher-level
    logic as no exceptions at all are expected to be raised in the first
    place,

  - no distinction is made between SIGINT and SIGTERM; the only purpose
    of the signal handler is to make the server exit cleanly.

Given the above, make both AsyncServer._handle_exception() and
AsyncServer._signal_done() idempotent by ignoring
asyncio.InvalidStateError exceptions raised by the relevant
asyncio.Future.set_*() calls.
2025-12-21 06:25:56 +01:00
Matthijs Mekking
3679bd4888 Update optout test to reconfig to NSEC
If we change from NSEC3 to NSEC we should not produce a zone with
missing NSEC records.

The code only considered having seen a record if there was previously
a signature present at the owner name. However with opt-out, insecure
delegations don't have a RRSIG record. Reconfiguring to NSEC causes
all insecure delegations to have a missing NSEC record.

Add a DNAME record to the test zone to also cover DNAME delegations.
2025-12-19 16:55:18 +01:00
Michal Nowak
9e7b5a4ad4 Revert "Add ans6 blackhole server to notify system test"
This reverts commit 21295bc188.

In a sense, the ans6 black holeserver, based on asyncserver, "does
nothing". In our case, it won't respond to any query, and if the
IgnoreAllConnections connection handler was installed, it would not read
anything from the client socket.

Previously, sending notifications to an unconfigured address resulted in
no communication from the target (10.53.10.53); hence, the ns3
configuration comment requested a "non-responsive notify recipient (no
reply, no ICMP errors)".

However, examining the PCAP of ans6 reveals some communication from the
10.53.0.6 server to the 10.53.0.3 client, including ICMP Destination
Unreachable (Port Unreachable), and TCP SYN/ACK.

The ans6 communication seems to be sufficiently different to touch
different code paths in named, resulting in the BIND 9.20 backport
failing in the "checking notify retries expire within 30 seconds" test.
But we better revert it from "main" as well.
2025-12-19 16:15:32 +01:00
Matthijs Mekking
e69eb0528a Test invalid DSYNC RRset is rejected
The RFC says There MUST NOT be more than one DSYNC record for each
combination of RRtype and Scheme. If we encounter more we should drop
the response, as the DSYNC RRset is invalid.
2025-12-19 15:01:49 +01:00
Matthijs Mekking
35a7024e8c Test sending NOTIFY(CDS) messages during rollover
When doing rollover and the CDS/CDNSKEY RRset is updated, test that a
NOTIFY(CDS) message is sent. For other steps in the rollover, prohibit
any dsyncfetch activity.
2025-12-19 15:01:36 +01:00
Matthijs Mekking
e344fe18bc Test sending NOTIFY(CDS) messages
When starting up the services, send notifies for the existing CDS RRset.
This requires setting up a chain of trust for the test, so the DSYNC
records can be retrieved and validated.

This feature requires enabling 'notify-cds' and 'dnssec-validation'.

In this test, the scanner is pointed to ns2. Since there is no code
for receiving NOTIFY(CDS) messages for delegations, this is treated
as "not authoritative". Checking for this log message ensures us that
the NOTIFY(CDS) message was actually sent.
2025-12-19 15:01:36 +01:00
Matthijs Mekking
9fa0493a94 Adjust tests to new notify logs
Now that we log the type of the notify, some expected log messages
in the system tests need to be adjusted accordingly.

The bin/tests/system/nsec3/tests_nsec3_retransfer.py log is changed
to zone_needdump because it is more reliable.  Other tests were
adjusted similar in MR !11265, but !11226 introduced a new
"sending notify" log line.
2025-12-19 14:08:15 +01:00
Matthijs Mekking
6554a5f9f7 Add new 'notify-cds' configuration option
Add a new configuration option to enable/disable sending NOTIFY(CDS)
messages.
2025-12-19 14:08:15 +01:00
Matthijs Mekking
594ff0816a Drop and replace CmdHelper with EnvCmd
A generic helper that calls environment-specified binaries has been added,
drop and replace the introduced CmdHelper for the more generic method.
2025-12-19 11:49:00 +01:00
Matthijs Mekking
e172b4ff1a rollover-zsk-prepub: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.

Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
2025-12-19 11:47:50 +01:00
Matthijs Mekking
da04c75cec rollover-straight2none: From setup.sh to pytest bootstrap
Similar to rollover-going-insecure.
2025-12-19 11:47:50 +01:00
Matthijs Mekking
0016791c91 rollover-lifetime: Update templates
This test does not require a trust chain. Merely update the template
zone files to not point to the common template.
2025-12-19 11:47:50 +01:00
Matthijs Mekking
b6c091d113 rollover-multisigner: Update templates
This test does not require a trust chain. However, it does have a setup
script. Rewrite the setup shell script to a pytest bootstrap method.
2025-12-19 11:47:50 +01:00
Matthijs Mekking
4ed35f02b1 rollover-ksk-3crowd: From setup.sh to pytest bootstrap
Similar to rollover-ksk-doubleksk.
2025-12-19 11:47:50 +01:00
Matthijs Mekking
08236f4bd6 rollover-ksk-doubleksk: From setup.sh to pytest bootstrap
Symlink ns1 and ns2 to rollover/ns1 and rollover/ns2.
Symlink ns3/template.db.j2.manual to rollover/ns3/template.db.j2.manual.

Since the bootstrapping is done before the templates are rendered
automatically, replace @DEFAULT_ALGORITHM@ in ns3/kasp.conf.j2 to
ecdsa256 and rename to ns3/kasp.conf.
2025-12-19 11:47:50 +01:00