diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index f16d98257b..349aa00f43 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -269,8 +269,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")), @@ -284,7 +284,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); @@ -782,7 +782,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); diff --git a/bin/named/server.c b/bin/named/server.c index 5ce695b5ee..839438161c 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -9121,18 +9121,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); @@ -14528,7 +14535,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; @@ -14647,8 +14653,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); diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 9102367470..2765b77e69 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -913,6 +913,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; @@ -1248,19 +1249,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; @@ -1561,7 +1558,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), @@ -1575,7 +1572,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; @@ -1586,7 +1583,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); @@ -1673,7 +1670,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); @@ -1692,6 +1690,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); } } @@ -2139,11 +2142,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); @@ -2155,6 +2162,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 @@ -2164,51 +2203,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"); } } diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 12b3fa9e0e..4519717fa6 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -960,22 +960,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" diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 3e0b341d39..1473b5385b 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -1015,9 +1015,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; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index af7208f56b..8cee35515f 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -694,6 +694,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); /*%< diff --git a/lib/dns/update.c b/lib/dns/update.c index 43dad7035a..808a636a81 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -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. diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 6e723fe2b8..4747fbdfbd 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -1278,6 +1278,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 @@ -1366,6 +1367,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 diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a6a3e0b683..80d43ce71f 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1830,7 +1830,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); } @@ -5833,6 +5833,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)); @@ -6784,17 +6860,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); @@ -6872,8 +6949,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. @@ -7308,7 +7384,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; @@ -7425,7 +7501,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; @@ -7521,7 +7596,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; } } @@ -9165,6 +9240,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; @@ -9221,7 +9297,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; @@ -9258,16 +9333,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 { @@ -9452,7 +9531,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. @@ -16462,7 +16541,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; } @@ -19747,7 +19826,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; @@ -19818,9 +19897,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); } @@ -19833,9 +19913,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) { @@ -19851,6 +19929,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); @@ -20063,7 +20151,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; diff --git a/lib/isccfg/include/isccfg/kaspconf.h b/lib/isccfg/include/isccfg/kaspconf.h index 0f8ac1dd7e..43f6e690a7 100644 --- a/lib/isccfg/include/isccfg/kaspconf.h +++ b/lib/isccfg/include/isccfg/kaspconf.h @@ -25,22 +25,23 @@ 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: diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index 9a006c8963..3e0e0874f4 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -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);