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:
parent
63c5b453e0
commit
aa49850b5e
@ -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:
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
164
lib/dns/keymgr.c
164
lib/dns/keymgr.c
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user