2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

Implement manual-mode for kasp

When a key retire, key generation/introduction, or a state transition
to RUMOURED/UNRETENTIVE should happen, instead they are logged.
When those logs look good, you can run 'rndc dnssec -step' to run the
keymgr and apply those steps.
This commit is contained in:
Matthijs Mekking 2025-03-19 17:10:25 +01:00
parent 63c5b453e0
commit aa49850b5e
5 changed files with 173 additions and 51 deletions

View File

@ -6612,7 +6612,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
* Ensure that zone keys are reloaded on reconfig * Ensure that zone keys are reloaded on reconfig
*/ */
if (dns_zone_getkasp(zone) != NULL) { if (dns_zone_getkasp(zone) != NULL) {
dns_zone_rekey(zone, fullsign); dns_zone_rekey(zone, fullsign, false);
} }
cleanup: cleanup:
@ -12026,7 +12026,7 @@ named_server_rekey(named_server_t *server, isc_lex_t *lex,
if (dns_zone_getkasp(zone) == NULL) { if (dns_zone_getkasp(zone) == NULL) {
result = ISC_R_NOPERM; result = ISC_R_NOPERM;
} else { } else {
dns_zone_rekey(zone, fullsign); dns_zone_rekey(zone, fullsign, false);
} }
dns_zone_detach(&zone); dns_zone_detach(&zone);
@ -14358,6 +14358,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
dns_dnsseckeylist_t keys; dns_dnsseckeylist_t keys;
char *ptr, *zonetext = NULL; char *ptr, *zonetext = NULL;
const char *msg = NULL; const char *msg = NULL;
/* variables for -step */
bool forcestep = false;
/* variables for -checkds */ /* variables for -checkds */
bool checkds = false, dspublish = false; bool checkds = false, dspublish = false;
/* variables for -rollover */ /* variables for -rollover */
@ -14401,6 +14403,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
rollover = true; rollover = true;
} else if (strcasecmp(ptr, "-checkds") == 0) { } else if (strcasecmp(ptr, "-checkds") == 0) {
checkds = true; checkds = true;
} else if (strcasecmp(ptr, "-step") == 0) {
forcestep = true;
} else { } else {
CHECK(DNS_R_SYNTAX); CHECK(DNS_R_SYNTAX);
} }
@ -14557,7 +14561,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
* Rekey after checkds command because the next key * Rekey after checkds command because the next key
* event may have changed. * event may have changed.
*/ */
dns_zone_rekey(zone, false); dns_zone_rekey(zone, false, false);
if (use_keyid) { if (use_keyid) {
char tagbuf[6]; char tagbuf[6];
@ -14607,7 +14611,7 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
* Rekey after rollover command because the next key * Rekey after rollover command because the next key
* event may have changed. * event may have changed.
*/ */
dns_zone_rekey(zone, false); dns_zone_rekey(zone, false, false);
if (use_keyid) { if (use_keyid) {
char tagbuf[6]; char tagbuf[6];
@ -14631,7 +14635,10 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
CHECK(putstr(text, isc_result_totext(ret))); CHECK(putstr(text, isc_result_totext(ret)));
break; break;
} }
} else if (forcestep) {
dns_zone_rekey(zone, false, true);
} }
CHECK(putnull(text)); CHECK(putnull(text));
cleanup: cleanup:
@ -16094,7 +16101,7 @@ named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
CHECK(putnull(text)); CHECK(putnull(text));
} else { } else {
/* Schedule a rekey */ /* Schedule a rekey */
dns_zone_rekey(zone, false); dns_zone_rekey(zone, false, false);
} }
cleanup: cleanup:

View File

@ -21,6 +21,11 @@
#include <dst/dst.h> #include <dst/dst.h>
#define DNS_KEYMGRATTR_NONE 0x00 /*%< No ordering. */
#define DNS_KEYMGRATTR_S2I 0x01 /*%< Secure to insecure. */
#define DNS_KEYMGRATTR_NOROLL 0x02 /*%< No rollover allowed. */
#define DNS_KEYMGRATTR_FORCESTEP 0x04 /*%< Force next step in manual-mode */
void void
dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first); dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first);
/*%< /*%<
@ -36,7 +41,8 @@ isc_result_t
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
isc_mem_t *mctx, dns_dnsseckeylist_t *keyring, isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
dns_dnsseckeylist_t *dnskeys, const char *keydir, 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 options, isc_stdtime_t now,
isc_stdtime_t *nexttime);
/*%< /*%<
* Manage keys in 'keyring' 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. Append all such keys, along * Create new keys for 'origin' if necessary. Append all such keys, along
@ -45,6 +51,10 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
* Update key states and store changes back to disk. Store when to run next * Update key states and store changes back to disk. Store when to run next
* in 'nexttime'. * in 'nexttime'.
* *
* If 'options' has DNS_KEYMGRATTR_FORCESTEP set, the next steps in the process
* are allowed, even if 'kasp' has 'manual-mode' enabled. Other options should
* not be set in 'options'.
*
* Requires: * Requires:
*\li 'origin' is a valid FQDN. *\li 'origin' is a valid FQDN.
*\li 'mctx' is a valid memory context. *\li 'mctx' is a valid memory context.

View File

@ -104,6 +104,7 @@ typedef enum {
DNS_ZONEOPT_CHECKSVCB = 1 << 30, /*%< check SVBC records */ DNS_ZONEOPT_CHECKSVCB = 1 << 30, /*%< check SVBC records */
DNS_ZONEOPT_ZONEVERSION = 1U << 31, /*%< enable zoneversion */ DNS_ZONEOPT_ZONEVERSION = 1U << 31, /*%< enable zoneversion */
DNS_ZONEOPT_FULLSIGN = 1ULL << 32, /*%< fully sign zone */ DNS_ZONEOPT_FULLSIGN = 1ULL << 32, /*%< fully sign zone */
DNS_ZONEOPT_FORCEKEYMGR = 1ULL << 33, /*%< force keymgr step */
DNS_ZONEOPT___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */ DNS_ZONEOPT___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
} dns_zoneopt_t; } dns_zoneopt_t;
@ -2210,7 +2211,7 @@ dns_zone_getprivatetype(dns_zone_t *zone);
*/ */
void void
dns_zone_rekey(dns_zone_t *zone, bool fullsign); dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr);
/*%< /*%<
* Update the zone's DNSKEY set from the key repository. * Update the zone's DNSKEY set from the key repository.
* *
@ -2218,6 +2219,9 @@ dns_zone_rekey(dns_zone_t *zone, bool fullsign);
* the zone with the new key. Otherwise, if there are no keys or * the zone with the new key. Otherwise, if there are no keys or
* if the new keys are for algorithms that have already signed the * if the new keys are for algorithms that have already signed the
* zone, then the zone can be re-signed incrementally. * zone, then the zone can be re-signed incrementally.
*
* If 'forcekeymgr' is true, trigger a rekey event and allow the
* next steps in the run to happen.
*/ */
isc_result_t isc_result_t

View File

@ -342,7 +342,8 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
} }
static void 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]; char keystr[DST_KEY_FORMATSIZE];
isc_result_t ret; isc_result_t ret;
isc_stdtime_t retire; isc_stdtime_t retire;
@ -352,17 +353,39 @@ keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
REQUIRE(key != NULL); REQUIRE(key != NULL);
REQUIRE(key->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); ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
if (ret != ISC_R_SUCCESS || (retire > now)) { if (ret != ISC_R_SUCCESS || (retire > now)) {
dst_key_settime(key->key, DST_TIME_INACTIVE, now); dst_key_settime(key->key, DST_TIME_INACTIVE, now);
} }
dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN);
keymgr_settime_remove(key, kasp); 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) { if (dst_key_getstate(key->key, DST_KEY_DNSKEY, &s) != ISC_R_SUCCESS) {
dst_key_setstate(key->key, DST_KEY_DNSKEY, OMNIPRESENT); 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_DNSKEY, now);
@ -391,11 +414,6 @@ keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
dst_key_settime(key->key, DST_TIME_ZRRSIG, 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. */ /* Update lifetime and retire and remove time accordingly. */
@ -963,7 +981,7 @@ keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring,
*/ */
static bool static bool
keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type, 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) */ /* (3a) */
dst_key_state_t states[2][NUM_KEYSTATES] = { dst_key_state_t states[2][NUM_KEYSTATES] = {
/* DNSKEY, ZRRSIG, KRRSIG, DS */ /* DNSKEY, ZRRSIG, KRRSIG, DS */
@ -981,7 +999,7 @@ keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
states[0], na, false, false) || states[0], na, false, false) ||
keymgr_key_exists_with_state(keyring, key, type, next_state, keymgr_key_exists_with_state(keyring, key, type, next_state,
states[1], na, false, false) || states[1], na, false, false) ||
(secure_to_insecure && ((opts & DNS_KEYMGRATTR_S2I) != 0 &&
keymgr_key_exists_with_state(keyring, key, type, next_state, na, keymgr_key_exists_with_state(keyring, key, type, next_state, na,
na, false, false)); na, false, false));
} }
@ -1220,17 +1238,14 @@ keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
*/ */
static bool static bool
keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
int type, dst_key_state_t next_state, int type, dst_key_state_t next_state, uint8_t opts) {
bool secure_to_insecure) {
/* Debug logging. */ /* Debug logging. */
if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) { if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b; bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b;
char keystr[DST_KEY_FORMATSIZE]; char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key->key, keystr, sizeof(keystr)); dst_key_format(key->key, keystr, sizeof(keystr));
rule1a = keymgr_have_ds(keyring, key, type, NA, rule1a = keymgr_have_ds(keyring, key, type, NA, opts);
secure_to_insecure); rule1b = keymgr_have_ds(keyring, key, type, next_state, opts);
rule1b = keymgr_have_ds(keyring, key, type, next_state,
secure_to_insecure);
rule2a = keymgr_have_dnskey(keyring, key, type, NA); rule2a = keymgr_have_dnskey(keyring, key, type, NA);
rule2b = keymgr_have_dnskey(keyring, key, type, next_state); rule2b = keymgr_have_dnskey(keyring, key, type, next_state);
rule3a = keymgr_have_rrsig(keyring, key, type, NA); rule3a = keymgr_have_rrsig(keyring, key, type, NA);
@ -1255,9 +1270,8 @@ keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
* invalid state. If the rule check passes, also check if * invalid state. If the rule check passes, also check if
* the next state is also still a valid situation. * 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, NA, opts) ||
keymgr_have_ds(keyring, key, type, next_state, keymgr_have_ds(keyring, key, type, next_state, opts)) &&
secure_to_insecure)) &&
/* /*
* Rule 2: There must be a DNSKEY at all times. Again, first * Rule 2: There must be a DNSKEY at all times. Again, first
* check the current situation, then assess the next state. * check the current situation, then assess the next state.
@ -1448,8 +1462,9 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
*/ */
static isc_result_t static isc_result_t
keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now, 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 changed;
bool force = ((opts & DNS_KEYMGRATTR_FORCESTEP) != 0);
/* Repeat until nothing changed. */ /* Repeat until nothing changed. */
transition: transition:
@ -1534,8 +1549,7 @@ transition:
/* Is the transition DNSSEC safe? */ /* Is the transition DNSSEC safe? */
if (!keymgr_transition_allowed(keyring, dkey, i, if (!keymgr_transition_allowed(keyring, dkey, i,
next_state, next_state, opts))
secure_to_insecure))
{ {
/* No, this would make the zone bogus. */ /* No, this would make the zone bogus. */
isc_log_write( isc_log_write(
@ -1572,6 +1586,28 @@ transition:
continue; 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, isc_log_write(DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
"keymgr: transition %s %s type %s " "keymgr: transition %s %s type %s "
@ -1580,7 +1616,6 @@ transition:
keystatetags[i], keystatestrings[state], keystatetags[i], keystatestrings[state],
keystatestrings[next_state]); keystatestrings[next_state]);
/* It is safe to make the transition. */
dst_key_setstate(dkey->key, i, next_state); dst_key_setstate(dkey->key, i, next_state);
dst_key_settime(dkey->key, keystatetimes[i], now); dst_key_settime(dkey->key, keystatetimes[i], now);
INSIST(dst_key_ismodified(dkey->key)); INSIST(dst_key_ismodified(dkey->key));
@ -1590,6 +1625,8 @@ transition:
/* We changed something, continue processing. */ /* We changed something, continue processing. */
if (changed) { if (changed) {
/* No longer force for the next run */
force = false;
goto transition; goto transition;
} }
@ -1716,9 +1753,10 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys, dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys,
const dns_name_t *origin, dns_rdataclass_t rdclass, const dns_name_t *origin, dns_rdataclass_t rdclass,
dns_kasp_t *kasp, const char *keydir, uint32_t lifetime, 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) { isc_mem_t *mctx) {
char keystr[DST_KEY_FORMATSIZE]; char keystr[DST_KEY_FORMATSIZE];
char namestr[DNS_NAME_FORMATSIZE];
isc_stdtime_t retire = 0, active = 0, prepub = 0; isc_stdtime_t retire = 0, active = 0, prepub = 0;
dns_dnsseckey_t *new_key = NULL; dns_dnsseckey_t *new_key = NULL;
dst_key_t *dst_key = NULL; dst_key_t *dst_key = NULL;
@ -1795,7 +1833,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
/* /*
* If rollover is not allowed, warn. * If rollover is not allowed, warn.
*/ */
if (!rollover) { if ((opts & DNS_KEYMGRATTR_NOROLL) != 0) {
dst_key_format(active_key->key, keystr, sizeof(keystr)); dst_key_format(active_key->key, keystr, sizeof(keystr));
isc_log_write(DNS_LOGCATEGORY_DNSSEC, isc_log_write(DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
@ -1806,7 +1844,6 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
} }
} else if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) { } else if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) {
char namestr[DNS_NAME_FORMATSIZE];
dns_name_format(origin, namestr, sizeof(namestr)); dns_name_format(origin, namestr, sizeof(namestr));
isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC,
ISC_LOG_DEBUG(1), ISC_LOG_DEBUG(1),
@ -1830,6 +1867,49 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
} }
} }
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) { if (new_key == NULL) {
/* No key available in keyring, create a new one. */ /* No key available in keyring, create a new one. */
bool csk = (dns_kasp_key_ksk(kaspkey) && bool csk = (dns_kasp_key_ksk(kaspkey) &&
@ -2039,10 +2119,10 @@ isc_result_t
dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
isc_mem_t *mctx, dns_dnsseckeylist_t *keyring, isc_mem_t *mctx, dns_dnsseckeylist_t *keyring,
dns_dnsseckeylist_t *dnskeys, const char *keydir, 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; isc_result_t result = ISC_R_SUCCESS;
dns_dnsseckeylist_t newkeys; dns_dnsseckeylist_t newkeys;
bool secure_to_insecure = false;
int numkeys = 0; int numkeys = 0;
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE); int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
char keystr[DST_KEY_FORMATSIZE]; char keystr[DST_KEY_FORMATSIZE];
@ -2103,7 +2183,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
/* No match, so retire unwanted retire key. */ /* No match, so retire unwanted retire key. */
if (!found_match) { if (!found_match) {
keymgr_key_retire(dkey, kasp, now); keymgr_key_retire(dkey, kasp, opts, now);
} }
/* Check purge-keys interval. */ /* Check purge-keys interval. */
@ -2129,7 +2209,6 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) { ISC_LIST_FOREACH(dns_kasp_keys(kasp), kkey, link) {
uint32_t lifetime = dns_kasp_key_lifetime(kkey); uint32_t lifetime = dns_kasp_key_lifetime(kkey);
dns_dnsseckey_t *active_key = NULL; dns_dnsseckey_t *active_key = NULL;
bool rollover_allowed = true;
/* Do we have keys available for this kasp key? */ /* Do we have keys available for this kasp key? */
ISC_LIST_FOREACH(*keyring, dkey, link) { ISC_LIST_FOREACH(*keyring, dkey, link) {
@ -2168,7 +2247,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
* Retire excess keys in use. * Retire excess keys in use.
*/ */
keymgr_key_retire(dkey, kasp, keymgr_key_retire(dkey, kasp,
now); opts, now);
} }
continue; continue;
} }
@ -2206,7 +2285,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
keystr, keystr,
keymgr_keyrole(dnskey->key), keymgr_keyrole(dnskey->key),
dns_kasp_getname(kasp)); dns_kasp_getname(kasp));
rollover_allowed = false; opts |= DNS_KEYMGRATTR_NOROLL;
active_key = dnskey; active_key = dnskey;
break; break;
} }
@ -2214,10 +2293,11 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
} }
/* See if this key requires a rollover. */ /* See if this key requires a rollover. */
RETERR(keymgr_key_rollover(kkey, active_key, keyring, &newkeys, RETERR(keymgr_key_rollover(
origin, rdclass, kasp, keydir, kkey, active_key, keyring, &newkeys, origin, rdclass,
lifetime, rollover_allowed, now, kasp, keydir, lifetime, opts, now, nexttime, mctx));
nexttime, mctx));
opts &= ~DNS_KEYMGRATTR_NOROLL;
} }
/* Walked all kasp key configurations. Append new keys. */ /* Walked all kasp key configurations. Append new keys. */
@ -2229,10 +2309,12 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
* If the policy has an empty key list, this means the zone is going * If the policy has an empty key list, this means the zone is going
* back to unsigned. * 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. */ /* 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. */ /* Store key states and update hints. */
ISC_LIST_FOREACH(*keyring, dkey, link) { ISC_LIST_FOREACH(*keyring, dkey, link) {

View File

@ -21211,7 +21211,7 @@ checkds_done(void *arg) {
/* Rekey after checkds. */ /* Rekey after checkds. */
if (rekey) { if (rekey) {
dns_zone_rekey(zone, false); dns_zone_rekey(zone, false, false);
} }
failure: failure:
@ -22233,6 +22233,7 @@ zone_rekey(dns_zone_t *zone) {
bool newalg = false; bool newalg = false;
bool fullsign; bool fullsign;
bool offlineksk = false; bool offlineksk = false;
uint8_t options = 0;
uint32_t sigval = 0; uint32_t sigval = 0;
dns_ttl_t ttl = 3600; dns_ttl_t ttl = 3600;
const char *dir = NULL; const char *dir = NULL;
@ -22351,6 +22352,14 @@ zone_rekey(dns_zone_t *zone) {
*/ */
fullsign = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FULLSIGN); fullsign = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FULLSIGN);
/*
* True when called from "rndc dnssec -step". Indicates the zone
* is allowed to do the next step(s) in the keymgr process.
*/
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FORCEKEYMGR)) {
options |= DNS_KEYMGRATTR_FORCESTEP;
}
if (offlineksk) { if (offlineksk) {
/* Lookup the correct bundle in the SKR. */ /* Lookup the correct bundle in the SKR. */
LOCK_ZONE(zone); LOCK_ZONE(zone);
@ -22456,7 +22465,7 @@ zone_rekey(dns_zone_t *zone) {
dns_zone_lock_keyfiles(zone); dns_zone_lock_keyfiles(zone);
result = dns_keymgr_run(&zone->origin, zone->rdclass, result = dns_keymgr_run(&zone->origin, zone->rdclass,
mctx, &keys, &dnskeys, dir, mctx, &keys, &dnskeys, dir,
kasp, now, &nexttime); kasp, options, now, &nexttime);
dns_zone_unlock_keyfiles(zone); dns_zone_unlock_keyfiles(zone);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
@ -22936,6 +22945,13 @@ failure:
0); 0);
isc_time_nowplusinterval(&zone->refreshkeytime, &ival); isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
} }
/*
* Clear forcekeymgr flag, if it was set, so we don't do
* another force next time.
*/
DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
dns_diff_clear(&diff); dns_diff_clear(&diff);
@ -22974,7 +22990,7 @@ failure:
} }
void void
dns_zone_rekey(dns_zone_t *zone, bool fullsign) { dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr) {
isc_time_t now; isc_time_t now;
if (zone->type == dns_zone_primary && zone->loop != NULL) { if (zone->type == dns_zone_primary && zone->loop != NULL) {
@ -22983,6 +22999,9 @@ dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
if (fullsign) { if (fullsign) {
DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FULLSIGN); DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FULLSIGN);
} }
if (forcekeymgr) {
DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
}
now = isc_time_now(); now = isc_time_now();
zone->refreshkeytime = now; zone->refreshkeytime = now;