]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update find_zone_keys for dynamic update
authorMatthijs Mekking <matthijs@isc.org>
Tue, 4 Oct 2022 13:54:30 +0000 (15:54 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 14 Jun 2023 07:08:56 +0000 (09:08 +0200)
The find_zone_keys() function was not working properly for
inline-signed zones. It only worked if the DNSKEY records were also
published in the unsigned version of the zone. But this is not the
case when you use dnssec-policy, the DNSKEY records will only occur
in the signed version of the zone. Therefor, when looking for keys
to sign the zone, only the newly added keys in the dynamic update
were found (which could be zero), ignoring existing keys.

Also, if a DNSKEY was added, it would try to sign the zone with just
this new key, and this would only work if the key files for that key
were imported into the key-directory.

This is a design error, because the goal is to sign the zone with the
keys for which we actually have key files for. So instead of looking
for DNSKEY records to then search for the matching key files, call
dns_dnssec_findmatchingkeys() which just looks for the keys we have
on disk for the given zone. It will also set the correct DNSSEC
signing hints.

lib/dns/update.c

index 43a30a311fba52be80bf4f9368e98034d3c43242..710e98f28e35546fb106b282cc04253b837c184e 100644 (file)
@@ -1055,26 +1055,49 @@ failure:
 }
 
 static isc_result_t
-find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
-              isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
-              unsigned int *nkeys) {
+find_zone_keys(dns_zone_t *zone, isc_mem_t *mctx, unsigned int maxkeys,
+              dst_key_t **keys, unsigned int *nkeys) {
+       dns_dnsseckeylist_t keylist;
+       dns_dnsseckey_t *k = NULL;
+       unsigned int count = 0;
        isc_result_t result;
        isc_stdtime_t now = isc_stdtime_now();
-       dns_dbnode_t *node = NULL;
-       const char *directory = dns_zone_getkeydirectory(zone);
 
-       CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
+       ISC_LIST_INIT(keylist);
 
        dns_zone_lock_keyfiles(zone);
-       result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
-                                        directory, now, mctx, maxkeys, keys,
-                                        nkeys);
+       result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
+                                            dns_zone_getkeydirectory(zone),
+                                            now, mctx, &keylist);
        dns_zone_unlock_keyfiles(zone);
 
-failure:
-       if (node != NULL) {
-               dns_db_detachnode(db, &node);
+       if (result != ISC_R_SUCCESS) {
+               *nkeys = 0;
+               return (result);
        }
+
+       /* Add new 'dnskeys' to 'keys' */
+       while ((k = ISC_LIST_HEAD(keylist)) != NULL) {
+               if (count >= maxkeys) {
+                       result = ISC_R_NOSPACE;
+                       goto next;
+               }
+
+               /* Detect inactive keys */
+               if (!dns_dnssec_keyactive(k->key, now)) {
+                       dst_key_setinactive(k->key, true);
+               }
+
+               keys[count] = k->key;
+               k->key = NULL;
+               count++;
+
+       next:
+               ISC_LIST_UNLINK(keylist, k, link);
+               dns_dnsseckey_destroy(mctx, &k);
+       }
+
+       *nkeys = count;
        return (result);
 }
 
@@ -1544,10 +1567,13 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
                state->nkeys = 0;
                state->build_nsec3 = false;
 
-               result = find_zone_keys(zone, db, newver, diff->mctx,
-                                       DNS_MAXZONEKEYS, state->zone_keys,
-                                       &state->nkeys);
-               if (result != ISC_R_SUCCESS) {
+               result = find_zone_keys(zone, diff->mctx, DNS_MAXZONEKEYS,
+                                       state->zone_keys, &state->nkeys);
+               if (result == ISC_R_NOSPACE) {
+                       update_log(log, zone, ISC_LOG_ERROR,
+                                  "too many zone keys for secure "
+                                  "dynamic update");
+               } else if (result != ISC_R_SUCCESS) {
                        update_log(log, zone, ISC_LOG_ERROR,
                                   "could not get zone keys for secure "
                                   "dynamic update");