*
*/
+isc_result_t
+dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
+ const char *directory, isc_stdtime_t now,
+ isc_stdtime_t when, dns_keytag_t id,
+ unsigned int algorithm);
+/*%<
+ * Rollover key with given 'id'. If the 'algorithm' is non-zero, it must
+ * match the key's algorithm. The changes are stored in the key state file.
+ *
+ * A rollover means adjusting the key metadata so that keymgr will start the
+ * actual rollover on the next run. Update the 'inactive' time and adjust
+ * key lifetime to match the 'when' to rollover time.
+ *
+ * The 'when' time may be in the past. In that case keymgr will roll the
+ * key as soon as possible.
+ *
+ * The 'when' time may be in the future. This may extend the lifetime,
+ * overriding the default lifetime from the policy.
+ *
+ * Requires:
+ *\li 'kasp' is not NULL.
+ *\li 'keyring' is not NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS (No error).
+ *\li #ISC_R_FAILURE (More than one matching keys found).
+ *\li #ISC_R_NOTFOUND (No matching keys found).
+ *\li #ISC_R_UNEXPECTED (Key is not active).
+ *
+ */
+
void
dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
isc_stdtime_t now, char *out, size_t out_len);
"key rrsig: ", DST_KEY_KRRSIG);
}
}
+
+isc_result_t
+dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
+ const char *directory, isc_stdtime_t now,
+ isc_stdtime_t when, dns_keytag_t id,
+ unsigned int algorithm) {
+ int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE);
+ isc_dir_t dir;
+ isc_result_t result;
+ dns_dnsseckey_t *key = NULL;
+ isc_stdtime_t active, retire, prepub;
+
+ REQUIRE(DNS_KASP_VALID(kasp));
+ REQUIRE(keyring != NULL);
+
+ for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
+ dkey = ISC_LIST_NEXT(dkey, link))
+ {
+ if (dst_key_id(dkey->key) != id) {
+ continue;
+ }
+ if (algorithm > 0 && dst_key_alg(dkey->key) != algorithm) {
+ continue;
+ }
+ if (key != NULL) {
+ /*
+ * Only rollover for one key at a time.
+ */
+ return (ISC_R_FAILURE);
+ }
+ key = dkey;
+ }
+
+ if (key == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
+ if (result != ISC_R_SUCCESS) {
+ /**
+ * Default to as if this key was not scheduled to
+ * become retired, as if it had unlimited lifetime.
+ */
+ retire = 0;
+ }
+
+ /**
+ * Usually when is set to now, which is before the scheduled
+ * prepublication time, meaning we reduce the lifetime of the
+ * key. But in some cases, the lifetime can also be extended.
+ * We accept it, but we can return an error here if that
+ * turns out to be unintuitive behavior.
+ */
+ prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) +
+ dns_kasp_zonepropagationdelay(kasp);
+ retire = when + prepub;
+
+ dst_key_settime(key->key, DST_TIME_INACTIVE, retire);
+ dst_key_setnum(key->key, DST_NUM_LIFETIME, (retire - active));
+
+ /* Store key state and update hints. */
+ isc_dir_init(&dir);
+ if (directory == NULL) {
+ directory = ".";
+ }
+ result = isc_dir_open(&dir, directory);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
+
+ dns_dnssec_get_hints(key, now);
+ result = dst_key_tofile(key->key, options, directory);
+ isc_dir_close(&dir);
+
+ return (result);
+}