2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 21:47:59 +00:00

9452 Commits

Author SHA1 Message Date
Mark Andrews
27e74b2e4b Only create private records for DNSKEYs that have changed
We don't need to create private records for DNSKEY records that
have only had their TTL's changed.
2024-01-03 12:09:11 +11:00
Mark Andrews
d601a90ea3 sync_secure_db failed to handle some TTL changes
If the DNSKEY, CDNSKEY or CDS RRset had different TTLs then the
filtering of these RRset resulted in dns_diff_apply failing with
"not exact". Identify tuple pairs that are just TTL changes and
allow them through the filter.
2024-01-03 12:09:11 +11:00
Mark Andrews
21be35c54e Use the current CDS and CDNSKEY TTLs
When adding new CDS and CDNSKEY records use the existing RRset
TTL if they already exist.
2024-01-03 12:09:11 +11:00
Mark Andrews
dcb7799061 Update the DNSKEY, CDNSKEY and CDS TTLs to match dnskey-ttl
If the TTLs of the DNSKEY, CDNSKEY and CDS do not match the
dnskey-ttl update them by removing all records and re-adding
them with the correct TTL.
2024-01-03 12:09:11 +11:00
Michał Kępień
9cf1f39b54
Silence a scan-build warning in dns_rbt_addname()
Clang Static Analyzer is unable to grasp that when dns_rbt_addnode()
returns ISC_R_EXISTS, it always sets the pointer passed to it via its
'nodep' parameter to a non-NULL value.  Add an extra safety check in the
conditional expression used in dns_rbt_addname() to silence that
warning.
2023-12-22 19:27:37 +01:00
Evan Hunt
ea9a8cb392 prevent an infinite loop in fix_iterator()
it was possible for fix_iterator() to get stuck in a loop while
trying to find the predecessor of a missing node. this has been
fixed and a regression test has been added.
2023-12-21 09:18:30 -08:00
Evan Hunt
84f79cd164 fix_iterator() could produce incoherent iterator stacks
the fix_iterator() function moves an iterator so that it points
to the predecessor of the searched-for name when that name doesn't
exist in the database. the tests only checked the correctness of
the top of the stack, however, and missed some cases where interior
branches in the stack could be missing or duplicated. in these
cases, the iterator would produce inconsistent results when walked.

the predecessors test case in qp_test has been updated to walk
each iterator to the end and ensure that the expected number of
nodes are found.
2023-12-21 09:18:30 -08:00
Mark Andrews
0509351e92 Update the NSEC3PARAM TTL to match the SOA minimum
When building NSEC3 chains update the NSEC3PARAM TTL to match
the SOA minimum.  Delete all records using the old TTL then
re-add them using the new TTL.
2023-12-21 20:12:09 +11:00
Mark Andrews
f3ae88d84e Don't delete the NSEC3PARAM immediately
Wait until the new NSEC or NSEC3 chain is generated then it should
be deleted.
2023-12-21 20:12:09 +11:00
Mark Andrews
a3d0476d17 Don't look for KSK status here and squash memory leak
Just remove the key from  consideration as it is being removed.

The old code could leak a key reference as dst_free_key was not
called every time we continued. This simplification will address
this as well.
2023-12-21 09:18:45 +11:00
Mark Andrews
6ccb93884d dns_request_cancel needs to be callable from any thread
Check the tid and cancel the request immediately or pass it to the
appropriate loop for processing.  Call request->cb directly from
req_sendevent as it is now always called with the correct tid.
2023-12-21 08:11:59 +11:00
Michał Kępień
efcba4dd23
Do not destroy IXFR journal in xfrin_end()
The xfrin_end() function is run when a zone transfer is finished or
canceled.  One of the actions it takes for incremental transfers (IXFR)
is calling dns_journal_destroy() on the zone journal structure that is
stored in the relevant zone transfer context (xfr->ixfr.journal).  That
immediately invalidates that structure as it is not reference-counted.
However, since the changes present in the IXFR stream are applied to the
journal asynchronously (via isc_work_enqueue()), it is possible that
some zone changes may still be in the process of being written to the
journal by the time xfrin_end() destroys the relevant structure.  Such a
scenario leads to crashes.

Fix by not destroying the zone journal structure until the entire zone
transfer context is destroyed.  xfrin_destroy() already conditionally
calls dns_journal_destroy() and when the former is called, all
asynchronous work for a given zone transfer process is guaranteed to be
complete.
2023-12-20 17:21:14 +01:00
Matthijs Mekking
16f2c811e3 Revert "Remove kasp mutex lock"
This reverts commit 634c80ea1237520b7660a8469af2c38b7865ca24.
2023-12-20 08:30:44 +00:00
Mark Andrews
c896e07277 Log what change generated a 'not exact' error 2023-12-20 01:56:38 +11:00
Matthijs Mekking
634c80ea12 Remove kasp mutex lock
Multiple zones should be able to read the same key and signing policy
at the same time. Since writing the kasp lock only happens during
reconfiguration, and the complete kasp list is being replaced, there
is actually no need for a lock. Reference counting ensures that a kasp
structure is not destroyed when still being attached to one or more
zones.

This significantly improves the load configuration time.
2023-12-19 14:53:51 +01:00
Mark Andrews
6066e41948 Use 'now' rather than 'inception' in 'add_sigs'
When kasp support was added 'inception' was used as a proxy for
'now' and resulted in signatures not being generated or the wrong
signatures being generated.  'inception' is the time to be set
in the signatures being generated and is usually in the past to
allow for clock skew.  'now' determines what keys are to be used
for signing.
2023-12-19 11:21:46 +11:00
Michał Kępień
2a3b6d1406
Fix reference counting in do_nsfetch()
Each function queuing a do_nsfetch() call using isc_async_run() is
expected to increase the given zone's internal reference count
(zone->irefs), which is then correspondingly decreased in either
do_nsfetch() itself (when the dns_resolver_createfetch() fails) or in
nsfetch_done() (when recursion is finished).

However, do_nsfetch() can also return early if either the zone itself or
the relevant view's resolver object is being shut down.  In that case,
do_nsfetch() simply returns without decreasing the internal reference
count for the zone.  This leaves a dangling zone reference around, which
leads to hangs during named shutdown.

Fix by executing the same cleanup code for early returns from
do_nsfetch() as for a failed dns_resolver_createfetch() call in that
function as the reference count will not be decreased in nsfetch_done()
in any of these cases.
2023-12-18 11:33:43 +01:00
Aram Sargsyan
791a046cc7 Use atomic store operations instead of atomic initialize
The atomic_init() function makes sense to use with structure's
members when creating a new instance of a strucutre. In other
places, use atomic store operations instead, in order to avoid
data races.
2023-12-15 09:56:44 +00:00
Matthijs Mekking
21867f200a Refactor getpred code
Move the code to find the predecessor into one function, as it is shares
quite some similarities: In both cases we first need to find the
immediate predecessor/successor, then we need to find the immediate
predecessor if the iterator is not already pointing at it.
2023-12-11 21:01:29 +00:00
Matthijs Mekking
ab8a0c4b5a and fix yet another dns_qp_lookup() iterator bug
This one is similar to the bug when searching for a key, reaching a
dead-end branch that doesn't match, because the branch offset point
is after the point where the search key differs.

This fixes the case where we are multiple levels deep. In other
words, we had a more-than-one matches *after* the point where the
search key differs.

For example, consider the following qp-trie:

branch: "[e]", "[m]":
 - leaf: "a.b.c.d.e"
 - branch: "moo[g]", "moo[k]", "moo[n]":
   - leaf: "moog"
   - branch: "mook[e]", "mook[o]"
     - leaf: "mooker"
     - leaf: "mooko"
   - leaf: "moon"

If searching for a key "monky", we would reach the branch with
twigs "moo[k]" and "moo[n]". The key matches on the 'k' on offset=4,
and reaches the branch with twigs "mook[e]" and "mook[o]". This time
we cannot find a twig that matches our key at offset=5, there is no
twig for 'y'. The closest name we found was "mooker".

Note that on a branch it can't detect it is on a dead branch because the
key is not encapsulated in a branch node.

In the previous code we considered "mooker" to be the successor of
"monky" and so we needed to the predecessor of "mooker" to find the
predecessor for "monky". However, since the search key alread differed
before entering this branch, this is not enough. We would be left with
"moog" as the predecessor of "monky", while in this example "a.b.c.d.e"
is the actual predecessor.

Instead, we need to go up a level, find the predecessor and check
again if we are on the right branch, and repeat the process until we
are.

Unit tests to cover the scenario are now added.
2023-12-11 21:01:29 +00:00
Matthijs Mekking
276bdcf5cf and fix another dns_qp_lookup() iterator bug
There was yet another edge case in which an iterator could be
positioned at the wrong node after dns_qp_lookup(). When searching for
a key, it's possible to reach a leaf that matches at the given offset,
but because the offset point is *after* the point where the search key
differs from the leaf's contents, we are now at the wrong leaf.

In other words, the bug fixed the previous commit for dead-end branches
must also be applied on matched leaves.

For example, if searching for the key "monpop", we could reach a branch
containing "moop" and "moor". the branch offset point - i.e., the point
after which the branch's leaves differ from each other - is the
fourth character ("p" or "r"). The search key matches the fourth
character "p", and takes that twig to the next node (which can be
a branch for names starting with "moop", or could be a leaf node for
"moop").

The old code failed to detect this condition, and would have
incorrectly left the iterator pointing at some successor, and not
at the predecessor of the "moop".

To find the right predecessor in this case, we need to get to the
previous branch and get the previous from there.

This has been fixed and the unit test now includes several new
scenarios for testing search names that match and unmatch on the
offset but have a different character before the offset.
2023-12-11 21:01:29 +00:00
Mark Andrews
7e462c2b26 Also cleanup the space for the rbt nodes
As we are in overmem state we want to free more memory than we are
adding so we need to add in an allowance for the rbtnodes that may
have been added and the names stored with them.  There is the node
for the owner name and a possible ENT node if there was a node split.
2023-12-07 02:59:04 +00:00
Mark Andrews
5e8f0e9ceb Process the combined LRU lists in LRU order
Only cleanup headers that are less than equal to the rbt's last_used
time.  Adjust the rbt's last_used time when the target cleaning was
not achieved to the oldest value of the remaining set of headers.

When updating delegating NS and glue records last_used was not being
updated when it should have been.

When adding zero TTL records to the tail of the LRU lists set
last_used to rbtdb->last_used + 1 rather than now.  This appoximately
preserves the lists LRU order.
2023-12-07 02:59:04 +00:00
Evan Hunt
7d05590a6f clean up client.c
- make dns_client_startresolve() static since it's only used internally
- remove outdated comments
2023-12-06 17:31:38 -08:00
Evan Hunt
50dd6aad34 remove unused functions in dns_master
dns_master_dumpnode() and dns_master_dumpnodetostream() were
never used and can be removed.
2023-12-06 17:31:38 -08:00
Evan Hunt
66496d550b remove resolver-retry-interval and resolver-nonbackoff-tries
fully remove these options and mark them as ancient.
2023-12-06 11:54:59 -08:00
Evan Hunt
60a33ae6bb fix another dns_qp_lookup() iterator bug
there was another edge case in which an iterator could be positioned at
the wrong node after dns_qp_lookup().  when searching for a key, it's
possible to reach a dead-end branch that doesn't match, because the
branch offset point is *after* the point where the search key differs
from the branch's contents.

for example, if searching for the key "mop", we could reach a branch
containing "moon" and "moor". the branch offset point - i.e., the
point after which the branch's leaves differ from each other - is the
fourth character ("n" or "r"). however, both leaves differ from the
search key at position *three* ("o" or "p"). the old code failed to
detect this condition, and would have incorrectly left the iterator
pointing at some lower value and not at "moor".

this has been fixed and the unit test now includes this scenario.
2023-12-06 11:03:30 -08:00
Evan Hunt
8612902476 fix dns_qp_lookup() iterator bug
in some cases it was possible for the iterator to be positioned in the
wrong place by dns_qp_lookup(). previously, when a leaf node was found
which matched the search key at its parent branch's offset point, but
did not match after that point, the code incorrectly assumed the leaf
it had found was a successor to the searched-for name, and stepped the
iterator back to find a predecessor.  however, it was possible for the
non-matching leaf to be the predecessor, in which case stepping the
iterator back was wrong.

(for example: a branch contains "aba" and "abcd", and we are searching
for "abcde". we step down to the twig matching the letter "c" in
position 3. "abcd" is the predecessor of "abcde", so the iterator is
already correctly positioned, but because the twig was an exact match,
we would have moved it back one step to "aba".)

this previously went unnoticed due to a mistake in the qp_test unit
test, which had the wrong expected result for the test case that should
have detected the error. both the code and the test have been fixed.
2023-12-06 11:03:30 -08:00
Evan Hunt
947bc0a432 add an iterator argument to dns_qp_lookup()
the 'predecessor' argument to dns_qp_lookup() turns out not to
be sufficient for our needs: the predecessor node in a QP database
could have become "empty" (for the current version) because of an
update or because cache data expired, and in that case the caller
would have to iterate more than one step back to find the predecessor
node that it needs.

it may also be necessary for a caller to iterate forward, in
order to determine whether a node has any children.

for both of these reasons, we now replace the 'predecessor'
argument with an 'iter' argument. if set, this points to memory
with enough space for a dns_qpiter object.

when an exact match is found by the lookup, the iterator will be
pointing to the matching node. if not, it will be pointing to the
lexical predecessor of the nae that was searched for.

a dns_qpiter_current() method has been added for examining
the current value of the iterator without moving it in either
direction.
2023-12-06 11:03:30 -08:00
Artem Boldariev
b109fa9192 Fix TLS certs store deletion on concurrent access
During initialisation or reconfiguration, it is possible that multiple
threads are trying to create a TLS context and associated data (like
TLS certs store) concurrently. In some cases, a thread might be too
late to add newly created data to the TLS contexts cache, in which
case it needs to be discarded. In the code that handles that case, it
was not taken into account that, in some cases, the TLS certs store
could not have been created or should not be deleted, as it is being
managed by the TLS contexts cache already. Deleting the store in such
cases might lead to crashes.

This commit fixes the issue.
2023-12-06 16:01:20 +02:00
Artem Boldariev
5ed3a76f9d BIND: Add 'allow-proxy' and 'allow-proxy-on' options
The main intention of PROXY protocol is to pass endpoints information
to a back-end server (in our case - BIND). That means that it is a
valid way to spoof endpoints information, as the addresses and ports
extracted from PROXYv2 headers, from the point of view of BIND, are
used instead of the real connection addresses.

Of course, an ability to easily spoof endpoints information can be
considered a security issue when used uncontrollably. To resolve that,
we introduce 'allow-proxy' and 'allow-proxy-on' ACL options. These are
the only ACL options in BIND that work with real PROXY connections
addresses, allowing a DNS server operator to specify from what clients
and on which interfaces he or she is willing to accept PROXY
headers. By default, for security reasons we do not allow to accept
them.
2023-12-06 15:15:25 +02:00
Artem Boldariev
eb52015db1 Stream DNS: add PROXY over TLS support
This commit extends Stream DNS with PROXY over TLS support.
2023-12-06 15:15:25 +02:00
Artem Boldariev
e97903ca14 Add PROXY support to Stream DNS
This commit makes it possible to use Stream DNS on top of PROXY Stream
either directly or indirectly (in the case when TLS is involved).
2023-12-06 15:15:24 +02:00
Matthijs Mekking
ff4201e388 Lower the maximum allowed NSEC3 iterations to 50
BIND 9 will now treat the response as insecure when processing NSEC3
records with iterations larger than 50.

Earlier, we limited the number of iterations to 150 (in #2445).

RFC 9276 says: Because there has been a large growth of open (public)
DNSSEC validating resolvers that are subject to compute resource
constraints when handling requests from anonymous clients, this
document recommends that validating resolvers reduce their iteration
count limits over time. Specifically, validating resolver operators and
validating resolver software implementers are encouraged to continue
evaluating NSEC3 iteration count deployment trends and lower their
acceptable iteration limits over time.

After evaluation, we decided that the next major BIND release should
lower the maximum allowed NSEC3 iterations to 50, which should be
fine for 99,87% of the domain names.
2023-12-05 14:58:58 +00:00
Mark Andrews
7ee20d7d10 Destroy the message before detaching the view
With shared name memory pools (f5af981831ea8a707090c1b09a47c25b75d86b5a)
the message needs to be destroyed before the view is detached which
in turn detaches the resolver which checks that all resources have
been returned.
2023-12-04 22:00:25 +00:00
Ondřej Surý
14bdd21e0a
Refactor the handling of isc_mem overmem condition
Previously, there were two methods of working with the overmem
condition:

1. hi/lo water callback - when the overmem condition was reached
   for the first time, the water callback was called with HIWATER
   mark and .is_overmem boolean was set internally.  Similarly,
   when the used memory went below the lo water mark, the water
   callback would be called with LOWATER mark and .is_overmem
   was reset.  This check would be called **every** time memory
   was allocated or freed.

2. isc_mem_isovermem() - a simple getter for the internal
   .is_overmem flag

This commit refactors removes the first method and move the hi/lo water
checks to the isc_mem_isovermem() function, thus we now have only a
single method of checking overmem condition and the check for hi/lo
water is removed from the hot path for memory contexts that doesn't use
overmem checks.
2023-11-29 14:16:20 +01:00
Mark Andrews
decc17d3b0 Ineffective DbC protections
Dereference before NULL checks.  Thanks to Eric Sesterhenn from X41
D-Sec GmbH for reporting this.
2023-11-21 14:48:43 +11:00
Matthijs Mekking
71f023a1c3 Recognize escapes when reading the public key
Escapes are valid in DNS names, and should be recognized when reading
the public key from disk.
2023-11-20 08:31:39 +01:00
Evan Hunt
9643281453 set loadtime during initial transfer of a secondary zone
when transferring in a non-inline-signing secondary for the first time,
we previously never set the value of zone->loadtime, so it remained
zero. this caused a test failure in the statschannel system test,
and that test case was temporarily disabled.  the value is now set
correctly and the test case has been reinstated.
2023-11-15 17:23:25 -08:00
Mark Andrews
a069513234 Check that buffer length in dns_message_renderbegin
The maximum DNS message size is 65535 octets. Check that the buffer
being passed to dns_message_renderbegin does not exceed this as the
compression code assumes that all offsets are no bigger than this.
2023-11-16 11:15:49 +11:00
Aram Sargsyan
c584899b1a Fix catz db update callback registration logic error (take two)
Please see the 998765fea536daacfba96d8ed0a4855668d2e242 commit for
the description of the original issue. The commit had fixed the
logic error, but it was reintroduced again later with the
a1afa31a5a7d318508efe5a32001104d094be057 commit, where the check of
the 'db_registered' flag was removed in dns__catz_update_cb(). The
check was removed, because the registration function was made
idempotent, so double registration is not an issue, but the check
also prevented from unneeded registration, on which the original
fix relied.

This commit just removes the update callback registration code from
the dns__catz_update_cb() function instead of bringing back the check,
because after code flow analysis, it is now clear that it's not required
at all. The "call onupdate() artificially" comment (which was mentioned
by the removed code) is speaking about the dns_catz_dbupdate_callback()
function, which is called by server.c on (re)configuration, and that
function already takes care of update callback's registration since the
998765fea536daacfba96d8ed0a4855668d2e242 commit was applied, so there
is no need to do that here again.
2023-11-14 08:59:48 +00:00
Ondřej Surý
79d9360011
Reformat sources with up-to-date clang-format-17 2023-11-13 16:52:35 +01:00
Aram Sargsyan
6687de854f Use a read lock when iterating over a hashmap
The 'dns_tsigkeyring_t' structure has a read/write lock to protect
its 'keys' member, which is a 'isc_hashmap_t' pointer and needs to
be protected.

The dns_tsigkeyring_dump() function, however, doesn't use the lock,
which can introduce a race with another thread, if the other thread
tries to modify the hashmap.

Add a read lock around the code, which iterates over the hashmap.
2023-11-13 12:06:26 +00:00
Evan Hunt
461b9a0442 if GLUEOK is set, and glue is found in a zone DB, don't check the cache
EXPERIMENT: when DNS_DB_GLUEOK is set, dns_view_find() will now return
glue if it is found it a local zone database, without checking to see
if a better answer has been cached previously.
2023-11-01 16:49:08 +01:00
Mark Andrews
9227b82e71 Also look for additional records in dns_adb_find
If a child zone is served by the same servers as a parent zone and
a NS query is made for the zone name then the addresses of the
nameservers are returned in the additional section are tagged as
trust additional.
2023-11-01 16:49:08 +01:00
Mark Andrews
578da93581 Turn on QNAME minimisation when fetching nameserver addresses 2023-11-01 16:49:08 +01:00
Evan Hunt
b12f709f05 restore isc_mem_setwater() call in the cache
Commit 4db150437e14b28c5b50ae466af9ce502fd73185 incorrectly removed the
call to isc_mem_setwater() from dns_cache_setcachesize().  The water()
function is a no-op, but we still need to set high- and low-water marks
in the memory context, otherwise overmem conditions will not be
detected.
2023-11-01 15:18:02 +00:00
Ondřej Surý
c855ed6a0b
Bump the mempool sizes in dns_message
Increasing the initial and freemax sizes for dns_message memory pools
restores the root zone performance.  The former sizes were suited for
per-dns_message memory pools and we need to bump the sizes up for
per-thread memory pools.
2023-10-27 15:28:27 +02:00
Evan Hunt
03183baa6d Prevent a possible race in dns_qpmulti_query() and _snapshot()
The `.reader` member of dns_qpmulti_t was accessed without RCU
protection; reader_open() calls rcu_dereference() on it, and this
call needs to be inside an RCU critical section.

A similar problem was identified in the dns_qpmulti_snapshot() - the
RCU critical section was completely missing.

These are relicts of the isc_qsbr - in the QSBR mode the rcu_read_lock()
and rcu_read_unlock() are no-ops and whole event loop is a critical section.
2023-10-26 00:32:22 -07:00
Ondřej Surý
6bb42939cf
Refactor dns_message using ISC_LIST_FOREACH macros
Do a light refactoring and cleanups that replaces common list walking
patterns with ISC_LIST_FOREACH macros and split some nested loops into
separate static functions to reduce the nesting depth.
2023-10-25 12:36:37 +02:00