]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement manual-mode for kasp
authorMatthijs Mekking <matthijs@isc.org>
Wed, 19 Mar 2025 16:10:25 +0000 (17:10 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Thu, 21 Aug 2025 14:08:16 +0000 (16:08 +0200)
When a key retire, key generation/introduction, or a state transition
to RUMOURED/UNRETENTIVE should happen, instead they are logged.
When those logs look good, you can run 'rndc dnssec -step' to run the
keymgr and apply those steps.

bin/named/server.c
lib/dns/include/dns/keymgr.h
lib/dns/include/dns/zone.h
lib/dns/keymgr.c
lib/dns/zone.c

index 7afd9af9cf77c619e335e4c8e48364838c8b86e0..84fb21ec21eb15f0ba507c32e6c186dc9571aa87 100644 (file)
@@ -6612,7 +6612,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
         * Ensure that zone keys are reloaded on reconfig
         */
        if (dns_zone_getkasp(zone) != NULL) {
-               dns_zone_rekey(zone, fullsign);
+               dns_zone_rekey(zone, fullsign, false);
        }
 
 cleanup:
@@ -12026,7 +12026,7 @@ named_server_rekey(named_server_t *server, isc_lex_t *lex,
        if (dns_zone_getkasp(zone) == NULL) {
                result = ISC_R_NOPERM;
        } else {
-               dns_zone_rekey(zone, fullsign);
+               dns_zone_rekey(zone, fullsign, false);
        }
 
        dns_zone_detach(&zone);
@@ -14358,6 +14358,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
        dns_dnsseckeylist_t keys;
        char *ptr, *zonetext = NULL;
        const char *msg = NULL;
+       /* variables for -step */
+       bool forcestep = false;
        /* variables for -checkds */
        bool checkds = false, dspublish = false;
        /* variables for -rollover */
@@ -14401,6 +14403,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
                rollover = true;
        } else if (strcasecmp(ptr, "-checkds") == 0) {
                checkds = true;
+       } else if (strcasecmp(ptr, "-step") == 0) {
+               forcestep = true;
        } else {
                CHECK(DNS_R_SYNTAX);
        }
@@ -14557,7 +14561,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
                         * Rekey after checkds command because the next key
                         * event may have changed.
                         */
-                       dns_zone_rekey(zone, false);
+                       dns_zone_rekey(zone, false, false);
 
                        if (use_keyid) {
                                char tagbuf[6];
@@ -14607,7 +14611,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
                         * Rekey after rollover command because the next key
                         * event may have changed.
                         */
-                       dns_zone_rekey(zone, false);
+                       dns_zone_rekey(zone, false, false);
 
                        if (use_keyid) {
                                char tagbuf[6];
@@ -14631,7 +14635,10 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
                        CHECK(putstr(text, isc_result_totext(ret)));
                        break;
                }
+       } else if (forcestep) {
+               dns_zone_rekey(zone, false, true);
        }
+
        CHECK(putnull(text));
 
 cleanup:
@@ -16094,7 +16101,7 @@ named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
                CHECK(putnull(text));
        } else {
                /* Schedule a rekey */
-               dns_zone_rekey(zone, false);
+               dns_zone_rekey(zone, false, false);
        }
 
 cleanup:
index bf24457e3cbe7eda4bbade0b1e41ae2a92809b2c..b8cbf2d3552718908964e889eed1c749c0b6a482 100644 (file)
 
 #include <dst/dst.h>
 
+#define DNS_KEYMGRATTR_NONE     0x00 /*%< No ordering. */
+#define DNS_KEYMGRATTR_S2I      0x01 /*%< Secure to insecure. */
+#define DNS_KEYMGRATTR_NOROLL   0x02 /*%< No rollover allowed. */
+#define DNS_KEYMGRATTR_FORCESTEP 0x04 /*%< Force next step in manual-mode */
+
 void
 dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first);
 /*%<
@@ -36,7 +41,8 @@ isc_result_t
 dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
               isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
               dns_dnsseckeylist_t *dnskeys, const char *keydir,
-              dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime);
+              dns_kasp_t *kasp, uint8_t options, isc_stdtime_t now,
+              isc_stdtime_t *nexttime);
 /*%<
  * Manage keys in 'keyring' and update timing data according to 'kasp' policy.
  * Create new keys for 'origin' if necessary.  Append all such keys, along
@@ -45,6 +51,10 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
  * Update key states and store changes back to disk. Store when to run next
  * in 'nexttime'.
  *
+ * If 'options' has DNS_KEYMGRATTR_FORCESTEP set, the next steps in the process
+ * are allowed, even if 'kasp' has 'manual-mode' enabled. Other options should
+ * not be set in 'options'.
+ *
  *     Requires:
  *\li          'origin' is a valid FQDN.
  *\li          'mctx' is a valid memory context.
index 193121b920612bcb313d52b70c923fe5abbb7df5..39c11830455c35bb1179925bf446b14ece547aad 100644 (file)
@@ -104,6 +104,7 @@ typedef enum {
        DNS_ZONEOPT_CHECKSVCB = 1 << 30,      /*%< check SVBC records */
        DNS_ZONEOPT_ZONEVERSION = 1U << 31,   /*%< enable zoneversion */
        DNS_ZONEOPT_FULLSIGN = 1ULL << 32,    /*%< fully sign zone */
+       DNS_ZONEOPT_FORCEKEYMGR = 1ULL << 33, /*%< force keymgr step */
        DNS_ZONEOPT___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
 } dns_zoneopt_t;
 
@@ -2210,7 +2211,7 @@ dns_zone_getprivatetype(dns_zone_t *zone);
  */
 
 void
-dns_zone_rekey(dns_zone_t *zone, bool fullsign);
+dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr);
 /*%<
  * Update the zone's DNSKEY set from the key repository.
  *
@@ -2218,6 +2219,9 @@ dns_zone_rekey(dns_zone_t *zone, bool fullsign);
  * the zone with the new key.  Otherwise, if there are no keys or
  * if the new keys are for algorithms that have already signed the
  * zone, then the zone can be re-signed incrementally.
+ *
+ * If 'forcekeymgr' is true, trigger a rekey event and allow the
+ * next steps in the run to happen.
  */
 
 isc_result_t
index 3a18b2622473e328bd669c8c10485c0d63991fa1..e9ab2a866a4a940258479b11ab9f439c1c393ba1 100644 (file)
@@ -342,7 +342,8 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
 }
 
 static void
-keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
+keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, uint8_t opts,
+                 isc_stdtime_t now) {
        char keystr[DST_KEY_FORMATSIZE];
        isc_result_t ret;
        isc_stdtime_t retire;
@@ -352,17 +353,39 @@ keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
        REQUIRE(key != NULL);
        REQUIRE(key->key != NULL);
 
-       /* This key wants to retire and hide in a corner. */
+       dst_key_format(key->key, keystr, sizeof(keystr));
+
+       ret = dst_key_getstate(key->key, DST_KEY_GOAL, &s);
+       INSIST(ret == ISC_R_SUCCESS);
+
+       if (dns_kasp_manualmode(kasp) &&
+           (opts & DNS_KEYMGRATTR_FORCESTEP) == 0 && s != HIDDEN)
+       {
+               isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+                             ISC_LOG_INFO,
+                             "keymgr-manual-mode: block retire DNSKEY "
+                             "%s (%s)",
+                             keystr, keymgr_keyrole(key->key));
+               return;
+       } else {
+               /* This key wants to retire and hide in a corner. */
+               isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+                             ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)",
+                             keystr, keymgr_keyrole(key->key));
+
+               dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
+       }
+
+       /*
+        * This key may not have key states set yet. Pretend as if they are
+        * in the OMNIPRESENT state.
+        */
        ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
        if (ret != ISC_R_SUCCESS || (retire > now)) {
                dst_key_settime(key->key, DST_TIME_INACTIVE, now);
        }
-       dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
        keymgr_settime_remove(key, kasp);
 
-       /* This key may not have key states set yet. Pretend as if they are
-        * in the OMNIPRESENT state.
-        */
        if (dst_key_getstate(key->key, DST_KEY_DNSKEY, &s) != ISC_R_SUCCESS) {
                dst_key_setstate(key->key, DST_KEY_DNSKEY, OMNIPRESENT);
                dst_key_settime(key->key, DST_TIME_DNSKEY, now);
@@ -391,11 +414,6 @@ keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
                        dst_key_settime(key->key, DST_TIME_ZRRSIG, now);
                }
        }
-
-       dst_key_format(key->key, keystr, sizeof(keystr));
-       isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
-                     ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)", keystr,
-                     keymgr_keyrole(key->key));
 }
 
 /* Update lifetime and retire and remove time accordingly. */
@@ -963,7 +981,7 @@ keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring,
  */
 static bool
 keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
-              dst_key_state_t next_state, bool secure_to_insecure) {
+              dst_key_state_t next_state, uint8_t opts) {
        /* (3a) */
        dst_key_state_t states[2][NUM_KEYSTATES] = {
                /* DNSKEY, ZRRSIG, KRRSIG, DS */
@@ -981,7 +999,7 @@ keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
                                            states[0], na, false, false) ||
               keymgr_key_exists_with_state(keyring, key, type, next_state,
                                            states[1], na, false, false) ||
-              (secure_to_insecure &&
+              ((opts & DNS_KEYMGRATTR_S2I) != 0 &&
                keymgr_key_exists_with_state(keyring, key, type, next_state, na,
                                             na, false, false));
 }
@@ -1220,17 +1238,14 @@ keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
  */
 static bool
 keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
-                         int type, dst_key_state_t next_state,
-                         bool secure_to_insecure) {
+                         int type, dst_key_state_t next_state, uint8_t opts) {
        /* Debug logging. */
        if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
                bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b;
                char keystr[DST_KEY_FORMATSIZE];
                dst_key_format(key->key, keystr, sizeof(keystr));
-               rule1a = keymgr_have_ds(keyring, key, type, NA,
-                                       secure_to_insecure);
-               rule1b = keymgr_have_ds(keyring, key, type, next_state,
-                                       secure_to_insecure);
+               rule1a = keymgr_have_ds(keyring, key, type, NA, opts);
+               rule1b = keymgr_have_ds(keyring, key, type, next_state, opts);
                rule2a = keymgr_have_dnskey(keyring, key, type, NA);
                rule2b = keymgr_have_dnskey(keyring, key, type, next_state);
                rule3a = keymgr_have_rrsig(keyring, key, type, NA);
@@ -1255,9 +1270,8 @@ keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
                 * invalid state.  If the rule check passes, also check if
                 * the next state is also still a valid situation.
                 */
-               (!keymgr_have_ds(keyring, key, type, NA, secure_to_insecure) ||
-                keymgr_have_ds(keyring, key, type, next_state,
-                               secure_to_insecure)) &&
+               (!keymgr_have_ds(keyring, key, type, NA, opts) ||
+                keymgr_have_ds(keyring, key, type, next_state, opts)) &&
                /*
                 * Rule 2: There must be a DNSKEY at all times.  Again, first
                 * check the current situation, then assess the next state.
@@ -1448,8 +1462,9 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
  */
 static isc_result_t
 keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now,
-             isc_stdtime_t *nexttime, bool secure_to_insecure) {
+             isc_stdtime_t *nexttime, uint8_t opts) {
        bool changed;
+       bool force = ((opts & DNS_KEYMGRATTR_FORCESTEP) != 0);
 
        /* Repeat until nothing changed. */
 transition:
@@ -1534,8 +1549,7 @@ transition:
 
                        /* Is the transition DNSSEC safe? */
                        if (!keymgr_transition_allowed(keyring, dkey, i,
-                                                      next_state,
-                                                      secure_to_insecure))
+                                                      next_state, opts))
                        {
                                /* No, this would make the zone bogus. */
                                isc_log_write(
@@ -1572,6 +1586,28 @@ transition:
                                continue;
                        }
 
+                       /*
+                        * Are we allowed to make the transition automatically?
+                        */
+                       if (next_state != OMNIPRESENT && next_state != HIDDEN) {
+                               if (dns_kasp_manualmode(kasp) && !force) {
+                                       isc_log_write(
+                                               DNS_LOGCATEGORY_DNSSEC,
+                                               DNS_LOGMODULE_DNSSEC,
+                                               ISC_LOG_INFO,
+                                               "keymgr-manual-mode: block "
+                                               "transition "
+                                               "%s %s type %s "
+                                               "state %s to state %s",
+                                               keymgr_keyrole(dkey->key),
+                                               keystr, keystatetags[i],
+                                               keystatestrings[state],
+                                               keystatestrings[next_state]);
+                                       continue;
+                               }
+                       }
+
+                       /* It is safe to make the transition. */
                        isc_log_write(DNS_LOGCATEGORY_DNSSEC,
                                      DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
                                      "keymgr: transition %s %s type %s "
@@ -1580,7 +1616,6 @@ transition:
                                      keystatetags[i], keystatestrings[state],
                                      keystatestrings[next_state]);
 
-                       /* It is safe to make the transition. */
                        dst_key_setstate(dkey->key, i, next_state);
                        dst_key_settime(dkey->key, keystatetimes[i], now);
                        INSIST(dst_key_ismodified(dkey->key));
@@ -1590,6 +1625,8 @@ transition:
 
        /* We changed something, continue processing. */
        if (changed) {
+               /* No longer force for the next run */
+               force = false;
                goto transition;
        }
 
@@ -1716,9 +1753,10 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
                    dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys,
                    const dns_name_t *origin, dns_rdataclass_t rdclass,
                    dns_kasp_t *kasp, const char *keydir, uint32_t lifetime,
-                   bool rollover, isc_stdtime_t now, isc_stdtime_t *nexttime,
+                   uint8_t opts, isc_stdtime_t now, isc_stdtime_t *nexttime,
                    isc_mem_t *mctx) {
        char keystr[DST_KEY_FORMATSIZE];
+       char namestr[DNS_NAME_FORMATSIZE];
        isc_stdtime_t retire = 0, active = 0, prepub = 0;
        dns_dnsseckey_t *new_key = NULL;
        dst_key_t *dst_key = NULL;
@@ -1795,7 +1833,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
                /*
                 * If rollover is not allowed, warn.
                 */
-               if (!rollover) {
+               if ((opts & DNS_KEYMGRATTR_NOROLL) != 0) {
                        dst_key_format(active_key->key, keystr, sizeof(keystr));
                        isc_log_write(DNS_LOGCATEGORY_DNSSEC,
                                      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
@@ -1806,7 +1844,6 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
                        return ISC_R_SUCCESS;
                }
        } else if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
-               char namestr[DNS_NAME_FORMATSIZE];
                dns_name_format(origin, namestr, sizeof(namestr));
                isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
                              ISC_LOG_DEBUG(1),
@@ -1830,6 +1867,49 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
                }
        }
 
+       if (dns_kasp_manualmode(kasp) && (opts & DNS_KEYMGRATTR_FORCESTEP) == 0)
+       {
+               if (active_key != NULL && new_key != NULL) {
+                       char keystr2[DST_KEY_FORMATSIZE];
+                       dst_key_format(active_key->key, keystr, sizeof(keystr));
+                       dst_key_format(new_key->key, keystr2, sizeof(keystr2));
+                       dns_name_format(origin, namestr, sizeof(namestr));
+                       isc_log_write(
+                               DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+                               ISC_LOG_INFO,
+                               "keymgr-manual-mode: block %s rollover for key "
+                               "%s to key %s (policy %s)",
+                               keymgr_keyrole(active_key->key), keystr,
+                               keystr2, dns_kasp_getname(kasp));
+               } else if (active_key != NULL) {
+                       dst_key_format(active_key->key, keystr, sizeof(keystr));
+                       dns_name_format(origin, namestr, sizeof(namestr));
+                       isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+                                     DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+                                     "keymgr-manual-mode: block %s rollover "
+                                     "for key %s (policy %s)",
+                                     keymgr_keyrole(active_key->key), keystr,
+                                     dns_kasp_getname(kasp));
+               } else if (new_key != NULL) {
+                       dst_key_format(new_key->key, keystr, sizeof(keystr));
+                       dns_name_format(origin, namestr, sizeof(namestr));
+                       isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+                                     DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+                                     "keymgr-manual-mode: block %s "
+                                     "introduction %s (policy %s)",
+                                     keymgr_keyrole(new_key->key), keystr,
+                                     dns_kasp_getname(kasp));
+               } else {
+                       dns_name_format(origin, namestr, sizeof(namestr));
+                       isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+                                     DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+                                     "keymgr-manual-mode: block new key "
+                                     "generation for zone %s (policy %s)",
+                                     namestr, dns_kasp_getname(kasp));
+               }
+               return ISC_R_SUCCESS;
+       }
+
        if (new_key == NULL) {
                /* No key available in keyring, create a new one. */
                bool csk = (dns_kasp_key_ksk(kaspkey) &&
@@ -2039,10 +2119,10 @@ isc_result_t
 dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
               isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
               dns_dnsseckeylist_t *dnskeys, const char *keydir,
-              dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime) {
+              dns_kasp_t *kasp, uint8_t opts, isc_stdtime_t now,
+              isc_stdtime_t *nexttime) {
        isc_result_t result = ISC_R_SUCCESS;
        dns_dnsseckeylist_t newkeys;
-       bool secure_to_insecure = false;
        int numkeys = 0;
        int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
        char keystr[DST_KEY_FORMATSIZE];
@@ -2103,7 +2183,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
 
                /* No match, so retire unwanted retire key. */
                if (!found_match) {
-                       keymgr_key_retire(dkey, kasp, now);
+                       keymgr_key_retire(dkey, kasp, opts, now);
                }
 
                /* Check purge-keys interval. */
@@ -2129,7 +2209,6 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
        ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
                uint32_t lifetime = dns_kasp_key_lifetime(kkey);
                dns_dnsseckey_t *active_key = NULL;
-               bool rollover_allowed = true;
 
                /* Do we have keys available for this kasp key? */
                ISC_LIST_FOREACH(*keyring, dkey, link) {
@@ -2168,7 +2247,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
                                                 * Retire excess keys in use.
                                                 */
                                                keymgr_key_retire(dkey, kasp,
-                                                                 now);
+                                                                 opts, now);
                                        }
                                        continue;
                                }
@@ -2206,7 +2285,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
                                                keystr,
                                                keymgr_keyrole(dnskey->key),
                                                dns_kasp_getname(kasp));
-                                       rollover_allowed = false;
+                                       opts |= DNS_KEYMGRATTR_NOROLL;
                                        active_key = dnskey;
                                        break;
                                }
@@ -2214,10 +2293,11 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
                }
 
                /* See if this key requires a rollover. */
-               RETERR(keymgr_key_rollover(kkey, active_key, keyring, &newkeys,
-                                          origin, rdclass, kasp, keydir,
-                                          lifetime, rollover_allowed, now,
-                                          nexttime, mctx));
+               RETERR(keymgr_key_rollover(
+                       kkey, active_key, keyring, &newkeys, origin, rdclass,
+                       kasp, keydir, lifetime, opts, now, nexttime, mctx));
+
+               opts &= ~DNS_KEYMGRATTR_NOROLL;
        }
 
        /* Walked all kasp key configurations.  Append new keys. */
@@ -2229,10 +2309,12 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
         * If the policy has an empty key list, this means the zone is going
         * back to unsigned.
         */
-       secure_to_insecure = dns_kasp_keylist_empty(kasp);
+       if (dns_kasp_keylist_empty(kasp)) {
+               opts |= DNS_KEYMGRATTR_S2I;
+       }
 
        /* Read to update key states. */
-       keymgr_update(keyring, kasp, now, nexttime, secure_to_insecure);
+       keymgr_update(keyring, kasp, now, nexttime, opts);
 
        /* Store key states and update hints. */
        ISC_LIST_FOREACH(*keyring, dkey, link) {
index 0ca4efad232ec9bf634dd3778c7235319ebd075b..2ccfe722ca29346b24679a68de0516e0af4154d7 100644 (file)
@@ -21211,7 +21211,7 @@ checkds_done(void *arg) {
 
        /* Rekey after checkds. */
        if (rekey) {
-               dns_zone_rekey(zone, false);
+               dns_zone_rekey(zone, false, false);
        }
 
 failure:
@@ -22233,6 +22233,7 @@ zone_rekey(dns_zone_t *zone) {
        bool newalg = false;
        bool fullsign;
        bool offlineksk = false;
+       uint8_t options = 0;
        uint32_t sigval = 0;
        dns_ttl_t ttl = 3600;
        const char *dir = NULL;
@@ -22351,6 +22352,14 @@ zone_rekey(dns_zone_t *zone) {
         */
        fullsign = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FULLSIGN);
 
+       /*
+        * True when called from "rndc dnssec -step". Indicates the zone
+        * is allowed to do the next step(s) in the keymgr process.
+        */
+       if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FORCEKEYMGR)) {
+               options |= DNS_KEYMGRATTR_FORCESTEP;
+       }
+
        if (offlineksk) {
                /* Lookup the correct bundle in the SKR. */
                LOCK_ZONE(zone);
@@ -22456,7 +22465,7 @@ zone_rekey(dns_zone_t *zone) {
                        dns_zone_lock_keyfiles(zone);
                        result = dns_keymgr_run(&zone->origin, zone->rdclass,
                                                mctx, &keys, &dnskeys, dir,
-                                               kasp, now, &nexttime);
+                                               kasp, options, now, &nexttime);
                        dns_zone_unlock_keyfiles(zone);
 
                        if (result != ISC_R_SUCCESS) {
@@ -22936,6 +22945,13 @@ failure:
                                 0);
                isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
        }
+
+       /*
+        * Clear forcekeymgr flag, if it was set, so we don't do
+        * another force next time.
+        */
+       DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
+
        UNLOCK_ZONE(zone);
 
        dns_diff_clear(&diff);
@@ -22974,7 +22990,7 @@ failure:
 }
 
 void
-dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
+dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr) {
        isc_time_t now;
 
        if (zone->type == dns_zone_primary && zone->loop != NULL) {
@@ -22983,6 +22999,9 @@ dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
                if (fullsign) {
                        DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FULLSIGN);
                }
+               if (forcekeymgr) {
+                       DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
+               }
 
                now = isc_time_now();
                zone->refreshkeytime = now;