mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-22 01:56:00 -04:00
Merge tag 'v9.21.14'
This commit is contained in:
commit
c2a672bbae
21 changed files with 886 additions and 251 deletions
|
|
@ -18,6 +18,8 @@ Changelog
|
|||
development. Regular users should refer to :ref:`Release Notes <relnotes>`
|
||||
for changes relevant to them.
|
||||
|
||||
.. include:: ../changelog/changelog-9.21.14.rst
|
||||
.. include:: ../changelog/changelog-9.21.13.rst
|
||||
.. include:: ../changelog/changelog-9.21.12.rst
|
||||
.. include:: ../changelog/changelog-9.21.11.rst
|
||||
.. include:: ../changelog/changelog-9.21.10.rst
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ The list of known issues affecting the latest version in the 9.21 branch can be
|
|||
found at
|
||||
https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21
|
||||
|
||||
.. include:: ../notes/notes-9.21.14.rst
|
||||
.. include:: ../notes/notes-9.21.13.rst
|
||||
.. include:: ../notes/notes-9.21.12.rst
|
||||
.. include:: ../notes/notes-9.21.11.rst
|
||||
.. include:: ../notes/notes-9.21.10.rst
|
||||
|
|
|
|||
|
|
@ -2186,6 +2186,8 @@ Boolean Options
|
|||
autodetection of DNS COOKIE support to determine when to retry a
|
||||
request over TCP.
|
||||
|
||||
For DNAME lookups the default is ``yes`` and it is enforced. Servers
|
||||
serving DNAME must correctly support DNS over TCP.
|
||||
|
||||
.. note::
|
||||
If a UDP response is signed using TSIG, :iscman:`named` accepts it even if
|
||||
|
|
|
|||
18
doc/changelog/changelog-9.21.13.rst
Normal file
18
doc/changelog/changelog-9.21.13.rst
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
..
|
||||
.. See the COPYRIGHT file distributed with this work for additional
|
||||
.. information regarding copyright ownership.
|
||||
|
||||
BIND 9.21.13
|
||||
------------
|
||||
|
||||
.. note::
|
||||
|
||||
The BIND 9.21.13 release was withdrawn after the discovery of a
|
||||
regression in a security fix in it during pre-release testing.
|
||||
441
doc/changelog/changelog-9.21.14.rst
Normal file
441
doc/changelog/changelog-9.21.14.rst
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
..
|
||||
.. See the COPYRIGHT file distributed with this work for additional
|
||||
.. information regarding copyright ownership.
|
||||
|
||||
BIND 9.21.14
|
||||
------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- [CVE-2025-8677] DNSSEC validation fails if matching but invalid DNSKEY
|
||||
is found. ``1d851c23529``
|
||||
|
||||
Previously, if a matching but cryptographically invalid key was
|
||||
encountered during DNSSEC validation, the key was skipped and not
|
||||
counted towards validation failures. :iscman:`named` now treats such
|
||||
DNSSEC keys as hard failures and the DNSSEC validation fails
|
||||
immediately, instead of continuing with the next DNSKEYs in the RRset.
|
||||
|
||||
ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One
|
||||
Security and Privacy Laboratory at Nankai University for bringing this
|
||||
vulnerability to our attention. :gl:`#5343`
|
||||
|
||||
- [CVE-2025-40778] Address various spoofing attacks. ``7b95c382dbd``
|
||||
|
||||
Previously, several issues could be exploited to poison a DNS cache
|
||||
with spoofed records for zones which were not DNSSEC-signed or if the
|
||||
resolver was configured to not do DNSSEC validation. These issues were
|
||||
assigned CVE-2025-40778 and have now been fixed.
|
||||
|
||||
As an additional layer of protection, :iscman:`named` no longer
|
||||
accepts DNAME records or extraneous NS records in the AUTHORITY
|
||||
section unless these are received via spoofing-resistant transport
|
||||
(TCP, UDP with DNS cookies, TSIG, or SIG(0)).
|
||||
|
||||
ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin
|
||||
Duan from Tsinghua University for bringing this vulnerability to our
|
||||
attention. :gl:`#5414`
|
||||
|
||||
- [CVE-2025-40780] Cache-poisoning due to weak pseudo-random number
|
||||
generator. ``6876753c7cc``
|
||||
|
||||
It was discovered during research for an upcoming academic paper that
|
||||
a xoshiro128\*\* internal state can be recovered by an external 3rd
|
||||
party, allowing the prediction of UDP ports and DNS IDs in outgoing
|
||||
queries. This could lead to an attacker spoofing the DNS answers with
|
||||
great efficiency and poisoning the DNS cache.
|
||||
|
||||
The internal random generator has been changed to a cryptographically
|
||||
secure pseudo-random generator.
|
||||
|
||||
ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from
|
||||
Hebrew University of Jerusalem for bringing this vulnerability to our
|
||||
attention. :gl:`#5484`
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- Add extra tokens to the zone file name template. ``b449fa95005``
|
||||
|
||||
Extend the `$name`, `$view` and `$type` tokens (expanding into the
|
||||
zone name, zone's view name and type); the new following tokens are
|
||||
now also accepted:
|
||||
|
||||
- `$name` or `%s` is replaced with the zone name in lower case;
|
||||
- `$type` or `%t` is replaced with the zone type -- i.e., primary,
|
||||
secondary, etc);
|
||||
- `$view` or `%v` is replaced with the view name;
|
||||
- `$char1` or `%1` is replaced with the first character of the zone
|
||||
name;
|
||||
- `$char2` or `%2` is replaced with the second character of the zone
|
||||
name (or a dot if there is no second character);
|
||||
- `$char3` or `%3` is replaced with the third character of the zone
|
||||
name (or a dot if there is no third character);
|
||||
- `$label1` or `%z` is replaced with the toplevel domain of the zone
|
||||
(or a dot if it is the root zone);
|
||||
- `$label2` or `%y` is replaced with the next label under the toplevel
|
||||
domain (or a dot if there is no next label);
|
||||
- `$label3` or `%x` is replaced with the next-next label under the
|
||||
toplevel domain (or a dot if there is no next-next label).
|
||||
|
||||
:gl:`#85` :gl:`!10779`
|
||||
|
||||
- Add support for synthetic records. ``cefed841046``
|
||||
|
||||
Add a query plugin which, in "reverse" mode, enables the server to
|
||||
build a synthesized response to a PTR query when the PTR record
|
||||
requested is not found in the zone. The dynamically-built name is
|
||||
constructed from a static prefix (passed as a plugin parameter), the
|
||||
IP address (extracted from the query name) and a suffix (also passed
|
||||
as a plugin parameter). An `allow-synth` address-match list can be
|
||||
used to limit the network addresses for which the plugin may generate
|
||||
responses. The plugin can also be used in "forward" mode, to
|
||||
build synthesized A/AAAA records from names using the same format as
|
||||
the dynamically-built PTR names. The same parameters are used: the
|
||||
plugin will react and answer a query if the name matches the
|
||||
configured prefix and origin, and encodes an IP address that is within
|
||||
`allow-synth`. :gl:`#1586` :gl:`!10348`
|
||||
|
||||
- Support for zone-specific plugins. ``65fa5693572``
|
||||
|
||||
Query plugins can now be configured at the `zone` level, as well as
|
||||
globally or at the `view` level. A plugin's hooks are then called only
|
||||
while that specific zone's database is being used to answer a query.
|
||||
|
||||
This simplifies the implementation of plugins that are only needed for
|
||||
specific namespaces for which the server is authoritative. It can also
|
||||
enable quicker responses, since plugins will only be called when they
|
||||
are needed. :gl:`#5356` :gl:`!10483`
|
||||
|
||||
- Add dnssec-policy keys configuration check to named-checkconf.
|
||||
``23a79b42ea4``
|
||||
|
||||
A new option `-k` is added to `named-checkconf` that allows checking
|
||||
the `dnssec-policy` `keys` configuration against the configured key
|
||||
stores. If the found key files are not in sync with the given
|
||||
`dnssec-policy`, the check will fail.
|
||||
|
||||
This is useful to run before migrating to `dnssec-policy`. :gl:`#5486`
|
||||
:gl:`!10907`
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- Remove randomized RRset ordering. ``014a05a2781``
|
||||
|
||||
The rrset-order random doesn't offer uniform distribution of all
|
||||
permutations and it isn't superior to cyclic order in any way. Make
|
||||
the random ordering an alias to the cyclic ordering. :gl:`#5513`
|
||||
:gl:`!10912`
|
||||
|
||||
- Remove CHECK_FOR_GLUE_IN_ANSWER. ``7fa4cbedc50``
|
||||
|
||||
Macro CHECK_FOR_GLUE_IN_ANSWER is defined in `lib/dns/resolver.c`
|
||||
only, documented nowhere and not exposed as build configuration. This
|
||||
is valid at least for 9.21+, 9.20 and 9.18. Furthermore, it doesn't
|
||||
compile anymore on 9.21+ with -DCHECK_FOR_GLUE_IN_ANSWER=1.
|
||||
|
||||
Considering it is very unlikely that anyone build named with this,
|
||||
remove the code rather than fixing it. :gl:`#5538` :gl:`!11029`
|
||||
|
||||
- Remove orphan dns_loadmgr_t type. ``96855b5449f``
|
||||
|
||||
dns_loadmgr_t typedef is declared but never defines as well as a
|
||||
pointer of this type in named_server_t. Removing it. :gl:`!10974`
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Add a circular reference between slabtops for type and RRSIG(type)
|
||||
``a20c8fe74b0``
|
||||
|
||||
Previously, the slabtops for "type" and its signature was only loosely
|
||||
coupled and the headers could expire at different time (both TTL and
|
||||
LRU based expiry). Add a .related member to the slabtop that allows
|
||||
us to expire the headers in both related headers and also optimize the
|
||||
lookups because now both slabtops are looked up at the same time.
|
||||
:gl:`#3396` :gl:`!10985`
|
||||
|
||||
- Refactor view creation/configuration loops in dedicated functions.
|
||||
``cb0807be2be``
|
||||
|
||||
Refactor a bit of `apply_configuration` by extracting (into respective
|
||||
dedicated function) the logic to build the keystores list, the KASP
|
||||
list as well as creating the view/zones and configuring those. This is
|
||||
the next step of MR !10895 and !10901
|
||||
|
||||
While the code is extracted, some global variables has been changed
|
||||
into a function parameters which enable to have a clear view of the
|
||||
dependency of the function, typically, to know if it depends on local
|
||||
configuration object or runtime "production" object. The end goal (not
|
||||
in this MR, but later on) is to move as much as possible
|
||||
initialization logic outside of the exclusive mode.
|
||||
|
||||
As a first step, latest commits move the keystores list, KASP list and
|
||||
view/zones creation outside of the exclusive mode. (The view/zone
|
||||
configuration remain in exclusive mode for now, because of a
|
||||
dependency to the runtime "cachelist". This is the target of a next
|
||||
MR.
|
||||
|
||||
For the record; while moving the keystores list, KASP list and
|
||||
view/zone creation doesn't have a significant impact on the time the
|
||||
exclusive mode is taken (from my experiment on a 1M small zones
|
||||
instance); moving `configure_views` did have a _massive_ impact
|
||||
(basically, the time spend in the exclusive mode is then non
|
||||
calculable). Configuring views outside the exclusive mode needs more
|
||||
work, which will be done in future MRs. :gl:`#4673` :gl:`!10910`
|
||||
|
||||
- Add option to always build fuzz binaries. ``54c8252c6e2``
|
||||
|
||||
Currently the fuzzer binaries are only built when someone requests a
|
||||
fuzzer. This might cause us to inadvertently break fuzzing when
|
||||
changing function signatures. It also deviates with the behaviour we
|
||||
had with autotools, where the fuzz binaries were built with make test.
|
||||
|
||||
This commit splits the -Dfuzzing option into two: fuzzing, and
|
||||
fuzzing-backend. The fuzzing option controls whether the fuzzing
|
||||
binaries are built. The fuzzing-backend option controls which backend
|
||||
to use, and defaults to none. If the value none is used the binaries
|
||||
are built, but no backend is used or guaranteed, which means that the
|
||||
binaries might be non-functional. :gl:`#5526` :gl:`!10990`
|
||||
|
||||
- Rename cfg_aclconfctx_t variables to aclctx. ``0411142f826``
|
||||
|
||||
ACL configuration context variables are inconsistently named as
|
||||
`actx`, `ac`, or `aclconfctx`, which caused confusion during code
|
||||
reviews. This commit renames all `cfg_aclconfctx_t` variables to
|
||||
`aclctx`, which is short, consistent, and unambiguous. :gl:`#5530`
|
||||
:gl:`!11003`
|
||||
|
||||
- Provide more context when registering plugins. ``ac4cf4cce8d``
|
||||
|
||||
Add a new type, `ns_pluginregister_ctx_t`, which is passed to
|
||||
`plugin_register()` in place of the `source` parameter. The source
|
||||
value is now just part of the structure, which also holds a pointer to
|
||||
the zone origin if the plugin is loaded at a zone level. This
|
||||
provides more contextual information, enabling the plugin to make
|
||||
specific configuration decisions based on the name of the zone for
|
||||
which it is loaded. It's also flexible if more contextual data
|
||||
are needed in the future: add a new field to
|
||||
`ns_pluginregister_ctx_t`, and new plugins can use it without
|
||||
affecting compatibility with existing plugins. :gl:`#5533`
|
||||
:gl:`!11019`
|
||||
|
||||
- Add option to compile named with static linking and LTO.
|
||||
``b6971fb7240``
|
||||
|
||||
Statically linking lib{isc,dns,ns,cfg,isccc} and enabling LTO shows
|
||||
over 10% improvements on all almost measurements in perflab. That
|
||||
said, we can't use Meson's option for LTO since it would result in
|
||||
every binary being compiled with LTO and a great increase in compile
|
||||
time.
|
||||
|
||||
To work around it, we add a configuration option that enables LTO and
|
||||
static linking only for the `named` binary. :gl:`!10761`
|
||||
|
||||
- Convert slabtop and slabheader to use the cds list. ``7443ff330cc``
|
||||
|
||||
This is the first MR in series that aims to reduce the node locking by
|
||||
replacing the single-linked list of slabtop(s) and slabheader(s) with
|
||||
CDS linked list. This commit doesn't do anything else beyond
|
||||
replacing .next and .down links with the cds_list_head. The RCU
|
||||
semantics will be added later. :gl:`!10944`
|
||||
|
||||
- Make the database ownercase modifiable only via addrdataset()
|
||||
``dbc47312925``
|
||||
|
||||
Simplify the implementation around the database ownercase. Remove the
|
||||
dns_rdataset_setownercase() implementation for the slabheaders and
|
||||
only allow setting ownercase on rdatalists and rdatasets. The
|
||||
ownercase in the database can now be set only with
|
||||
dns_db_addrdataset() by passing rdataset with correctly set ownercase.
|
||||
:gl:`!10971`
|
||||
|
||||
- Minor refactor of dst code. ``f5af3e431b9``
|
||||
|
||||
Convert the defines to enums. Initialize the tags more explicitly and
|
||||
less ugly. :gl:`!11000`
|
||||
|
||||
- Rename ns_pluginregister_ctx_t into ns_pluginctx_t. ``029a7152bba``
|
||||
|
||||
The type `ns_pluginregister_ctx_t` was initially added to pass plugin
|
||||
contextual data when the plugin is registered, but this is also now
|
||||
passed into `plugin_check`. Furthermore, those various data are not
|
||||
specific to the registration in particular. Rename the type into
|
||||
`ns_pluginctx_t` for clarity. :gl:`!11035`
|
||||
|
||||
- Simplify nchildren count in isc_nm_listenudp. ``722ce92f107``
|
||||
|
||||
Slight simplification of the logic to define .nchildren listening UDP
|
||||
socket. :gl:`!10978`
|
||||
|
||||
- Squash the qpcache tree and nsec tries. ``22803b93e3f``
|
||||
|
||||
The dns_qpcache already had all the namespace changes needed to put
|
||||
the normal data and auxiliary NSEC data into a single tree. Remove
|
||||
the extra nsec QP trie and use the single QP trie for all the cache
|
||||
data. :gl:`!10975`
|
||||
|
||||
- Use lock-free hashtable for storing resolver fetch contexts.
|
||||
``0ac744ee4de``
|
||||
|
||||
Replace the locked hashmap with the lock-free hashtable from the RCU
|
||||
library and protect the fetch contexts against reuse by replacing the
|
||||
libisc reference counting with urcu_ref that can soft-fail in
|
||||
situation where the reference count is already zero. This allows us
|
||||
to easily skip re-using the fetch context if it is already in process
|
||||
of being destroyed. :gl:`!10653`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Use signer name when disabling DNSSEC algorithms. ``7e0318df857``
|
||||
|
||||
``disable-algorithms`` could cause DNSSEC validation failures when the
|
||||
parent zone was signed with the algorithms that were being disabled
|
||||
for the child zone. This has been fixed; `disable-algorithms` now
|
||||
works on a whole-of-zone basis.
|
||||
|
||||
If the zone's name is at or below the ``disable-algorithms`` name the
|
||||
algorithm is disabled for that zone, using deepest match when there
|
||||
are multiple ``disable-algorithms`` clauses. :gl:`#5165` :gl:`!10837`
|
||||
|
||||
- Rndc sign during ZSK rollover will now replace signatures.
|
||||
``6246f9d7cb1``
|
||||
|
||||
When performing a ZSK rollover, if the new DNSKEY is omnipresent, the
|
||||
:option:`rndc sign` command now signs the zone completely with the
|
||||
successor key, replacing all zone signatures from the predecessor key
|
||||
with new ones. :gl:`#5483` :gl:`!10867`
|
||||
|
||||
- Missing DNSSEC information when CD bit is set in query.
|
||||
``5fcc063ce9a``
|
||||
|
||||
The RRSIGs for glue records were not being cached correctly for CD=1
|
||||
queries. This has been fixed. :gl:`#5502` :gl:`!10938`
|
||||
|
||||
- Fix datarace between unlocking fctx lock and shuttingdown fctx.
|
||||
``2924f59cb3e``
|
||||
|
||||
There was a data race where new fetch response could be added to the
|
||||
fetch context after we unlock the fetch context and before we shut it
|
||||
down. This could cause assertion failure when fctx__done() was called
|
||||
with ISC_R_SUCCESS because there was originally no fetch response, but
|
||||
new fetch response without associated dataset was added before we had
|
||||
a chance to shutdown the fetch context. This manifested in the
|
||||
validated() callback, where cache_rrset() now returns ISC_R_SUCCESS
|
||||
instead of DNS_R_UNCHANGED when cache was not changed. However the
|
||||
data race was wrong on a general level.
|
||||
|
||||
Add new argument to fctx__done() that allows to call it with
|
||||
fctx->lock already acquired to prevent these data races. :gl:`#5507`
|
||||
:gl:`!10961`
|
||||
|
||||
- Add chroot check to meson.build. ``f2f2488bbe1``
|
||||
|
||||
The meson build procedure was not checking for the existence of the
|
||||
chroot function. This has been fixed. :gl:`#5519` :gl:`!10973`
|
||||
|
||||
- Preserve cache when reload fails and reload the server again.
|
||||
``33bcff46d30``
|
||||
|
||||
Fixes an issue where failing to reconfigure/reload the server would
|
||||
prevent to preserved the views caches on the subsequent server
|
||||
reconfiguration/reload. :gl:`#5523` :gl:`!10984`
|
||||
|
||||
- Apply_configuration: leave exclusive mode after viewlist cleanup.
|
||||
``5c53695bf32``
|
||||
|
||||
When a re-configuration fails, `apply_configuration` flows jump to a
|
||||
cleanup label and, at some point, leave the exclusive mode and cleanup
|
||||
the viewlist. It looks fine as the viewlist is at this point only
|
||||
locally known (if this is a configuration failure, this is the new
|
||||
view list, if this is a success, this is the old list which has been
|
||||
swapped out from the production list during the exclusive mode).
|
||||
|
||||
However, the view and zone initialization code enqueues job callbacks,
|
||||
for instance from `dns_zone_setsigninginterval` (but there are others
|
||||
cases) which will be called for the new views and zones after the
|
||||
exclusive mode is over.
|
||||
|
||||
Depending where the configuration fails, those views and zones can be
|
||||
half-configured, for instance a view might have an unfrozen resolver.
|
||||
Hence, leaving the exclusive mode before cleaning up those views ans
|
||||
zones will immediately called the previously enqueued callbacks and
|
||||
lead to this reconfiguration-failure crash stack:
|
||||
|
||||
``` isc_assertion_failed dns_resolver_createfetch do_keyfetch
|
||||
isc__async_cb ... uv_run loop_thread thread_body thread_run
|
||||
start_thread ... ```
|
||||
|
||||
To avoid the problem, the views are now cleaned up before leaving the
|
||||
exclusive mode (which also clean up the zones and enqueued callbacks).
|
||||
|
||||
As context, the bug was introduced by !10910 which moved the creation
|
||||
(not configuration) of the view outsides of the exclusive mode. This
|
||||
is a safe move (as at this point, the newly view are only known
|
||||
locally by `apply_configuration`) but the re-order was wrong regarding
|
||||
the point where the exclusive mode was ended (before the change, the
|
||||
exclusive mode as always ended before the new view are detached).
|
||||
:gl:`!11016`
|
||||
|
||||
- Check plugin config before registering. ``0e575d150fd``
|
||||
|
||||
In `named_config_parsefile()`, when checking the validity of
|
||||
`named.conf`, the checking of plugin correctness was deliberately
|
||||
postponed until the plugin is loaded and registered. However, the
|
||||
checking was never actually done: the `plugin_register()`
|
||||
implementation was called, but `plugin_check()` was not.
|
||||
|
||||
`ns_plugin_register()` (used by `named`) now calls the check function
|
||||
before the register function, and aborts if either one fails.
|
||||
`ns_plugin_check()` (used by `named-checkconf`) calls only the check
|
||||
function. :gl:`!11031`
|
||||
|
||||
- Clean up the dns_db API. ``29fc7850f1e``
|
||||
|
||||
Some of the API calls in `dns_db` were obsolete, and have been
|
||||
removed. Others were more complicated than necessary, and have been
|
||||
refactored to simplify. :gl:`!10830`
|
||||
|
||||
- Do not inline dns_zone_gethooktable. ``e7156fe57ae``
|
||||
|
||||
Since !10959 `dns_zone_gethooktable()` is only called once per query,
|
||||
and the suspicion (from perflab analysis) that this (simple, as just
|
||||
returning a pointer) call was slowing things down (perhaps because of
|
||||
code locality reasons?) doesn't matter anymore. So even if !10959
|
||||
inlined it, it shouldn't matter anymore. :gl:`!10962`
|
||||
|
||||
- Fix detection of whether node is active in find_wildcard()
|
||||
``f717bad1086``
|
||||
|
||||
The current code would fail during the write transaction. The first
|
||||
header would not match the search->serial and the node might be
|
||||
incorrectly detected as inactive. :gl:`!10972`
|
||||
|
||||
- Hookasyncctx renaming. ``6ec65c3d1ad``
|
||||
|
||||
The field `ns_hookasync_t` was initially named `hook_actx` and wrongly
|
||||
renamed `hook_aclctx` during a mass-renaming of various names for the
|
||||
config acl context into a consistent `aclctx` name (see !11003). Of
|
||||
course this is wrong as `ns_hookasync_t` has nothing to do with ACL
|
||||
but about _async_ context. This commit fixes the mistake by renaming
|
||||
this field `hookasyncctx` :gl:`!11021`
|
||||
|
||||
- Minimize zone hooktable lookups. ``89039e0d78e``
|
||||
|
||||
Merging !10483 caused a performance regression because the zone
|
||||
hooktable had to be looked up every time a hook point was reached,
|
||||
even if no zone plugins were configured. We now look up the zone
|
||||
hooktable when a zone is attached to the query context, and keep a
|
||||
pointer to it until the qctx is destroyed. :gl:`!10959`
|
||||
|
||||
|
||||
18
doc/notes/notes-9.21.13.rst
Normal file
18
doc/notes/notes-9.21.13.rst
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
..
|
||||
.. See the COPYRIGHT file distributed with this work for additional
|
||||
.. information regarding copyright ownership.
|
||||
|
||||
Notes for BIND 9.21.13
|
||||
----------------------
|
||||
|
||||
.. note::
|
||||
|
||||
The BIND 9.21.13 release was withdrawn after the discovery of a
|
||||
regression in a security fix in it during pre-release testing.
|
||||
158
doc/notes/notes-9.21.14.rst
Normal file
158
doc/notes/notes-9.21.14.rst
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
..
|
||||
.. See the COPYRIGHT file distributed with this work for additional
|
||||
.. information regarding copyright ownership.
|
||||
|
||||
Notes for BIND 9.21.14
|
||||
----------------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- DNSSEC validation fails if matching but invalid DNSKEY is found.
|
||||
:cve:`2025-8677`
|
||||
|
||||
Previously, if a matching but cryptographically invalid key was
|
||||
encountered during DNSSEC validation, the key was skipped and not
|
||||
counted towards validation failures. :iscman:`named` now treats such
|
||||
DNSSEC keys as hard failures and the DNSSEC validation fails
|
||||
immediately, instead of continuing with the next DNSKEYs in the RRset.
|
||||
|
||||
ISC would like to thank Zuyao Xu and Xiang Li from the All-in-One
|
||||
Security and Privacy Laboratory at Nankai University for bringing this
|
||||
vulnerability to our attention. :gl:`#5343`
|
||||
|
||||
- Address various spoofing attacks. :cve:`2025-40778`
|
||||
|
||||
Previously, several issues could be exploited to poison a DNS cache
|
||||
with spoofed records for zones which were not DNSSEC-signed or if the
|
||||
resolver was configured to not do DNSSEC validation. These issues were
|
||||
assigned CVE-2025-40778 and have now been fixed.
|
||||
|
||||
As an additional layer of protection, :iscman:`named` no longer
|
||||
accepts DNAME records or extraneous NS records in the AUTHORITY
|
||||
section unless these are received via spoofing-resistant transport
|
||||
(TCP, UDP with DNS cookies, TSIG, or SIG(0)).
|
||||
|
||||
ISC would like to thank Yuxiao Wu, Yunyi Zhang, Baojun Liu, and Haixin
|
||||
Duan from Tsinghua University for bringing this vulnerability to our
|
||||
attention. :gl:`#5414`
|
||||
|
||||
- Cache-poisoning due to weak pseudo-random number generator.
|
||||
:cve:`2025-40780`
|
||||
|
||||
It was discovered during research for an upcoming academic paper that
|
||||
a xoshiro128\*\* internal state can be recovered by an external 3rd
|
||||
party, allowing the prediction of UDP ports and DNS IDs in outgoing
|
||||
queries. This could lead to an attacker spoofing the DNS answers with
|
||||
great efficiency and poisoning the DNS cache.
|
||||
|
||||
The internal random generator has been changed to a cryptographically
|
||||
secure pseudo-random generator.
|
||||
|
||||
ISC would like to thank Prof. Amit Klein and Omer Ben Simhon from
|
||||
Hebrew University of Jerusalem for bringing this vulnerability to our
|
||||
attention. :gl:`#5484`
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- Add :any:`dnssec-policy` keys configuration check to
|
||||
:iscman:`named-checkconf`.
|
||||
|
||||
A new option :option:`-k <named-checkconf -k>` was added to
|
||||
:iscman:`named-checkconf` that allows checking the
|
||||
:any:`dnssec-policy` :any:`keys` configuration against the configured
|
||||
key stores. If the found key files are not in sync with the given
|
||||
:any:`dnssec-policy`, the check will fail.
|
||||
|
||||
This is useful to run before migrating to :any:`dnssec-policy`.
|
||||
:gl:`#5486`
|
||||
|
||||
- Add support for synthetic records.
|
||||
|
||||
Add :iscman:`synthrecord` query plugin which, in "reverse" mode,
|
||||
enables the server to build a synthesized response to a PTR query when
|
||||
the PTR record requested is not found in the zone.
|
||||
|
||||
The dynamically built name is constructed from a static prefix (passed
|
||||
as a plugin parameter), the IP address (extracted from the query
|
||||
name), and a suffix (also passed as a plugin parameter). An
|
||||
``allow-synth`` address-match list can be used to limit the network
|
||||
addresses for which the plugin may generate responses.
|
||||
|
||||
The plugin can also be used in "forward" mode, to build synthesized
|
||||
A/AAAA records from names using the same format as the dynamically
|
||||
built PTR names. The same parameters are used: the plugin reacts and
|
||||
answers a query if the name matches the configured prefix and origin,
|
||||
and encodes an IP address that is within ``allow-synth``. :gl:`#1586`
|
||||
|
||||
- Support for zone-specific plugins.
|
||||
|
||||
Query plugins can now be configured at the :any:`zone` level, as well
|
||||
as globally or at the :any:`view` level. A plugin's hooks are then
|
||||
called only while that specific zone's database is being used to
|
||||
answer a query.
|
||||
|
||||
This simplifies the implementation of plugins that are only needed for
|
||||
specific namespaces for which the server is authoritative. It can also
|
||||
enable quicker responses, since plugins are only called when they are
|
||||
needed. :gl:`#5356`
|
||||
|
||||
- Support for additional tokens in the zone file name template.
|
||||
|
||||
See :any:`file` for a complete list of currently supported tokens.
|
||||
:gl:`#85`
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- Remove randomized RRset ordering.
|
||||
|
||||
:any:`rrset-order` ``random`` did not offer uniform distribution of
|
||||
all permutations and it was not superior to the ``cyclic`` order in
|
||||
any way. ``random`` ordering is now an alias for ``cyclic`` ordering.
|
||||
:gl:`#5513`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Missing DNSSEC information when CD bit is set in query.
|
||||
|
||||
The RRSIGs for glue records were not being cached correctly for CD=1
|
||||
queries. This has been fixed. :gl:`#5502`
|
||||
|
||||
- :option:`rndc sign` during ZSK rollover will now replace signatures.
|
||||
|
||||
When performing a ZSK rollover, if the new DNSKEY is omnipresent, the
|
||||
:option:`rndc sign` command now signs the zone completely with the
|
||||
successor key, replacing all zone signatures from the predecessor key
|
||||
with new ones. :gl:`#5483`
|
||||
|
||||
- Add a check for ``chroot()`` to the build system.
|
||||
|
||||
The Meson build procedure was not checking for the existence of the
|
||||
``chroot()`` function. This has been fixed. :gl:`#5519`
|
||||
|
||||
- Use signer name when disabling DNSSEC algorithms.
|
||||
|
||||
:any:`disable-algorithms` could cause DNSSEC validation failures when
|
||||
the parent zone was signed with the algorithms that were being
|
||||
disabled for the child zone. This has been fixed;
|
||||
:any:`disable-algorithms` now works on a whole-of-zone basis.
|
||||
|
||||
If the zone's name is at or below the :any:`disable-algorithms` name
|
||||
the algorithm is disabled for that zone, using deepest match when
|
||||
there are multiple :any:`disable-algorithms` clauses. :gl:`#5165`
|
||||
|
||||
- Preserve cache when reload fails and reload the server again.
|
||||
|
||||
This fixes an issue where failing to reconfigure/reload the server
|
||||
would fail to preserve the views' caches for subsequent server
|
||||
reconfigurations/reloads. :gl:`#5523`
|
||||
|
|
@ -261,6 +261,7 @@ struct dns_message {
|
|||
unsigned int rdclass_set : 1; /* 14 */
|
||||
unsigned int fuzzing : 1; /* 15 */
|
||||
unsigned int free_pools : 1; /* 16 */
|
||||
unsigned int has_dname : 1; /* 17 */
|
||||
unsigned int : 0;
|
||||
|
||||
unsigned int opt_reserved;
|
||||
|
|
@ -1456,3 +1457,10 @@ dns_message_createpools(isc_mem_t *mctx, isc_mempool_t **namepoolp,
|
|||
isc_mempool_t **rdspoolp);
|
||||
void
|
||||
dns_message_destroypools(isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp);
|
||||
|
||||
bool
|
||||
dns_message_hasdname(dns_message_t *msg);
|
||||
/*%<
|
||||
* Return whether a DNAME was detected in the ANSWER section of a QUERY
|
||||
* message when it was parsed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -442,6 +442,7 @@ msginit(dns_message_t *m) {
|
|||
m->cc_bad = 0;
|
||||
m->tkey = 0;
|
||||
m->rdclass_set = 0;
|
||||
m->has_dname = 0;
|
||||
m->querytsig = NULL;
|
||||
m->indent.string = "\t";
|
||||
m->indent.count = 0;
|
||||
|
|
@ -1492,6 +1493,11 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
|
|||
*/
|
||||
msg->tsigname->attributes.nocompress = true;
|
||||
free_name = false;
|
||||
} else if (rdtype == dns_rdatatype_dname &&
|
||||
sectionid == DNS_SECTION_ANSWER &&
|
||||
msg->opcode == dns_opcode_query)
|
||||
{
|
||||
msg->has_dname = 1;
|
||||
}
|
||||
rdataset = NULL;
|
||||
|
||||
|
|
@ -5081,3 +5087,9 @@ dns_message_destroypools(isc_mempool_t **namepoolp, isc_mempool_t **rdspoolp) {
|
|||
isc_mempool_destroy(rdspoolp);
|
||||
isc_mempool_destroy(namepoolp);
|
||||
}
|
||||
|
||||
bool
|
||||
dns_message_hasdname(dns_message_t *msg) {
|
||||
REQUIRE(DNS_MESSAGE_VALID(msg));
|
||||
return msg->has_dname;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -854,6 +854,7 @@ typedef struct respctx {
|
|||
bool get_nameservers; /* get a new NS rrset at
|
||||
* zone cut? */
|
||||
bool resend; /* resend this query? */
|
||||
bool secured; /* message was signed or had a valid cookie */
|
||||
bool nextitem; /* invalid response; keep
|
||||
* listening for the correct one */
|
||||
bool truncated; /* response was truncated */
|
||||
|
|
@ -6357,7 +6358,8 @@ mark_related(dns_name_t *name, dns_rdataset_t *rdataset, bool external,
|
|||
* locally served zone.
|
||||
*/
|
||||
static inline bool
|
||||
name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) {
|
||||
name_external(const dns_name_t *name, dns_rdatatype_t type, respctx_t *rctx) {
|
||||
fetchctx_t *fctx = rctx->fctx;
|
||||
isc_result_t result;
|
||||
dns_forwarders_t *forwarders = NULL;
|
||||
dns_name_t *apex = NULL;
|
||||
|
|
@ -6367,7 +6369,7 @@ name_external(const dns_name_t *name, dns_rdatatype_t type, fetchctx_t *fctx) {
|
|||
dns_namereln_t rel;
|
||||
|
||||
apex = (ISDUALSTACK(fctx->addrinfo) || !ISFORWARDER(fctx->addrinfo))
|
||||
? fctx->domain
|
||||
? rctx->ns_name != NULL ? rctx->ns_name : fctx->domain
|
||||
: fctx->fwdname;
|
||||
|
||||
/*
|
||||
|
|
@ -6464,7 +6466,7 @@ check_section(void *arg, const dns_name_t *addname, dns_rdatatype_t type,
|
|||
result = dns_message_findname(rctx->query->rmessage, section, addname,
|
||||
dns_rdatatype_any, 0, &name, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
external = name_external(name, type, fctx);
|
||||
external = name_external(name, type, rctx);
|
||||
if (type == dns_rdatatype_a) {
|
||||
ISC_LIST_FOREACH(name->list, rdataset, link) {
|
||||
if (dns_rdatatype_issig(rdataset->type)) {
|
||||
|
|
@ -7275,13 +7277,10 @@ rctx_cookiecheck(respctx_t *rctx) {
|
|||
resquery_t *query = rctx->query;
|
||||
|
||||
/*
|
||||
* If TSIG signed, sent via TCP, or cookie present,
|
||||
* no need to continue.
|
||||
* If the message was secured or TCP is already in the
|
||||
* retry flags, no need to continue.
|
||||
*/
|
||||
if (dns_message_gettsig(query->rmessage, NULL) != NULL ||
|
||||
query->rmessage->cc_ok || query->rmessage->cc_bad ||
|
||||
(rctx->retryopts & DNS_FETCHOPT_TCP) != 0)
|
||||
{
|
||||
if (rctx->secured || (rctx->retryopts & DNS_FETCHOPT_TCP) != 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -7344,6 +7343,47 @@ rctx_cookiecheck(respctx_t *rctx) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static bool
|
||||
rctx_need_tcpretry(respctx_t *rctx) {
|
||||
resquery_t *query = rctx->query;
|
||||
if ((rctx->retryopts & DNS_FETCHOPT_TCP) != 0) {
|
||||
/* TCP is already in the retry flags */
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the message was secured, no need to continue.
|
||||
*/
|
||||
if (rctx->secured) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently the only extra reason why we might need to
|
||||
* retry a UDP response over TCP is a DNAME in the message.
|
||||
*/
|
||||
if (dns_message_hasdname(query->rmessage)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
rctx_tcpretry(respctx_t *rctx) {
|
||||
/*
|
||||
* Do we need to retry a UDP response over TCP?
|
||||
*/
|
||||
if (rctx_need_tcpretry(rctx)) {
|
||||
rctx->retryopts |= DNS_FETCHOPT_TCP;
|
||||
rctx->resend = true;
|
||||
rctx_done(rctx, ISC_R_SUCCESS);
|
||||
return ISC_R_COMPLETE;
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
resquery_response_continue(void *arg, isc_result_t result) {
|
||||
respctx_t *rctx = arg;
|
||||
|
|
@ -7363,6 +7403,17 @@ resquery_response_continue(void *arg, isc_result_t result) {
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember whether this message was signed or had a
|
||||
* valid client cookie; if not, we may need to retry over
|
||||
* TCP later.
|
||||
*/
|
||||
if (query->rmessage->cc_ok || query->rmessage->tsig != NULL ||
|
||||
query->rmessage->sig0 != NULL)
|
||||
{
|
||||
rctx->secured = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The dispatcher should ensure we only get responses with QR
|
||||
* set.
|
||||
|
|
@ -7370,13 +7421,21 @@ resquery_response_continue(void *arg, isc_result_t result) {
|
|||
INSIST((query->rmessage->flags & DNS_MESSAGEFLAG_QR) != 0);
|
||||
|
||||
/*
|
||||
* Check for cookie issues.
|
||||
* Check for cookie issues; if found, maybe retry over TCP.
|
||||
*/
|
||||
result = rctx_cookiecheck(rctx);
|
||||
if (result == ISC_R_COMPLETE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we need to retry over TCP for some other reason.
|
||||
*/
|
||||
result = rctx_tcpretry(rctx);
|
||||
if (result == ISC_R_COMPLETE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for EDNS issues.
|
||||
*/
|
||||
|
|
@ -8089,8 +8148,8 @@ rctx_answer_positive(respctx_t *rctx) {
|
|||
}
|
||||
|
||||
/*
|
||||
* Cache records in the authority section, if
|
||||
* there are any suitable for caching.
|
||||
* Cache records in the authority section, if there are
|
||||
* any suitable for caching.
|
||||
*/
|
||||
rctx_authority_positive(rctx);
|
||||
|
||||
|
|
@ -8150,7 +8209,7 @@ rctx_answer_scan(respctx_t *rctx) {
|
|||
/*
|
||||
* Don't accept DNAME from parent namespace.
|
||||
*/
|
||||
if (name_external(name, dns_rdatatype_dname, fctx)) {
|
||||
if (name_external(name, dns_rdatatype_dname, rctx)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -8428,22 +8487,29 @@ rctx_answer_dname(respctx_t *rctx) {
|
|||
|
||||
/*
|
||||
* rctx_authority_positive():
|
||||
* Examine the records in the authority section (if there are any) for a
|
||||
* positive answer. We expect the names for all rdatasets in this
|
||||
* section to be subdomains of the domain being queried; any that are
|
||||
* not are skipped. We expect to find only *one* owner name; any names
|
||||
* after the first one processed are ignored. We expect to find only
|
||||
* rdatasets of type NS, RRSIG, or SIG; all others are ignored. Whatever
|
||||
* remains can be cached at trust level authauthority or additional
|
||||
* (depending on whether the AA bit was set on the answer).
|
||||
* If a positive answer was received over TCP or secured with a cookie
|
||||
* or TSIG, examine the authority section. We expect names for all
|
||||
* rdatasets in this section to be subdomains of the domain being queried;
|
||||
* any that are not are skipped. We expect to find only *one* owner name;
|
||||
* any names after the first one processed are ignored. We expect to find
|
||||
* only rdatasets of type NS; all others are ignored. Whatever remains can
|
||||
* be cached at trust level authauthority or additional (depending on
|
||||
* whether the AA bit was set on the answer).
|
||||
*/
|
||||
static void
|
||||
rctx_authority_positive(respctx_t *rctx) {
|
||||
fetchctx_t *fctx = rctx->fctx;
|
||||
|
||||
dns_message_t *msg = rctx->query->rmessage;
|
||||
|
||||
/* If it's spoofable, don't cache it. */
|
||||
if (!rctx->secured && (rctx->query->options & DNS_FETCHOPT_TCP) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MSG_SECTION_FOREACH(msg, DNS_SECTION_AUTHORITY, name) {
|
||||
if (!name_external(name, dns_rdatatype_ns, fctx)) {
|
||||
if (!name_external(name, dns_rdatatype_ns, rctx) &&
|
||||
dns_name_issubdomain(fctx->name, name))
|
||||
{
|
||||
/*
|
||||
* We expect to find NS or SIG NS rdatasets, and
|
||||
* nothing else.
|
||||
|
|
|
|||
|
|
@ -366,6 +366,12 @@ trynsec3:
|
|||
static void
|
||||
resume_answer_with_key_done(void *arg);
|
||||
|
||||
static bool
|
||||
over_max_fails(dns_validator_t *val);
|
||||
|
||||
static void
|
||||
consume_validation_fail(dns_validator_t *val);
|
||||
|
||||
static void
|
||||
resume_answer_with_key(void *arg) {
|
||||
dns_validator_t *val = arg;
|
||||
|
|
@ -374,6 +380,13 @@ resume_answer_with_key(void *arg) {
|
|||
isc_result_t result = select_signing_key(val, rdataset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
val->keyset = &val->frdataset;
|
||||
} else if (result != ISC_R_NOTFOUND) {
|
||||
val->result = result;
|
||||
if (over_max_fails(val)) {
|
||||
INSIST(val->key == NULL);
|
||||
val->result = ISC_R_QUOTA;
|
||||
}
|
||||
consume_validation_fail(val);
|
||||
}
|
||||
|
||||
(void)validate_async_run(val, resume_answer_with_key_done);
|
||||
|
|
@ -383,6 +396,16 @@ static void
|
|||
resume_answer_with_key_done(void *arg) {
|
||||
dns_validator_t *val = arg;
|
||||
|
||||
switch (val->result) {
|
||||
case ISC_R_CANCELED: /* Validation was canceled */
|
||||
case ISC_R_SHUTTINGDOWN: /* Server shutting down */
|
||||
case ISC_R_QUOTA: /* Validation fails quota reached */
|
||||
dns_validator_cancel(val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
resume_answer(val);
|
||||
}
|
||||
|
||||
|
|
@ -1047,9 +1070,6 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
|
|||
val->key = NULL;
|
||||
result = dns_rdataset_next(rdataset);
|
||||
}
|
||||
if (result == ISC_R_NOMORE) {
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) {
|
||||
dns_rdata_rrsig_t *siginfo = val->siginfo;
|
||||
|
|
@ -1072,18 +1092,11 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
|
|||
continue;
|
||||
}
|
||||
|
||||
result = dns_dnssec_keyfromrdata(&siginfo->signer, &rdata,
|
||||
val->view->mctx, &val->key);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/* found the key we wanted */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result == ISC_R_NOMORE) {
|
||||
result = ISC_R_NOTFOUND;
|
||||
return dns_dnssec_keyfromrdata(&siginfo->signer, &rdata,
|
||||
val->view->mctx, &val->key);
|
||||
}
|
||||
|
||||
return result;
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -1311,6 +1324,7 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
dns_name_t *name = val->name;
|
||||
isc_result_t result;
|
||||
isc_mem_t *mctx = val->view->mctx;
|
||||
bool match = false;
|
||||
|
||||
if (rdataset->type != dns_rdatatype_dnskey) {
|
||||
return DNS_R_NOKEYMATCH;
|
||||
|
|
@ -1344,17 +1358,16 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
|
||||
/*
|
||||
* If the REVOKE bit is not set we have a
|
||||
* theoretically self signed DNSKEY RRset.
|
||||
* This will be verified later.
|
||||
* theoretically self-signed DNSKEY RRset;
|
||||
* this will be verified later.
|
||||
*
|
||||
* We don't return the answer yet, though,
|
||||
* because we need to check the remaining keys
|
||||
* and possbly remove them if they're revoked.
|
||||
*/
|
||||
if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx,
|
||||
&dstkey);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
continue;
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1364,6 +1377,20 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
if (DNS_TRUST_PENDING(rdataset->trust) &&
|
||||
dns_view_istrusted(val->view, name, &key))
|
||||
{
|
||||
result = dns_dnssec_keyfromrdata(
|
||||
name, &keyrdata, mctx, &dstkey);
|
||||
if (result == DST_R_UNSUPPORTEDALG) {
|
||||
/* don't count towards max fails */
|
||||
break; /* continue with next key */
|
||||
} else if (result != ISC_R_SUCCESS) {
|
||||
consume_validation(val);
|
||||
if (over_max_fails(val)) {
|
||||
return ISC_R_QUOTA;
|
||||
}
|
||||
consume_validation_fail(val);
|
||||
break; /* continue with next key */
|
||||
}
|
||||
|
||||
if (over_max_validations(val)) {
|
||||
dst_key_free(&dstkey);
|
||||
return ISC_R_QUOTA;
|
||||
|
|
@ -1397,6 +1424,8 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
consume_validation_fail(val);
|
||||
break;
|
||||
}
|
||||
|
||||
dst_key_free(&dstkey);
|
||||
} else if (rdataset->trust >= dns_trust_secure) {
|
||||
/*
|
||||
* We trust this RRset so if the key is
|
||||
|
|
@ -1404,12 +1433,14 @@ selfsigned_dnskey(dns_validator_t *val) {
|
|||
*/
|
||||
dns_view_untrust(val->view, name, &key);
|
||||
}
|
||||
|
||||
dst_key_free(&dstkey);
|
||||
}
|
||||
}
|
||||
|
||||
return DNS_R_NOKEYMATCH;
|
||||
if (!match) {
|
||||
return DNS_R_NOKEYMATCH;
|
||||
}
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*%
|
||||
|
|
@ -1594,7 +1625,7 @@ validate_answer_signing_key_done(void *arg);
|
|||
static void
|
||||
validate_answer_signing_key(void *arg) {
|
||||
dns_validator_t *val = arg;
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
isc_result_t result;
|
||||
|
||||
if (CANCELED(val) || CANCELING(val)) {
|
||||
val->result = ISC_R_CANCELED;
|
||||
|
|
@ -1617,15 +1648,21 @@ validate_answer_signing_key(void *arg) {
|
|||
default:
|
||||
/* Select next signing key */
|
||||
result = select_signing_key(val, val->keyset);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
INSIST(val->key != NULL);
|
||||
} else if (result == ISC_R_NOTFOUND) {
|
||||
INSIST(val->key == NULL);
|
||||
} else {
|
||||
val->result = result;
|
||||
if (over_max_fails(val)) {
|
||||
INSIST(val->key == NULL);
|
||||
val->result = ISC_R_QUOTA;
|
||||
}
|
||||
consume_validation_fail(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
INSIST(val->key != NULL);
|
||||
} else {
|
||||
INSIST(val->key == NULL);
|
||||
}
|
||||
|
||||
(void)validate_async_run(val, validate_answer_signing_key_done);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <isc/entropy.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
#include <isc/uv.h>
|
||||
|
||||
void
|
||||
isc_entropy_get(void *buf, size_t buflen) {
|
||||
int r = uv_random(NULL, NULL, buf, buflen, 0, NULL);
|
||||
|
||||
UV_RUNTIME_CHECK(uv_random, r);
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#include <isc/ascii.h>
|
||||
#include <isc/entropy.h>
|
||||
#include <isc/hash.h> /* IWYU pragma: keep */
|
||||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
|
|
@ -35,7 +34,7 @@ isc__hash_initialize(void) {
|
|||
*/
|
||||
uint8_t key[16] = { 1 };
|
||||
#if !FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
isc_entropy_get(key, sizeof(key));
|
||||
isc_random_buf(key, sizeof(key));
|
||||
#endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
|
||||
STATIC_ASSERT(sizeof(key) >= sizeof(isc_hash_key),
|
||||
"sizeof(key) < sizeof(isc_hash_key)");
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <isc/ascii.h>
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/entropy.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/hashmap.h>
|
||||
#include <isc/magic.h>
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*! \file isc/entropy.h
|
||||
* \brief Implements wrapper around CSPRNG cryptographic library calls
|
||||
* for getting cryptographically secure pseudo-random numbers.
|
||||
*
|
||||
* Uses synchronous version of uv_random().
|
||||
*/
|
||||
|
||||
void
|
||||
isc_entropy_get(void *buf, size_t buflen);
|
||||
/*!<
|
||||
* \brief Get cryptographically-secure pseudo-random data.
|
||||
*/
|
||||
|
|
@ -15,12 +15,16 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <isc/random.h>
|
||||
|
||||
/*! \file isc/nonce.h
|
||||
* \brief Provides a function for generating an arbitrarily long nonce.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_nonce_buf(void *buf, size_t buflen);
|
||||
static inline void
|
||||
isc_nonce_buf(void *buf, size_t buflen) {
|
||||
isc_random_buf(buf, buflen);
|
||||
}
|
||||
/*!<
|
||||
* Fill 'buf', up to 'buflen' bytes, with random data from the
|
||||
* crypto provider's random function.
|
||||
|
|
|
|||
|
|
@ -19,23 +19,16 @@
|
|||
#include <isc/types.h>
|
||||
|
||||
/*! \file isc/random.h
|
||||
* \brief Implements wrapper around a non-cryptographically secure
|
||||
* \brief Implements wrapper around a cryptographically secure
|
||||
* pseudo-random number generator.
|
||||
*
|
||||
*/
|
||||
|
||||
uint8_t
|
||||
isc_random8(void);
|
||||
/*!<
|
||||
* \brief Returns a single 8-bit random value.
|
||||
*/
|
||||
|
||||
uint16_t
|
||||
isc_random16(void);
|
||||
/*!<
|
||||
* \brief Returns a single 16-bit random value.
|
||||
*/
|
||||
|
||||
#if HAVE_ARC4RANDOM && !defined(__linux__)
|
||||
#define isc_random32() arc4random()
|
||||
#define isc_random_buf(buf, buflen) arc4random_buf(buf, buflen)
|
||||
#define isc_random_uniform(upper_bound) arc4random_uniform(upper_bound)
|
||||
#else /* HAVE_ARC4RANDOM && !defined(__linux__) */
|
||||
uint32_t
|
||||
isc_random32(void);
|
||||
/*!<
|
||||
|
|
@ -64,3 +57,21 @@ isc_random_uniform(uint32_t upper_bound);
|
|||
* resample is very small when the upper_bound is small, rising to 0.5
|
||||
* when upper_bound is UINT32_MAX/2.
|
||||
*/
|
||||
|
||||
#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */
|
||||
|
||||
static inline uint8_t
|
||||
isc_random8(void) {
|
||||
return (uint8_t)isc_random32();
|
||||
}
|
||||
/*!<
|
||||
* \brief Returns a single 8-bit random value.
|
||||
*/
|
||||
|
||||
static inline uint16_t
|
||||
isc_random16(void) {
|
||||
return (uint16_t)isc_random32();
|
||||
}
|
||||
/*!<
|
||||
* \brief Returns a single 16-bit random value.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ isc_srcset.add(
|
|||
'counter.c',
|
||||
'crypto.c',
|
||||
'dir.c',
|
||||
'entropy.c',
|
||||
'errno.c',
|
||||
'errno2result.c',
|
||||
'error.c',
|
||||
|
|
@ -106,7 +105,6 @@ isc_srcset.add(
|
|||
'net.c',
|
||||
'netaddr.c',
|
||||
'netscope.c',
|
||||
'nonce.c',
|
||||
'openssl_shim.c',
|
||||
'os.c',
|
||||
'parseint.c',
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* See the COPYRIGHT file distributed with this work for additional
|
||||
* information regarding copyright ownership.
|
||||
*/
|
||||
|
||||
#include <isc/entropy.h>
|
||||
#include <isc/nonce.h>
|
||||
|
||||
void
|
||||
isc_nonce_buf(void *buf, size_t buflen) {
|
||||
isc_entropy_get(buf, buflen);
|
||||
}
|
||||
135
lib/isc/random.c
135
lib/isc/random.c
|
|
@ -30,126 +30,55 @@
|
|||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#if !HAVE_ARC4RANDOM || defined(__linux__)
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <isc/entropy.h>
|
||||
#include <isc/os.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/thread.h>
|
||||
#include <isc/types.h>
|
||||
#include <isc/util.h>
|
||||
#include <isc/uv.h>
|
||||
|
||||
/*
|
||||
* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
||||
*
|
||||
* To the extent possible under law, the author has dedicated all
|
||||
* copyright and related and neighboring rights to this software to the
|
||||
* public domain worldwide. This software is distributed without any
|
||||
* warranty.
|
||||
*
|
||||
* See <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
#define ISC_RANDOM_BUFSIZE (ISC_OS_CACHELINE_SIZE / sizeof(uint32_t))
|
||||
|
||||
/*
|
||||
* This is xoshiro128** 1.0, our 32-bit all-purpose, rock-solid generator.
|
||||
* It has excellent (sub-ns) speed, a state size (128 bits) that is large
|
||||
* enough for mild parallelism, and it passes all tests we are aware of.
|
||||
*
|
||||
* The state must be seeded so that it is not everywhere zero.
|
||||
*/
|
||||
|
||||
static thread_local bool initialized = false;
|
||||
static thread_local uint32_t seed[4] = { 0 };
|
||||
|
||||
static uint32_t
|
||||
rotl(const uint32_t x, int k) {
|
||||
return (x << k) | (x >> (32 - k));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
next(void) {
|
||||
uint32_t result_starstar, t;
|
||||
|
||||
result_starstar = rotl(seed[0] * 5, 7) * 9;
|
||||
t = seed[1] << 9;
|
||||
|
||||
seed[2] ^= seed[0];
|
||||
seed[3] ^= seed[1];
|
||||
seed[1] ^= seed[2];
|
||||
seed[0] ^= seed[3];
|
||||
|
||||
seed[2] ^= t;
|
||||
|
||||
seed[3] = rotl(seed[3], 11);
|
||||
|
||||
return result_starstar;
|
||||
}
|
||||
|
||||
static void
|
||||
isc__random_initialize(void) {
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/*
|
||||
* A fixed seed helps with problem reproduction when fuzzing. It must be
|
||||
* non-zero else xoshiro128starstar will generate only zeroes, and the
|
||||
* first result needs to be non-zero as expected by random_test.c
|
||||
*/
|
||||
seed[0] = 1;
|
||||
#endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
|
||||
|
||||
while (seed[0] == 0 && seed[1] == 0 && seed[2] == 0 && seed[3] == 0) {
|
||||
isc_entropy_get(seed, sizeof(seed));
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
isc_random8(void) {
|
||||
isc__random_initialize();
|
||||
return (uint8_t)next();
|
||||
}
|
||||
|
||||
uint16_t
|
||||
isc_random16(void) {
|
||||
isc__random_initialize();
|
||||
return (uint16_t)next();
|
||||
}
|
||||
thread_local static uint32_t isc__random_pool[ISC_RANDOM_BUFSIZE];
|
||||
thread_local static size_t isc__random_pos = ISC_RANDOM_BUFSIZE;
|
||||
|
||||
uint32_t
|
||||
isc_random32(void) {
|
||||
isc__random_initialize();
|
||||
return next();
|
||||
#if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/*
|
||||
* A fixed stream of numbers helps with problem reproduction when
|
||||
* fuzzing. The first result needs to be non-zero as expected by
|
||||
* random_test.c (it starts with ISC_RANDOM_BUFSIZE, see above).
|
||||
*/
|
||||
return (uint32_t)(isc__random_pos++);
|
||||
#endif /* if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
|
||||
|
||||
if (isc__random_pos == ISC_RANDOM_BUFSIZE) {
|
||||
isc_random_buf(isc__random_pool, sizeof(isc__random_pool));
|
||||
isc__random_pos = 0;
|
||||
}
|
||||
|
||||
return isc__random_pool[isc__random_pos++];
|
||||
}
|
||||
|
||||
void
|
||||
isc_random_buf(void *buf, size_t buflen) {
|
||||
REQUIRE(buf != NULL);
|
||||
REQUIRE(buflen > 0);
|
||||
REQUIRE(buflen == 0 || buf != NULL);
|
||||
|
||||
int i;
|
||||
uint32_t r;
|
||||
|
||||
isc__random_initialize();
|
||||
|
||||
for (i = 0; i + sizeof(r) <= buflen; i += sizeof(r)) {
|
||||
r = next();
|
||||
memmove((uint8_t *)buf + i, &r, sizeof(r));
|
||||
if (buf == NULL || buflen == 0) {
|
||||
return;
|
||||
}
|
||||
r = next();
|
||||
memmove((uint8_t *)buf + i, &r, buflen % sizeof(r));
|
||||
return;
|
||||
|
||||
int r = uv_random(NULL, NULL, buf, buflen, 0, NULL);
|
||||
UV_RUNTIME_CHECK(uv_random, r);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
isc_random_uniform(uint32_t limit) {
|
||||
isc__random_initialize();
|
||||
|
||||
/*
|
||||
* Daniel Lemire's nearly-divisionless unbiased bounded random numbers.
|
||||
*
|
||||
|
|
@ -161,7 +90,7 @@ isc_random_uniform(uint32_t limit) {
|
|||
* integer part (upper 32 bits), and we will use the fraction part
|
||||
* (lower 32 bits) to determine whether or not we need to resample.
|
||||
*/
|
||||
uint64_t num = (uint64_t)next() * (uint64_t)limit;
|
||||
uint64_t num = (uint64_t)isc_random32() * (uint64_t)limit;
|
||||
/*
|
||||
* In the fast path, we avoid doing a division in most cases by
|
||||
* comparing the fraction part of `num` with the limit, which is
|
||||
|
|
@ -213,7 +142,7 @@ isc_random_uniform(uint32_t limit) {
|
|||
* our valid range, it is superfluous, and we resample.
|
||||
*/
|
||||
while ((uint32_t)(num) < residue) {
|
||||
num = (uint64_t)next() * (uint64_t)limit;
|
||||
num = (uint64_t)isc_random32() * (uint64_t)limit;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
@ -221,3 +150,5 @@ isc_random_uniform(uint32_t limit) {
|
|||
*/
|
||||
return (uint32_t)(num >> 32);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ARC4RANDOM && !defined(__linux__) */
|
||||
|
|
|
|||
|
|
@ -321,7 +321,9 @@ random_test(pvalue_func_t *func, isc_random_func test_func) {
|
|||
}
|
||||
break;
|
||||
case ISC_RANDOM_BYTES:
|
||||
isc_random_buf(values, sizeof(values));
|
||||
for (i = 0; i < ARRAY_SIZE(values); i++) {
|
||||
values[i] = isc_random32();
|
||||
}
|
||||
break;
|
||||
case ISC_RANDOM_UNIFORM:
|
||||
uniform_values = (uint16_t *)values;
|
||||
|
|
|
|||
Loading…
Reference in a new issue