]> git.ipfire.org Git - thirdparty/bind9.git/log
thirdparty/bind9.git
9 days agoDon't synthesize negative responses with pending NSEC
Evan Hunt [Fri, 22 May 2026 07:57:24 +0000 (00:57 -0700)] 
Don't synthesize negative responses with pending NSEC

If a cached record has not yet been validated and has trust
level pending, don't use it to synthesize negative responses.

Fixes: isc-projects/bind9#5872
Fixes: isc-projects/bind9#5887
Fixes: isc-projects/bind9#5977
9 days agofix: dev: Detect UTF-16 surrogates in `isc_utf8_valid()`
Colin Vidal [Wed, 8 Jul 2026 09:03:52 +0000 (11:03 +0200)] 
fix: dev: Detect UTF-16 surrogates in `isc_utf8_valid()`

UTF-8 standard forbid usage of unicode character between the range of
0xD800..0xDFFF (reserved, and used as UTF-16 surrogates, see RFC 3629).

However, `usc_utf8_valid()` was not checking if the encoded unicode
character was in this range, which then would accept invalid UTF-8
strings. This is now fixed.

Closes #6151

Merge branch '6151-utf16-surrogates-detection' into 'main'

See merge request isc-projects/bind9!12345

9 days agoAdd UTF-8 unit test 12345/head
Colin Vidal [Thu, 2 Jul 2026 07:52:22 +0000 (09:52 +0200)] 
Add UTF-8 unit test

Add a unit test suite for `isc_utf8_valid()` function. It test the
varioutes encoding lower/upper ranges as well as UTF-16 surrogate
exclusion.

Also add unit tests for `usc_utf8_bom()` function.

9 days agoDetect UTF-16 surrogates in `isc_utf8_valid()`
Colin Vidal [Thu, 2 Jul 2026 07:52:09 +0000 (09:52 +0200)] 
Detect UTF-16 surrogates in `isc_utf8_valid()`

UTF-8 standard forbid usage of unicode character between the range of
0xD800..0xDFFF (reserved, and used as UTF-16 surrogates, see RFC 3629).

However, `usc_utf8_valid()` was not checking if the encoded unicode
character was in this range, which then would accept invalid UTF-8
strings. This is now fixed.

10 days agofix: dev: Remove ACL detach deadcode from dyndb
Colin Vidal [Wed, 8 Jul 2026 06:02:53 +0000 (08:02 +0200)] 
fix: dev: Remove ACL detach deadcode from dyndb

Since `188aa43e`, `dns_acl_any()` can't
fail (and thus would always set memory to its target). Removing deadcode
that would detach the ACL if `dns_acl_any()` would return some error
while the ACL would be created and attached.

Merge branch 'colin/remove-acl-detach-deadcode' into 'main'

See merge request isc-projects/bind9!12333

10 days agoRemove ACL detach deadcode from dyndb 12333/head
Colin Vidal [Wed, 1 Jul 2026 08:30:53 +0000 (10:30 +0200)] 
Remove ACL detach deadcode from dyndb

Since `188aa43e48379572ffa758e45333c67214917d39`, `dns_acl_any()` can't
fail (and thus would always set memory to its target). Removing deadcode
that would detach the ACL if `dns_acl_any()` would return some error
while the ACL would be created and attached.

10 days agochg: dev: Mark the related slabheader as visited on cache hit
Ondřej Surý [Tue, 7 Jul 2026 14:28:42 +0000 (16:28 +0200)] 
chg: dev: Mark the related slabheader as visited on cache hit

A cache hit only marked the looked-up header as SIEVE-visited, leaving
its related header (the flattened counterpart) a candidate for eviction.
Mark both so related slabheaders age together.

Merge branch 'ondrej/mark-related-header-visited-on-cache-hit' into 'main'

See merge request isc-projects/bind9!12306

10 days agoMark the related slabheader as visited on cache hit 12306/head
Ondřej Surý [Wed, 24 Jun 2026 05:13:16 +0000 (07:13 +0200)] 
Mark the related slabheader as visited on cache hit

A cache hit only marked the looked-up header as SIEVE-visited, leaving
its related header (the flattened counterpart) a candidate for eviction.
Mark both so related slabheaders age together.

10 days agofix: dev: Include the IPv6 address's brackets in the parsed URL/URI host 6204-openssl-1-1-pkcs-11-ecdsa-soft-keygen
Arаm Sаrgsyаn [Tue, 7 Jul 2026 12:19:26 +0000 (12:19 +0000)] 
fix: dev: Include the IPv6 address's brackets in the parsed URL/URI host

The brackets are not included in the host component of the parsed
URL/URI. Change the parser to include the brackets.

Closes #6147

Merge branch '6147-isc_url_parse-ipv6-brackets-fix' into 'main'

See merge request isc-projects/bind9!12266

10 days agoInclude the brackets when parsing a URI with a IPv6 address 12266/head
Aram Sargsyan [Wed, 17 Jun 2026 15:43:01 +0000 (15:43 +0000)] 
Include the brackets when parsing a URI with a IPv6 address

The brackets are not included in the host component of the parsed
URL/URI. Change the parser to include the brackets.

10 days agofix: dev: Improve the input validation of the isc_url_parse() function
Arаm Sаrgsyаn [Tue, 7 Jul 2026 11:22:59 +0000 (11:22 +0000)] 
fix: dev: Improve the input validation of the isc_url_parse() function

The isc_url_parse() function failed to check the input buffer's
length and assumed that it can't be bigger than UINT16_MAX, because
both the 'off' and 'len' fields of the 'isc_url_parser_t' structure
are uint16_t.

Add a check to not accept a buffer longer than 8192 octets.

Closes #6150

Merge branch '6150-isc_url_parse-buffer-size-check-fix' into 'main'

See merge request isc-projects/bind9!12252

10 days agoLimit allowed URL/URI size to 8192 bytes in the parser 12252/head
Aram Sargsyan [Thu, 18 Jun 2026 09:03:46 +0000 (09:03 +0000)] 
Limit allowed URL/URI size to 8192 bytes in the parser

RFC 9110 Section 4.1 recommends at least 8000 octets, and 65535
is too excessive. Limit the maximum length to 8192 octets.

10 days agoAdd IPv6 and authority cases to the isc_url_t unit test
Ondřej Surý [Wed, 17 Jun 2026 04:41:29 +0000 (06:41 +0200)] 
Add IPv6 and authority cases to the isc_url_t unit test

Cover IPv6 literal hosts (the brackets are stripped from the host, zone
identifiers are kept verbatim), userinfo, explicit ports and case
preservation, plus inputs that isc_url_parse() rejects although a generic
RFC 3986 parser would accept them: a '+' in the scheme, an IPvFuture
literal, and a percent-encoded port. The cases are drawn from the
Addressable URI test suite. The shared table runner is factored out so
both table-driven tests reuse it.

Assisted-by: Claude:claude-opus-4-8
10 days agoExtend the isc_url_t unit test with RFC 3986 cases
Ondřej Surý [Wed, 17 Jun 2026 04:30:51 +0000 (06:30 +0200)] 
Extend the isc_url_t unit test with RFC 3986 cases

Parse the absolute URIs from RFC 3986 section 5.4 and verify the
component split, and assert the input-length boundary (UINT16_MAX is
accepted, UINT16_MAX + 1 is rejected). isc_url_parse() splits request
targets but does not resolve relative references, so the dot-segments
in path/query/fragment are expected to survive verbatim.

Assisted-by: Claude:claude-opus-4-8
10 days agoAdd a unit test for isc_url_t
Aram Sargsyan [Tue, 16 Jun 2026 11:10:21 +0000 (11:10 +0000)] 
Add a unit test for isc_url_t

The test has some basic checks for the URL/URI parser.

10 days agoAdd a maximum length for isc_url_parse() input buffer
Aram Sargsyan [Tue, 16 Jun 2026 11:08:14 +0000 (11:08 +0000)] 
Add a maximum length for isc_url_parse() input buffer

The isc_url_parse() function failed to check the input buffer's
length and assumed that it can't be bigger than UINT16_MAX, because
both the 'off' and 'len' fields of the 'isc_url_parser_t' structure
are uint16_t.

Add a check to not accept a buffer longer than UINT16_MAX.

10 days agofix: dev: Fix PROXYv2 header size truncation bug
Arаm Sаrgsyаn [Tue, 7 Jul 2026 10:07:45 +0000 (10:07 +0000)] 
fix: dev: Fix PROXYv2 header size truncation bug

The 'isc_proxy2_handler_t' structure stores some size values in a
'uint16_t' type, while the maximum size can be bigger, which results
in truncation. Change the affected types to 'size_t'.

Closes #6142

Merge branch '6142-proxyv2-header-length-fix' into 'main'

See merge request isc-projects/bind9!12294

10 days agoAdd new proxyheader unit tests 12294/head
Aram Sargsyan [Sat, 20 Jun 2026 14:56:22 +0000 (14:56 +0000)] 
Add new proxyheader unit tests

Check the maximum size and bigger than the maximum size headers.

10 days agoFix PROXYv2 header size truncation bug
Aram Sargsyan [Sat, 20 Jun 2026 14:56:17 +0000 (14:56 +0000)] 
Fix PROXYv2 header size truncation bug

The 'isc_proxy2_handler_t' structure stores some size values in a
'uint16_t' type, while the maximum size can be bigger, which results
in truncation. Change the affected types to 'size_t'.

10 days agonew: test: Test multi-master dnssec-policy setup
Matthijs Mekking [Tue, 7 Jul 2026 08:55:23 +0000 (08:55 +0000)] 
new: test: Test multi-master dnssec-policy setup

Update the manual rollover system test with a multi-master setup.

Merge branch 'matthijs-test-dnssec-policy-multimaster' into 'main'

See merge request isc-projects/bind9!11268

11 days agoTest multi-master dnssec-policy setup 11268/head
Matthijs Mekking [Mon, 24 Nov 2025 08:45:51 +0000 (09:45 +0100)] 
Test multi-master dnssec-policy setup

Update the manual rollover test case with a multi-master setup.  In this
scenario, key files are generated, as well as rollovers are started
on one server (ns3) and key files are copied to the other server (ns4).

Add checks that the begin and end key states are the same.

2 weeks agofix: usr: Unvalidated opt-out NSEC3 could be accepted in insecurity proof alessio/split-query-delegation-baseline
Evan Hunt [Fri, 3 Jul 2026 07:01:30 +0000 (07:01 +0000)] 
fix: usr: Unvalidated opt-out NSEC3 could be accepted in insecurity proof

When determining whether an insecure delegation is legitimate, NSEC3 opt-out records which had not yet passed validation could be used. This has been fixed.

Closes #5970

Merge branch '5970-pending-nsec3' into 'main'

See merge request isc-projects/bind9!12283

2 weeks agoMerge "nsec3_wrong_zone" into "dnssec_nsec3"
Evan Hunt [Fri, 19 Jun 2026 05:58:07 +0000 (22:58 -0700)] 
Merge "nsec3_wrong_zone" into "dnssec_nsec3"

These tests are similar in structure and topic, and can be merged.

2 weeks agoReproducer for #5970 acceptance of unvalidated NSEC3
Alessio Podda [Thu, 4 Jun 2026 14:46:45 +0000 (16:46 +0200)] 
Reproducer for #5970 acceptance of unvalidated NSEC3

Add "dnssec_nsec3" system test.

Co-Authored-By: Evan Hunt <each@isc.org>
2 weeks agoUnvalidated opt-out NSEC3 could be accepted in insecurity proof
Evan Hunt [Thu, 11 Jun 2026 00:58:31 +0000 (17:58 -0700)] 
Unvalidated opt-out NSEC3 could be accepted in insecurity proof

Ignore NSEC3 records that failed in the sub-validator when determining
whether an insecure delegation is legitimate.

Fixes: isc-projects/bind9#5970
2 weeks agofix: usr: Fix DNSSEC validation failures for names under an apex DNAME
Ondřej Surý [Thu, 2 Jul 2026 14:47:22 +0000 (16:47 +0200)] 
fix: usr: Fix DNSSEC validation failures for names under an apex DNAME

DNSSEC validation could fail with SERVFAIL for names covered by a DNAME
at the apex of a signed zone, unless the zone's keys were already validated
in the cache. This regression was introduced by the recent fix for resolver
stalls on CNAME responses to DS queries.

Closes #6176

Merge branch '6176-validator-apex-dname' into 'main'

See merge request isc-projects/bind9!12353

2 weeks agoAdd a system test resolving through a signed apex DNAME
Ondřej Surý [Thu, 2 Jul 2026 13:35:56 +0000 (15:35 +0200)] 
Add a system test resolving through a signed apex DNAME

The dnssec system test signs a DNAME-at-apex zone but only ever
queried the apex directly; nothing resolved a name under the DNAME
through the validating resolver, so a validator regression on that
path went unnoticed.

Assisted-by: Claude:claude-fable-5
2 weeks agoRestrict the alias-chain deadlock check to chaining CNAMEs
Ondřej Surý [Thu, 2 Jul 2026 13:35:56 +0000 (15:35 +0200)] 
Restrict the alias-chain deadlock check to chaining CNAMEs

check_deadlock() aborted any fetch whose name equals the owner of a
chaining rdataset, assuming nothing the validator needs can live at an
alias.  That is true for a CNAME, but a DNAME aliases only the names
below its owner: with a DNAME at a zone apex, the DNSKEY signing the
DNAME lives at the owner name itself, so every answer synthesized from
a signed apex DNAME failed validation whenever that key was not
already validated in the cache.

Chaining CNAMEs, including those synthesized from a DNAME, still cover
the self-join case the check was added for.

2 weeks agofix: test: Support serving signed child zone from its parent's nameserver
Nicki Křížek [Thu, 2 Jul 2026 14:42:15 +0000 (16:42 +0200)] 
fix: test: Support serving signed child zone from its parent's nameserver

When a signed zone is served by the same nameserver instance as
its parent, the child's dnssec-signzone has already written
dsset-<child>. into that directory. Don't attempt to copy the dsset if
the destination and source files are the same.

Assisted-by: Claude:claude-opus-4-8
Merge branch 'nicki/serve-signed-child-same-ns' into 'main'

See merge request isc-projects/bind9!12354

2 weeks agoSupport serving signed child zone from its parent's nameserver
Nicki Křížek [Thu, 2 Jul 2026 14:00:55 +0000 (16:00 +0200)] 
Support serving signed child zone from its parent's nameserver

When a signed zone is served by the same nameserver instance as
its parent, the child's dnssec-signzone has already written
dsset-<child>. into that directory. Don't attempt to copy the dsset if
the destination and source files are the same.

Assisted-by: Claude:claude-opus-4-8
2 weeks agochg: test: Update AsyncDnsServer-related test cookbook parts
Michał Kępień [Thu, 2 Jul 2026 13:09:50 +0000 (15:09 +0200)] 
chg: test: Update AsyncDnsServer-related test cookbook parts

Add practical tips about specific handler classes.  Mention some good
practices and point developers at existing code written in the desired
manner.  Document common pitfalls.  Suggest preferred approaches for
splitting up complex response handling code.

Merge branch 'michal/update-asyncdnsserver-related-test-cookbook-parts' into 'main'

See merge request isc-projects/bind9!12260

2 weeks agoMove ans.py-related information to README.md
Michał Kępień [Thu, 2 Jul 2026 13:07:40 +0000 (15:07 +0200)] 
Move ans.py-related information to README.md

COOKBOOK.md is supposed to be minimal and heavy on examples, so move the
lengthy section about implementing custom ans.py servers from
COOKBOOK.md to README.md.

2 weeks agoUpdate AsyncDnsServer-related test cookbook parts
Michał Kępień [Thu, 2 Jul 2026 13:07:40 +0000 (15:07 +0200)] 
Update AsyncDnsServer-related test cookbook parts

Add practical tips about specific handler classes.  Mention some good
practices and point developers at existing code written in the desired
manner.  Document common pitfalls.  Suggest preferred approaches for
splitting up complex response handling code.

2 weeks agochg: test: Unify system test key and algorithm handling
Nicki Křížek [Thu, 2 Jul 2026 12:51:52 +0000 (14:51 +0200)] 
chg: test: Unify system test key and algorithm handling

This is a followup from https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/11807.

De-duplicates the key material handling and moves algorithm-related things into a dedicated shared module.

Merge branch 'nicki/pytest-key-reconcile' into 'main'

See merge request isc-projects/bind9!12255

2 weeks agoMove algorithm definitions into a top-level isctest.algorithms module
Nicki Křížek [Tue, 16 Jun 2026 16:23:23 +0000 (16:23 +0000)] 
Move algorithm definitions into a top-level isctest.algorithms module

The Algorithm type, the per-algorithm constants, and the ALL_ALGORITHMS*
lookup tables are general DNSSEC key definitions used across isctest
package and the tests. Move them into a dedicated module to separate
these from the environment-specific setup that remains in
isctest.vars.algorithms.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoAdd private_key support to all ZoneKey implementations
Nicki Křížek [Tue, 16 Jun 2026 14:38:53 +0000 (16:38 +0200)] 
Add private_key support to all ZoneKey implementations

Extend the ZoneKeyFile to read the file-backed private key and return it
in a format suitable for use with dnspython. Add ZoneKey.private_key
property to unify the interface.

2 weeks agoReplace get_dnsalg() with kasp.Key.algorithm
Nicki Křížek [Tue, 16 Jun 2026 15:56:00 +0000 (17:56 +0200)] 
Replace get_dnsalg() with kasp.Key.algorithm

The get_dnsalg() was just a compatibility layer for 9.18 which lacked
the Algorithm support - remove it in favor of using the .algorithm
property.

In order to properly support private OID algorithms, use the DST value
which is unique across all algorithms.

Also fix private_type_record(): the choice between the 5- and 7-byte
signing record depends on the DST value (256/257 for the private-OID
algorithms), not the on-wire number, which never reaches 256.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoAdd NSEC3RSASHA1 to list of algorithms
Nicki Křížek [Tue, 16 Jun 2026 15:54:56 +0000 (17:54 +0200)] 
Add NSEC3RSASHA1 to list of algorithms

This algorithm is deprecated and not currently used in our system tests,
but it should be in the list of all algorithms.

2 weeks agoMove dnskey method from kasp.Key to zone.FileZoneKey
Nicki Křížek [Tue, 16 Jun 2026 12:32:28 +0000 (12:32 +0000)] 
Move dnskey method from kasp.Key to zone.FileZoneKey

Code move with one change - switch dnskey TTL from 300s (DEFAULT_TTL) to
3600s (DNSKEY_TTL).

Assisted-by: Claude:claude-opus-4-8
2 weeks agoMerge kasp.Key functionality into zone.FileZoneKey
Nicki Křížek [Tue, 16 Jun 2026 12:34:48 +0000 (12:34 +0000)] 
Merge kasp.Key functionality into zone.FileZoneKey

Make zone.FileZoneKey the single representation of a file-backed key
(typically generated by dnssec-keygen). Move the common key-related
functionality into zone.FileZoneKey, and extend that functionality in
kasp.Key to also add state and timing related operations on top. Remove
duplicate into_ta() function.

Note that is_ksk() is implemented differently for kasp.Key: with the
metadata file available, the KSK status is loaded from that file, as it
indicates the authoritative policy decision which makes the key a KSK.
In zone.FileZoneKey which doesn't work with the metadata file, the KSK
status if inferred from the DNSKEY SEP flag - the best information
available for that class.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoRead DNSKEY TTL from kasp.Key.dnskey
Nicki Křížek [Tue, 16 Jun 2026 13:57:48 +0000 (15:57 +0200)] 
Read DNSKEY TTL from kasp.Key.dnskey

Remove the redundant ttl() method. The DNSKEY RR already provides the
TTL.

2 weeks agochg: dev: Replace query and inner client attribute bitfields with named bools
Ondřej Surý [Thu, 2 Jul 2026 11:27:27 +0000 (13:27 +0200)] 
chg: dev: Replace query and inner client attribute bitfields with named bools

Replace the unsigned int attributes field in struct ns_query and the unsigned int attributes field in struct ns_client_inner with individual bool bitfields.

Merge branch 'ondrej/query-attributes-to-bitfields' into 'main'

See merge request isc-projects/bind9!11732

2 weeks agoReplace query and client attribute bitfield with named bools
Ondřej Surý [Sat, 21 Mar 2026 16:13:56 +0000 (17:13 +0100)] 
Replace query and client attribute bitfield with named bools

Replace the unsigned int attributes field in struct ns_query with
individual bool bitfields.  This removes the NS_QUERYATTR_* constants
and the 12 accessor macros (USECACHE, RECURSIONOK, RECURSING, etc.)
from query.c, replacing all bit manipulation with direct bool access.

And replace the unsigned int attributes field in struct ns_client_inner
with individual bool bitfields.  This removes the NS_CLIENTATTR_*
constants and the accessor macros (TCP, WANTDNSSEC, etc.), replacing
all bit manipulation with direct bool access.

2 weeks agofix: usr: Resolver could terminate unexpectedly when processing a malformed RRSIG
Ondřej Surý [Thu, 2 Jul 2026 11:27:00 +0000 (13:27 +0200)] 
fix: usr: Resolver could terminate unexpectedly when processing a malformed RRSIG

A recursive resolver could terminate unexpectedly when an authoritative
server returned a crafted RRSIG(RRSIG) record for an insecure zone. Such
records are now rejected.

Closes #6184

Merge branch '6184-reject-rrsig-covering-signature' into 'main'

See merge request isc-projects/bind9!12347

2 weeks agoAdd a regression test for an RRSIG that covers a signature
Ondřej Surý [Thu, 2 Jul 2026 08:21:40 +0000 (10:21 +0200)] 
Add a regression test for an RRSIG that covers a signature

The qpcache_rrsig_any test enumerated only meta-types as the covered
type, so an RRSIG covering RRSIG -- a non-meta signature type -- slipped
through the earlier meta-type hardening. Probe that case too.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoReject an RRSIG that covers a signature type
Ondřej Surý [Thu, 2 Jul 2026 08:05:30 +0000 (10:05 +0200)] 
Reject an RRSIG that covers a signature type

An RRSIG whose Type-Covered field is RRSIG is not a meta-type, so it
passed the message parser, and for an insecure domain the resolver
cached it as a standalone signature. The QP cache pairs every RRSIG
header with the non-signature header it covers and never expects the
covered type to itself be a signature, so a signature covering a
signature broke that invariant and aborted named on a crafted response.
Reject the record in the parser, and tighten the cache precondition so
a positive signature header must cover a non-signature type.

2 weeks agofix: dev: Correct locator decoding for NID, L64, and L32 records
Ondřej Surý [Thu, 2 Jul 2026 10:54:52 +0000 (12:54 +0200)] 
fix: dev: Correct locator decoding for NID, L64, and L32 records

NID, L64, and L32 records were decoded incorrectly when converted into their
parsed structures, because the preference field was not skipped before the
locator.

Closes #6097

Merge branch '6097-nid-l64-l32-tostruct-consume' into 'main'

See merge request isc-projects/bind9!12348

2 weeks agoAdd NID/L64/L32 round-trip coverage to the rdata unit test
Ondřej Surý [Thu, 2 Jul 2026 09:38:44 +0000 (11:38 +0200)] 
Add NID/L64/L32 round-trip coverage to the rdata unit test

These types had no entries in the rdata test table, so the
tostruct/fromstruct round-trip in check_struct_conversions() never ran
against them -- which is why the missing preference consume in their
tostruct routines went unnoticed for years. Add text and wire vectors
for all three.

Assisted-by: Claude:claude-fable-5
2 weeks agoConsume the preference before reading the locator in NID/L64/L32 tostruct
Ondřej Surý [Thu, 2 Jul 2026 09:38:40 +0000 (11:38 +0200)] 
Consume the preference before reading the locator in NID/L64/L32 tostruct

tostruct_nid() and tostruct_l64() read the 16-bit preference with the
non-consuming uint16_fromregion() and then memmove()'d the whole
remaining region -- still ten octets, still anchored at the preference
-- into the eight-octet nid[]/l64[] arrays. That folded the preference
into the first two locator octets and stored two octets past the end of
the array. tostruct_l32() shares the root cause: it read the 32-bit
locator from the same unconsumed offset, so the value was built from the
preference plus the first two locator octets.

Consume the two preference octets first, matching the sibling
tostruct_lp(), and assert the expected framing on the fixed-size types.

2 weeks agofix: usr: Don't evict DNSSEC-validated cache data on a CD=1 NXDOMAIN
Evan Hunt [Thu, 2 Jul 2026 07:44:53 +0000 (07:44 +0000)] 
fix: usr: Don't evict DNSSEC-validated cache data on a CD=1 NXDOMAIN

When a client sent a query with the checking-disabled (CD) bit set and the
answer was NXDOMAIN, the resolver cached that unvalidated negative response and
discarded any DNSSEC-validated records it already held for the same name, even
though the validated data was more trustworthy. A single such response -
including a forged one - could flush validated records from the cache and force
the resolver to fetch them again. The resolver now checks the trust level of the
existing data first and leaves the cache unchanged when it is already validated.

Closes #5877

Merge branch '5877-cd-nxdomain' into 'main'

See merge request isc-projects/bind9!11946

2 weeks agoAdd a system test for CD=1 NXDOMAIN cache protection
Ondřej Surý [Thu, 4 Jun 2026 18:01:37 +0000 (20:01 +0200)] 
Add a system test for CD=1 NXDOMAIN cache protection

Cache a DNSSEC-validated A record, then make a CD=1 query elicit an
unvalidated NXDOMAIN for the name: the secure RRset must survive, and an
uncached-type query must not get the wrong RRset back.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoCheck for secure data before caching CD=1 NXDOMAIN
Evan Hunt [Fri, 1 May 2026 19:15:07 +0000 (12:15 -0700)] 
Check for secure data before caching CD=1 NXDOMAIN

An unvalidated NXDOMAIN (e.g. from a CD=1 query) marked every RRset at
the name ancient without checking trust, evicting DNSSEC-validated data.
Keep the cache unchanged when any existing RRset is already secure.

dns_ncache_add() now returns DNS_R_UNCHANGED for the rejected add;
negcache() serves a matching cached negative or the queried type, else
SERVFAIL (never the unrelated RRset the add bound), and rctx_ncache()
forwards it so the fetch fails fast.

2 weeks agofix: usr: Properly detect private records before copying
Mark Andrews [Thu, 2 Jul 2026 01:10:32 +0000 (11:10 +1000)] 
fix: usr: Properly detect private records before copying

We were triggering an assertion when trying to copy a private record
to a buffer for modifying.  Extend the private type detection and
copy the contents after we have rejected invalid private records.

Closes #5857

Merge branch '5857-properly-detect-private-records-before-copying' into 'main'

See merge request isc-projects/bind9!11816

2 weeks agoAdd DNS_PRIVATE_BUFFERSIZE and use it
Mark Andrews [Fri, 15 May 2026 01:06:38 +0000 (11:06 +1000)] 
Add DNS_PRIVATE_BUFFERSIZE and use it

The size of a private records is 1 byte more than the corresponding
NSEC3PARAM record.

2 weeks agoProperly detect private records before copying
Mark Andrews [Wed, 8 Apr 2026 04:43:23 +0000 (14:43 +1000)] 
Properly detect private records before copying

We were triggering an assertion when trying to copy a private record
to a buffer for modifying.  Extend the private type detection and
copy the contents after we have rejected invalid private records.

2 weeks agoTest oversized private record is properly ignored
Mark Andrews [Wed, 8 Apr 2026 04:43:16 +0000 (14:43 +1000)] 
Test oversized private record is properly ignored

2 weeks agochg: doc: Add non-IN RR classes to list of unsupported configurations
Ondřej Surý [Wed, 1 Jul 2026 11:06:10 +0000 (13:06 +0200)] 
chg: doc: Add non-IN RR classes to list of unsupported configurations

This adds a note to the security documentation that configuring
resources with non-Internet DNS classes (CHAOS, HESIOD, ...) is not
a supported configuration and could potentially cause issues.

Closes #5805

Merge branch '5805-add-clarification-on-non-IN-classes' into 'main'

See merge request isc-projects/bind9!11667

2 weeks agoamend! Add non-IN RR classes to list of unsupported configurations
Nicki Křížek [Mon, 29 Jun 2026 13:34:29 +0000 (13:34 +0000)] 
amend! Add non-IN RR classes to list of unsupported configurations

Document that non-IN RR class issues are out of CVE scope

CVE-2026-5946 covered assertion failures reachable only through the
handling of resource record classes other than Internet (IN).
Configuring zones or views with such classes is a supported feature;
document in the security assumptions that problems reachable only
through it cannot be the basis for CVE assignment.

Closes #5805

Assisted-by: Claude:claude-opus-4-8
2 weeks agoAdd non-IN RR classes to list of unsupported configurations
Ondřej Surý [Wed, 11 Mar 2026 18:18:32 +0000 (19:18 +0100)] 
Add non-IN RR classes to list of unsupported configurations

This adds a note to the security documentation that configuring
resources with non-Internet DNS classes (CHAOS, HESIOD, ...) is not
a supported configuration and could potentially cause issues.

2 weeks agofix: dev: Fix a memory leak when updating a zone with more than 32 DNSSEC keys
Ondřej Surý [Wed, 1 Jul 2026 07:23:10 +0000 (09:23 +0200)] 
fix: dev: Fix a memory leak when updating a zone with more than 32 DNSSEC keys

Applying changes to a signed zone — via DNS UPDATE or the inline-signing
raw-to-secure sync — leaked the surplus keys when the zone's key
directory held more than 32, slowly growing named's memory use.

Closes #6051

Merge branch '6051-find-zone-keys-key-leak' into 'main'

See merge request isc-projects/bind9!12328

2 weeks agoAdd a regression test for the find_zone_keys() key leak
Ondřej Surý [Mon, 29 Jun 2026 06:48:03 +0000 (08:48 +0200)] 
Add a regression test for the find_zone_keys() key leak

Generate more than DNS_MAXZONEKEYS distinct matching private keys for a
zone and call find_zone_keys() through it.  The keys past the limit must
be released; the default memory context's leak check, armed with
isc_mem_checkdestroyed(), fails the test if any are abandoned.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoStop leaking DNSSEC keys past the zone key limit
Ondřej Surý [Mon, 29 Jun 2026 06:48:03 +0000 (08:48 +0200)] 
Stop leaking DNSSEC keys past the zone key limit

find_zone_keys() collects every matching private key into a local list,
hands the first DNS_MAXZONEKEYS keys to the caller, and frees the rest.
On overflow it destroyed only the first surplus key before breaking out
of the loop, so any keys after it stayed linked on the local list and
were lost when the function returned.

Unlink and destroy every list entry, transferring a key to the caller
only while under the limit.  No entry is left behind, so a zone with
more than DNS_MAXZONEKEYS matching keys no longer leaks memory on each
signing attempt.

2 weeks agochg: usr: Introduce a minimum TTL for cached delegations
Colin Vidal [Wed, 1 Jul 2026 06:40:18 +0000 (08:40 +0200)] 
chg: usr: Introduce a minimum TTL for cached delegations

Delegations are now cached with a minimum TTL of 60 seconds by default. Any NS record or A/AAAA glue record with a TTL below this threshold will be raised to 60 seconds.

A new configuration option `min-delegation-ttl` has been added to adjust this limit, or disable it by setting the value to `0`. The corresponding `max-delegation-ttl` option allows the user to configure a maximum TTL for delegations; it is disabled by default.

Closes #6031

Merge branch '6031-delegdb-ttl' into 'main'

See merge request isc-projects/bind9!12102

2 weeks agoRemove useless TTL override in rctx_referral()
Colin Vidal [Fri, 29 May 2026 20:06:30 +0000 (22:06 +0200)] 
Remove useless TTL override in rctx_referral()

Function `rctx_referral()` used to force the TTL of an NS record with
TTL 0 to be 1.  This has now been removed, as the delegation database
already forces a minimum hard-coded TTL of 1 when the delegation has
a TTL of 0.

2 weeks agoSystem test for delegation TTL options
Colin Vidal [Fri, 29 May 2026 08:59:41 +0000 (10:59 +0200)] 
System test for delegation TTL options

Add a system test which covers the behavior of the `min-delegation-ttl`
and `max-delegation-ttl` options (including default, disabling, and
enforcing that min- must be strictly less than max-).

2 weeks agoDelegations have a minimal TTL of 60 seconds
Colin Vidal [Tue, 26 May 2026 13:58:44 +0000 (15:58 +0200)] 
Delegations have a minimal TTL of 60 seconds

Delegations are now stored in delegdb with a TTL of at least 60 seconds
by default. A new configuration option `min-delegation-ttl` allows
overriding this value or disabling entirely it with `0`.

This hardens the resolver against misconfigured glue or NS records
with very low TTLs, which would otherwise trigger delegation refetches
too often.

A new option `max-delegation-ttl` (which default to `0`) is also added,
enabling an operator to enforce a maximum TTL check for delegations.

2 weeks agoIntroduce min/max TTL bounds for delegations
Colin Vidal [Tue, 26 May 2026 13:56:03 +0000 (15:56 +0200)] 
Introduce min/max TTL bounds for delegations

The TTL of cached delegations can now have a minimum bound and a maximum
bound. By default, delegdb does not enable TTL bound checking, but this
can be configured from the caller using `dns_delegdb_config_t`.

2 weeks agoNaming convention fix for delegdb_lookup
Colin Vidal [Tue, 26 May 2026 07:52:53 +0000 (09:52 +0200)] 
Naming convention fix for delegdb_lookup

As `dns__delegdb_lookup()` is static and thus not used internally by
other modules of `libdns`, it can be renamed `delegdb_lookup()`.

2 weeks agofix: nil: Remove non-standard integer types
Ondřej Surý [Wed, 1 Jul 2026 06:05:10 +0000 (08:05 +0200)] 
fix: nil: Remove non-standard integer types

Replace u_char with uint8_t and uint with unsigned int.

Merge branch 'ondrej/replace-u_char-with-uint8_t' into 'main'

See merge request isc-projects/bind9!12331

2 weeks agoReplace uint with unsigned int in the histo.c unit
Ondřej Surý [Wed, 1 Jul 2026 04:46:09 +0000 (06:46 +0200)] 
Replace uint with unsigned int in the histo.c unit

Similarly, uint is not a standard type, replace it with standard
unsigned int type.

2 weeks agoReplace u_char remnants with uint8_t
Ondřej Surý [Wed, 1 Jul 2026 04:34:59 +0000 (06:34 +0200)] 
Replace u_char remnants with uint8_t

The u_char is BSDism that works, but since we have C11 integer types,
uint8_t is a better fit.

2 weeks agochg: dev: Simplify and modernize the radix tree implementation
Ondřej Surý [Wed, 1 Jul 2026 05:56:59 +0000 (07:56 +0200)] 
chg: dev: Simplify and modernize the radix tree implementation

Refactor the radix tree used for ACL IP prefix matching, originally imported
from the MRT routing toolkit in 1999 and never modernized.  Node size drops
from 100+ bytes across two allocations to 64 bytes in a single cache line.
Expand the unit test suite.

Merge branch 'ondrej/refactor-isc_radix-unit' into 'main'

See merge request isc-projects/bind9!11731

2 weeks agoReplace void* data pointers with match enum in radix nodes
Ondřej Surý [Sun, 22 Mar 2026 11:14:03 +0000 (12:14 +0100)] 
Replace void* data pointers with match enum in radix nodes

The node data[] array only ever held pointers to two static bools
(dns_iptable_pos/neg). Replace with isc_radix_match_t enum
(RADIX_UNSET/RADIX_ALLOW/RADIX_DENY) stored directly in the node.

This eliminates the void* casts, the static bool variables, the
isc_radix_destroyfunc_t callback (always NULL), and shrinks
isc_radix_node_t from 80 to 64 bytes. Also use sa_family_t for
the prefix family field.

2 weeks agoReplace RADIX_WALK macro with isc_radix_foreach function
Ondřej Surý [Sun, 22 Mar 2026 10:58:30 +0000 (11:58 +0100)] 
Replace RADIX_WALK macro with isc_radix_foreach function

Replace the RADIX_WALK/RADIX_WALK_END macro pair (which injected
hidden variables and split a do/while block across two macros)
with a proper isc_radix_foreach() function that takes a callback
and user argument.

This also eliminates the insecure_prefix_found global variable
and its associated mutex in acl.c -- the foreach argument replaces
both.

2 weeks agoMake isc_radix_insert, dns_iptable_addprefix/merge return void
Ondřej Surý [Sun, 22 Mar 2026 10:06:37 +0000 (11:06 +0100)] 
Make isc_radix_insert, dns_iptable_addprefix/merge return void

isc_radix_insert can no longer fail: node allocation uses
isc_mem_get which aborts on OOM, and prefix copying was eliminated
by inlining. Propagate the void return through dns_iptable_addprefix,
dns_iptable_merge, dns_acl_any, dns_acl_none, and all their callers.

2 weeks agoClean up radix tree code style
Ondřej Surý [Sun, 22 Mar 2026 00:18:47 +0000 (01:18 +0100)] 
Clean up radix tree code style

Improve the radix tree code:

- Rename node children from .l/.r to .left/.right
- Rename static functions to drop reserved leading underscores
- Rename legacy macro variables (Xrn, Xsp, Xstack) to
  readable names (cur, sp, stack)
- Narrow variable scopes to point of first use
- Use size_t for loop iterators, uint8_t for byte values
- Replace do/while(0) with plain blocks in macros
- Clean up unit test with helpers and meaningful data values

2 weeks agoRemove AF_UNSPEC and has_prefix from radix tree
Ondřej Surý [Sat, 21 Mar 2026 16:26:30 +0000 (17:26 +0100)] 
Remove AF_UNSPEC and has_prefix from radix tree

Instead of treating AF_UNSPEC as a special "any" prefix that sets
both IPv4 and IPv6 data slots, insert two separate entries (one
per address family). Both land on the same 0/0 node via the
existing dual-family data[] mechanism.

This eliminates AF_UNSPEC handling from isc_radix_insert (4 branch
blocks removed), removes the has_prefix bool from isc_radix_node_t
(using family==0 for glue nodes instead), and simplifies the
NETADDR_TO_PREFIX_T macro.

2 weeks agoInline prefix into radix tree node
Ondřej Surý [Sat, 21 Mar 2026 16:19:40 +0000 (17:19 +0100)] 
Inline prefix into radix tree node

Embed isc_prefix_t directly in isc_radix_node_t instead of heap-
allocating it separately. This eliminates per-node isc_mem_get/put
and isc_mem_attach/detach calls, removes a pointer dereference on
every search comparison, and simplifies the code by removing the
_new_prefix, _ref_prefix, and _deref_prefix helpers entirely.

Remove isc_mem_t from isc_prefix_t since it is now a plain value
type with no memory management. Remove per-node isc_mem_t since
nodes use the tree's memory context. Reorder struct fields to
eliminate padding holes.

2 weeks agoRemove prefix refcounting from radix tree
Ondřej Surý [Sat, 21 Mar 2026 16:12:15 +0000 (17:12 +0100)] 
Remove prefix refcounting from radix tree

Radix tree prefixes were reference-counted to allow sharing between
nodes, with refcount==0 used as a sentinel for stack-allocated
prefixes. Since the radix tree is only modified during config
parsing (single-threaded) and read-only during query processing,
the sharing optimization is unnecessary. Always copy prefixes
instead, eliminating the refcount field and the sentinel hack.

2 weeks agonew: test: Add build-time check for unregistered rdata files
Michal Nowak [Tue, 30 Jun 2026 17:20:11 +0000 (19:20 +0200)] 
new: test: Add build-time check for unregistered rdata files

Fail at meson configure if an rdata source file in lib/dns/rdata is not
registered in dns_header_depfiles, so edits no longer silently skip
header regeneration (as happened with brid, dsync, hhit, and wallet).

Assisted-by: Claude:claude-opus-4-8
Merge branch 'mnowak/check-rdata-registration' into 'main'

See merge request isc-projects/bind9!12219

2 weeks agoCheck for unregistered rdata files in CI
Michal Nowak [Tue, 9 Jun 2026 16:11:51 +0000 (16:11 +0000)] 
Check for unregistered rdata files in CI

Verify in the misc CI job that every rdata source file under
lib/dns/rdata is an input of the generated lib/dns/code.h, i.e.
registered in dns_header_depfiles.  An unregistered file is still
compiled into BIND 9 (gen.c scans the directories directly), but
editing it does not trigger regeneration of code.h.

Assisted-by: Claude:claude-opus-4-8
2 weeks agofix: dev: Assorted Meson fixes
Michal Nowak [Tue, 30 Jun 2026 17:01:50 +0000 (19:01 +0200)] 
fix: dev: Assorted Meson fixes

Merge branch 'mnowak/meson-ci-fixes' into 'main'

See merge request isc-projects/bind9!12167

2 weeks agoFix typo in build_vars comment
Michal Nowak [Tue, 2 Jun 2026 09:37:09 +0000 (09:37 +0000)] 
Fix typo in build_vars comment

Assisted-by: Claude:claude-opus-4-8
2 weeks agoQuote paths in the meson helper scripts
Michal Nowak [Tue, 2 Jun 2026 09:37:07 +0000 (09:37 +0000)] 
Quote paths in the meson helper scripts

Quote variable expansions, guard MESON_BUILD_ROOT, and enable
nullglob so paths with spaces and empty globs are handled.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoRaise nm timeout in the sanitizer defaults check
Michal Nowak [Tue, 2 Jun 2026 09:37:03 +0000 (09:37 +0000)] 
Raise nm timeout in the sanitizer defaults check

A 1 second timeout could abort the check on loaded runners.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoBase the readline check on the configured flags
Michal Nowak [Tue, 2 Jun 2026 09:37:02 +0000 (09:37 +0000)] 
Base the readline check on the configured flags

WITH_LIBEDIT/WITHOUT_LIBEDIT are always-set globals, so the check
always asserted libedit was absent. Inspect EXTRA_CONFIGURE instead.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoDrop duplicate dnstap-read.rst entry
Michal Nowak [Tue, 2 Jun 2026 09:36:57 +0000 (09:36 +0000)] 
Drop duplicate dnstap-read.rst entry

It was added both unconditionally and gated on HAVE_DNSTAP; keep
only the gated entry.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoInstall the synthrecord man page
Michal Nowak [Tue, 2 Jun 2026 09:36:55 +0000 (09:36 +0000)] 
Install the synthrecord man page

It was missing from man_srcset, unlike the other plugin man pages.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoTrack new generic rdata files for header generation
Michal Nowak [Tue, 2 Jun 2026 09:36:50 +0000 (09:36 +0000)] 
Track new generic rdata files for header generation

brid, dsync, hhit and wallet were missing from the header
dependency list, so edits to them did not regenerate headers.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoAvoid leaking FLAKY into every unit test
Michal Nowak [Tue, 2 Jun 2026 09:36:43 +0000 (09:36 +0000)] 
Avoid leaking FLAKY into every unit test

meson stores the test env by reference, so mutating the shared
test_env leaked FLAKY and TIMEOUT into all later tests. Build a
fresh environment for flaky tests instead.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoFix named.conf and named.pid path substitutions
Michal Nowak [Tue, 2 Jun 2026 09:36:36 +0000 (09:36 +0000)] 
Fix named.conf and named.pid path substitutions

Both substitutions wrongly expanded to named.key.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoCheck the host system for dtrace on macOS
Michal Nowak [Tue, 2 Jun 2026 09:36:31 +0000 (09:36 +0000)] 
Check the host system for dtrace on macOS

The macOS dtrace check used build_machine, breaking cross builds;
use host_machine like every other Darwin check.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoLook up urcu-common without the lib prefix
Michal Nowak [Tue, 2 Jun 2026 09:36:27 +0000 (09:36 +0000)] 
Look up urcu-common without the lib prefix

cc.find_library() expects the bare library name, so liburcu-common
was never found on liburcu < 0.13.0.

Assisted-by: Claude:claude-opus-4-8
2 weeks agoSet HAVE_ARM_YIELD instead of HAVE_SPARC_PAUSE on arm
Michal Nowak [Tue, 2 Jun 2026 09:36:23 +0000 (09:36 +0000)] 
Set HAVE_ARM_YIELD instead of HAVE_SPARC_PAUSE on arm

pause.h keys the arm yield instruction off HAVE_ARM_YIELD, so 32-bit
arm never got the fast path.

Assisted-by: Claude:claude-opus-4-8
2 weeks agofix: dev: Fold receive_secure_serial into zone maintainance
Alessio Podda [Tue, 30 Jun 2026 13:36:46 +0000 (13:36 +0000)] 
fix: dev: Fold receive_secure_serial into zone maintainance

Having two separate zone maintainance async jobs increases the risk of
race conditions. This commit folds the inline-signing resigning job
into the zone maintainance of the secure zone, ensuring only one async
job acts on a zone.

Closes #5816

Merge branch '5816-resign-single-source-of-truth' into 'main'

See merge request isc-projects/bind9!12005

2 weeks agoSplit inline sync state into a separate struct
Alessio Podda [Thu, 4 Jun 2026 12:05:08 +0000 (14:05 +0200)] 
Split inline sync state into a separate struct

The inline sync state is only needed when there is a raw-to-secure sync
in progress, and should be handled "atomically".

This commit creates a separate structure that holds all the inline sync
state to streamline the creation and cleanup.

2 weeks agoRename inline sync related methods
Alessio Podda [Thu, 4 Jun 2026 09:55:15 +0000 (11:55 +0200)] 
Rename inline sync related methods

The inline sync related methods and structs retained the old
receive_secure_ prefix. Since there is no async tasks involved anymore
we change the naming scheme to a more descriptive one.

2 weeks agoFix rss_state leak in receive_secure_serial_cancel
Alessio Podda [Thu, 21 May 2026 11:05:55 +0000 (13:05 +0200)] 
Fix rss_state leak in receive_secure_serial_cancel

Previously receive_secure_serial_cancel() could leak .rss_state on
inline secure bootstrap or zone shutdown, if a pre-existing DNSSEC
signing pass was paused. This has been fixed.

2 weeks agoSerialize zone maintenance requests
Alessio Podda [Sun, 24 May 2026 12:03:38 +0000 (14:03 +0200)] 
Serialize zone maintenance requests

Some rndc-driven maintenance operations interact with raw-to-secure
synchronization in the same way as setting NSEC3PARAM did. They are
scheduled via async tasks, which can interleave with raw-to-secure sync
and cause crashes.

To solve this, treat them the same as NSEC3PARAM changes, and extend
the pending NSEC3PARAM change queue to a generic maintenance queue that
rndc can post commands to.

These commands are dispatched by the zone_maintenance() callback, which
delays them if a raw-to-secure sync is in progress.

2 weeks agoFix setnsec3param DNSSEC maintenance ordering
Alessio Podda [Sun, 24 May 2026 11:57:24 +0000 (13:57 +0200)] 
Fix setnsec3param DNSSEC maintenance ordering

Before this commit, NSEC3PARAM changes were scheduled through an async
callback. This leads to a similar problem of interleaving with an
existing raw-to-secure sync, which is unsound since only one writer
version can be active at a time.

The zone already has a queue of "pending" NSEC3PARAM changes, so the
use of async tasks is also redundant. With this commit, we schedule
NSEC3PARAM changes using the pre-existing queues plus a timer.