Commit graph

418 commits

Author SHA1 Message Date
Aram Sargsyan
19efc4be5a 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.

(cherry picked from commit f85d9f5ef3)
2026-07-07 13:24:33 +00:00
Aram Sargsyan
d39d0410d0 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.

(cherry picked from commit efa8ca2267)
2026-07-07 12:00:40 +00:00
Ondřej Surý
383f483d98 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
(cherry picked from commit 874f34545f)
2026-07-07 12:00:40 +00:00
Ondřej Surý
bd8d5d2a52 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
(cherry picked from commit 220a270930)
2026-07-07 12:00:40 +00:00
Aram Sargsyan
bf58c9d9d8 Add a unit test for isc_url_t
The test has some basic checks for the URL/URI parser.

(cherry picked from commit 3bd33a817a)
2026-07-07 11:37:22 +00:00
Mark Andrews
f81a1cfa8e Add DNS_PRIVATE_BUFFERSIZE and use it
The size of a private records is 1 byte more than the corresponding
NSEC3PARAM record.

(cherry picked from commit 5d7387b185)
2026-07-03 04:07:30 +10:00
Ondřej Surý
4e6028883d 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
(cherry picked from commit f28bea94e3)
2026-07-02 10:55:30 +00:00
Ondřej Surý
fc1055d539 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
(cherry picked from commit 3d0c452cad)
2026-07-01 14:04:36 +02:00
Ondřej Surý
173255127f Add the tcp-reuse-timeout option
The idle timeout that bounds how long a reused outgoing TCP/TLS
connection is held open for reuse was only tunable through the 'named -T
tcpidletimeout' developer hook added earlier on this branch. Make it a
proper configuration option, tcp-reuse-timeout (options block, in units
of 100 milliseconds like the other tcp-*-timeout options), and drop the
-T hook.

(cherry picked from commit 477130cf8e)
2026-06-25 11:37:51 +02:00
Ondřej Surý
dc78507aa0 Keep idle reused outgoing TCP connections under read
A reused TCP/TLS dispatch with no outstanding responses was left in the
reuse pool with no read pending, so a peer closing the idle connection
went unnoticed: the socket lingered in CLOSE-WAIT and the dead dispatch
was later handed to a new query, which failed and the fetch timed out.
Keep a read pending on an idle connected dispatch, bounded by an idle
timeout, so the close is seen promptly and the connection is dropped
from the pool instead of reused.

The idle read may only be (re)armed while the dispatch is still
connected; arming it on a dispatch that is already shutting down
re-reads a dying handle and double-schedules a netmgr job.

On shutdown, close the connection as soon as the dispatch reaches its
terminal state instead of waiting for the last reference to drop, so an
unexpected read (or a peer-side close) cannot leave the socket in
CLOSE-WAIT while a reference still lingers.

(cherry picked from commit febeac215d)
2026-06-25 11:37:51 +02:00
Ondřej Surý
5df459bcde Fix use-after-free when destroying the bad and unreachable caches
Eviction of an entry owned by another loop was bounced to that loop via
isc_async_run(), so a queued list removal could run after the cache had
freed its LRU lists.  Use a single mutex-guarded LRU list instead, removing
entries synchronously under the lock, and let each entry hold its own
memory-context reference so the RCU free never touches a gone loop.

(cherry picked from commit bb43ecaf51)
2026-06-24 15:49:56 +02:00
Ondřej Surý
6fb070acc3
Add unit test for stale CNAME and other fresh data
Regression test for the find loop accepting a stale CNAME as a final
answer and stopping early even though a fresh record of the requested
type exists at the same node.

(cherry picked from commit b7144fb9cf)
2026-06-24 07:04:22 +02:00
Ondřej Surý
cd348cf255
Replace the shared work pool with per-loop, per-lane worker threads
Offloaded work used two different mechanisms: a per-loop isc_helper
thread for CPU-bound crypto (DNSSEC validation, message signature
checks) and the process-global libuv thread pool for blocking I/O (zone
load and dump, inbound transfer apply). Neither could cancel a queued
task, and the two disagreed about exclusive mode — the helper paused
with its loop under isc_loopmgr_pause() but the libuv pool did not, so
blocking offloaded work kept running while a loop held the exclusive
lock.

Unify both behind isc_work: each loop gets its own worker thread per
lane — FAST for short, bounded tasks and SLOW for long, blocking ones —
fed by a private queue. Separate lanes keep a short crypto task off the
path of a multi-second zone dump once both run on per-loop workers;
every lane parks with isc_loopmgr_pause() so exclusive mode now quiesces
offloaded work too; and a still-queued task can be canceled before it
starts (isc_work_cancel). isc_helper is removed and its callers select a
lane.

(cherry picked from commit a5f13b3410)
2026-06-17 21:15:17 +02:00
Ondřej Surý
78a7f7da4f
Enforce strict RSA DNSKEY shape during DNSSEC validation
A resolver that validated DNSSEC accepted RSA DNSKEYs of any modulus
size up to OpenSSL's compile-time ceiling, and accepted any public
exponent the wire format could carry.  RSA verification cost grows
sharply with the modulus length, so an authoritative server could
publish an oversized DNSKEY to make each signature check on the
resolver many times more expensive than for a normally sized key.

The intended verify-time cap had no effect because the helper it called
returned the public-exponent bit length rather than the modulus bit
length, so the test was always satisfied.  Replace it with an honest
modulus-range check and a stricter exponent check that accepts only odd
exponents in the closed range [3, 2^32 + 1] (covering every Fermat
prime up to F5 and the odd intermediate values seen in deployed keys),
reject anything outside those bounds at every RSA key load path so an
invalid key never reaches the verifier, and keep the same checks at the
verifier as a backstop against future load paths.

(cherry picked from commit 8b2c490811)
2026-06-08 20:54:22 +02:00
Evan Hunt
849aaacaae Add "warn_unused_result" to attributes.h
A new ISC_ATTR_WARN_UNUSED_RESULT macro now defines
__attribute__((warn_unused_result)) and is used for
dns_rdata_fromstruct().

(cherry picked from commit 07c8c1d242)
2026-06-04 09:49:41 -07:00
Ondřej Surý
5fe9e7f6ed Fix use-after-free in concurrent dns_tsigkey_delete()
Two TSIG-authenticated TKEY DELETE queries for the same dynamic key,
arriving on different worker loops, could each enter
dns_tsigkey_delete() and cause over-decrementing the key refcount.

This has been fixed by making dns_tsigkey_delete() idempotent.

(cherry picked from commit 5c8dcd4419)
2026-05-28 11:05:34 +02:00
Michal Nowak
e574119a19 Call tzset() after setenv("TZ", ...) in unit tests
POSIX does not require localtime_r() to behave as if tzset() was called,
so the TZ environment change isn't picked up if some library has already
primed libc's tz cache.  Loading pkcs11-provider during OpenSSL init
does exactly that, causing the time and dnstap cmocka tests to format
timestamps in UTC instead of the requested zone.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit c14f7881f2)
2026-05-26 17:09:11 +02:00
Andoni Duarte
3d293e2a1e Merge tag 'v9.20.23' into bind-9.20 2026-05-20 10:18:28 +00:00
Ondřej Surý
38dd0e0ccc Switch UDP fetches to TCP on the first response with a wrong query id
Until now, the dispatcher silently dropped UDP responses from the
expected peer that carried the wrong DNS message id and kept listening
for the correct id to arrive within the read timeout.  An off-path
attacker who knows the destination address and source port of an
outgoing fetch could exploit that quiet retry window to flood the
resolver with guessed responses; with a gigabit link the per-query
success probability grows linearly with the number of guesses that
arrive before the legitimate answer or the timeout.

Treat any such mismatch as a possible spoofing attempt and let the
resolver immediately retry the same query over TCP, the same control
path the truncation handler already uses.

Add a resolver statistics counter - exposed as 'queries retried over TCP
after a response with mismatched query id' in rndc stats and
'MismatchTCP' in the statistics channel

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit 11bca1051f)
2026-05-15 08:49:19 +02:00
Ondřej Surý
ddd5586a51
Make isc_mem_isovermem() probabilistic
Replace the hysteretic hi_water/lo_water switch with a stochastic
check: always false below lo_water, always true at or above hi_water,
linearly ramped probability in between.  This spreads cache cleaning
across many inserts instead of triggering a thundering herd once the
hi_water mark is crossed (which causes every addrdataset to enter the
LRU purge path simultaneously and serializes lookups behind the node
write locks).

The is_overmem atomic and its stores are no longer needed and are
removed.  The existing tests that asserted specific hysteretic state
transitions are simplified to check only the deterministic boundaries.

(cherry picked from commit ee24d2a1c3361dcc1c48fb29bb2e0b91bc3405e8)
2026-05-07 13:09:18 +02:00
Ondřej Surý
d35bc843c5 Implement seamless TCP connection reuse in dns_dispatch
Previously, the user of dns_dispatch API had to first call
dns_dispatch_gettcp() and if that failed create a new TCP dispatch with
dns_dispatch_createtcp().  This has been changed and the TCP connection
reuse happens transparently inside dns_dispatch_createtcp().  There are
separate buckets for dns_resolver, dns_request and dns_xfrin units, so
these don't get mixed together.

(cherry picked from commit d5ee86b799)
2026-05-06 15:05:48 +02:00
Ondřej Surý
2bbbd60de3
Reject oversized RRsets at slab construction
dns_rdataslab_fromrdataset(), dns_rdataslab_merge() and
dns_rdataslab_subtract() summed per-record storage into an
unsigned int with no upper-bound check.  An RRset whose total
encoded size exceeds DNS_RDATA_MAXLENGTH cannot fit in a DNS
message and is unservable; building its in-memory representation
only burns memory on data that will fail at response time, and at
the upper bound the running sum could in theory wrap.

Cap the running total at DNS_RDATA_MAXLENGTH and return ISC_R_NOSPACE
when exceeded.  Update the qpdb cache memory-purge test to use a
record size that fits within the new limit.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit f9d24b1b85)
2026-05-05 19:24:29 +02:00
Ondřej Surý
2b18aa9d59 Reject RSA DNSKEYs with oversize public exponents at parse time
The wire-format RSA DNSKEY parser was the only key path with no upper
bound on the public exponent — opensslrsa_parse and opensslrsa_fromlabel
already cap at RSA_MAX_PUBEXP_BITS.  An attacker-controlled DNSKEY could
therefore force a validator to compute s^e mod n with e up to ~|n| bits,
amplifying every verify by ~120x for typical 2048-bit moduli (OpenSSL
itself only caps the exponent for moduli above 3072 bits).  Apply the
same bit-count cap to wire-format keys.

Assisted-by: Claude:claude-opus-4-7
(cherry picked from commit ab8c1a77e0)
2026-04-30 13:16:30 +02:00
Mark Andrews
9be3bccf6d Test the ability to walk the iterators multiple times
It should be possible to walk APL, HIP, HTTPS and SVBC record
elements multiple times.  We now test this.

(cherry picked from commit aa2a41b2d1)
2026-03-27 12:45:25 +00:00
Mark Andrews
6159980235 Test walking apl list entries
(cherry picked from commit e435b0b7fb)
2026-03-27 12:38:01 +00:00
Aram Sargsyan
77d60acb86 Convert dns_dtenv_t reference counting to standard macors
Use standard reference counting macros for dns_dtenv_t instead of
custom attach/detach functions.

(cherry picked from commit 4ac3a6520e)
2026-03-18 17:04:56 +00:00
Ondřej Surý
d4b96af062
Enforce isc_work enqueue loop affinity
Add a REQUIRE(isc_loop() == loop) assertion to isc_work_enqueue()
to strictly enforce that work is enqueued from the loop it is
assigned to. This loudly prohibits cross-thread queue manipulation
before it inevitably turns into a concurrency debugging nightmare.

(cherry picked from commit f1311d2d19)
2026-03-14 07:52:56 +01:00
Michal Nowak
82991c7881
Use clang-format-22 to update formatting
(cherry picked from commit 239464f276)
2026-03-04 12:18:27 +01:00
Mark Andrews
a38d599260 Test maximum length NSEC3 hash detection
Adds text and wire format unit tests to verify the newly enforced
maximum NSEC3 hash length constraints.  These tests ensure that hash
lengths up to the 39-byte maximum are accepted, while larger sizes
correctly fail.

(cherry picked from commit e83a182056)
2026-02-24 17:10:52 +01:00
Mark Andrews
c88aa8a380 Enforce NSEC3 record consistency
NSEC3 hashes are required to fit within a single DNS label.  Since there
are 5 bits per label byte without pad characters, the maximum hash size
is floor(63*5/8) (39 bytes).

This patch enforces this maximum length for unknown algorithms, while
strictly enforcing the exact expected digest length for known algorithms
like SHA-1.

(cherry picked from commit 3801d0ebbf)
2026-02-24 17:10:52 +01:00
Matthijs Mekking
440ada653d Add a regression test for the BRID/HHIT crash
Add two short records to example.com.db that cause assertion failures
when converted to wire form.

The checks added to tests.sh are technically not required: the relevant
assertion failures are already hit when the zone is transferred out of
ns1.

Update the relevant unit tests with 1-byte records.

Co-authored-by: Mark Andrews <marka@isc.org>
(cherry picked from commit ce1d68cbc5)
2026-02-05 18:23:49 +00:00
Alessio Podda
97f2816947 Fix formatting
Cleanup formatting after IXFR changes.

(cherry picked from commit ad0a382092)
2026-02-02 10:32:38 +01:00
Alessio Podda
62a8d325bd Add unit tests
Add diffop unit tests.

(cherry picked from commit fb72ebcdd8)
2026-02-02 10:32:38 +01:00
Alessio Podda
0a5e27deef Implement qpzone specific update path
This commit implements a batch update function for qpzone. The main
reason for this is speed: using addrdataset would cause a qp transaction
per rrdataset added, leading to a substantial slowdown compared to
RBTDB. The new API results in a qp transaction per applied diff.

(cherry picked from commit da53708dcb)
2026-02-02 10:32:38 +01:00
Mark Andrews
84f955a972 ISC_RUN_TEST_IMPL should use a static declaration
These functions don't need to be called from multiple places and
by making them static we will detect when they are not added to the
list functions to be tested.

(cherry picked from commit 22d664aa15)
2026-01-29 00:26:35 +11:00
Mark Andrews
016baaa06c Fix brid and hhit unit tests
These tests were not being run.

(cherry picked from commit 97af8fc519)
2026-01-27 05:46:17 +00:00
Mark Andrews
1c32c8dba2 Fix and call tsig_badsig unit test
(cherry picked from commit 8da2310511)
2026-01-24 07:29:59 +11:00
Mark Andrews
5b4e36fbfc Fix dsync unit test
The dsync unit test was not being run and the domain names in
the test data should have been fully qualified.

(cherry picked from commit 2159f74a1f)
2026-01-23 14:24:27 +00:00
Nicki Křížek
0a09df0b7a Support compilation with cmocka 2.0.0+
The `assert_in_range()` function was deprecated in favor of
`assert_int_in_range()` and `assert_uint_in_range()`. Add compatibility
shims for cmocka<2.0.0 and use the new functions.

(cherry picked from commit 6843a4bd9a)
2026-01-07 11:17:42 +01:00
Matthijs Mekking
63262fd0f4 Implement dns_dbiterator_seek3
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)
2025-12-11 13:53:25 +01:00
Evan Hunt
25c9fb54da standardize CHECK and RETERR macros
previously, there were over 40 separate definitions of CHECK macros, of
which most used "goto cleanup", and the rest "goto failure" or "goto
out". there were another 10 definitions of RETERR, of which most were
identical to CHECK, but some simply returned a result code instead of
jumping to a cleanup label.

this has now been standardized throughout the code base: RETERR is for
returning an error code in the case of an error, and CHECK is for jumping
to a cleanup tag, which is now always called "cleanup". both macros are
defined in isc/util.h.

(cherry picked from commit 52bba5cc34)
2025-12-03 19:17:20 -08:00
Mark Andrews
b6d9d4f7a6 AMTRELAY type 0 presentation format handling was wrong
RFC 8777 specifies a placeholder value of "." for the gateway field
when the gateway type is 0 (no gateway).

(cherry picked from commit ae484d4501)
2025-11-20 08:47:22 +00:00
Ondřej Surý
2c2cb31394
Drop the unit test for testing randomness
Since we are using system routines for randomness, there's no point
in spending time and run the statistical suite for testing PRNG.

(cherry picked from commit 90b3def5e9)
2025-11-04 20:51:22 +01:00
Michał Kępień
b35d6513d8 Merge tag 'v9.20.15' into bind-9.20 2025-10-22 16:16:59 +00:00
Aram Sargsyan
3a1922f464 Fix dnssec-keygen key collision checking for KEY rrtype keys
When generating a new key, dnssec-keygen checks for possible
key ID collisions with existing keys. The dnssec.c:findmatchingkeys()
function, which is supposed to get the list of the existing keys,
fails to do that for the existing KEY rrtype keys (i.e. generated
using 'dnssec-keygen -T KEY') because it doesn't pass down to the
dst_key_fromnamedfile() -> dst_key_read_public() functions the type
of the keys it's interested in. Fix the issue by introducing a new
function parameter which tells in which type of keys the caller is
currently interested in.

(cherry picked from commit 49b7ce9a54)
2025-10-22 12:55:41 +11:00
Michal Nowak
bc35b646b9
Use clang-format-21 to update formatting 2025-10-21 12:12:01 +02:00
Ondřej Surý
2924910eee
Use cryptographically-secure pseudo-random generator everywhere
It was discovered in an upcoming academic paper that a xoshiro128**
internal state can be recovered by an external 3rd party allowing to
predict UDP ports and DNS IDs in the outgoing queries.  This could lead
to an attacker spoofing the DNS answers with great efficiency and
poisoning the DNS cache.

Change the internal random generator to system CSPRNG with buffering to
avoid excessive syscalls.

Thanks Omer Ben Simhon and Amit Klein of Hebrew University of Jerusalem
for responsibly reporting this to us.  Very cool research!

(cherry picked from commit cffcab9d5f)
2025-10-02 13:49:33 +02:00
Ondřej Surý
f65c7b0c02
Fix dns_qpmulti_memusage() on empty dns_qpmulti_t instance
The dns_qpmulti_memusage() causes assertion failure when called on
freshly created qpmulti instance because the qp->usage hasn't been
allocated yet.

(cherry picked from commit b2f653b332)
2025-09-17 14:01:44 +02:00
Mark Andrews
c0b39b9093 Add tests for BRID and HHIT
(cherry picked from commit 92621e6390)
2025-09-03 11:02:15 +10:00
Mark Andrews
ae6704b4fb Add tests for DSYNC
(cherry picked from commit 53c8c5233a)
2025-08-06 13:47:33 +10:00