From: Matthijs Mekking Date: Tue, 19 Aug 2025 13:16:39 +0000 (+0200) Subject: Update the retire interval after full sign X-Git-Tag: v9.21.14~21^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=489752eb1f7f4e09bcf96d723ae64158cf785f97;p=thirdparty%2Fbind9.git Update the retire interval after full sign After a full sign we no longer have to need to take the sign delay into account. Update the timing checks in keymgr_transition_time to determine the start of the interval: Either the last change, or if SigPublish/ SigDelete is set. The latter case indicates a full sign was done and so we no longer have to take the sign delay into account. --- diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index a794c9d5bb8..88a488772c0 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -117,7 +117,7 @@ static const char *timingtags[TIMING_NTAGS] = { "DNSKEYChange:", "ZRRSIGChange:", "KRRSIGChange:", "DSChange:", - "DSRemoved:" + "DSRemoved:", "ZRRSIGPublish", "ZRRSIGRemoved" }; #define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1) @@ -1991,6 +1991,8 @@ write_key_state(const dst_key_t *key, int type, const char *directory) { printtime(key, DST_TIME_DELETE, "Removed", fp); printtime(key, DST_TIME_DSPUBLISH, "DSPublish", fp); printtime(key, DST_TIME_DSDELETE, "DSRemoved", fp); + printtime(key, DST_TIME_SIGPUBLISH, "SigPublish", fp); + printtime(key, DST_TIME_SIGDELETE, "SigRemoved", fp); printtime(key, DST_TIME_SYNCPUBLISH, "PublishCDS", fp); printtime(key, DST_TIME_SYNCDELETE, "DeleteCDS", fp); diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c index 5e53a19e494..479d23c603b 100644 --- a/lib/dns/dst_parse.c +++ b/lib/dns/dst_parse.c @@ -54,10 +54,9 @@ #define TIMING_NTAGS (DST_MAX_TIMES + 1) static const char *timetags[TIMING_NTAGS] = { - "Created:", "Publish:", "Activate:", "Revoke:", - "Inactive:", "Delete:", "DSPublish:", "SyncPublish:", - "SyncDelete:", NULL, NULL, NULL, - NULL + "Created:", "Publish:", "Activate:", "Revoke:", "Inactive:", + "Delete:", "DSPublish:", "SyncPublish:", "SyncDelete:", NULL, + NULL, NULL, NULL, NULL, NULL }; #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1) diff --git a/lib/dns/include/dns/keymgr.h b/lib/dns/include/dns/keymgr.h index 8fcc6dbfbbb..8e1508304ac 100644 --- a/lib/dns/include/dns/keymgr.h +++ b/lib/dns/include/dns/keymgr.h @@ -24,7 +24,8 @@ #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 */ +#define DNS_KEYMGRATTR_FORCESTEP 0x04 /*%< Force next step in manual-mode. */ +#define DNS_KEYMGRATTR_FULLSIGN 0x08 /*%< Full sign was issued. */ void dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first); diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h index f3eaa538346..ecd952e845c 100644 --- a/lib/dns/include/dst/dst.h +++ b/lib/dns/include/dst/dst.h @@ -152,7 +152,9 @@ typedef enum dst_algorithm { #define DST_TIME_KRRSIG 11 #define DST_TIME_DS 12 #define DST_TIME_DSDELETE 13 -#define DST_MAX_TIMES 13 +#define DST_TIME_SIGPUBLISH 14 +#define DST_TIME_SIGDELETE 15 +#define DST_MAX_TIMES 15 /* Numeric metadata definitions */ #define DST_NUM_PREDECESSOR 0 diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index bb1f831673a..152c6016bb9 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -1296,9 +1296,9 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type, dst_key_state_t next_state, dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *when) { isc_result_t ret; - isc_stdtime_t lastchange, dstime, nexttime = now; + isc_stdtime_t lastchange, dstime, sigtime, nexttime = now; dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true); - uint32_t dsstate; + uint32_t dsstate, sigstate, signdelay = 0; /* * No need to wait if we move things into an uncertain state. @@ -1352,6 +1352,17 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type, switch (next_state) { case OMNIPRESENT: case HIDDEN: + /* Was there a full sign? */ + sigstate = (next_state == HIDDEN) ? DST_TIME_SIGDELETE + : DST_TIME_SIGPUBLISH; + ret = dst_key_gettime(key->key, sigstate, &sigtime); + if (ret == ISC_R_SUCCESS && sigtime <= now) { + signdelay = 0; + } else { + sigtime = lastchange; + signdelay = dns_kasp_signdelay(kasp); + } + /* * RFC 7583: The retire interval (Iret) is the amount * of time that must elapse after a DNSKEY or @@ -1369,7 +1380,7 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type, * * Dsgn + zone-propagation-delay + max-zone-ttl. */ - nexttime = lastchange + ttlsig + + nexttime = sigtime + ttlsig + dns_kasp_zonepropagationdelay(kasp); /* * Only add the sign delay Dsgn and retire-safety if @@ -1383,7 +1394,7 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type, DST_NUM_SUCCESSOR, &tag); } if (ret == ISC_R_SUCCESS) { - nexttime += dns_kasp_signdelay(kasp) + + nexttime += signdelay + dns_kasp_retiresafety(kasp); } break; @@ -2106,6 +2117,32 @@ dst_key_doublematch(dns_dnsseckey_t *key, dns_kasp_t *kasp) { return matches > 1; } +static void +keymgr_zrrsig(dns_dnsseckeylist_t *keyring, isc_stdtime_t now) { + ISC_LIST_FOREACH(*keyring, dkey, link) { + isc_result_t ret; + bool zsk = false; + + ret = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk); + if (ret == ISC_R_SUCCESS && zsk) { + dst_key_state_t state; + isc_result_t result = dst_key_getstate( + dkey->key, DST_KEY_ZRRSIG, &state); + if (result == ISC_R_SUCCESS) { + if (state == RUMOURED) { + dst_key_settime(dkey->key, + DST_TIME_SIGPUBLISH, + now); + } else if (state == UNRETENTIVE) { + dst_key_settime(dkey->key, + DST_TIME_SIGDELETE, + now); + } + } + } + } +} + /* * Examine 'keys' and match 'kasp' policy. * @@ -2308,6 +2345,11 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, opts |= DNS_KEYMGRATTR_S2I; } + /* In case of a full sign, store ZRRSIGPublish/ZRRSIGDelete. */ + if ((opts & DNS_KEYMGRATTR_FULLSIGN) != 0) { + keymgr_zrrsig(keyring, now); + } + /* Read to update key states. */ isc_result_t retval = keymgr_update(keyring, kasp, now, nexttime, opts); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index fa151311063..901336780a1 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -22460,6 +22460,9 @@ zone_rekey(dns_zone_t *zone) { * fully signed now. */ fullsign = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FULLSIGN); + if (fullsign) { + options |= DNS_KEYMGRATTR_FULLSIGN; + } /* * True when called from "rndc dnssec -step". Indicates the zone