]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update keymgr to allow transition to insecure mode
authorMatthijs Mekking <matthijs@isc.org>
Thu, 3 Dec 2020 15:04:28 +0000 (16:04 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 23 Dec 2020 10:56:54 +0000 (11:56 +0100)
The keymgr prevented zones from going to insecure mode. If we
have a policy with an empty key list this is a signal that the zone
wants to go back to insecure mode. In this case allow one extra state
transition to be valid when checking for DNSSEC safety.

(cherry picked from commit 913410006912984b49f9e8efa74e7c1f274cbe4d)

lib/dns/keymgr.c

index 2518b48739067129b6f13c3c7e38e14730e36145..bfd8009c3a5a92760aa4211fdb781ba50b40877e 100644 (file)
@@ -777,7 +777,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) {
+              dst_key_state_t next_state, bool secure_to_insecure) {
        dst_key_state_t states[2][4] = {
                /* DNSKEY, ZRRSIG, KRRSIG, DS */
                { NA, NA, NA, OMNIPRESENT }, /* DS present */
@@ -792,7 +792,10 @@ keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
        return (keymgr_key_exists_with_state(keyring, key, type, next_state,
                                             states[0], na, false, false) ||
                keymgr_key_exists_with_state(keyring, key, type, next_state,
-                                            states[1], na, false, false));
+                                            states[1], na, false, false) ||
+               (secure_to_insecure &&
+                keymgr_key_exists_with_state(keyring, key, type, next_state,
+                                             na, na, false, false)));
 }
 
 /*
@@ -1022,14 +1025,17 @@ 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) {
+                         int type, dst_key_state_t next_state,
+                         bool secure_to_insecure) {
        /* Debug logging. */
        if (isc_log_wouldlog(dns_lctx, 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);
-               rule1b = keymgr_have_ds(keyring, key, type, next_state);
+               rule1a = keymgr_have_ds(keyring, key, type, NA,
+                                       secure_to_insecure);
+               rule1b = keymgr_have_ds(keyring, key, type, next_state,
+                                       secure_to_insecure);
                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);
@@ -1054,8 +1060,9 @@ 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) ||
-                keymgr_have_ds(keyring, key, type, next_state)) &&
+               (!keymgr_have_ds(keyring, key, type, NA, secure_to_insecure) ||
+                keymgr_have_ds(keyring, key, type, next_state,
+                               secure_to_insecure)) &&
                /*
                 * Rule 2: There must be a DNSKEY at all times.  Again, first
                 * check the current situation, then assess the next state.
@@ -1246,7 +1253,7 @@ 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) {
+             isc_stdtime_t *nexttime, bool secure_to_insecure) {
        bool changed;
 
        /* Repeat until nothing changed. */
@@ -1328,7 +1335,9 @@ transition:
 
                        /* Is the transition DNSSEC safe? */
                        if (!keymgr_transition_allowed(keyring, dkey, i,
-                                                      next_state)) {
+                                                      next_state,
+                                                      secure_to_insecure))
+                       {
                                /* No, this would make the zone bogus. */
                                isc_log_write(
                                        dns_lctx, DNS_LOGCATEGORY_DNSSEC,
@@ -1677,6 +1686,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
        dns_dnsseckey_t *newkey = NULL;
        isc_dir_t dir;
        bool dir_open = false;
+       bool secure_to_insecure = false;
        int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
        char keystr[DST_KEY_FORMATSIZE];
 
@@ -1832,8 +1842,14 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
                ISC_LIST_APPENDLIST(*keyring, newkeys, link);
        }
 
+       /*
+        * 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);
+
        /* Read to update key states. */
-       keymgr_update(keyring, kasp, now, nexttime);
+       keymgr_update(keyring, kasp, now, nexttime, secure_to_insecure);
 
        /* Store key states and update hints. */
        for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;