]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Treat dnssec-policy "none" as a builtin zone
authorMatthijs Mekking <matthijs@isc.org>
Thu, 3 Dec 2020 14:01:42 +0000 (15:01 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 23 Dec 2020 10:56:33 +0000 (11:56 +0100)
Configure "none" as a builtin policy. Change the 'cfg_kasp_fromconfig'
api so that the 'name' will determine what policy needs to be
configured.

When transitioning a zone from secure to insecure, there will be
cases when a zone with no DNSSEC policy (dnssec-policy none) should
be using KASP. When there are key state files available, this is an
indication that the zone once was DNSSEC signed but is reconfigured
to become insecure.

If we would not run the keymgr, named would abruptly remove the
DNSSEC records from the zone, making the zone bogus. Therefore,
change the code such that a zone will use kasp if there is a valid
dnssec-policy configured, or if there are state files available.

(cherry picked from commit cf420b2af0d45693d0f5f34d9113ea411b5f2225)

bin/dnssec/dnssec-keygen.c
bin/named/server.c
bin/named/zoneconf.c
bin/tests/system/kasp/tests.sh
lib/bind9/check.c
lib/dns/include/dns/zone.h
lib/dns/update.c
lib/dns/win32/libdns.def.in
lib/dns/zone.c
lib/isccfg/include/isccfg/kaspconf.h
lib/isccfg/kaspconf.c

index ce93fbf5189bac66781c0d5a1880b612aec7e8f1..3e931bafc24d2618f5ab0fba4ab9a50272b2dc9c 100644 (file)
@@ -268,8 +268,8 @@ kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
                        continue;
                }
 
-               result = cfg_kasp_fromconfig(kconfig, mctx, lctx, &kasplist,
-                                            &kasp);
+               result = cfg_kasp_fromconfig(kconfig, NULL, mctx, lctx,
+                                            &kasplist, &kasp);
                if (result != ISC_R_SUCCESS) {
                        fatal("failed to configure dnssec-policy '%s': %s",
                              cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
@@ -283,7 +283,7 @@ kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
        *kaspp = kasp;
 
        /*
-        * Same cleanup for kasp list.
+        * Cleanup kasp list.
         */
        for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
                kasp_next = ISC_LIST_NEXT(kasp, link);
@@ -781,7 +781,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
                }
 
                /* Set dnssec-policy related metadata */
-               if (ctx->policy) {
+               if (ctx->policy != NULL) {
                        dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
                        dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
                        dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
index 7462b3981265d3089776154ed2f171d983769519..33faa4b42e4e60ad9ba99c89d5a3c5205a5936f9 100644 (file)
@@ -8950,18 +8950,25 @@ load_configuration(const char *filename, named_server_t *server,
        {
                cfg_obj_t *kconfig = cfg_listelt_value(element);
                kasp = NULL;
-               CHECK(cfg_kasp_fromconfig(kconfig, named_g_mctx, named_g_lctx,
-                                         &kasplist, &kasp));
+               CHECK(cfg_kasp_fromconfig(kconfig, NULL, named_g_mctx,
+                                         named_g_lctx, &kasplist, &kasp));
                INSIST(kasp != NULL);
                dns_kasp_freeze(kasp);
                dns_kasp_detach(&kasp);
        }
        /*
-        * Create the default kasp.
+        * Create the built-in kasp policies ("default", "none").
         */
        kasp = NULL;
-       CHECK(cfg_kasp_fromconfig(NULL, named_g_mctx, named_g_lctx, &kasplist,
-                                 &kasp));
+       CHECK(cfg_kasp_fromconfig(NULL, "default", named_g_mctx, named_g_lctx,
+                                 &kasplist, &kasp));
+       INSIST(kasp != NULL);
+       dns_kasp_freeze(kasp);
+       dns_kasp_detach(&kasp);
+
+       kasp = NULL;
+       CHECK(cfg_kasp_fromconfig(NULL, "none", named_g_mctx, named_g_lctx,
+                                 &kasplist, &kasp));
        INSIST(kasp != NULL);
        dns_kasp_freeze(kasp);
        dns_kasp_detach(&kasp);
@@ -14317,7 +14324,6 @@ named_server_signing(named_server_t *server, isc_lex_t *lex,
                     isc_buffer_t **text) {
        isc_result_t result = ISC_R_SUCCESS;
        dns_zone_t *zone = NULL;
-       dns_kasp_t *kasp = NULL;
        dns_name_t *origin;
        dns_db_t *db = NULL;
        dns_dbnode_t *node = NULL;
@@ -14436,8 +14442,7 @@ named_server_signing(named_server_t *server, isc_lex_t *lex,
                CHECK(ISC_R_UNEXPECTEDEND);
        }
 
-       kasp = dns_zone_getkasp(zone);
-       if (kasp != NULL) {
+       if (dns_zone_use_kasp(zone)) {
                (void)putstr(text, "zone uses dnssec-policy, use rndc dnssec "
                                   "command instead");
                (void)putnull(text);
index 05639b94d8646cd6f1bd628cfffacdfa52ffed97..218c385cdd194a49bfb83ebb44082fa1be6d2278 100644 (file)
@@ -892,6 +892,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        bool check = false, fail = false;
        bool warn = false, ignore = false;
        bool ixfrdiff;
+       bool use_kasp = false;
        dns_masterformat_t masterformat;
        const dns_master_style_t *masterstyle = &dns_master_style_default;
        isc_stats_t *zoneqrystats;
@@ -1227,19 +1228,15 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                result = named_config_get(maps, "dnssec-policy", &obj);
                if (result == ISC_R_SUCCESS) {
                        kaspname = cfg_obj_asstring(obj);
-                       if (strcmp(kaspname, "none") != 0) {
-                               result = dns_kasplist_find(kasplist, kaspname,
-                                                          &kasp);
-                               if (result != ISC_R_SUCCESS) {
-                                       cfg_obj_log(obj, named_g_lctx,
-                                                   ISC_LOG_ERROR,
-                                                   "'dnssec-policy '%s' not "
-                                                   "found ",
-                                                   kaspname);
-                                       RETERR(result);
-                               }
-                               dns_zone_setkasp(zone, kasp);
+                       result = dns_kasplist_find(kasplist, kaspname, &kasp);
+                       if (result != ISC_R_SUCCESS) {
+                               cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
+                                           "'dnssec-policy '%s' not found ",
+                                           kaspname);
+                               RETERR(result);
                        }
+                       dns_zone_setkasp(zone, kasp);
+                       use_kasp = dns_zone_use_kasp(zone);
                }
 
                obj = NULL;
@@ -1529,7 +1526,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                bool allow = false, maint = false;
                bool sigvalinsecs;
 
-               if (kasp != NULL) {
+               if (use_kasp) {
                        if (dns_kasp_nsec3(kasp)) {
                                result = dns_zone_setnsec3param(
                                        zone, 1, dns_kasp_nsec3flags(kasp),
@@ -1543,7 +1540,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                        INSIST(result == ISC_R_SUCCESS);
                }
 
-               if (kasp != NULL) {
+               if (use_kasp) {
                        seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp);
                } else {
                        obj = NULL;
@@ -1554,7 +1551,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                }
                dns_zone_setkeyvalidityinterval(zone, seconds);
 
-               if (kasp != NULL) {
+               if (use_kasp) {
                        seconds = (uint32_t)dns_kasp_sigvalidity(kasp);
                        dns_zone_setsigvalidityinterval(zone, seconds);
                        seconds = (uint32_t)dns_kasp_sigrefresh(kasp);
@@ -1641,7 +1638,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
 
                obj = NULL;
                result = cfg_map_get(zoptions, "auto-dnssec", &obj);
-               if (dns_zone_getkasp(zone) != NULL) {
+               if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
+               {
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true);
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, true);
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true);
@@ -1660,6 +1658,11 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
                        dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
+               } else {
+                       bool s2i = dns_zone_secure_to_insecure(zone, false);
+                       dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, s2i);
+                       dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
+                       dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, s2i);
                }
        }
 
@@ -2103,11 +2106,15 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
 bool
 named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
                         const cfg_obj_t *vconfig, const cfg_obj_t *config) {
+       isc_result_t res;
        const cfg_obj_t *zoptions = NULL;
        const cfg_obj_t *voptions = NULL;
        const cfg_obj_t *options = NULL;
        const cfg_obj_t *signing = NULL;
-       bool inline_signing;
+       const cfg_obj_t *allowupdate = NULL;
+       const cfg_obj_t *updatepolicy = NULL;
+       bool zone_is_dynamic = false;
+       bool inline_signing = false;
 
        (void)cfg_map_get(config, "options", &options);
 
@@ -2119,6 +2126,38 @@ named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
        inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) ==
                                  ISC_R_SUCCESS &&
                          cfg_obj_asboolean(signing));
+       if (inline_signing) {
+               return (true);
+       }
+
+       if (cfg_map_get(zoptions, "update-policy", &updatepolicy) ==
+           ISC_R_SUCCESS) {
+               zone_is_dynamic = true;
+       } else {
+               res = cfg_map_get(zoptions, "allow-update", &allowupdate);
+               if (res != ISC_R_SUCCESS && voptions != NULL) {
+                       res = cfg_map_get(voptions, "allow-update",
+                                         &allowupdate);
+               }
+               if (res != ISC_R_SUCCESS && options != NULL) {
+                       res = cfg_map_get(options, "allow-update",
+                                         &allowupdate);
+               }
+               if (res == ISC_R_SUCCESS) {
+                       dns_acl_t *acl = NULL;
+                       cfg_aclconfctx_t *actx = NULL;
+                       res = cfg_acl_fromconfig(
+                               allowupdate, config, named_g_lctx, actx,
+                               dns_zone_getmctx(zone), 0, &acl);
+                       if (res == ISC_R_SUCCESS && acl != NULL &&
+                           !dns_acl_isnone(acl)) {
+                               zone_is_dynamic = true;
+                       }
+                       if (acl != NULL) {
+                               dns_acl_detach(&acl);
+                       }
+               }
+       }
 
        /*
         * If inline-signing is not set, perhaps implictly through a
@@ -2128,51 +2167,24 @@ named_zone_inlinesigning(dns_zone_t *zone, const cfg_obj_t *zconfig,
         * inline-signing.
         */
        signing = NULL;
-       if (!inline_signing &&
+       if (!inline_signing && !zone_is_dynamic &&
            cfg_map_get(zoptions, "dnssec-policy", &signing) == ISC_R_SUCCESS &&
-           signing != NULL && strcmp(cfg_obj_asstring(signing), "none") != 0)
+           signing != NULL)
        {
-               {
-                       isc_result_t res;
-                       bool zone_is_dynamic = false;
-                       const cfg_obj_t *au = NULL;
-                       const cfg_obj_t *up = NULL;
-
-                       if (cfg_map_get(zoptions, "update-policy", &up) ==
-                           ISC_R_SUCCESS) {
-                               zone_is_dynamic = true;
-                       } else {
-                               res = cfg_map_get(zoptions, "allow-update",
-                                                 &au);
-                               if (res != ISC_R_SUCCESS && voptions != NULL) {
-                                       res = cfg_map_get(voptions,
-                                                         "allow-update", &au);
-                               }
-                               if (res != ISC_R_SUCCESS && options != NULL) {
-                                       res = cfg_map_get(options,
-                                                         "allow-update", &au);
-                               }
-                               if (res == ISC_R_SUCCESS) {
-                                       dns_acl_t *acl = NULL;
-                                       cfg_aclconfctx_t *actx = NULL;
-                                       res = cfg_acl_fromconfig(
-                                               au, config, named_g_lctx, actx,
-                                               dns_zone_getmctx(zone), 0,
-                                               &acl);
-                                       if (res == ISC_R_SUCCESS &&
-                                           acl != NULL && !dns_acl_isnone(acl))
-                                       {
-                                               zone_is_dynamic = true;
-                                       }
-                                       if (acl != NULL) {
-                                               dns_acl_detach(&acl);
-                                       }
-                               }
-                       }
-
-                       if (!zone_is_dynamic) {
-                               inline_signing = true;
-                       }
+               if (strcmp(cfg_obj_asstring(signing), "none") != 0) {
+                       inline_signing = true;
+                       dns_zone_log(
+                               zone, ISC_LOG_DEBUG(1), "inline-signing: %s",
+                               inline_signing
+                                       ? "implicitly through dnssec-policy"
+                                       : "no");
+               } else {
+                       inline_signing = dns_zone_secure_to_insecure(zone,
+                                                                    true);
+                       dns_zone_log(
+                               zone, ISC_LOG_DEBUG(1), "inline-signing: %s",
+                               inline_signing ? "transitioning to insecure"
+                                              : "no");
                }
        }
 
index 9f53253401f11679d5f949b2dd50b454d44b414c..420d85c95df0e6127c5898229826e5c826bc3c33 100644 (file)
@@ -961,22 +961,18 @@ check_dnssecstatus() {
 
        rndccmd $_server dnssec -status $_zone in $_view > rndc.dnssec.status.out.$_zone.$n || log_error "rndc dnssec -status zone ${_zone} failed"
 
-       if [ "$_policy" = "none" ]; then
-               grep "Zone does not have dnssec-policy" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for unsigned zone ${_zone}"
-       else
-               grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for signed zone ${_zone}"
-               if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
-                       grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY1 ID) from dnssec status"
-               fi
-               if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
-                       grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY2 ID) from dnssec status"
-               fi
-               if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
-                       grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY3 ID) from dnssec status"
-               fi
-               if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
-                       grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY4 ID) from dnssec status"
-               fi
+       grep "dnssec-policy: ${_policy}" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "bad dnssec status for signed zone ${_zone}"
+       if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
+               grep "key: $(key_get KEY1 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY1 ID) from dnssec status"
+       fi
+       if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
+               grep "key: $(key_get KEY2 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY2 ID) from dnssec status"
+       fi
+       if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
+               grep "key: $(key_get KEY3 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY3 ID) from dnssec status"
+       fi
+       if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
+               grep "key: $(key_get KEY4 ID)" rndc.dnssec.status.out.$_zone.$n > /dev/null || log_error "missing key $(key_get KEY4 ID) from dnssec status"
        fi
 
        test "$ret" -eq 0 || echo_i "failed"
index 751db4d9c822d35b962f51b207be216695c0c64a..b2dee8f61818a0e93104ddf3222d9830aa5a3c88 100644 (file)
@@ -1014,9 +1014,9 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
                                                continue;
                                        }
 
-                                       ret = cfg_kasp_fromconfig(kconfig, mctx,
-                                                                 logctx, &list,
-                                                                 &kasp);
+                                       ret = cfg_kasp_fromconfig(kconfig, NULL,
+                                                                 mctx, logctx,
+                                                                 &list, &kasp);
                                        if (ret != ISC_R_SUCCESS) {
                                                if (result == ISC_R_SUCCESS) {
                                                        result = ret;
index 5e1abc312f1a7a00cacf3ddecd4a467c0cedbf02..12160448e4d35777774ffa6addbde8b170b55ba6 100644 (file)
@@ -676,6 +676,32 @@ dns_zone_getkasp(dns_zone_t *zone);
  *\li  'zone' to be a valid zone.
  */
 
+bool
+dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig);
+/*%<
+ *     Returns true if the zone is transitioning to insecure.
+ *     Only can happen if a zone previously used a dnssec-policy,
+ *     but changed the value to "none" (or removed the configuration
+ *     option). If 'reconfig' is true, only check the key files,
+ *     because the zone structure is not yet updated with the
+ *     newest configuration.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
+bool
+dns_zone_use_kasp(dns_zone_t *zone);
+/*%<
+ *     Check if zone needs to use kasp.
+ *     True if there is a policy that is not "none",
+ *     or if there are state files associated with the keys
+ *     related to this zone.
+ *
+ * Require:
+ *\li  'zone' to be a valid zone.
+ */
+
 void
 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp);
 /*%<
index 43dad7035a331bab00f4e4ba937f92c57e9fd877..808a636a8140e74954bfa34064901df7efb18e19 100644 (file)
@@ -1087,7 +1087,6 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
         bool keyset_kskonly) {
        isc_result_t result;
        dns_dbnode_t *node = NULL;
-       dns_kasp_t *kasp = dns_zone_getkasp(zone);
        dns_rdataset_t rdataset;
        dns_rdata_t sig_rdata = DNS_RDATA_INIT;
        dns_stats_t *dnssecsignstats = dns_zone_getdnssecsignstats(zone);
@@ -1095,11 +1094,13 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
        unsigned char data[1024]; /* XXX */
        unsigned int i, j;
        bool added_sig = false;
+       bool use_kasp = false;
        isc_mem_t *mctx = diff->mctx;
 
-       if (kasp != NULL) {
+       if (dns_zone_use_kasp(zone)) {
                check_ksk = false;
                keyset_kskonly = true;
+               use_kasp = true;
        }
 
        dns_rdataset_init(&rdataset);
@@ -1174,7 +1175,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
                        }
                }
 
-               if (kasp != NULL) {
+               if (use_kasp) {
                        /*
                         * A dnssec-policy is found. Check what RRsets this
                         * key should sign.
index 3a169309cd1b3265b260bf71f95aad256a98f7e4..cb9919f483daf543a9ab9b9ab297418f0c377001 100644 (file)
@@ -1297,6 +1297,7 @@ dns_zone_rekey
 dns_zone_replacedb
 dns_zone_rpz_enable
 dns_zone_rpz_enable_db
+dns_zone_secure_to_insecure
 dns_zone_set_parentcatz
 dns_zone_setadded
 dns_zone_setalsonotify
@@ -1383,6 +1384,7 @@ dns_zone_setzeronosoattl
 dns_zone_signwithkey
 dns_zone_synckeyzone
 dns_zone_unload
+dns_zone_use_kasp
 dns_zone_verifydb
 dns_zonekey_iszonekey
 dns_zonemgr_attach
index 7b7d1f36c324005488b057cd10230856819badb3..0df09eb67a7a8cf2d35c15be88a6fa1cd3872b95 100644 (file)
@@ -1801,7 +1801,7 @@ dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
        }
 
        /* Kasp zones are always dynamic. */
-       if (dns_zone_getkasp(zone) != NULL) {
+       if (dns_zone_use_kasp(zone)) {
                return (true);
        }
 
@@ -5792,6 +5792,82 @@ dns_zone_getkasp(dns_zone_t *zone) {
        return (zone->kasp);
 }
 
+static bool
+statefile_exist(dns_zone_t *zone) {
+       isc_result_t ret;
+       dns_dnsseckeylist_t keys;
+       dns_dnsseckey_t *key = NULL;
+       isc_stdtime_t now;
+       isc_time_t timenow;
+       bool found = false;
+
+       TIME_NOW(&timenow);
+       now = isc_time_seconds(&timenow);
+
+       ISC_LIST_INIT(keys);
+
+       ret = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
+                                         dns_zone_getkeydirectory(zone), now,
+                                         dns_zone_getmctx(zone), &keys);
+       if (ret == ISC_R_SUCCESS) {
+               for (key = ISC_LIST_HEAD(keys); key != NULL;
+                    key = ISC_LIST_NEXT(key, link)) {
+                       if (dst_key_haskasp(key->key)) {
+                               found = true;
+                               break;
+                       }
+               }
+       }
+
+       /* Clean up keys */
+       while (!ISC_LIST_EMPTY(keys)) {
+               key = ISC_LIST_HEAD(keys);
+               ISC_LIST_UNLINK(keys, key, link);
+               dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
+       }
+
+       return (found);
+}
+
+bool
+dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+
+       /*
+        * If checking during reconfig, the zone is not yet updated
+        * with the new kasp configuration, so only check the key
+        * files.
+        */
+       if (reconfig) {
+               return (statefile_exist(zone));
+       }
+
+       if (zone->kasp == NULL) {
+               return (false);
+       }
+       if (strcmp(dns_kasp_getname(zone->kasp), "none") != 0) {
+               return (false);
+       }
+       /*
+        * "dnssec-policy none", but if there are key state files
+        * this zone used to be secure but is transitioning back to
+        * insecure.
+        */
+       return (statefile_exist(zone));
+}
+
+bool
+dns_zone_use_kasp(dns_zone_t *zone) {
+       dns_kasp_t *kasp = dns_zone_getkasp(zone);
+
+       if (kasp == NULL) {
+               return (false);
+       } else if (strcmp(dns_kasp_getname(kasp), "none") != 0) {
+               return (true);
+       }
+       return dns_zone_secure_to_insecure(zone, false);
+}
+
 void
 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
        REQUIRE(DNS_ZONE_VALID(zone));
@@ -6743,17 +6819,18 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
         isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
        isc_result_t result;
        dns_dbnode_t *node = NULL;
-       dns_kasp_t *kasp = dns_zone_getkasp(zone);
        dns_stats_t *dnssecsignstats;
        dns_rdataset_t rdataset;
        dns_rdata_t sig_rdata = DNS_RDATA_INIT;
        unsigned char data[1024]; /* XXX */
        isc_buffer_t buffer;
        unsigned int i, j;
+       bool use_kasp = false;
 
-       if (kasp != NULL) {
+       if (dns_zone_use_kasp(zone)) {
                check_ksk = false;
                keyset_kskonly = true;
+               use_kasp = true;
        }
 
        dns_rdataset_init(&rdataset);
@@ -6831,8 +6908,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
                                }
                        }
                }
-
-               if (kasp != NULL) {
+               if (use_kasp) {
                        /*
                         * A dnssec-policy is found. Check what RRsets this
                         * key should sign.
@@ -7267,7 +7343,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
                dns_rdata_reset(&rdata);
        }
 
-       if (kasp) {
+       if (dns_zone_use_kasp(zone)) {
                dns_kasp_key_t *kkey;
                int zsk_count = 0;
                bool approved;
@@ -7384,7 +7460,6 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
            bool is_zsk, bool keyset_kskonly, bool is_bottom_of_zone,
            dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx) {
        isc_result_t result;
-       dns_kasp_t *kasp = dns_zone_getkasp(zone);
        dns_rdatasetiter_t *iterator = NULL;
        dns_rdataset_t rdataset;
        dns_rdata_t rdata = DNS_RDATA_INIT;
@@ -7480,7 +7555,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
                } else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
                                                         inception, &when)) {
                        /* Only applies to dnssec-policy. */
-                       if (kasp != NULL) {
+                       if (dns_zone_use_kasp(zone)) {
                                goto next_rdataset;
                        }
                }
@@ -9124,6 +9199,7 @@ zone_sign(dns_zone_t *zone) {
        bool is_bottom_of_zone;
        bool build_nsec = false;
        bool build_nsec3 = false;
+       bool use_kasp = false;
        bool first;
        isc_result_t result;
        isc_stdtime_t now, inception, soaexpire, expire;
@@ -9180,7 +9256,6 @@ zone_sign(dns_zone_t *zone) {
        }
 
        kasp = dns_zone_getkasp(zone);
-
        sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
        inception = now - 3600; /* Allow for clock skew. */
        soaexpire = now + sigvalidityinterval;
@@ -9217,16 +9292,20 @@ zone_sign(dns_zone_t *zone) {
        signing = ISC_LIST_HEAD(zone->signing);
        first = true;
 
-       check_ksk = (kasp != NULL)
-                           ? false
-                           : DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
-       keyset_kskonly = (kasp != NULL)
-                                ? true
-                                : DNS_ZONE_OPTION(zone,
-                                                  DNS_ZONEOPT_DNSKEYKSKONLY);
+       if (dns_zone_use_kasp(zone)) {
+               check_ksk = false;
+               keyset_kskonly = true;
+               use_kasp = true;
+       } else {
+               check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+               keyset_kskonly = DNS_ZONE_OPTION(zone,
+                                                DNS_ZONEOPT_DNSKEYKSKONLY);
+       }
+       dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
+                  use_kasp ? "yes" : "no");
 
        /* Determine which type of chain to build */
-       if (kasp != NULL) {
+       if (use_kasp) {
                build_nsec3 = dns_kasp_nsec3(kasp);
                build_nsec = !build_nsec3;
        } else {
@@ -9411,7 +9490,7 @@ zone_sign(dns_zone_t *zone) {
                                        }
                                }
                        }
-                       if (kasp != NULL) {
+                       if (use_kasp) {
                                /*
                                 * A dnssec-policy is found. Check what
                                 * RRsets this key can sign.
@@ -16410,7 +16489,7 @@ copy_non_dnssec_records(dns_zone_t *zone, dns_db_t *db, dns_db_t *version,
                         * Allow DNSSEC records with dnssec-policy.
                         * WMM: Perhaps add config option for it.
                         */
-                       if (dns_zone_getkasp(zone) == NULL) {
+                       if (!dns_zone_use_kasp(zone)) {
                                dns_rdataset_disassociate(&rdataset);
                                continue;
                        }
@@ -19693,7 +19772,7 @@ zone_rekey(dns_zone_t *zone) {
        dns__zonediff_t zonediff;
        bool commit = false, newactive = false;
        bool newalg = false;
-       bool fullsign;
+       bool fullsign, use_kasp;
        dns_ttl_t ttl = 3600;
        const char *dir = NULL;
        isc_mem_t *mctx = NULL;
@@ -19764,9 +19843,10 @@ zone_rekey(dns_zone_t *zone) {
         * True when called from "rndc sign".  Indicates the zone should be
         * fully signed now.
         */
-       kasp = dns_zone_getkasp(zone);
        fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
 
+       kasp = dns_zone_getkasp(zone);
+       use_kasp = dns_zone_use_kasp(zone);
        if (kasp != NULL) {
                LOCK(&kasp->lock);
        }
@@ -19779,9 +19859,7 @@ zone_rekey(dns_zone_t *zone) {
                           isc_result_totext(result));
        }
 
-       if (kasp != NULL &&
-           (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
-               ttl = dns_kasp_dnskeyttl(kasp);
+       if (use_kasp && (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
                result = dns_keymgr_run(&zone->origin, zone->rdclass, dir, mctx,
                                        &keys, kasp, now, &nexttime);
                if (result != ISC_R_SUCCESS) {
@@ -19797,6 +19875,16 @@ zone_rekey(dns_zone_t *zone) {
        }
 
        if (result == ISC_R_SUCCESS) {
+               bool insecure = dns_zone_secure_to_insecure(zone, false);
+
+               /*
+                * Only update DNSKEY TTL if we have a policy.
+                */
+               if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
+               {
+                       ttl = dns_kasp_dnskeyttl(kasp);
+               }
+
                result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
                                               &zone->origin, ttl, &diff, mctx,
                                               dnssec_report);
@@ -20009,7 +20097,7 @@ zone_rekey(dns_zone_t *zone) {
        /*
         * If keymgr provided a next time, use the calculated next rekey time.
         */
-       if (kasp != NULL) {
+       if (use_kasp) {
                isc_time_t timenext;
                uint32_t nexttime_seconds;
 
index 0f8ac1dd7e7908741399143bc83dd3a7de2db12a..43f6e690a7edf855a2b9110ac765b92ef85e354e 100644 (file)
 ISC_LANG_BEGINDECLS
 
 isc_result_t
-cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
-                   dns_kasplist_t *kasplist, dns_kasp_t **kaspp);
+cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
+                   isc_log_t *logctx, dns_kasplist_t *kasplist,
+                   dns_kasp_t **kaspp);
 /*%<
- * Create and configure a KASP. If 'config' is NULL, the default configuration
- * is used. If a 'kasplist' is provided, a lookup happens and if a KASP
- * already exists with the same name, no new KASP is created, and no attach to
- * 'kaspp' happens.
+ * Create and configure a KASP. If 'config' is NULL, a built-in configuration
+ * is used, referred to by 'name'. If a 'kasplist' is provided, a lookup
+ * happens and if a KASP already exists with the same name, no new KASP is
+ * created, and no attach to 'kaspp' happens.
  *
  * Requires:
  *
+ *\li  'name' is either NULL, or a valid C string.
+ *
  *\li  'mctx' is a valid memory context.
  *
  *\li  'logctx' is a valid logging context.
  *
- *\li  'name' is a valid C string.
- *
  *\li  kaspp != NULL && *kaspp == NULL
  *
  * Returns:
index 9a006c896359979f699902bfcfab65c865d20531..3e0e0874f4c38035e7238321a1a63919fd28095f 100644 (file)
@@ -253,8 +253,9 @@ cfg_nsec3param_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
 }
 
 isc_result_t
-cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
-                   dns_kasplist_t *kasplist, dns_kasp_t **kaspp) {
+cfg_kasp_fromconfig(const cfg_obj_t *config, const char *name, isc_mem_t *mctx,
+                   isc_log_t *logctx, dns_kasplist_t *kasplist,
+                   dns_kasp_t **kaspp) {
        isc_result_t result;
        const cfg_obj_t *maps[2];
        const cfg_obj_t *koptions = NULL;
@@ -267,11 +268,10 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
 
        REQUIRE(kaspp != NULL && *kaspp == NULL);
 
-       kaspname = (config != NULL)
+       kaspname = (name == NULL)
                           ? cfg_obj_asstring(cfg_tuple_get(config, "name"))
-                          : "default";
-
-       REQUIRE(strcmp(kaspname, "none") != 0);
+                          : name;
+       INSIST(kaspname != NULL);
 
        result = dns_kasplist_find(kasplist, kaspname, &kasp);
 
@@ -317,12 +317,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
                                                    DNS_KASP_RETIRE_SAFETY));
 
        (void)confget(maps, "keys", &keys);
-       if (keys == NULL) {
-               result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
-               if (result != ISC_R_SUCCESS) {
-                       goto cleanup;
-               }
-       } else {
+       if (keys != NULL) {
                for (element = cfg_list_first(keys); element != NULL;
                     element = cfg_list_next(element))
                {
@@ -332,8 +327,19 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx, isc_log_t *logctx,
                                goto cleanup;
                        }
                }
+               INSIST(!(dns_kasp_keylist_empty(kasp)));
+       } else if (strcmp(kaspname, "none") == 0) {
+               /* "dnssec-policy none": key list must be empty */
+               INSIST(strcmp(kaspname, "none") == 0);
+               INSIST(dns_kasp_keylist_empty(kasp));
+       } else {
+               /* No keys clause configured, use the "default". */
+               result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
+               if (result != ISC_R_SUCCESS) {
+                       goto cleanup;
+               }
+               INSIST(!(dns_kasp_keylist_empty(kasp)));
        }
-       INSIST(!(dns_kasp_keylist_empty(kasp)));
 
        /* Configuration: NSEC3 */
        (void)confget(maps, "nsec3param", &nsec3);