It was not explicitly clear that ``rndc sign`` replaces signatures of inactive keys and updates signatures that are not so fresh.
Closes#5490
Backport of MR !11396
Merge branch 'backport-5490-clear-rndc-sign-on-error-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11409
It was not explicitly clear that 'rndc sign' replaces signatures of
inactive keys and updates signatures that are not so fresh.
(cherry picked from commit 3f52303ef7)
Closes#5414
Backport of MR !11406
Merge branch 'backport-5414-add-various-bailiwick-related-tests-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11407
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>
(cherry picked from commit e223ee7097)
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>
(cherry picked from commit b5dc46fe6e)
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>
(cherry picked from commit 658d2e9f8e)
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>
(cherry picked from commit 26eed16d61)
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>
(cherry picked from commit 607974b1bc)
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.
(cherry picked from commit 440e510f75)
A zone that is signed with NSEC3, opt-out enabled, and then reconfigured to use NSEC, causes the zone to be published with missing NSEC records. This has been fixed.
Closes#5679
Backport of MR !11359
Merge branch 'backport-5679-nsec3-optout-to-nsec-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11401
When switching from NSEC3 opt-out to NSEC, add NSEC records if we saw an
RR. This corrects a mistake in style cleanups done in commit
308ab1b4a5.
(cherry picked from commit 6f285bff6a)
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.
(cherry picked from commit 3679bd4888)
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.
(cherry picked from commit 1acde358ea)
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.
(cherry picked from commit 0ec94e501a)
Several changes to the interface of isctest.asyncserver has been made
during the development of the rewrites, propagate these to all the others.
Others have become clear as well but have been deferred as multiple
rewrites have been in review at once.
Introduce all of these in this MR.
Backport of MR !11179
Merge branch 'backport-stepan/asyncserver-improvements-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11389
Previously, this was only possible by making a new response by calling
make_response on qctx.query. This however ignored the `default_aa` and
`default_rcode` parameters of AsyncDnsServer.
Add prepare_new_response and save_initialized_response methods to
QueryContext.
(cherry picked from commit 5384998ccd)
Previously, ResponseHandlers had to reparse the queries themselves if
they wanted to use TSIG. This led to `default_aa` and `default_rcode`
information being lost from the newly created messages.
Add support for TSIG keyrings to the AsyncDnsServer class directly.
(cherry picked from commit de266fff4c)
Previously, the server relied on the modules being imported by the
isctest.asyncserver module. This is fragile and confuses tooling.
Clean up stray imports in the process.
(cherry picked from commit 5761de5531)
Previously, all responses had to be set as authoritative explicitly
using DnsResponseSend(..., authoritative=True). After using this,
it became obvious that this is obnoxious.
Add an optional keyword-only parameter to AsyncDnsServer that sets the
default value of the AA bit on outgoing responses.
Make all the other parameters keyword-only as well.
(cherry picked from commit 6e684d44e0)
When this class was introduced, the constructor of its base class had no
parameters. This was changed in the meantime and these parameters were
not accessible by users of the subclass.
Don't override the constructor.
Move command setup to methods.
Move subclass-specific storage to cached properties.
Take instances of Command instead of the classes themselves for
symmetry with install_response_handler.
(cherry picked from commit a0970f3d04)
Add a tag pipeline CI job to update the stable tag after a release.
Backport of MR !11291
Merge branch 'backport-andoni/add-ci-job-to-update-stable-tag-in-a-release-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11385
Introduce a CI job to update the "stable" tag with the latest released
stable version tag. This is a manual job that only runs in tag
pipelines in the context of a release.
(cherry picked from commit 2bca6c0d5e)
The :iscman:`named` process could terminate unexpectedly during
reconfiguration when a catalog zone update was taking place at
the same time. This has been fixed.
Backport of MR !11366
Merge branch 'backport-aram/catz-reconfig-crash-fix-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11386
A catalog zone is updated in an offloaded thread, which is not
stopped during a reconfiguration in an exclusive mode, and so
can cause a race condition with it.
Waiting for the offloaded threads to complete their work before
entering into the exclusive mode can potentially cause unwanted
delays, because offloaded threads are generally "allowed" to take
a longer amount of time before they complete.
Add a dns_catz_zone_prereconfig()/dns_catz_zone_postreconfig() pair
of functions which currently just lock the catalog zone when
reconfiguring it. The change should eliminate the race.
As a side note, there was already a similar pair of functions,
dns_catz_prereconfig() and dns_catz_postreconfig() which are called
before and after reconfiguring a 'dns_catz_zones_t' object.
Below are the stack traces of the reconfiguration thread which has
asserted, and a catalog zone update thread which was caught in the
middle of its work despite the fact that the exclusive mode is
turned on.
Stack trace of thread 23859:
#0 0x00007f80e7b8e52f raise (libc.so.6)
#1 0x00007f80e7b61e65 abort (libc.so.6)
#2 0x0000000000422558 assertion_failed (named)
#3 0x00007f80eaa6799e isc_assertion_failed (libisc-9.18.41.so)
#4 0x00007f80ea5bc788 dns_catz_entry_getname (libdns-9.18.41.so)
#5 0x000000000042ce0e catz_reconfigure (named)
#6 0x000000000042d3c5 configure_catz_zone (named)
#7 0x000000000042d7a4 configure_catz (named)
#8 0x0000000000430645 configure_view (named)
#9 0x000000000043d998 load_configuration (named)
#10 0x000000000044184f loadconfig (named)
#11 0x0000000000442525 named_server_reconfigcommand (named)
#12 0x000000000041b277 named_control_docommand (named)
#13 0x000000000041c74a control_command (named)
#14 0x00007f80eaa912ae task_run (libisc-9.18.41.so)
#15 0x00007f80eaa914cd isc_task_run (libisc-9.18.41.so)
#16 0x00007f80eaa46435 isc__nm_async_task (libisc-9.18.41.so)
#17 0x00007f80eaa467aa process_netievent (libisc-9.18.41.so)
#18 0x00007f80eaa475a6 process_queue (libisc-9.18.41.so)
#19 0x00007f80eaa46227 process_all_queues (libisc-9.18.41.so)
#20 0x00007f80eaa462a1 async_cb (libisc-9.18.41.so)
#21 0x00007f80e8d01893 uv__async_io.part.3 (libuv.so.1)
#22 0x00007f80e8d13ac4 uv__io_poll (libuv.so.1)
#23 0x00007f80e8d023fb uv_run (libuv.so.1)
#24 0x00007f80eaa45ced nm_thread (libisc-9.18.41.so)
#25 0x00007f80eaa9bda3 isc__trampoline_run (libisc-9.18.41.so)
#26 0x00007f80e7f1e1ca start_thread (libpthread.so.0)
#27 0x00007f80e7b798d3 __clone (libc.so.6)
...
...
Stack trace of thread 23912:
#0 0x00007f80ea5bc2da dns_catz_options_setdefault (libdns-9.18.41.so)
#1 0x00007f80ea5bd411 dns__catz_zones_merge (libdns-9.18.41.so)
#2 0x00007f80ea5c3c2f dns__catz_update_cb (libdns-9.18.41.so)
#3 0x00007f80eaa4fee9 isc__nm_work_run (libisc-9.18.41.so)
#4 0x00007f80eaa9bda3 isc__trampoline_run (libisc-9.18.41.so)
#5 0x00007f80eaa4ff48 isc__nm_work_cb (libisc-9.18.41.so)
#6 0x00007f80e8cfc75e worker (libuv.so.1)
#7 0x00007f80e7f1e1ca start_thread (libpthread.so.0)
#8 0x00007f80e7b798d3 __clone (libc.so.6)
(cherry picked from commit aed9cafd5c)
This adds more information about the active fetches for debugging and diagnostic purposes.
Backport of MR !11305
Merge branch 'backport-ondrej/provide-more-information-in-dns_resolver_dumpfetches-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11358
It is possible to have a fetch that is active, but it has been cloned,
so it won't be used when found in the hash table. The fetch options
also prevent matching in the hash table, so add a hexadecimal dump of
the fctx->options to the output.
(cherry picked from commit 23ae5544be)
We need this to be able to use pytest 9.0 from Debian "sid".
Additionally, this error needs to be addressed before pytest 9.1 is
released, as the filter will no longer work. Also, all pytests in CI
images need to be upgraded to version 7, where the new API is supported.
Related #5690
Backport of MR !11379
Merge branch 'backport-mnowak/ignore-pytest-PytestRemovedIn9Warning-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11380
We need this to be able to use pytest 9.0 from Debian "sid".
Additionally, this error needs to be addressed before pytest 9.1 is
released, as the filter will no longer work. Also, all pytests in CI
images need to be upgraded to version 7, where the new API is supported.
We can't have the "filterwarnings" section in pytest.ini directly as
only pytest 8.0 knows about it.
(cherry picked from commit 0c5d9c00ef)
Backport of MR !11370
Merge branch 'backport-mnowak/add-tsan-reports-glob-to-expected-artifacts-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11371
When a query for type ANY triggered a delegation response, all additional data was omitted from the response, including mandatory glue. This has been corrected.
Closes#5659
Merge branch '5659-any-glue' into 'bind-9.20'
See merge request isc-projects/bind9!11283
when a query for type ANY triggers a delegation response, all
additional data was omitted from the response, including
mandatory glue. this has been corrected.
BIND 9.20 takes much more time signing a large delegation zone with NSEC3 optout compared to version 9.18. This has been restored.
Closes#5672
Backport of MR !11354
Merge branch 'backport-5672-nsec3-optout-takes-too-long-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!11362
Instead of creating new nodes for every possible NSEC3 record, only
create them if we are actually going to add a new NSEC3 record.
(cherry picked from commit 6f7abbfaac)
This is a new seek function for dbiterator that is meant to find an
NSEC3 node in a zone database. The difference with dns_dbiterator_seek
is that if the node does not exist, this seek function will point the
iterator to the next NSEC3 name.
(cherry picked from commit 41159e9062)
This test signs a large delegation with mostly insecure delegations
with NSEC3 optout. Once the NSEC3PARAM record is published, run
dnssec-verify to ensure the zone is correctly signed.
(cherry picked from commit 5e704bbb59)