]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add manual key rollover logic
authorMatthijs Mekking <matthijs@isc.org>
Fri, 21 Aug 2020 13:31:57 +0000 (15:31 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Mon, 5 Oct 2020 08:52:19 +0000 (10:52 +0200)
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.

lib/dns/include/dns/keymgr.h
lib/dns/keymgr.c
lib/dns/win32/libdns.def.in

index 507026482c173e4af45fbfa903cf0b8e694f81a6..bd53b1c58af8ce88854170ac9eec92a6b582b033 100644 (file)
@@ -77,6 +77,37 @@ dns_keymgr_checkds_id(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
  *
  */
 
+isc_result_t
+dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
+                   const char *directory, isc_stdtime_t now,
+                   isc_stdtime_t when, dns_keytag_t id,
+                   unsigned int algorithm);
+/*%<
+ * Rollover key with given 'id'. If the 'algorithm' is non-zero, it must
+ * match the key's algorithm. The changes are stored in the key state file.
+ *
+ * A rollover means adjusting the key metadata so that keymgr will start the
+ * actual rollover on the next run. Update the 'inactive' time and adjust
+ * key lifetime to match the 'when' to rollover time.
+ *
+ * The 'when' time may be in the past. In that case keymgr will roll the
+ * key as soon as possible.
+ *
+ * The 'when' time may be in the future. This may extend the lifetime,
+ * overriding the default lifetime from the policy.
+ *
+ *     Requires:
+ *\li          'kasp' is not NULL.
+ *\li          'keyring' is not NULL.
+ *
+ *     Returns:
+ *\li          #ISC_R_SUCCESS (No error).
+ *\li          #ISC_R_FAILURE (More than one matching keys found).
+ *\li          #ISC_R_NOTFOUND (No matching keys found).
+ *\li          #ISC_R_UNEXPECTED (Key is not active).
+ *
+ */
+
 void
 dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
                  isc_stdtime_t now, char *out, size_t out_len);
index ab9ad185550b1f971e9bd6a45f798cd63c30c061..36bb4a3f71ef4d1c7987e04502d9a028cd31c3ae 100644 (file)
@@ -2143,3 +2143,84 @@ dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
                                "key rrsig:      ", DST_KEY_KRRSIG);
        }
 }
+
+isc_result_t
+dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
+                   const char *directory, isc_stdtime_t now,
+                   isc_stdtime_t when, dns_keytag_t id,
+                   unsigned int algorithm) {
+       int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
+       isc_dir_t dir;
+       isc_result_t result;
+       dns_dnsseckey_t *key = NULL;
+       isc_stdtime_t active, retire, prepub;
+
+       REQUIRE(DNS_KASP_VALID(kasp));
+       REQUIRE(keyring != NULL);
+
+       for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
+            dkey = ISC_LIST_NEXT(dkey, link))
+       {
+               if (dst_key_id(dkey->key) != id) {
+                       continue;
+               }
+               if (algorithm > 0 && dst_key_alg(dkey->key) != algorithm) {
+                       continue;
+               }
+               if (key != NULL) {
+                       /*
+                        * Only rollover for one key at a time.
+                        */
+                       return (ISC_R_FAILURE);
+               }
+               key = dkey;
+       }
+
+       if (key == NULL) {
+               return (ISC_R_NOTFOUND);
+       }
+
+       result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
+       if (result != ISC_R_SUCCESS) {
+               return (ISC_R_UNEXPECTED);
+       }
+
+       result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
+       if (result != ISC_R_SUCCESS) {
+               /**
+                * Default to as if this key was not scheduled to
+                * become retired, as if it had unlimited lifetime.
+                */
+               retire = 0;
+       }
+
+       /**
+        * Usually when is set to now, which is before the scheduled
+        * prepublication time, meaning we reduce the lifetime of the
+        * key. But in some cases, the lifetime can also be extended.
+        * We accept it, but we can return an error here if that
+        * turns out to be unintuitive behavior.
+        */
+       prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) +
+                dns_kasp_zonepropagationdelay(kasp);
+       retire = when + prepub;
+
+       dst_key_settime(key->key, DST_TIME_INACTIVE, retire);
+       dst_key_setnum(key->key, DST_NUM_LIFETIME, (retire - active));
+
+       /* Store key state and update hints. */
+       isc_dir_init(&dir);
+       if (directory == NULL) {
+               directory = ".";
+       }
+       result = isc_dir_open(&dir, directory);
+       if (result != ISC_R_SUCCESS) {
+               return result;
+       }
+
+       dns_dnssec_get_hints(key, now);
+       result = dst_key_tofile(key->key, options, directory);
+       isc_dir_close(&dir);
+
+       return (result);
+}
index c8f308dec9b0bcf3316bc9992c5f62fe2d80405a..4f3bd285936002a08ca0ac7cd9ed0722efa45c7d 100644 (file)
@@ -470,6 +470,7 @@ dns_keydata_todnskey
 dns_keyflags_fromtext
 dns_keymgr_checkds
 dns_keymgr_checkds_id
+dns_keymgr_rollover
 dns_keymgr_run
 dns_keymgr_status
 dns_keynode_dsset