}
static void
-keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
+keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, uint8_t opts,
+ isc_stdtime_t now) {
char keystr[DST_KEY_FORMATSIZE];
isc_result_t ret;
isc_stdtime_t retire;
REQUIRE(key != NULL);
REQUIRE(key->key != NULL);
- /* This key wants to retire and hide in a corner. */
+ dst_key_format(key->key, keystr, sizeof(keystr));
+
+ ret = dst_key_getstate(key->key, DST_KEY_GOAL, &s);
+ INSIST(ret == ISC_R_SUCCESS);
+
+ if (dns_kasp_manualmode(kasp) &&
+ (opts & DNS_KEYMGRATTR_FORCESTEP) == 0 && s != HIDDEN)
+ {
+ isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_INFO,
+ "keymgr-manual-mode: block retire DNSKEY "
+ "%s (%s)",
+ keystr, keymgr_keyrole(key->key));
+ return;
+ } else {
+ /* This key wants to retire and hide in a corner. */
+ isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)",
+ keystr, keymgr_keyrole(key->key));
+
+ dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
+ }
+
+ /*
+ * This key may not have key states set yet. Pretend as if they are
+ * in the OMNIPRESENT state.
+ */
ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
if (ret != ISC_R_SUCCESS || (retire > now)) {
dst_key_settime(key->key, DST_TIME_INACTIVE, now);
}
- dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
keymgr_settime_remove(key, kasp);
- /* This key may not have key states set yet. Pretend as if they are
- * in the OMNIPRESENT state.
- */
if (dst_key_getstate(key->key, DST_KEY_DNSKEY, &s) != ISC_R_SUCCESS) {
dst_key_setstate(key->key, DST_KEY_DNSKEY, OMNIPRESENT);
dst_key_settime(key->key, DST_TIME_DNSKEY, now);
dst_key_settime(key->key, DST_TIME_ZRRSIG, now);
}
}
-
- dst_key_format(key->key, keystr, sizeof(keystr));
- isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
- ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)", keystr,
- keymgr_keyrole(key->key));
}
/* Update lifetime and retire and remove time accordingly. */
*/
static bool
keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
- dst_key_state_t next_state, bool secure_to_insecure) {
+ dst_key_state_t next_state, uint8_t opts) {
/* (3a) */
dst_key_state_t states[2][NUM_KEYSTATES] = {
/* DNSKEY, ZRRSIG, KRRSIG, DS */
states[0], na, false, false) ||
keymgr_key_exists_with_state(keyring, key, type, next_state,
states[1], na, false, false) ||
- (secure_to_insecure &&
+ ((opts & DNS_KEYMGRATTR_S2I) != 0 &&
keymgr_key_exists_with_state(keyring, key, type, next_state, na,
na, false, false));
}
*/
static bool
keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
- int type, dst_key_state_t next_state,
- bool secure_to_insecure) {
+ int type, dst_key_state_t next_state, uint8_t opts) {
/* Debug logging. */
if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b;
char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key->key, keystr, sizeof(keystr));
- rule1a = keymgr_have_ds(keyring, key, type, NA,
- secure_to_insecure);
- rule1b = keymgr_have_ds(keyring, key, type, next_state,
- secure_to_insecure);
+ rule1a = keymgr_have_ds(keyring, key, type, NA, opts);
+ rule1b = keymgr_have_ds(keyring, key, type, next_state, opts);
rule2a = keymgr_have_dnskey(keyring, key, type, NA);
rule2b = keymgr_have_dnskey(keyring, key, type, next_state);
rule3a = keymgr_have_rrsig(keyring, key, type, NA);
* invalid state. If the rule check passes, also check if
* the next state is also still a valid situation.
*/
- (!keymgr_have_ds(keyring, key, type, NA, secure_to_insecure) ||
- keymgr_have_ds(keyring, key, type, next_state,
- secure_to_insecure)) &&
+ (!keymgr_have_ds(keyring, key, type, NA, opts) ||
+ keymgr_have_ds(keyring, key, type, next_state, opts)) &&
/*
* Rule 2: There must be a DNSKEY at all times. Again, first
* check the current situation, then assess the next state.
*/
static isc_result_t
keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now,
- isc_stdtime_t *nexttime, bool secure_to_insecure) {
+ isc_stdtime_t *nexttime, uint8_t opts) {
bool changed;
+ bool force = ((opts & DNS_KEYMGRATTR_FORCESTEP) != 0);
/* Repeat until nothing changed. */
transition:
/* Is the transition DNSSEC safe? */
if (!keymgr_transition_allowed(keyring, dkey, i,
- next_state,
- secure_to_insecure))
+ next_state, opts))
{
/* No, this would make the zone bogus. */
isc_log_write(
continue;
}
+ /*
+ * Are we allowed to make the transition automatically?
+ */
+ if (next_state != OMNIPRESENT && next_state != HIDDEN) {
+ if (dns_kasp_manualmode(kasp) && !force) {
+ isc_log_write(
+ DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_INFO,
+ "keymgr-manual-mode: block "
+ "transition "
+ "%s %s type %s "
+ "state %s to state %s",
+ keymgr_keyrole(dkey->key),
+ keystr, keystatetags[i],
+ keystatestrings[state],
+ keystatestrings[next_state]);
+ continue;
+ }
+ }
+
+ /* It is safe to make the transition. */
isc_log_write(DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
"keymgr: transition %s %s type %s "
keystatetags[i], keystatestrings[state],
keystatestrings[next_state]);
- /* It is safe to make the transition. */
dst_key_setstate(dkey->key, i, next_state);
dst_key_settime(dkey->key, keystatetimes[i], now);
INSIST(dst_key_ismodified(dkey->key));
/* We changed something, continue processing. */
if (changed) {
+ /* No longer force for the next run */
+ force = false;
goto transition;
}
dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys,
const dns_name_t *origin, dns_rdataclass_t rdclass,
dns_kasp_t *kasp, const char *keydir, uint32_t lifetime,
- bool rollover, isc_stdtime_t now, isc_stdtime_t *nexttime,
+ uint8_t opts, isc_stdtime_t now, isc_stdtime_t *nexttime,
isc_mem_t *mctx) {
char keystr[DST_KEY_FORMATSIZE];
+ char namestr[DNS_NAME_FORMATSIZE];
isc_stdtime_t retire = 0, active = 0, prepub = 0;
dns_dnsseckey_t *new_key = NULL;
dst_key_t *dst_key = NULL;
/*
* If rollover is not allowed, warn.
*/
- if (!rollover) {
+ if ((opts & DNS_KEYMGRATTR_NOROLL) != 0) {
dst_key_format(active_key->key, keystr, sizeof(keystr));
isc_log_write(DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
return ISC_R_SUCCESS;
}
} else if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
- char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(origin, namestr, sizeof(namestr));
isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
ISC_LOG_DEBUG(1),
}
}
+ if (dns_kasp_manualmode(kasp) && (opts & DNS_KEYMGRATTR_FORCESTEP) == 0)
+ {
+ if (active_key != NULL && new_key != NULL) {
+ char keystr2[DST_KEY_FORMATSIZE];
+ dst_key_format(active_key->key, keystr, sizeof(keystr));
+ dst_key_format(new_key->key, keystr2, sizeof(keystr2));
+ dns_name_format(origin, namestr, sizeof(namestr));
+ isc_log_write(
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
+ ISC_LOG_INFO,
+ "keymgr-manual-mode: block %s rollover for key "
+ "%s to key %s (policy %s)",
+ keymgr_keyrole(active_key->key), keystr,
+ keystr2, dns_kasp_getname(kasp));
+ } else if (active_key != NULL) {
+ dst_key_format(active_key->key, keystr, sizeof(keystr));
+ dns_name_format(origin, namestr, sizeof(namestr));
+ isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+ "keymgr-manual-mode: block %s rollover "
+ "for key %s (policy %s)",
+ keymgr_keyrole(active_key->key), keystr,
+ dns_kasp_getname(kasp));
+ } else if (new_key != NULL) {
+ dst_key_format(new_key->key, keystr, sizeof(keystr));
+ dns_name_format(origin, namestr, sizeof(namestr));
+ isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+ "keymgr-manual-mode: block %s "
+ "introduction %s (policy %s)",
+ keymgr_keyrole(new_key->key), keystr,
+ dns_kasp_getname(kasp));
+ } else {
+ dns_name_format(origin, namestr, sizeof(namestr));
+ isc_log_write(DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
+ "keymgr-manual-mode: block new key "
+ "generation for zone %s (policy %s)",
+ namestr, dns_kasp_getname(kasp));
+ }
+ return ISC_R_SUCCESS;
+ }
+
if (new_key == NULL) {
/* No key available in keyring, create a new one. */
bool csk = (dns_kasp_key_ksk(kaspkey) &&
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
dns_dnsseckeylist_t *dnskeys, const char *keydir,
- dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime) {
+ dns_kasp_t *kasp, uint8_t opts, isc_stdtime_t now,
+ isc_stdtime_t *nexttime) {
isc_result_t result = ISC_R_SUCCESS;
dns_dnsseckeylist_t newkeys;
- bool secure_to_insecure = false;
int numkeys = 0;
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
char keystr[DST_KEY_FORMATSIZE];
/* No match, so retire unwanted retire key. */
if (!found_match) {
- keymgr_key_retire(dkey, kasp, now);
+ keymgr_key_retire(dkey, kasp, opts, now);
}
/* Check purge-keys interval. */
ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
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? */
ISC_LIST_FOREACH(*keyring, dkey, link) {
* Retire excess keys in use.
*/
keymgr_key_retire(dkey, kasp,
- now);
+ opts, now);
}
continue;
}
keystr,
keymgr_keyrole(dnskey->key),
dns_kasp_getname(kasp));
- rollover_allowed = false;
+ opts |= DNS_KEYMGRATTR_NOROLL;
active_key = dnskey;
break;
}
}
/* See if this key requires a rollover. */
- RETERR(keymgr_key_rollover(kkey, active_key, keyring, &newkeys,
- origin, rdclass, kasp, keydir,
- lifetime, rollover_allowed, now,
- nexttime, mctx));
+ RETERR(keymgr_key_rollover(
+ kkey, active_key, keyring, &newkeys, origin, rdclass,
+ kasp, keydir, lifetime, opts, now, nexttime, mctx));
+
+ opts &= ~DNS_KEYMGRATTR_NOROLL;
}
/* Walked all kasp key configurations. Append new keys. */
* If the policy has an empty key list, this means the zone is going
* back to unsigned.
*/
- secure_to_insecure = dns_kasp_keylist_empty(kasp);
+ if (dns_kasp_keylist_empty(kasp)) {
+ opts |= DNS_KEYMGRATTR_S2I;
+ }
/* Read to update key states. */
- keymgr_update(keyring, kasp, now, nexttime, secure_to_insecure);
+ keymgr_update(keyring, kasp, now, nexttime, opts);
/* Store key states and update hints. */
ISC_LIST_FOREACH(*keyring, dkey, link) {