--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-policy "bad-lifetime-ksk" {
+ /*
+ * The KSK lifetime is too short.
+ * The ZSK lifetime is good enough but should trigger a warning.
+ */
+ keys {
+ ksk lifetime PT3H algorithm 13;
+ zsk lifetime P8DT2H1S algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+dnssec-policy "bad-lifetime-zsk" {
+ /*
+ * The ZSK lifetime is too short.
+ * The KSK lifetime is good enough but should trigger a warning.
+ */
+ keys {
+ ksk lifetime PT3H1S algorithm 13;
+ zsk lifetime P8DT2H algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+dnssec-policy "bad-lifetime-csk" {
+ /*
+ * The CSK lifetime is too short.
+ */
+ keys {
+ csk lifetime PT3H algorithm 13;
+ };
+
+ dnskey-ttl PT1H;
+ publish-safety PT1H;
+ retire-safety PT1H;
+ zone-propagation-delay PT1H;
+ max-zone-ttl P1D;
+ signatures-validity P10D;
+ signatures-refresh P3D;
+ parent-ds-ttl PT1H;
+ parent-propagation-delay PT5M;
+};
+
+zone "bad-lifetime-ksk.example.net" {
+ type primary;
+ file "bad-lifetime-ksk.example.db";
+ dnssec-policy "bad-lifetime-ksk";
+};
+
+zone "bad-lifetime-zsk.example.net" {
+ type primary;
+ file "bad-lifetime-zsk.example.db";
+ dnssec-policy "bad-lifetime-zsk";
+};
+
+zone "bad-lifetime-csk.example.net" {
+ type primary;
+ file "bad-lifetime-csk.example.db";
+ dnssec-policy "bad-lifetime-csk";
+};
*/
static isc_result_t
cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
- isc_log_t *logctx) {
+ isc_log_t *logctx, uint32_t ksk_min_lifetime,
+ uint32_t zsk_min_lifetime) {
isc_result_t result;
dns_kasp_key_t *key = NULL;
const char *rolestr = NULL;
const cfg_obj_t *obj = NULL;
isc_consttextregion_t alg;
+ bool error = false;
rolestr = cfg_obj_asstring(cfg_tuple_get(config, "role"));
if (strcmp(rolestr, "ksk") == 0) {
if (cfg_obj_isduration(obj)) {
key->lifetime = cfg_obj_asduration(obj);
}
- if (key->lifetime > 0 && key->lifetime < 30 * (24 * 3600)) {
- cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
- "dnssec-policy: key lifetime is shorter "
- "than 30 days");
+ if (key->lifetime > 0) {
+ if (key->lifetime < 30 * (24 * 3600)) {
+ cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
+ "dnssec-policy: key lifetime is "
+ "shorter than 30 days");
+ }
+ if ((key->role & DNS_KASP_KEY_ROLE_KSK) != 0 &&
+ key->lifetime <= ksk_min_lifetime)
+ {
+ error = true;
+ }
+ if ((key->role & DNS_KASP_KEY_ROLE_ZSK) != 0 &&
+ key->lifetime <= zsk_min_lifetime)
+ {
+ error = true;
+ }
+ if (error) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "dnssec-policy: key lifetime is "
+ "shorter than the time it takes to "
+ "do a rollover");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
}
obj = cfg_tuple_get(config, "algorithm");
dns_kasp_t *kasp = NULL;
size_t i = 0;
uint32_t sigrefresh = 0, sigvalidity = 0;
+ uint32_t ipub = 0, iret = 0;
+ uint32_t ksk_min_lifetime = 0, zsk_min_lifetime = 0;
REQUIRE(kaspp != NULL && *kaspp == NULL);
DNS_KASP_SIG_REFRESH);
dns_kasp_setsigrefresh(kasp, sigrefresh);
- sigvalidity = get_duration(maps, "signatures-validity",
- DNS_KASP_SIG_VALIDITY);
- if (sigrefresh >= (sigvalidity * 0.9)) {
- cfg_obj_log(config, logctx, ISC_LOG_ERROR,
- "dnssec-policy: policy '%s' signatures-refresh "
- "must be at most 90%% of the signatures-validity",
- kaspname);
- result = ISC_R_FAILURE;
- }
- dns_kasp_setsigvalidity(kasp, sigvalidity);
-
sigvalidity = get_duration(maps, "signatures-validity-dnskey",
DNS_KASP_SIG_VALIDITY_DNSKEY);
if (sigrefresh >= (sigvalidity * 0.9)) {
}
dns_kasp_setsigvalidity_dnskey(kasp, sigvalidity);
+ sigvalidity = get_duration(maps, "signatures-validity",
+ DNS_KASP_SIG_VALIDITY);
+ if (sigrefresh >= (sigvalidity * 0.9)) {
+ cfg_obj_log(config, logctx, ISC_LOG_ERROR,
+ "dnssec-policy: policy '%s' signatures-refresh "
+ "must be at most 90%% of the signatures-validity",
+ kaspname);
+ result = ISC_R_FAILURE;
+ }
+ dns_kasp_setsigvalidity(kasp, sigvalidity);
+
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
dns_kasp_setpurgekeys(
kasp, get_duration(maps, "purge-keys", DNS_KASP_PURGE_KEYS));
+ ipub = get_duration(maps, "dnskey-ttl", DNS_KASP_KEY_TTL) +
+ get_duration(maps, "publish-safety", DNS_KASP_PUBLISH_SAFETY) +
+ get_duration(maps, "zone-propagation-delay",
+ DNS_KASP_ZONE_PROPDELAY);
+
+ iret = get_duration(maps, "parent-ds-ttl", DNS_KASP_DS_TTL) +
+ get_duration(maps, "retire-safety", DNS_KASP_RETIRE_SAFETY) +
+ get_duration(maps, "parent-propagation-delay",
+ DNS_KASP_PARENT_PROPDELAY);
+
+ ksk_min_lifetime = ISC_MAX(ipub, iret);
+
+ iret = (sigvalidity - sigrefresh) +
+ get_duration(maps, "max-zone-ttl", DNS_KASP_ZONE_MAXTTL) +
+ get_duration(maps, "retire-safety", DNS_KASP_RETIRE_SAFETY) +
+ get_duration(maps, "zone-propagation-delay",
+ DNS_KASP_ZONE_PROPDELAY);
+
+ zsk_min_lifetime = ISC_MAX(ipub, iret);
+
(void)confget(maps, "keys", &keys);
if (keys != NULL) {
char role[256] = { 0 };
element = cfg_list_next(element))
{
cfg_obj_t *kobj = cfg_listelt_value(element);
- result = cfg_kaspkey_fromconfig(kobj, kasp, logctx);
+ result = cfg_kaspkey_fromconfig(kobj, kasp, logctx,
+ ksk_min_lifetime,
+ zsk_min_lifetime);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
INSIST(dns_kasp_keylist_empty(kasp));
} else {
/* No keys clause configured, use the "default". */
- result = cfg_kaspkey_fromconfig(NULL, kasp, logctx);
+ result = cfg_kaspkey_fromconfig(NULL, kasp, logctx, 0, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}