The existing serve-stale tests all use negative answers with a two
second TTL, because they are there to exercise stale data. Nothing
covered the far more common case of a negative answer that is still
fresh, which is how the needless refresh went unnoticed.
ans2 grows a NODATA and an NXDOMAIN name backed by a SOA with a 600
second TTL and MINIMUM, so the cached entry cannot go stale while the
test runs, and the test counts the queries that reach ans2: priming the
cache may send one, the repeated client queries must send none.
Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 60b3cc0eca)
query_ncache() always passed a NULL rdataset to query_stale_refresh(),
which reads NULL as "this RRset is stale". NULL is only meaningful for
the DNS64 caller, whose rdataset has already been detached by the time
the answer is turned into an NXDOMAIN; everywhere else a perfectly fresh
negative cache entry was taken for a stale one.
With stale-answer-client-timeout 0 the staleness check is the only gate
left on the refresh, so every client query for a cached NXDOMAIN or
NODATA name started another fetch and negative caching stopped having
any effect.
(cherry picked from commit 4821290c31)
The OID in the "; alg = ..." comment of a PRIVATEOID key was truncated to sixteen characters.
Closes#6092
Backport of MR !12377
Merge branch 'backport-6092-fix-PRIVATEOID-output-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12378
The OID printed in the "; alg = ..." comment of a PRIVATEOID KEY,
DNSKEY, CDNSKEY or RKEY record was truncated to sixteen characters:
1.2.840.113549.1.1.11 came out as 1.2.840.113549.1. Only the comment
was ever affected, never the record itself.
(cherry picked from commit 4ba4b3bd8f)
The guard against synthesizing negative answers from a pending NSEC
(#5977) was only added to the QP cache's find_coveringnsec(); the RBT
cache database kept binding any covering NSEC regardless of trust. On
builds configured with --with-cachedb=rbt this lets a piggy-backed,
unvalidated NSEC drive a synthesized NXDOMAIN, reviving the cache
poisoning that was fixed for the default cache.
query_coveringnsec() only verifies the covering NSEC's trust on its
NODATA path; the NXDOMAIN path relies on the database returning a
secure record. Require the NSEC and its RRSIG to be dns_trust_secure
in find_coveringnsec(), matching the QP cache.
Closes#5977
Merge branch '5977-rbt-cachedb-covering-nsec-secure-trust' into 'bind-9.20'
See merge request isc-projects/bind9!12374
The guard against synthesizing negative answers from a pending NSEC
(#5977) was only added to the QP cache's find_coveringnsec(); the RBT
cache database kept binding any covering NSEC regardless of trust. On
builds configured with --with-cachedb=rbt this lets a piggy-backed,
unvalidated NSEC drive a synthesized NXDOMAIN, reviving the cache
poisoning that was fixed for the default cache.
query_coveringnsec() only verifies the covering NSEC's trust on its
NODATA path; the NXDOMAIN path relies on the database returning a
secure record. Require the NSEC and its RRSIG to be dns_trust_secure
in find_coveringnsec(), matching the QP cache.
Assisted-by: Claude:claude-opus-4-8
If an NSEC record has not yet been validated and is cached with trust
pending, don't use it to synthesize negative responses.
Closes#5872Closes#5887Closes#5977
Backport of MR !12281
Merge branch 'backport-5977-validate-synth-from-dnssec-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12368
The #5872 reproducer plants a covering NSEC that is rejected inside the
cache (find_coveringnsec), so it never reaches the trust check on the
exact-match NODATA branch of query_coveringnsec(). This adds a companion
case: an NSEC owned by the victim name itself, injected at pending trust
via a CD=1 query, is returned by the cache as a NODATA proof for the
exact node and must not be used to synthesize a NODATA that would deny
the victim's real A record.
Reuses the f004.test fixture with a victim-owned forged NSEC.
Assisted-by: Claude:claude-fable-5
(cherry picked from commit dc02732883)
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
Backport of MR !12353
Merge branch 'backport-6176-validator-apex-dname-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12356
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
(cherry picked from commit 38992e02bb)
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.
(cherry picked from commit 057ae0adb8)
Update the manual rollover system test with a multi-master setup.
Backport of MR !11268
Merge branch 'backport-matthijs-test-dnssec-policy-multimaster-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12360
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.
(cherry picked from commit affe84e55b)
The brackets are not included in the host component of the parsed
URL/URI. Change the parser to include the brackets.
Closes#6147
Backport of MR !12266
Merge branch 'backport-6147-isc_url_parse-ipv6-brackets-fix-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12362
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)
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
Backport of MR !12252
Merge branch 'backport-6150-isc_url_parse-buffer-size-check-fix-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12361
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)
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)
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)
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.
(cherry picked from commit b878f82409)
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
Backport of MR !12283
Merge branch 'backport-5970-pending-nsec3-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12358
Ignore NSEC3 records that failed in the sub-validator when determining
whether an insecure delegation is legitimate.
Fixes: isc-projects/bind9#5970
(cherry picked from commit 1bd458d3ba)
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
Backport of MR !11946
Merge branch 'backport-5877-cd-nxdomain-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12344
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
(cherry picked from commit ddb6cb5c93)
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.
(cherry picked from commit a7a90eb9d8)
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
Backport of MR !11816
Merge branch 'backport-5857-properly-detect-private-records-before-copying-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12340
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.
(cherry picked from commit 7182a03b82)
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
Backport of MR !12354
Merge branch 'backport-nicki/serve-signed-child-same-ns-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12355
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
(cherry picked from commit 246cca357b)
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
(cherry picked from commit 4d76b7bd9e)
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.
(cherry picked from commit ee73ba3bba)
This algorithm is deprecated and not currently used in our system tests,
but it should be in the list of all algorithms.
(cherry picked from commit 596e41553c)
Code move with one change - switch dnskey TTL from 300s (DEFAULT_TTL) to
3600s (DNSKEY_TTL).
Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 55cd4a1e11)
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
(cherry picked from commit 35fc5ce8b4)
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.
Backport of MR !12260
Merge branch 'backport-michal/update-asyncdnsserver-related-test-cookbook-parts-9.20' into 'bind-9.20'
See merge request isc-projects/bind9!12352