]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
dnssec-policy: to sign inline or not
authorMatthijs Mekking <matthijs@isc.org>
Wed, 8 Apr 2020 11:08:20 +0000 (13:08 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Thu, 16 Apr 2020 12:22:47 +0000 (14:22 +0200)
When dnssec-policy was introduced, it implicitly set inline-signing.
But DNSSEC maintenance required either inline-signing to be enabled,
or a dynamic zone.  In other words, not in all cases you want to
DNSSEC maintain your zone with inline-signing.

Change the behavior and determine whether inline-signing is
required: if the zone is dynamic, don't use inline-signing,
otherwise implicitly set it.

You can also explicitly set inline-signing to yes with dnssec-policy,
the restriction that both inline-signing and dnssec-policy cannot
be set at the same time is now lifted.

However, 'inline-signing no;' on a non-dynamic zone with a
dnssec-policy is not possible.

bin/named/server.c
bin/tests/system/checkconf/kasp-and-other-dnssec-options.conf
bin/tests/system/checkconf/tests.sh
bin/tests/system/kasp/ns3/named.conf.in
bin/tests/system/kasp/ns3/setup.sh
bin/tests/system/kasp/tests.sh
lib/bind9/check.c
lib/dns/zone.c

index 3a927b01bd4f953017f5551a935dcf571502dc22..3c4f8cf9a6a65f4c5ca6e6df371f5033bd667d9e 100644 (file)
@@ -6053,6 +6053,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
        dns_zone_t *raw = NULL;   /* New or reused raw zone */
        dns_zone_t *dupzone = NULL;
        const cfg_obj_t *options = NULL;
+       const cfg_obj_t *voptions = NULL;
        const cfg_obj_t *zoptions = NULL;
        const cfg_obj_t *typeobj = NULL;
        const cfg_obj_t *forwarders = NULL;
@@ -6071,11 +6072,16 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
        const char *ztypestr;
        dns_rpz_num_t rpz_num;
        bool zone_is_catz = false;
+       bool zone_maybe_inline = false;
+       bool inline_signing = false;
 
        options = NULL;
        (void)cfg_map_get(config, "options", &options);
 
        zoptions = cfg_tuple_get(zconfig, "options");
+       if (vconfig != NULL) {
+               voptions = cfg_tuple_get(vconfig, "options");
+       }
 
        /*
         * Get the zone origin as a dns_name_t.
@@ -6408,19 +6414,71 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
         */
        dns_zone_setadded(zone, added);
 
+       /*
+        * Determine if we need to set up inline signing.
+        */
+       zone_maybe_inline = ((strcasecmp(ztypestr, "primary") == 0 ||
+                             strcasecmp(ztypestr, "master") == 0 ||
+                             strcasecmp(ztypestr, "secondary") == 0 ||
+                             strcasecmp(ztypestr, "slave") == 0));
+
+       signing = NULL;
+       inline_signing = (zone_maybe_inline &&
+                         ((cfg_map_get(zoptions, "inline-signing", &signing) ==
+                                   ISC_R_SUCCESS &&
+                           cfg_obj_asboolean(signing))));
+
+       /*
+        * If inline-signing is not set, perhaps implictly through a
+        * dnssec-policy.  Since automated DNSSEC maintenance requires
+        * a dynamic zone, or inline-siging to be enabled, check if
+        * the zone with dnssec-policy allows updates.  If not, enable
+        * inline-signing.
+        */
        signing = NULL;
-       if ((strcasecmp(ztypestr, "primary") == 0 ||
-            strcasecmp(ztypestr, "master") == 0 ||
-            strcasecmp(ztypestr, "secondary") == 0 ||
-            strcasecmp(ztypestr, "slave") == 0) &&
-           ((cfg_map_get(zoptions, "inline-signing", &signing) ==
-                     ISC_R_SUCCESS &&
-             cfg_obj_asboolean(signing)) ||
-            (cfg_map_get(zoptions, "dnssec-policy", &signing) ==
-                     ISC_R_SUCCESS &&
-             signing != NULL &&
-             strcmp(cfg_obj_asstring(signing), "none") != 0)))
+       if (zone_maybe_inline && !inline_signing &&
+           cfg_map_get(zoptions, "dnssec-policy", &signing) == ISC_R_SUCCESS &&
+           signing != NULL && strcmp(cfg_obj_asstring(signing), "none") != 0)
        {
+               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,
+                                                        mctx, 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 (inline_signing) {
                dns_zone_getraw(zone, &raw);
                if (raw == NULL) {
                        CHECK(dns_zone_create(&raw, mctx));
index d7c1bf812329573bc56988c51c74336e08fc489b..a3eae44f7382768cb2cd243fa8247540800ad772 100644 (file)
@@ -20,9 +20,8 @@ zone "nsec3.net" {
        dnssec-dnskey-kskonly yes;
        dnssec-secure-to-insecure yes;
        dnssec-update-mode maintain;
-       inline-signing yes;
+       inline-signing no;
        sig-validity-interval 3600;
        update-check-ksk yes;
-       allow-update { any; };
 };
 
index ba8b314cb61b5db1dbb4e584848b2de5956fe6d0..270975bfe6c5b6483d2db51245ab47009d7226f6 100644 (file)
@@ -478,12 +478,12 @@ n=`expr $n + 1`
 echo_i "checking named-checkconf kasp errors ($n)"
 ret=0
 $CHECKCONF kasp-and-other-dnssec-options.conf > checkconf.out$n 2>&1 && ret=1
+grep "'inline-signing;' cannot be set to 'no' if dnssec-policy is also set on a non-dynamic DNS zone" < checkconf.out$n > /dev/null || ret=1
 grep "'auto-dnssec maintain;' cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "dnskey-sig-validity: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "dnssec-dnskey-kskonly: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "dnssec-secure-to-insecure: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "dnssec-update-mode: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
-grep "inline-signing: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "sig-validity-interval: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 grep "update-check-ksk: cannot be configured if dnssec-policy is also set" < checkconf.out$n > /dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; fi
index da7c04734e5f5f10e5d344f93f52cd5b9bee2873..8b71cab1f06c46eb9b104dcd854ad3360f0fb874 100644 (file)
@@ -87,6 +87,31 @@ zone "secondary.kasp" {
        dnssec-policy "rsasha1";
 };
 
+/* A dynamic zone with dnssec-policy. */
+zone "dynamic.kasp" {
+       type master;
+       file "dynamic.kasp.db";
+       dnssec-policy "default";
+       allow-update { any; };
+};
+
+/* A dynamic inline-signed zone with dnssec-policy. */
+zone "dynamic-inline-signing.kasp" {
+       type master;
+       file "dynamic-inline-signing.kasp.db";
+       dnssec-policy "default";
+       allow-update { any; };
+       inline-signing yes;
+};
+
+/* An inline-signed zone with dnssec-policy. */
+zone "inline-signing.kasp" {
+       type master;
+       file "inline-signing.kasp.db";
+       dnssec-policy "default";
+       inline-signing yes;
+};
+
 /*
  * A configured dnssec-policy but some keys already created.
  */
index 5be0f0b0c049573e7ca2b8033df6c1055fcc9ae1..354993364289b69040957dca42d2f7f9e6d4f386 100644 (file)
@@ -44,6 +44,7 @@ U="UNRETENTIVE"
 #
 for zn in default rsasha1 dnssec-keygen some-keys legacy-keys pregenerated \
          rumoured rsasha1-nsec3 rsasha256 rsasha512 ecdsa256 ecdsa384 \
+         dynamic dynamic-inline-signing inline-signing \
          inherit unlimited
 do
        setup "${zn}.kasp"
index da770695cb7e1e254cb51fe59d548257fb32ddc1..fee431d3eebe6d0af6f63552135d0d17d0ea0eca 100644 (file)
@@ -713,164 +713,6 @@ status=$((status+ret))
 
 next_key_event_threshold=$((next_key_event_threshold+i))
 
-#
-# Zone: default.kasp.
-#
-
-# Check the zone with default kasp policy has loaded and is signed.
-set_zone "default.kasp"
-set_policy "default" "1" "3600"
-set_server "ns3" "10.53.0.3"
-# Key properties.
-set_keyrole      "KEY1" "csk"
-set_keylifetime  "KEY1" "0"
-set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
-set_keysigning   "KEY1" "yes"
-set_zonesigning  "KEY1" "yes"
-
-# The first key is immediately published and activated.
-set_keytime  "KEY1" "PUBLISHED"    "yes"
-set_keytime  "KEY1" "ACTIVE"       "yes"
-# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
-set_keystate "KEY1" "GOAL"         "omnipresent"
-set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
-set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
-set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
-set_keystate "KEY1" "STATE_DS"     "hidden"
-
-n=$((n+1))
-echo_i "check key is created for zone ${ZONE} ($n)"
-ret=0
-ids=$(get_keyids "$DIR" "$ZONE")
-for id in $ids; do
-       check_key "KEY1" "$id"
-done
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status+ret))
-
-# Verify signed zone.
-dnssec_verify "$ZONE"
-
-# Test DNSKEY query.
-qtype="DNSKEY"
-n=$((n+1))
-echo_i "check ${qtype} rrset is signed correctly for zone ${ZONE} ($n)"
-ret=0
-dig_with_opts "$ZONE" "@${SERVER}" $qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${qtype} failed"
-grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
-grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${qtype}.*257.*.3.*$(key_get KEY1 ALG_NUM)" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${qtype} record in response"
-lines=$(get_keys_which_signed $qtype "dig.out.$DIR.test$n" | wc -l)
-test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-get_keys_which_signed $qtype "dig.out.$DIR.test$n" | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status+ret))
-
-# Test SOA query.
-qtype="SOA"
-n=$((n+1))
-echo_i "check ${qtype} rrset is signed correctly for zone ${ZONE} ($n)"
-ret=0
-dig_with_opts "$ZONE" "@${SERVER}" $qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${qtype} failed"
-grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
-grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*${qtype}.*mname1\..*\." "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${qtype} record in response"
-lines=$(get_keys_which_signed $qtype "dig.out.$DIR.test$n" | wc -l)
-test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-get_keys_which_signed $qtype "dig.out.$DIR.test$n" | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status+ret))
-
-# Update zone.
-n=$((n+1))
-echo_i "check that we can update unsigned zone file and new record gets signed for zone ${ZONE} ($n)"
-ret=0
-cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
-rndccmd 10.53.0.3 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
-_log=0
-i=0
-while [ $i -lt 5 ]
-do
-       ret=0
-
-       dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || log_error "dig a.${ZONE} A failed"
-       grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || log_error "mismatch status in DNS response"
-       grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" > /dev/null || log_error "missing a.${ZONE} A record in response"
-       lines=$(get_keys_which_signed A "dig.out.$DIR.test$n.a" | wc -l)
-       test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-       get_keys_which_signed A "dig.out.$DIR.test$n.a" | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
-
-       dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n".d || log_error "dig d.${ZONE} A failed"
-       grep "status: NOERROR" "dig.out.$DIR.test$n".d > /dev/null || log_error "mismatch status in DNS response"
-       grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n".d > /dev/null || log_error "missing d.${ZONE} A record in response"
-       lines=$(get_keys_which_signed A "dig.out.$DIR.test$n".d | wc -l)
-       test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
-       get_keys_which_signed A "dig.out.$DIR.test$n".d | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
-
-       i=$((i+1))
-       if [ $ret = 0 ]; then break; fi
-       echo_i "waiting ... ($i)"
-       sleep 1
-done
-_log=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status+ret))
-
-#
-# Zone: rsasha1.kasp.
-#
-set_zone "rsasha1.kasp"
-set_policy "rsasha1" "3" "1234"
-set_server "ns3" "10.53.0.3"
-# Key properties.
-key_clear        "KEY1"
-set_keyrole      "KEY1" "ksk"
-set_keylifetime  "KEY1" "315360000"
-set_keyalgorithm "KEY1" "5" "RSASHA1" "2048"
-set_keysigning   "KEY1" "yes"
-set_zonesigning  "KEY1" "no"
-
-key_clear        "KEY2"
-set_keyrole      "KEY2" "zsk"
-set_keylifetime  "KEY2" "157680000"
-set_keyalgorithm "KEY2" "5" "RSASHA1" "2048"
-set_keysigning   "KEY2" "no"
-set_zonesigning  "KEY2" "yes"
-
-key_clear        "KEY3"
-set_keyrole      "KEY3" "zsk"
-set_keylifetime  "KEY3" "31536000"
-set_keyalgorithm "KEY3" "5" "RSASHA1" "2000"
-set_keysigning   "KEY3" "no"
-set_zonesigning  "KEY3" "yes"
-# The first keys are immediately published and activated.
-# Because lifetime > 0, retired timing is also set.
-set_keytime  "KEY1" "PUBLISHED"    "yes"
-set_keytime  "KEY1" "ACTIVE"       "yes"
-set_keytime  "KEY1" "RETIRED"      "yes"
-
-set_keytime  "KEY2" "PUBLISHED"    "yes"
-set_keytime  "KEY2" "ACTIVE"       "yes"
-set_keytime  "KEY2" "RETIRED"      "yes"
-
-set_keytime  "KEY3" "PUBLISHED"    "yes"
-set_keytime  "KEY3" "ACTIVE"       "yes"
-set_keytime  "KEY3" "RETIRED"      "yes"
-# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
-# ZSK: DNSKEY, RRSIG (zsk) published.
-set_keystate "KEY1" "GOAL"         "omnipresent"
-set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
-set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
-set_keystate "KEY1" "STATE_DS"     "hidden"
-
-set_keystate "KEY2" "GOAL"         "omnipresent"
-set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
-set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
-
-set_keystate "KEY3" "GOAL"         "omnipresent"
-set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
-set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
-# Three keys only.
-key_clear "KEY4"
-
 # Check keys for a configured zone. This verifies:
 # 1. The right number of keys exist in the key pool ($1).
 # 2. The right number of keys is active. Checks KEY1, KEY2, KEY3, and KEY4.
@@ -1174,6 +1016,164 @@ check_subdomain() {
        status=$((status+ret))
 }
 
+#
+# Zone: default.kasp.
+#
+
+# Check the zone with default kasp policy has loaded and is signed.
+set_zone "default.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+set_keyrole      "KEY1" "csk"
+set_keylifetime  "KEY1" "0"
+set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
+set_keysigning   "KEY1" "yes"
+set_zonesigning  "KEY1" "yes"
+
+# The first key is immediately published and activated.
+set_keytime  "KEY1" "PUBLISHED"    "yes"
+set_keytime  "KEY1" "ACTIVE"       "yes"
+# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
+set_keystate "KEY1" "GOAL"         "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_ZRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS"     "hidden"
+
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+# Update zone.
+n=$((n+1))
+echo_i "check that we can update unsigned zone file and new record gets signed for zone ${ZONE} ($n)"
+ret=0
+cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
+rndccmd 10.53.0.3 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
+_log=0
+i=0
+while [ $i -lt 5 ]
+do
+       ret=0
+
+       dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || log_error "dig a.${ZONE} A failed"
+       grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || log_error "mismatch status in DNS response"
+       grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" > /dev/null || log_error "missing a.${ZONE} A record in response"
+       lines=$(get_keys_which_signed A "dig.out.$DIR.test$n.a" | wc -l)
+       test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
+       get_keys_which_signed A "dig.out.$DIR.test$n.a" | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
+
+       dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n".d || log_error "dig d.${ZONE} A failed"
+       grep "status: NOERROR" "dig.out.$DIR.test$n".d > /dev/null || log_error "mismatch status in DNS response"
+       grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n".d > /dev/null || log_error "missing d.${ZONE} A record in response"
+       lines=$(get_keys_which_signed A "dig.out.$DIR.test$n".d | wc -l)
+       test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
+       get_keys_which_signed A "dig.out.$DIR.test$n".d | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
+
+       i=$((i+1))
+       if [ $ret = 0 ]; then break; fi
+       echo_i "waiting ... ($i)"
+       sleep 1
+done
+_log=1
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+#
+# Zone: dynamic.kasp
+#
+set_zone "dynamic.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: dynamic-inline-signing.kasp
+#
+set_zone "dynamic-inline-signing.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: inline-signing.kasp
+#
+set_zone "inline-signing.kasp"
+set_policy "default" "1" "3600"
+set_server "ns3" "10.53.0.3"
+# Key properties, timings and states same as above.
+check_keys
+check_apex
+check_subdomain
+dnssec_verify
+
+#
+# Zone: rsasha1.kasp.
+#
+set_zone "rsasha1.kasp"
+set_policy "rsasha1" "3" "1234"
+set_server "ns3" "10.53.0.3"
+# Key properties.
+key_clear        "KEY1"
+set_keyrole      "KEY1" "ksk"
+set_keylifetime  "KEY1" "315360000"
+set_keyalgorithm "KEY1" "5" "RSASHA1" "2048"
+set_keysigning   "KEY1" "yes"
+set_zonesigning  "KEY1" "no"
+
+key_clear        "KEY2"
+set_keyrole      "KEY2" "zsk"
+set_keylifetime  "KEY2" "157680000"
+set_keyalgorithm "KEY2" "5" "RSASHA1" "2048"
+set_keysigning   "KEY2" "no"
+set_zonesigning  "KEY2" "yes"
+
+key_clear        "KEY3"
+set_keyrole      "KEY3" "zsk"
+set_keylifetime  "KEY3" "31536000"
+set_keyalgorithm "KEY3" "5" "RSASHA1" "2000"
+set_keysigning   "KEY3" "no"
+set_zonesigning  "KEY3" "yes"
+# The first keys are immediately published and activated.
+# Because lifetime > 0, retired timing is also set.
+set_keytime  "KEY1" "PUBLISHED"    "yes"
+set_keytime  "KEY1" "ACTIVE"       "yes"
+set_keytime  "KEY1" "RETIRED"      "yes"
+
+set_keytime  "KEY2" "PUBLISHED"    "yes"
+set_keytime  "KEY2" "ACTIVE"       "yes"
+set_keytime  "KEY2" "RETIRED"      "yes"
+
+set_keytime  "KEY3" "PUBLISHED"    "yes"
+set_keytime  "KEY3" "ACTIVE"       "yes"
+set_keytime  "KEY3" "RETIRED"      "yes"
+# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
+# ZSK: DNSKEY, RRSIG (zsk) published.
+set_keystate "KEY1" "GOAL"         "omnipresent"
+set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
+set_keystate "KEY1" "STATE_DS"     "hidden"
+
+set_keystate "KEY2" "GOAL"         "omnipresent"
+set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
+
+set_keystate "KEY3" "GOAL"         "omnipresent"
+set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
+set_keystate "KEY3" "STATE_ZRRSIG" "rumoured"
+# Three keys only.
+key_clear "KEY4"
+
 check_keys
 check_apex
 check_subdomain
index 3668bf90f37f39dd6df5d6b83d37e51e8dc62192..c1f8503b00cb23aef305e199889600c87b2ca1cd 100644 (file)
@@ -2275,9 +2275,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                        for (element = cfg_list_first(kasps); element != NULL;
                             element = cfg_list_next(element))
                        {
-                               const char *kn = cfg_obj_asstring(cfg_tuple_get(
-                                       cfg_listelt_value(element), "name"));
-                               if (strcmp(kaspname, kn) == 0) {
+                               const cfg_obj_t *kobj = cfg_tuple_get(
+                                       cfg_listelt_value(element), "name");
+                               if (strcmp(kaspname, cfg_obj_asstring(kobj)) ==
+                                   0) {
                                        has_dnssecpolicy = true;
                                }
                        }
@@ -2495,13 +2496,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                res1 = cfg_map_get(zoptions, "inline-signing", &obj);
                if (res1 == ISC_R_SUCCESS) {
                        signing = cfg_obj_asboolean(obj);
-               }
-
-               if (signing && has_dnssecpolicy) {
-                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
-                                   "inline-signing: cannot be configured if "
-                                   "dnssec-policy is also set");
-                       result = ISC_R_FAILURE;
+                       if (has_dnssecpolicy && !ddns && !signing) {
+                               cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                           "'inline-signing;' cannot be set "
+                                           "to 'no' "
+                                           "if dnssec-policy is also set on a "
+                                           "non-dynamic DNS zone");
+                               result = ISC_R_FAILURE;
+                       }
                }
 
                obj = NULL;
@@ -2511,7 +2513,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                        arg = cfg_obj_asstring(obj);
                }
                if (strcasecmp(arg, "off") != 0) {
-                       if (!ddns && !signing) {
+                       if (!ddns && !signing && strcasecmp(arg, "off") != 0) {
                                cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
                                            "'auto-dnssec %s;' requires%s "
                                            "inline-signing to be configured "
@@ -2524,7 +2526,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                                                                       : "");
                                result = ISC_R_FAILURE;
                        }
-                       if (has_dnssecpolicy) {
+
+                       if (strcasecmp(arg, "off") != 0 && has_dnssecpolicy) {
                                cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
                                            "'auto-dnssec %s;' cannot be "
                                            "configured if dnssec-policy is "
index 4ba75ef52d447546faf700a25f1d080803c3ae23..05121323af1b085b149e92ad336fd85358a0e371 100644 (file)
@@ -1809,6 +1809,11 @@ dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
                return (true);
        }
 
+       /* Kasp zones are always dynamic. */
+       if (dns_zone_getkasp(zone) != NULL) {
+               return (true);
+       }
+
        /* If !ignore_freeze, we need check whether updates are disabled.  */
        if (zone->type == dns_zone_master &&
            (!zone->update_disabled || ignore_freeze) &&
@@ -2054,8 +2059,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
                goto cleanup;
        }
 
-       is_dynamic = dns_zone_isdynamic(zone, false) ||
-                    dns_zone_getkasp(zone) != NULL;
+       is_dynamic = dns_zone_isdynamic(zone, false);
        if (zone->db != NULL && is_dynamic) {
                /*
                 * This is a slave, stub, dynamically updated, or kasp enabled
@@ -3909,7 +3913,6 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
        bool dynamic = (zone->type == dns_zone_master)
                               ? dns_zone_isdynamic(zone, false)
                               : false;
-       dynamic = dynamic || dns_zone_getkasp(zone);
 
        dns_rdataset_init(&rdataset);
        result = dns_db_findnode(db, &zone->origin, false, &node);
@@ -4842,8 +4845,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
         * journal file if it isn't, as we wouldn't be able to apply
         * updates otherwise.
         */
-       is_dynamic = dns_zone_isdynamic(zone, true) ||
-                    dns_zone_getkasp(zone) != NULL;
+       is_dynamic = dns_zone_isdynamic(zone, true);
        if (zone->journal != NULL && is_dynamic &&
            !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
        {
@@ -5140,8 +5142,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                        resume_addnsec3chain(zone);
                }
 
-               is_dynamic = dns_zone_isdynamic(zone, false) ||
-                            dns_zone_getkasp(zone) != NULL;
+               is_dynamic = dns_zone_isdynamic(zone, false);
                if (zone->type == dns_zone_master &&
                    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
                    is_dynamic && dns_db_issecure(db))
@@ -20928,8 +20929,7 @@ dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
        LOCK_ZONE(zone);
 
        if (!inline_secure(zone)) {
-               if (!dns_zone_isdynamic(zone, true) &&
-                   dns_zone_getkasp(zone) == NULL) {
+               if (!dns_zone_isdynamic(zone, true)) {
                        result = DNS_R_NOTDYNAMIC;
                        goto failure;
                }