mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-03 13:59:27 -04:00
Update key states in offline-ksk mode
With offline-ksk enabled, we don't run the keymgr because the key
timings are determined by the SKR. We do update the key states but
we derive them from the timing metadata.
Then, we can skip a other tasks in offline-ksk mode, like DS checking
at the parent and CDS synchronization, because the CDS and CDNSKEY
RRsets also come from the SKR.
(cherry picked from commit 2190aa904f)
This commit is contained in:
parent
6f6d000103
commit
56814221fd
3 changed files with 227 additions and 15 deletions
|
|
@ -52,6 +52,29 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
|
|||
*\li On error, keypool is unchanged
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_keymgr_offline(const dns_name_t *origin, dns_dnsseckeylist_t *keyring,
|
||||
dns_kasp_t *kasp, isc_stdtime_t now,
|
||||
isc_stdtime_t *nexttime);
|
||||
/*%<
|
||||
* Manage keys in 'keyring' when in offline-ksk mode, and update timing data
|
||||
* according to the metadata in the key files. KSKs are skipped.
|
||||
*
|
||||
* Update key states and store changes back to disk. Store when to run next
|
||||
* in 'nexttime'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'origin' is a valid FQDN.
|
||||
*\li 'mctx' is a valid memory context.
|
||||
*\li 'keyring' is not NULL.
|
||||
*\li 'kasp' is not NULL.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS
|
||||
*\li any error returned by dst_key_getstate(), dst_key_gettime(),
|
||||
* isc_dir_open(), or dst_key_to_file().
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
|
||||
isc_stdtime_t now, isc_stdtime_t when, bool dspublish);
|
||||
|
|
|
|||
174
lib/dns/keymgr.c
174
lib/dns/keymgr.c
|
|
@ -2664,3 +2664,177 @@ dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
|
|||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_keymgr_offline(const dns_name_t *origin, dns_dnsseckeylist_t *keyring,
|
||||
dns_kasp_t *kasp, isc_stdtime_t now,
|
||||
isc_stdtime_t *nexttime) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
|
||||
char keystr[DST_KEY_FORMATSIZE];
|
||||
|
||||
*nexttime = 0;
|
||||
|
||||
/* Store key states and update hints. */
|
||||
for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
|
||||
dkey = ISC_LIST_NEXT(dkey, link))
|
||||
{
|
||||
bool modified;
|
||||
bool ksk = false, zsk = false;
|
||||
isc_stdtime_t active = 0, published = 0, inactive = 0,
|
||||
remove = 0;
|
||||
isc_stdtime_t lastchange = 0, nextchange = 0;
|
||||
dst_key_state_t dnskey_state = HIDDEN, zrrsig_state = HIDDEN,
|
||||
goal_state = HIDDEN;
|
||||
dst_key_state_t current_dnskey, current_zrrsig, current_goal;
|
||||
|
||||
(void)dst_key_role(dkey->key, &ksk, &zsk);
|
||||
if (ksk || !zsk) {
|
||||
continue;
|
||||
}
|
||||
|
||||
keymgr_key_init(dkey, kasp, now, false);
|
||||
|
||||
/* Get current metadata */
|
||||
RETERR(dst_key_getstate(dkey->key, DST_KEY_DNSKEY,
|
||||
¤t_dnskey));
|
||||
RETERR(dst_key_getstate(dkey->key, DST_KEY_ZRRSIG,
|
||||
¤t_zrrsig));
|
||||
RETERR(dst_key_getstate(dkey->key, DST_KEY_GOAL,
|
||||
¤t_goal));
|
||||
RETERR(dst_key_gettime(dkey->key, DST_TIME_PUBLISH,
|
||||
&published));
|
||||
RETERR(dst_key_gettime(dkey->key, DST_TIME_ACTIVATE, &active));
|
||||
RETERR(dst_key_gettime(dkey->key, DST_TIME_INACTIVE,
|
||||
&inactive));
|
||||
RETERR(dst_key_gettime(dkey->key, DST_TIME_DELETE, &remove));
|
||||
|
||||
/* Determine key states from the metadata. */
|
||||
if (active <= now) {
|
||||
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
||||
ttlsig += dns_kasp_zonepropagationdelay(kasp);
|
||||
if ((active + ttlsig) <= now) {
|
||||
zrrsig_state = OMNIPRESENT;
|
||||
} else {
|
||||
zrrsig_state = RUMOURED;
|
||||
(void)dst_key_gettime(dkey->key,
|
||||
DST_TIME_ZRRSIG,
|
||||
&lastchange);
|
||||
nextchange = lastchange + ttlsig +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
}
|
||||
goal_state = OMNIPRESENT;
|
||||
}
|
||||
|
||||
if (published <= now) {
|
||||
dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
|
||||
key_ttl += dns_kasp_zonepropagationdelay(kasp);
|
||||
if ((published + key_ttl) <= now) {
|
||||
dnskey_state = OMNIPRESENT;
|
||||
} else {
|
||||
dnskey_state = RUMOURED;
|
||||
(void)dst_key_gettime(dkey->key,
|
||||
DST_TIME_DNSKEY,
|
||||
&lastchange);
|
||||
nextchange = lastchange + key_ttl +
|
||||
dns_kasp_publishsafety(kasp);
|
||||
}
|
||||
goal_state = OMNIPRESENT;
|
||||
}
|
||||
|
||||
if (inactive <= now) {
|
||||
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
|
||||
ttlsig += dns_kasp_zonepropagationdelay(kasp);
|
||||
if ((inactive + ttlsig) <= now) {
|
||||
zrrsig_state = HIDDEN;
|
||||
} else {
|
||||
zrrsig_state = UNRETENTIVE;
|
||||
(void)dst_key_gettime(dkey->key,
|
||||
DST_TIME_ZRRSIG,
|
||||
&lastchange);
|
||||
nextchange = lastchange + ttlsig +
|
||||
dns_kasp_retiresafety(kasp);
|
||||
}
|
||||
goal_state = HIDDEN;
|
||||
}
|
||||
|
||||
if (remove <= now) {
|
||||
dns_ttl_t key_ttl = dst_key_getttl(dkey->key);
|
||||
key_ttl += dns_kasp_zonepropagationdelay(kasp);
|
||||
if ((remove + key_ttl) <= now) {
|
||||
dnskey_state = HIDDEN;
|
||||
} else {
|
||||
dnskey_state = UNRETENTIVE;
|
||||
(void)dst_key_gettime(dkey->key,
|
||||
DST_TIME_DNSKEY,
|
||||
&lastchange);
|
||||
nextchange =
|
||||
lastchange + key_ttl +
|
||||
dns_kasp_zonepropagationdelay(kasp);
|
||||
}
|
||||
zrrsig_state = HIDDEN;
|
||||
goal_state = HIDDEN;
|
||||
}
|
||||
|
||||
if ((*nexttime == 0 || *nexttime > nextchange) &&
|
||||
nextchange > 0)
|
||||
{
|
||||
*nexttime = nextchange;
|
||||
}
|
||||
|
||||
/* Update key states if necessary. */
|
||||
if (goal_state != current_goal) {
|
||||
dst_key_setstate(dkey->key, DST_KEY_GOAL, goal_state);
|
||||
}
|
||||
if (dnskey_state != current_dnskey) {
|
||||
dst_key_setstate(dkey->key, DST_KEY_DNSKEY,
|
||||
dnskey_state);
|
||||
dst_key_settime(dkey->key, DST_TIME_DNSKEY, now);
|
||||
}
|
||||
if (zrrsig_state != current_zrrsig) {
|
||||
dst_key_setstate(dkey->key, DST_KEY_ZRRSIG,
|
||||
zrrsig_state);
|
||||
dst_key_settime(dkey->key, DST_TIME_ZRRSIG, now);
|
||||
if (zrrsig_state == RUMOURED) {
|
||||
dkey->first_sign = true;
|
||||
}
|
||||
}
|
||||
modified = dst_key_ismodified(dkey->key);
|
||||
|
||||
if (modified) {
|
||||
const char *directory = dst_key_directory(dkey->key);
|
||||
if (directory == NULL) {
|
||||
directory = ".";
|
||||
}
|
||||
|
||||
dns_dnssec_get_hints(dkey, now);
|
||||
|
||||
RETERR(dst_key_tofile(dkey->key, options, directory));
|
||||
dst_key_setmodified(dkey->key, false);
|
||||
|
||||
if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
|
||||
continue;
|
||||
}
|
||||
dst_key_format(dkey->key, keystr, sizeof(keystr));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
|
||||
"keymgr: DNSKEY %s (%s) "
|
||||
"saved to directory %s, policy %s",
|
||||
keystr, keymgr_keyrole(dkey->key),
|
||||
directory, dns_kasp_getname(kasp));
|
||||
}
|
||||
dst_key_setmodified(dkey->key, false);
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
failure:
|
||||
if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
dns_name_format(origin, namebuf, sizeof(namebuf));
|
||||
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
|
||||
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3),
|
||||
"keymgr: %s (offline-ksk) done", namebuf);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22187,7 +22187,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
isc_result_totext(result));
|
||||
}
|
||||
|
||||
if (kasp != NULL) {
|
||||
if (kasp != NULL && !offlineksk) {
|
||||
/*
|
||||
* Check DS at parental agents. Clear ongoing checks.
|
||||
*/
|
||||
|
|
@ -22227,6 +22227,15 @@ zone_rekey(dns_zone_t *zone) {
|
|||
goto failure;
|
||||
}
|
||||
}
|
||||
} else if (offlineksk) {
|
||||
/*
|
||||
* With offline-ksk enabled we don't run the keymgr.
|
||||
* Instead we derive the states from the timing metadata.
|
||||
*/
|
||||
dns_zone_lock_keyfiles(zone);
|
||||
result = dns_keymgr_offline(&zone->origin, &keys, kasp, now,
|
||||
&nexttime);
|
||||
dns_zone_unlock_keyfiles(zone);
|
||||
}
|
||||
|
||||
KASP_UNLOCK(kasp);
|
||||
|
|
@ -22245,6 +22254,25 @@ zone_rekey(dns_zone_t *zone) {
|
|||
bool sane_diff, sane_dnskey;
|
||||
isc_stdtime_t when;
|
||||
|
||||
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
|
||||
&zone->origin, ttl, &diff, mctx,
|
||||
dnssec_report);
|
||||
/*
|
||||
* Keys couldn't be updated for some reason;
|
||||
* try again later.
|
||||
*/
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dnssec_log(zone, ISC_LOG_ERROR,
|
||||
"zone_rekey:couldn't update zone keys: %s",
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (offlineksk) {
|
||||
/* We can skip a lot of things */
|
||||
goto post_sync;
|
||||
}
|
||||
|
||||
/*
|
||||
* Publish CDS/CDNSKEY DELETE records if the zone is
|
||||
* transitioning from secure to insecure.
|
||||
|
|
@ -22310,20 +22338,6 @@ zone_rekey(dns_zone_t *zone) {
|
|||
digests = dns_kasp_digests(zone->defaultkasp);
|
||||
}
|
||||
|
||||
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
|
||||
&zone->origin, ttl, &diff, mctx,
|
||||
dnssec_report);
|
||||
/*
|
||||
* Keys couldn't be updated for some reason;
|
||||
* try again later.
|
||||
*/
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dnssec_log(zone, ISC_LOG_ERROR,
|
||||
"zone_rekey:couldn't update zone keys: %s",
|
||||
isc_result_totext(result));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update CDS / CDNSKEY records.
|
||||
*/
|
||||
|
|
@ -22376,6 +22390,7 @@ zone_rekey(dns_zone_t *zone) {
|
|||
goto failure;
|
||||
}
|
||||
|
||||
post_sync:
|
||||
/*
|
||||
* See if any pre-existing keys have newly become active;
|
||||
* also, see if any new key is for a new algorithm, as in that
|
||||
|
|
|
|||
Loading…
Reference in a new issue