diff --git a/lib/dns/include/dns/keymgr.h b/lib/dns/include/dns/keymgr.h index 6c7e17ceee..ae4ab5da13 100644 --- a/lib/dns/include/dns/keymgr.h +++ b/lib/dns/include/dns/keymgr.h @@ -26,12 +26,12 @@ ISC_LANG_BEGINDECLS isc_result_t dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, const char *directory, isc_mem_t *mctx, - dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, - isc_stdtime_t now, isc_stdtime_t *nexttime); + dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *dnskeys, + dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime); /*%< - * Manage keys in 'keylist' and update timing data according to 'kasp' policy. + * Manage keys in 'keyring' and update timing data according to 'kasp' policy. * Create new keys for 'origin' if necessary in 'directory'. Append all such - * keys, along with use hints gleaned from their metadata, onto 'keylist'. + * keys, along with use hints gleaned from their metadata, onto 'keyring'. * * Update key states and store changes back to disk. Store when to run next * in 'nexttime'. diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index b4efb3aeb2..02dbd711e2 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -1640,8 +1640,9 @@ static isc_result_t keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key, dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys, const dns_name_t *origin, dns_rdataclass_t rdclass, - dns_kasp_t *kasp, uint32_t lifetime, isc_stdtime_t now, - isc_stdtime_t *nexttime, isc_mem_t *mctx) { + dns_kasp_t *kasp, uint32_t lifetime, bool rollover, + isc_stdtime_t now, isc_stdtime_t *nexttime, + isc_mem_t *mctx) { char keystr[DST_KEY_FORMATSIZE]; isc_stdtime_t retire = 0, active = 0, prepub = 0; dns_dnsseckey_t *new_key = NULL; @@ -1723,6 +1724,20 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key, /* It is time to do key rollover, we need a new key. */ + /* + * If rollover is not allowed, warn. + */ + if (!rollover) { + dst_key_format(active_key->key, keystr, sizeof(keystr)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, + "keymgr: DNSKEY %s (%s) is offline in policy %s, " + "cannot start rollover", + keystr, keymgr_keyrole(active_key->key), + dns_kasp_getname(kasp)); + return (ISC_R_SUCCESS); + } + /* * Check if there is a key available in pool because keys * may have been pregenerated with dnssec-keygen. @@ -1929,8 +1944,8 @@ keymgr_purge_keyfile(dst_key_t *key, const char *dir, int type) { isc_result_t dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, const char *directory, isc_mem_t *mctx, - dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, - isc_stdtime_t now, isc_stdtime_t *nexttime) { + dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *dnskeys, + dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime) { isc_result_t result = ISC_R_SUCCESS; dns_dnsseckeylist_t newkeys; dns_kasp_key_t *kkey; @@ -1974,8 +1989,17 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, dst_key_format(dkey->key, keystr, sizeof(keystr)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), - "keymgr: keyring: dnskey %s (policy %s)", - keystr, dns_kasp_getname(kasp)); + "keymgr: keyring: %s (policy %s)", keystr, + dns_kasp_getname(kasp)); + } + for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*dnskeys); + dkey != NULL; dkey = ISC_LIST_NEXT(dkey, link)) + { + dst_key_format(dkey->key, keystr, sizeof(keystr)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), + "keymgr: dnskeys: %s (policy %s)", keystr, + dns_kasp_getname(kasp)); } } @@ -2029,6 +2053,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, { uint32_t lifetime = dns_kasp_key_lifetime(kkey); dns_dnsseckey_t *active_key = NULL; + bool rollover_allowed = true; /* Do we have keys available for this kasp key? */ for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); @@ -2089,10 +2114,43 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, } } + if (active_key == NULL) { + /* + * We didn't found an active key, perhaps the .private + * key file is offline. If so, we don't want to create + * a successor key. Check if we have an appropriate + * state file. + */ + for (dns_dnsseckey_t *dnskey = ISC_LIST_HEAD(*dnskeys); + dnskey != NULL; + dnskey = ISC_LIST_NEXT(dnskey, link)) + { + if (keymgr_dnsseckey_kaspkey_match(dnskey, + kkey)) { + /* Found a match. */ + dst_key_format(dnskey->key, keystr, + sizeof(keystr)); + isc_log_write( + dns_lctx, + DNS_LOGCATEGORY_DNSSEC, + DNS_LOGMODULE_DNSSEC, + ISC_LOG_DEBUG(1), + "keymgr: DNSKEY %s (%s) " + "offline, policy %s", + keystr, + keymgr_keyrole(dnskey->key), + dns_kasp_getname(kasp)); + rollover_allowed = false; + active_key = dnskey; + break; + } + } + } + /* See if this key requires a rollover. */ - RETERR(keymgr_key_rollover(kkey, active_key, keyring, &newkeys, - origin, rdclass, kasp, lifetime, now, - nexttime, mctx)); + RETERR(keymgr_key_rollover( + kkey, active_key, keyring, &newkeys, origin, rdclass, + kasp, lifetime, rollover_allowed, now, nexttime, mctx)); } /* Walked all kasp key configurations. Append new keys. */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 2f685f4bf6..7d4c910917 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -19974,8 +19974,8 @@ zone_rekey(dns_zone_t *zone) { if (kasp != NULL) { if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) { result = dns_keymgr_run(&zone->origin, zone->rdclass, - dir, mctx, &keys, kasp, now, - &nexttime); + dir, mctx, &keys, &dnskeys, + kasp, now, &nexttime); if (result != ISC_R_SUCCESS) { dnssec_log(zone, ISC_LOG_ERROR, "zone_rekey:dns_dnssec_keymgr "