]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update the retire interval after full sign
authorMatthijs Mekking <matthijs@isc.org>
Tue, 19 Aug 2025 13:16:39 +0000 (15:16 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Fri, 26 Sep 2025 12:36:25 +0000 (14:36 +0200)
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.

(cherry picked from commit 489752eb1f7f4e09bcf96d723ae64158cf785f97)

lib/dns/dst_api.c
lib/dns/dst_parse.c
lib/dns/include/dns/keymgr.h
lib/dns/include/dst/dst.h
lib/dns/keymgr.c
lib/dns/zone.c

index 11edd569949c77b23850aa9fb11e28a48219ae75..c823fdac5f061b8767fa2408c783d02892ae37ca 100644 (file)
@@ -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)
@@ -2116,6 +2116,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);
 
index eb2a116b19770827381c347200429d8b74fcc0fa..a6967ad47e3ebe0638e12ca7b6066dafa915198d 100644 (file)
 
 #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)
index a0508f1f5fcd9c280a921b9d373ab6c3c8a4e868..30d05b78cd2f35302bdf6018bbf8e4e957edbb6c 100644 (file)
@@ -27,7 +27,8 @@ ISC_LANG_BEGINDECLS
 #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);
index a08a6092fad64b3fee3caf0c1b89ad2e3db1ab8b..1a6920753c09e71d7f1b8f17a002dbee473e8272 100644 (file)
@@ -147,7 +147,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
index 72edb27c6667e1c807fe002b050fdf031c007815..4f8f7cad765b04444aa7ec9e8bcfd18ba434997d 100644 (file)
@@ -1314,9 +1314,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.
@@ -1370,6 +1370,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
@@ -1387,7 +1398,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
@@ -1401,7 +1412,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;
@@ -2137,6 +2148,34 @@ 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) {
+       for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
+            dkey = ISC_LIST_NEXT(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.
  *
@@ -2359,6 +2398,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);
 
index 09cf734eaa92fa2b30e17d348e0233e26a3b0172..96fdf6b66d5e0784f98b29d96d1b1c16a1256087 100644 (file)
@@ -22553,6 +22553,9 @@ zone_rekey(dns_zone_t *zone) {
         * fully signed now.
         */
        fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
+       if (fullsign) {
+               options |= DNS_KEYMGRATTR_FULLSIGN;
+       }
 
        /*
         * True when called from "rndc dnssec -step". Indicates the zone