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
*/
if (dns_zone_getkasp(zone) != NULL) {
dns_zone_rekey(zone, fullsign);
dns_zone_rekey(zone, fullsign, false);
}
cleanup:
@ -12026,7 +12026,7 @@ named_server_rekey(named_server_t *server, isc_lex_t *lex,
if (dns_zone_getkasp(zone) == NULL) {
result = ISC_R_NOPERM;
} else {
dns_zone_rekey(zone, fullsign);
dns_zone_rekey(zone, fullsign, false);
}
dns_zone_detach(&zone);
@ -14358,6 +14358,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
dns_dnsseckeylist_t keys;
char *ptr, *zonetext = NULL;
const char *msg = NULL;
/* variables for -step */
bool forcestep = false;
/* variables for -checkds */
bool checkds = false, dspublish = false;
/* variables for -rollover */
@ -14401,6 +14403,8 @@ named_server_dnssec(named_server_t *server, isc_lex_t *lex,
rollover = true;
} else if (strcasecmp(ptr, "-checkds") == 0) {
checkds = true;
} else if (strcasecmp(ptr, "-step") == 0) {
forcestep = true;
} else {
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
* event may have changed.
*/
dns_zone_rekey(zone, false);
dns_zone_rekey(zone, false, false);
if (use_keyid) {
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
* event may have changed.
*/
dns_zone_rekey(zone, false);
dns_zone_rekey(zone, false, false);
if (use_keyid) {
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)));
break;
}
} else if (forcestep) {
dns_zone_rekey(zone, false, true);
}
CHECK(putnull(text));
cleanup:
@ -16094,7 +16101,7 @@ named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
CHECK(putnull(text));
} else {
/* Schedule a rekey */
dns_zone_rekey(zone, false);
dns_zone_rekey(zone, false, false);
}
cleanup:

View File

@ -21,6 +21,11 @@
#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
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,
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 options, isc_stdtime_t now,
isc_stdtime_t *nexttime);
/*%<
* Manage keys in 'keyring' and update timing data according to 'kasp' policy.
* 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
* 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:
*\li 'origin' is a valid FQDN.
*\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_ZONEVERSION = 1U << 31, /*%< enable zoneversion */
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_t;
@ -2210,7 +2211,7 @@ dns_zone_getprivatetype(dns_zone_t *zone);
*/
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.
*
@ -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
* if the new keys are for algorithms that have already signed the
* 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

View File

@ -342,7 +342,8 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
}
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;
@ -352,17 +353,39 @@ keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
REQUIRE(key != NULL);
REQUIRE(key->key != NULL);
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);
@ -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_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. */
@ -963,7 +981,7 @@ keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring,
*/
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 */
@ -981,7 +999,7 @@ keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type,
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));
}
@ -1220,17 +1238,14 @@ keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key,
*/
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);
@ -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
* 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.
@ -1448,8 +1462,9 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
*/
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:
@ -1534,8 +1549,7 @@ 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(
@ -1572,6 +1586,28 @@ transition:
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 "
@ -1580,7 +1616,6 @@ transition:
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));
@ -1590,6 +1625,8 @@ transition:
/* We changed something, continue processing. */
if (changed) {
/* No longer force for the next run */
force = false;
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,
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;
@ -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) {
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,
@ -1806,7 +1844,6 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
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),
@ -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) {
/* No key available in keyring, create a new one. */
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,
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];
@ -2103,7 +2183,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
/* 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. */
@ -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) {
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) {
@ -2168,7 +2247,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
* Retire excess keys in use.
*/
keymgr_key_retire(dkey, kasp,
now);
opts, now);
}
continue;
}
@ -2206,7 +2285,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
keystr,
keymgr_keyrole(dnskey->key),
dns_kasp_getname(kasp));
rollover_allowed = false;
opts |= DNS_KEYMGRATTR_NOROLL;
active_key = dnskey;
break;
}
@ -2214,10 +2293,11 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
}
/* 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. */
@ -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
* 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) {

View File

@ -21211,7 +21211,7 @@ checkds_done(void *arg) {
/* Rekey after checkds. */
if (rekey) {
dns_zone_rekey(zone, false);
dns_zone_rekey(zone, false, false);
}
failure:
@ -22233,6 +22233,7 @@ zone_rekey(dns_zone_t *zone) {
bool newalg = false;
bool fullsign;
bool offlineksk = false;
uint8_t options = 0;
uint32_t sigval = 0;
dns_ttl_t ttl = 3600;
const char *dir = NULL;
@ -22351,6 +22352,14 @@ zone_rekey(dns_zone_t *zone) {
*/
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) {
/* Lookup the correct bundle in the SKR. */
LOCK_ZONE(zone);
@ -22456,7 +22465,7 @@ zone_rekey(dns_zone_t *zone) {
dns_zone_lock_keyfiles(zone);
result = dns_keymgr_run(&zone->origin, zone->rdclass,
mctx, &keys, &dnskeys, dir,
kasp, now, &nexttime);
kasp, options, now, &nexttime);
dns_zone_unlock_keyfiles(zone);
if (result != ISC_R_SUCCESS) {
@ -22936,6 +22945,13 @@ failure:
0);
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);
dns_diff_clear(&diff);
@ -22974,7 +22990,7 @@ failure:
}
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;
if (zone->type == dns_zone_primary && zone->loop != NULL) {
@ -22983,6 +22999,9 @@ dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
if (fullsign) {
DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FULLSIGN);
}
if (forcekeymgr) {
DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
}
now = isc_time_now();
zone->refreshkeytime = now;