Commit graph

2273 commits

Author SHA1 Message Date
Matthijs Mekking
2f0b924ce6 Add NSEC3PARAM unit test, refactor zone.c
Add unit test to ensure the right NSEC3PARAM event is scheduled in
'dns_zone_setnsec3param()'.  To avoid scheduling and managing actual
tasks, split up the 'dns_zone_setnsec3param()' function in two parts:

1. 'dns__zone_lookup_nsec3param()' that will check if the requested
   NSEC3 parameters already exist, and if a new salt needs to be
   generated.

2. The actual scheduling of the new NSEC3PARAM event (if needed).

(cherry picked from commit 64db30942d)
2020-11-26 14:15:05 +00:00
Matthijs Mekking
6db879160f Detect NSEC3 salt collisions
When generating a new salt, compare it with the previous NSEC3
paremeters to ensure the new parameters are different from the
previous ones.

This moves the salt generation call from 'bin/named/*.s' to
'lib/dns/zone.c'. When setting new NSEC3 parameters, you can set a new
function parameter 'resalt' to enforce a new salt to be generated. A
new salt will also be generated if 'salt' is set to NULL.

Logging salt with zone context can now be done with 'dnssec_log',
removing the need for 'dns_nsec3_log_salt'.

(cherry picked from commit 6b5d7357df)
2020-11-26 14:15:05 +00:00
Matthijs Mekking
93f9d3b812 Move logging of salt in separate function
There may be a desire to log the salt without losing the context
of log module, level, and category.

(cherry picked from commit 7878f300ff)
2020-11-26 14:15:04 +00:00
Matthijs Mekking
52d3bf5f31 Change nsec3param salt config to saltlen
Upon request from Mark, change the configuration of salt to salt
length.

Introduce a new function 'dns_zone_checknsec3aram' that can be used
upon reconfiguration to check if the existing NSEC3 parameters are
in sync with the configuration. If a salt is used that matches the
configured salt length, don't change the NSEC3 parameters.

(cherry picked from commit 6f97bb6b1f)
2020-11-26 14:15:04 +00:00
Matthijs Mekking
d35dab3db8 Add check for NSEC3 and key algorithms
NSEC3 is not backwards compatible with key algorithms that existed
before the RFC 5155 specification was published.

(cherry picked from commit 00c5dabea3)
2020-11-26 14:15:03 +00:00
Matthijs Mekking
2a1793a2be Check nsec3param configuration values
Check 'nsec3param' configuration for the number of iterations.  The
maximum number of iterations that are allowed are based on the key
size (see https://tools.ietf.org/html/rfc5155#section-10.3).

Check 'nsec3param' configuration for correct salt. If the string is
not "-" or hex-based, this is a bad salt.

(cherry picked from commit 7039c5f805)
2020-11-26 14:15:03 +00:00
Matthijs Mekking
008e84e965 Support for NSEC3 in dnssec-policy
Implement support for NSEC3 in dnssec-policy.  Store the configuration
in kasp objects. When configuring a zone, call 'dns_zone_setnsec3param'
to queue an nsec3param event. This will ensure that any previous
chains will be removed and a chain according to the dnssec-policy is
created.

Add tests for dnssec-policy zones that uses the new 'nsec3param'
option, as well as changing to new values, changing to NSEC, and
changing from NSEC.

(cherry picked from commit 114af58ee2)
2020-11-26 14:15:02 +00:00
Matthijs Mekking
9b9ac92fd0 Move generate_salt function to lib/dns/nsec3
We will be using this function also on reconfig, so it should have
a wider availability than just bin/named/server.

(cherry picked from commit 84a4273074)
2020-11-26 14:14:56 +00:00
Diego Fronza
73c199dec7 Check 'stale-refresh-time' when sharing cache between views
This commit ensures that, along with previous restrictions, a cache is
shareable between views only if their 'stale-refresh-time' value are
equal.
2020-11-11 16:06:23 -03:00
Diego Fronza
8cc5abff23 Add stale-refresh-time option
Before this update, BIND would attempt to do a full recursive resolution
process for each query received if the requested rrset had its ttl
expired. If the resolution fails for any reason, only then BIND would
check for stale rrset in cache (if 'stale-cache-enable' and
'stale-answer-enable' is on).

The problem with this approach is that if an authoritative server is
unreachable or is failing to respond, it is very unlikely that the
problem will be fixed in the next seconds.

A better approach to improve performance in those cases, is to mark the
moment in which a resolution failed, and if new queries arrive for that
same rrset, try to respond directly from the stale cache, and do that
for a window of time configured via 'stale-refresh-time'.

Only when this interval expires we then try to do a normal refresh of
the rrset.

The logic behind this commit is as following:

- In query.c / query_gotanswer(), if the test of 'result' variable falls
  to the default case, an error is assumed to have happened, and a call
  to 'query_usestale()' is made to check if serving of stale rrset is
  enabled in configuration.

- If serving of stale answers is enabled, a flag will be turned on in
  the query context to look for stale records:
  query.c:6839
  qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;

- A call to query_lookup() will be made again, inside it a call to
  'dns_db_findext()' is made, which in turn will invoke rbdb.c /
  cache_find().

- In rbtdb.c / cache_find() the important bits of this change is the
  call to 'check_stale_header()', which is a function that yields true
  if we should skip the stale entry, or false if we should consider it.

- In check_stale_header() we now check if the DNS_DBFIND_STALEOK option
  is set, if that is the case we know that this new search for stale
  records was made due to a failure in a normal resolution, so we keep
  track of the time in which the failured occured in rbtdb.c:4559:
  header->last_refresh_fail_ts = search->now;

- In check_stale_header(), if DNS_DBFIND_STALEOK is not set, then we
  know this is a normal lookup, if the record is stale and the query
  time is between last failure time + stale-refresh-time window, then
  we return false so cache_find() knows it can consider this stale
  rrset entry to return as a response.

The last additions are two new methods to the database interface:
- setservestale_refresh
- getservestale_refresh

Those were added so rbtdb can be aware of the value set in configuration
option, since in that level we have no access to the view object.
2020-11-11 15:59:56 -03:00
Matthijs Mekking
63652ca58f Use explicit result codes for 'rndc dnssec' cmd
It is better to add new result codes than to overload existing codes.

(cherry picked from commit 70d1ec432f)
2020-10-05 11:20:35 +02:00
Matthijs Mekking
6bbb2a8581 Various rndc dnssec -checkds fixes
While working on 'rndc dnssec -rollover' I noticed the following
(small) issues:

- The key files where updated with hints set to "-when" and that
  should always be "now.
- The kasp system test did not properly update the test number when
  calling 'rndc dnssec -checkds' (and ensuring that works).
- There was a missing ']' in the rndc.c help output.

(cherry picked from commit edc53fc416)
2020-10-05 11:20:35 +02:00
Matthijs Mekking
ad48f07c9a Add manual key rollover logic
Add to the keymgr a function that will schedule a rollover. This
basically means setting the time when the key needs to retire,
and updating the key lifetime, then update the state file. The next
time that named runs the keymgr the new lifetime will be taken into
account.

(cherry picked from commit df8276aef0)
2020-10-05 11:20:35 +02:00
Ondřej Surý
f0989bdf03 The dns_message_create() cannot fail, change the return to void
The dns_message_create() function cannot soft fail (as all memory
allocations either succeed or cause abort), so we change the function to
return void and cleanup the calls.

(cherry picked from commit 33eefe9f85)
2020-09-30 14:26:26 +02:00
Diego Fronza
da84f8d1fd Refactored dns_message_t for using attach/detach semantics
This commit will be used as a base for the next code updates in
order to have a better control of dns_message_t objects' lifetime.

(cherry picked from commit 12d6d13100)
2020-09-30 11:34:42 +10:00
Matthijs Mekking
d77283ff63 Add -expired flag to rndc dumpdb command
This flag is the same as -cache, but will use a different style format
that will also print expired entries (awaiting cleanup) from the cache.

(cherry picked from commit 8beda7d2ea)
2020-09-25 08:20:02 +02:00
Mark Andrews
9e79a7d7ce Clone the saved / query message buffers
The message buffer passed to ns__client_request is only valid for
the life of the the ns__client_request call.  Save a copy of it
when we recurse or process a update as ns__client_request will
return before those operations complete.

(cherry picked from commit f0d9bf7c30)
2020-09-23 11:17:23 +10:00
Evan Hunt
df698d73f4 update all copyright headers to eliminate the typo 2020-09-14 16:50:58 -07:00
Mark Andrews
f3b25f1ffb Address use after free between view, resolver and nta.
Hold a weak reference to the view so that it can't go away while
nta is performing its lookups.  Cancel nta timers once all external
references to the view have gone to prevent them triggering new work.

(cherry picked from commit 0b2555e8cf)
2020-08-11 11:55:44 +10:00
Matthijs Mekking
624f1b9531 rndc dnssec -checkds set algorithm
In the rare case that you have multiple keys acting as KSK and that
have the same keytag, you can now set the algorithm when calling
'-checkds'.

(cherry picked from commit 46fcd927e7)
2020-08-07 13:34:10 +02:00
Matthijs Mekking
4892006a92 Make 'parent-registration-delay' obsolete
With the introduction of 'checkds', the 'parent-registration-delay'
option becomes obsolete.

(cherry picked from commit a25f49f153)
2020-08-07 13:30:50 +02:00
Matthijs Mekking
81d0c63ecb Implement 'rndc dnssec -checkds'
Add a new 'rndc' command 'dnssec -checkds' that allows the user to
signal named that a new DS record has been seen published in the
parent, or that an existing DS record has been withdrawn from the
parent.

Upon the 'checkds' request, 'named' will write out the new state for
the key, updating the 'DSPublish' or 'DSRemoved' timing metadata.

This replaces the "parent-registration-delay" configuration option,
this was unreliable because it was purely time based (if the user
did not actually submit the new DS to the parent for example, this
could result in an invalid DNSSEC state).

Because we cannot rely on the parent registration delay for state
transition, we need to replace it with a different guard. Instead,
if a key wants its DS state to be moved to RUMOURED, the "DSPublish"
time must be set and must not be in the future. If a key wants its
DS state to be moved to UNRETENTIVE, the "DSRemoved" time must be set
and must not be in the future.

By default, with '-checkds' you set the time that the DS has been
published or withdrawn to now, but you can set a different time with
'-when'. If there is only one KSK for the zone, that key has its
DS state moved to RUMOURED. If there are multiple keys for the zone,
specify the right key with '-key'.

(cherry picked from commit 04d8fc0143)
2020-08-07 13:30:19 +02:00
Ondřej Surý
aa72c31422 Fix the rbt hashtable and grow it when setting max-cache-size
There were several problems with rbt hashtable implementation:

1. Our internal hashing function returns uint64_t value, but it was
   silently truncated to unsigned int in dns_name_hash() and
   dns_name_fullhash() functions.  As the SipHash 2-4 higher bits are
   more random, we need to use the upper half of the return value.

2. The hashtable implementation in rbt.c was using modulo to pick the
   slot number for the hash table.  This has several problems because
   modulo is: a) slow, b) oblivious to patterns in the input data.  This
   could lead to very uneven distribution of the hashed data in the
   hashtable.  Combined with the single-linked lists we use, it could
   really hog-down the lookup and removal of the nodes from the rbt
   tree[a].  The Fibonacci Hashing is much better fit for the hashtable
   function here.  For longer description, read "Fibonacci Hashing: The
   Optimization that the World Forgot"[b] or just look at the Linux
   kernel.  Also this will make Diego very happy :).

3. The hashtable would rehash every time the number of nodes in the rbt
   tree would exceed 3 * (hashtable size).  The overcommit will make the
   uneven distribution in the hashtable even worse, but the main problem
   lies in the rehashing - every time the database grows beyond the
   limit, each subsequent rehashing will be much slower.  The mitigation
   here is letting the rbt know how big the cache can grown and
   pre-allocate the hashtable to be big enough to actually never need to
   rehash.  This will consume more memory at the start, but since the
   size of the hashtable is capped to `1 << 32` (e.g. 4 mio entries), it
   will only consume maximum of 32GB of memory for hashtable in the
   worst case (and max-cache-size would need to be set to more than
   4TB).  Calling the dns_db_adjusthashsize() will also cap the maximum
   size of the hashtable to the pre-computed number of bits, so it won't
   try to consume more gigabytes of memory than available for the
   database.

   FIXME: What is the average size of the rbt node that gets hashed?  I
   chose the pagesize (4k) as initial value to precompute the size of
   the hashtable, but the value is based on feeling and not any real
   data.

For future work, there are more places where we use result of the hash
value modulo some small number and that would benefit from Fibonacci
Hashing to get better distribution.

Notes:
a. A doubly linked list should be used here to speedup the removal of
   the entries from the hashtable.
b. https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/

(cherry picked from commit e24bc324b4)
2020-07-30 11:57:24 +02:00
Michał Kępień
0bc4d6cc7a Fix locking for LMDB 0.9.26
When "rndc reconfig" is run, named first configures a fresh set of views
and then tears down the old views.  Consider what happens for a single
view with LMDB enabled; "envA" is the pointer to the LMDB environment
used by the original/old version of the view, "envB" is the pointer to
the same LMDB environment used by the new version of that view:

 1. mdb_env_open(envA) is called when the view is first created.
 2. "rndc reconfig" is called.
 3. mdb_env_open(envB) is called for the new instance of the view.
 4. mdb_env_close(envA) is called for the old instance of the view.

This seems to have worked so far.  However, an upstream change [1] in
LMDB which will be part of its 0.9.26 release prevents the above
sequence of calls from working as intended because the locktable mutexes
will now get destroyed by the mdb_env_close() call in step 4 above,
causing any subsequent mdb_txn_begin() calls to fail (because all of the
above steps are happening within a single named process).

Preventing the above scenario from happening would require either
redesigning the way we use LMDB in BIND, which is not something we can
easily backport, or redesigning the way BIND carries out its
reconfiguration process, which would be an even more severe change.

To work around the problem, set MDB_NOLOCK when calling mdb_env_open()
to stop LMDB from controlling concurrent access to the database and do
the necessary locking in named instead.  Reuse the view->new_zone_lock
mutex for this purpose to prevent the need for modifying struct dns_view
(which would necessitate library API version bumps).  Drop use of
MDB_NOTLS as it is made redundant by MDB_NOLOCK: MDB_NOTLS only affects
where LMDB reader locktable slots are stored while MDB_NOLOCK prevents
the reader locktable from being used altogether.

[1] 2fd44e3251

(cherry picked from commit 53120279b5)
2020-07-10 11:30:31 +02:00
Matthijs Mekking
f1b3686cd2 Output rndc dnssec -status
Implement the 'rndc dnssec -status' command that will output
some information about the key states, such as which policy is
used for the zone, what keys are in use, and when rollover is
scheduled.

Add loose testing in the kasp system test, the actual times are
already tested via key file inspection.

(cherry picked from commit 19ce9ec1d4)
2020-07-01 09:57:44 +02:00
Mark Andrews
41e38c216d Add missing #pragma once to <dns/lmdb.h> 2020-06-19 12:12:45 +10:00
Mark Andrews
06cebcb6b7 val->keynode is no longer needed
(cherry picked from commit ff4fc3f8dc)
2020-06-11 16:09:43 +10:00
Mark Andrews
70c27df941 The dsset returned by dns_keynode_dsset needs to be thread safe.
- clone keynode->dsset rather than return a pointer so that thread
  use is independent of each other.
- hold a reference to the dsset (keynode) so it can't be deleted
  while in use.
- create a new keynode when removing DS records so that dangling
  pointers to the deleted records will not occur.
- use a rwlock when accessing the rdatalist to prevent instabilities
  when DS records are added.

(cherry picked from commit e5b2eca1d3)
2020-06-11 16:09:43 +10:00
Mark Andrews
b17f6eba6a Reject primary zones with an DS record at the zone apex.
DS records only belong at delegation points and if present
at the zone apex are invariably the result of administrative
errors.  Additionally they can't be queried for with modern
resolvers as the parent servers will be queried.

(cherry picked from commit 35a58d30c9)
2020-06-04 16:06:07 +02:00
Mark Andrews
b9c4f1b648 Reduce the number of fetches we make when looking up addresses
If there are more that 5 NS record for a zone only perform a
maximum of 4 address lookups for all the name servers.  This
limits the amount of remote lookup performed for server
addresses at each level for a given query.
2020-05-19 13:57:07 +02:00
Mark Andrews
eed4fab37b Report Extended DNS Error codes
(cherry picked from commit b144ae1bb0)
2020-05-13 10:26:39 +10:00
Ondřej Surý
af1b56240f Resolve the overlinking of the system libraries
Originally, every library and binaries got linked to everything, which
creates unnecessary overlinking.  This wasn't as straightforward as it
should be as we still support configuration without libtool for 9.16.

Couple of smaller issues related to include headers and an issue where
sanitizer overload dlopen and dlclose symbols, so we were getting false
negatives in the autoconf test.
2020-05-11 09:49:54 +02:00
Matthijs Mekking
ae19d0f60a Replace sign operation bool with enum
(cherry picked from commit 44b49955e1)
2020-04-03 10:04:07 +02:00
Matthijs Mekking
c3d738c883 Embed algorithm in key tag counter
Key tags are not unique across algorithms.

(cherry picked from commit b2028e26da)
2020-04-03 10:03:58 +02:00
Matthijs Mekking
f59f446122 Redesign dnssec sign statistics
The first attempt to add DNSSEC sign statistics was naive: for each
zone we allocated 64K counters, twice.  In reality each zone has at
most four keys, so the new approach only has room for four keys per
zone. If after a rollover more keys have signed the zone, existing
keys are rotated out.

The DNSSEC sign statistics has three counters per key, so twelve
counters per zone. First counter is actually a key id, so it is
clear what key contributed to the metrics.  The second counter
tracks the number of generated signatures, and the third tracks
how many of those are refreshes.

This means that in the zone structure we no longer need two separate
references to DNSSEC sign metrics: both the resign and refresh stats
are kept in a single dns_stats structure.

Incrementing dnssecsignstats:

Whenever a dnssecsignstat is incremented, we look up the key id
to see if we already are counting metrics for this key.  If so,
we update the corresponding operation counter (resign or
refresh).

If the key is new, store the value in a new counter and increment
corresponding counter.

If all slots are full, we rotate the keys and overwrite the last
slot with the new key.

Dumping dnssecsignstats:

Dumping dnssecsignstats is no longer a simple wrapper around
isc_stats_dump, but uses the same principle.  The difference is that
rather than dumping the index (key tag) and counter, we have to look
up the corresponding counter.

(cherry picked from commit 705810d577)
2020-04-03 10:03:30 +02:00
Evan Hunt
c5405c2700 improve calculation of database size
"max-journal-size" is set by default to twice the size of the zone
database. however, the calculation of zone database size was flawed.

- change the size calculations in dns_db_getsize() to more accurately
  represent the space needed for a journal file or *XFR message to
  contain the data in the database. previously we returned the sizes
  of all rdataslabs, including header overhead and offset tables,
  which resulted in the database size being reported as much larger
  than the equivalent journal transactions would have been.
- map files caused a particular problem here: the full name can't be
  determined from the node while a file is being deserialized, because
  the uppernode pointers aren't set yet. so we store "full name length"
  in the dns_rbtnode structure while serializing, and clear it after
  deserialization is complete.
2020-03-12 00:38:37 -07:00
Mark Andrews
5d64049301 Fix lists of installed header files 2020-03-06 13:00:04 +11:00
Witold Kręcicki
3dfa493f16 Add an arena to compressctx
(cherry picked from commit 3a3b5f557a)
2020-02-27 08:54:02 +01:00
Evan Hunt
11a0d771f9 fix spelling errors reported by Fossies.
(cherry picked from commit ba0313e649)
2020-02-21 07:05:31 +00:00
Ondřej Surý
829b461c54 Merge branch '46-enforce-clang-format-rules' into 'master'
Start enforcing the clang-format rules on changed files

Closes #46

See merge request isc-projects/bind9!3063

(cherry picked from commit a04cdde45d)

d2b5853b Start enforcing the clang-format rules on changed files
618947c6 Switch AlwaysBreakAfterReturnType from TopLevelDefinitions to All
654927c8 Add separate .clang-format files for headers
5777c44a Reformat using the new rules
60d29f69 Don't enforce copyrights on .clang-format
2020-02-14 08:45:59 +00:00
Ondřej Surý
cdef20bb66 Merge branch 'each-style-tweak' into 'master'
adjust clang-format options to get closer to ISC style

See merge request isc-projects/bind9!3061

(cherry picked from commit d3b49b6675)

0255a974 revise .clang-format and add a C formatting script in util
e851ed0b apply the modified style
2020-02-14 05:35:29 +00:00
Ondřej Surý
2e55baddd8 Merge branch '46-add-curly-braces' into 'master'
Add curly braces using uncrustify and then reformat with clang-format back

Closes #46

See merge request isc-projects/bind9!3057

(cherry picked from commit 67b68e06ad)

36c6105e Use coccinelle to add braces to nested single line statement
d14bb713 Add copy of run-clang-tidy that can fixup the filepaths
056e133c Use clang-tidy to add curly braces around one-line statements
2020-02-13 21:28:35 +00:00
Ondřej Surý
c931d8e417 Merge branch '46-just-use-clang-format-to-reformat-sources' into 'master'
Reformat source code with clang-format

Closes #46

See merge request isc-projects/bind9!2156

(cherry picked from commit 7099e79a9b)

4c3b063e Import Linux kernel .clang-format with small modifications
f50b1e06 Use clang-format to reformat the source files
11341c76 Update the definition files for Windows
df6c1f76 Remove tkey_test (which is no-op anyway)
2020-02-12 14:51:18 +00:00
Evan Hunt
58aa084edc add support for key algorithm mnemonics in dnssec-policy 2020-02-07 19:17:05 +01:00
Matthijs Mekking
b378d0371f Fix kasp bug new KSK on restart [#1593]
When you do a restart or reconfig of named, or rndc loadkeys, this
triggers the key manager to run.  The key manager will check if new
keys need to be created. If there is an active key, and key rollover
is scheduled far enough away, no new key needs to be created.

However, there was a bug that when you just start to sign your zone,
it takes a while before the KSK becomes an active key. An active KSK
has its DS submitted or published, but before the key manager allows
that, the DNSKEY needs to be omnipresent. If you restart named
or rndc loadkeys in quick succession when you just started to sign
your zone, new keys will be created because the KSK is not yet
considered active.

Fix is to check for introducing as well as active keys. These keys
all have in common that their goal is to become omnipresent.
2020-02-06 10:17:22 +01:00
Evan Hunt
dba0163dac Correctly handle catalog zone entries containing slashes
- Add quotes before and after zone name when generating "addzone"
  input so avoid "unexpected token" errors.
- Use a hex digest for zone filenames when the zone or view name
  contains a slash.
- Test with a domain name containing a slash.
- Incidentally added 'catzhash.py' to contrib/scripts to generate
  hash labels for catalog zones, as it was needed to write the test.
2020-02-03 16:08:20 -08:00
Evan Hunt
6799a222d1 keep the keynode attached as long as dsset is in use
when using the trust anchor dsset as val->dsset, keep a reference
to the keynode so dsset can't be freed.
2020-01-14 09:26:19 -08:00
Evan Hunt
2d249ebeae make dns_keytable_deletekey() work correctly
it now removes matching trust anchors from from the dslist while leaving
the other trust anchors in place.

also cleaned up the API to remove functions that were never being used.
2020-01-14 09:26:13 -08:00
Evan Hunt
678e2d3cfa fix a bug with the insertion of DS records into existing keynodes
NOTE: the keytable test is still failing because dns_keytable_deletekey()
is looking for exact matches in keynodes containing dst_key objects,
which no keynode has anymore.
2020-01-14 09:24:23 -08:00
Evan Hunt
b984a4b647 disable adding keys to keytable; only DS trust anchors can now be added
the internal keytable structure has not yet been changed, but
insertion of DS anchors is the only method now available.

NOTE: the keytable unit test is currently failing because of tests
that expect individual keynode objects to contain single DST key
objects.
2020-01-14 09:24:22 -08:00