]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Check if key metadata is modified before writing
authorMatthijs Mekking <matthijs@isc.org>
Tue, 3 May 2022 10:28:31 +0000 (12:28 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Mon, 16 May 2022 08:37:23 +0000 (10:37 +0200)
Add a new parameter to the dst_key structure, mark a key modified if
dst_key_(un)set[bool,num,state,time] is called. Only write out key
files during a keymgr run if the metadata has changed.

(cherry picked from commit 1da91b3ab46b3d875213a473595e671d9ff9c76f)

lib/dns/dst_api.c
lib/dns/dst_internal.h
lib/dns/include/dst/dst.h
lib/dns/keymgr.c

index d7d28aace6732dfc0d871e151cb16c1e3bb87efd..f36f087fd0e9cbe6f71b78b0b942ac2892b9150b 100644 (file)
@@ -469,6 +469,16 @@ dst_key_isexternal(dst_key_t *key) {
        return (key->external);
 }
 
+void
+dst_key_setmodified(dst_key_t *key, bool value) {
+       key->modified = value;
+}
+
+bool
+dst_key_ismodified(dst_key_t *key) {
+       return (key->modified);
+}
+
 isc_result_t
 dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
                    int type, const char *directory, isc_mem_t *mctx,
@@ -610,6 +620,7 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
            (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
        {
                RETERR(computeid(pubkey));
+               pubkey->modified = false;
                *keyp = pubkey;
                pubkey = NULL;
                goto out;
@@ -663,6 +674,7 @@ dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
                RETERR(DST_R_INVALIDPRIVATEKEY);
        }
 
+       key->modified = false;
        *keyp = key;
        key = NULL;
 
@@ -1016,6 +1028,8 @@ dst_key_setbool(dst_key_t *key, int type, bool value) {
        REQUIRE(type <= DST_MAX_BOOLEAN);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || !key->boolset[type] ||
+                       key->bools[type] != value;
        key->bools[type] = value;
        key->boolset[type] = true;
        isc_mutex_unlock(&key->mdlock);
@@ -1027,6 +1041,7 @@ dst_key_unsetbool(dst_key_t *key, int type) {
        REQUIRE(type <= DST_MAX_BOOLEAN);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || key->boolset[type];
        key->boolset[type] = false;
        isc_mutex_unlock(&key->mdlock);
 }
@@ -1054,6 +1069,8 @@ dst_key_setnum(dst_key_t *key, int type, uint32_t value) {
        REQUIRE(type <= DST_MAX_NUMERIC);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || !key->numset[type] ||
+                       key->nums[type] != value;
        key->nums[type] = value;
        key->numset[type] = true;
        isc_mutex_unlock(&key->mdlock);
@@ -1065,6 +1082,7 @@ dst_key_unsetnum(dst_key_t *key, int type) {
        REQUIRE(type <= DST_MAX_NUMERIC);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || key->numset[type];
        key->numset[type] = false;
        isc_mutex_unlock(&key->mdlock);
 }
@@ -1091,6 +1109,8 @@ dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
        REQUIRE(type <= DST_MAX_TIMES);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || !key->timeset[type] ||
+                       key->times[type] != when;
        key->times[type] = when;
        key->timeset[type] = true;
        isc_mutex_unlock(&key->mdlock);
@@ -1102,6 +1122,7 @@ dst_key_unsettime(dst_key_t *key, int type) {
        REQUIRE(type <= DST_MAX_TIMES);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || key->timeset[type];
        key->timeset[type] = false;
        isc_mutex_unlock(&key->mdlock);
 }
@@ -1129,6 +1150,8 @@ dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) {
        REQUIRE(type <= DST_MAX_KEYSTATES);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || !key->keystateset[type] ||
+                       key->keystates[type] != state;
        key->keystates[type] = state;
        key->keystateset[type] = true;
        isc_mutex_unlock(&key->mdlock);
@@ -1140,6 +1163,7 @@ dst_key_unsetstate(dst_key_t *key, int type) {
        REQUIRE(type <= DST_MAX_KEYSTATES);
 
        isc_mutex_lock(&key->mdlock);
+       key->modified = key->modified || key->keystateset[type];
        key->keystateset[type] = false;
        isc_mutex_unlock(&key->mdlock);
 }
@@ -2704,4 +2728,6 @@ dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) {
                        dst_key_unsetstate(to, i);
                }
        }
+
+       dst_key_setmodified(to, dst_key_ismodified(from));
 }
index 9a0b3ac905c9eed31a64068c74c60f8d76e50f73..9f5e8ee3b60d08e876c36d43664e687369a3d114 100644 (file)
@@ -122,6 +122,7 @@ struct dst_key {
        bool inactive; /*%< private key not present as it is
                        * inactive */
        bool external; /*%< external key */
+       bool modified; /*%< set to true if key file metadata has changed */
 
        int fmt_major; /*%< private key format, major version
                        * */
index c53a1adccfdc72f4d8dfc3c5b020f8ce4f958a6e..8fe32ab15c03081d2aea7310ac413ad8e736581e 100644 (file)
@@ -1106,6 +1106,26 @@ dst_key_isexternal(dst_key_t *key);
  *     'key' to be valid.
  */
 
+void
+dst_key_setmodified(dst_key_t *key, bool value);
+/*%<
+ * If 'value' is true, this marks the key to indicate that key file metadata
+ * has been modified. If 'value' is false, this resets the value, for example
+ * after you have written the key to file.
+ *
+ * Requires:
+ *     'key' to be valid.
+ */
+
+bool
+dst_key_ismodified(dst_key_t *key);
+/*%<
+ * Check if the key file has been modified.
+ *
+ * Requires:
+ *     'key' to be valid.
+ */
+
 bool
 dst_key_haskasp(dst_key_t *key);
 /*%<
index 204298548abef173044a54644ca26d95f4fa1111..ddd9a9a58395b89b908ccf9883a13f88d99b522c 100644 (file)
@@ -1511,6 +1511,7 @@ transition:
                        /* 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));
                        changed = true;
                }
        }
@@ -2182,9 +2183,10 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
        for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
             dkey = ISC_LIST_NEXT(dkey, link))
        {
-               if (!dkey->purge) {
+               if (dst_key_ismodified(dkey->key) && !dkey->purge) {
                        dns_dnssec_get_hints(dkey, now);
                        RETERR(dst_key_tofile(dkey->key, options, directory));
+                       dst_key_setmodified(dkey->key, false);
                }
        }
 
@@ -2204,6 +2206,13 @@ 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 done", namebuf);
+       }
        return (result);
 }
 
@@ -2281,6 +2290,9 @@ keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
 
        dns_dnssec_get_hints(ksk_key, now);
        result = dst_key_tofile(ksk_key->key, options, directory);
+       if (result == ISC_R_SUCCESS) {
+               dst_key_setmodified(ksk_key->key, false);
+       }
        isc_dir_close(&dir);
 
        return (result);
@@ -2581,6 +2593,9 @@ dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring,
 
        dns_dnssec_get_hints(key, now);
        result = dst_key_tofile(key->key, options, directory);
+       if (result == ISC_R_SUCCESS) {
+               dst_key_setmodified(key->key, false);
+       }
        isc_dir_close(&dir);
 
        return (result);