From b021320bea8a37934084a8a21eb20c430e1c4cc7 Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Thu, 2 Sep 2021 16:27:48 +0200
Subject: [PATCH] zonemd: reflect changes in configuration when reloaded

---
 src/knot/updates/zone-update.c              |  3 ++-
 src/knot/zone/digest.c                      | 10 +++++++++-
 src/knot/zone/digest.h                      |  3 ++-
 src/knot/zone/zonedb-load.c                 |  6 ++++++
 tests-extra/tests/zone/zonemd_flush/test.py |  9 ++++++++-
 5 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c
index fac41fb465..16387abdc1 100644
--- a/src/knot/updates/zone-update.c
+++ b/src/knot/updates/zone-update.c
@@ -887,7 +887,8 @@ int zone_update_commit(conf_t *conf, zone_update_t *update)
 	bool do_digest = (digest_alg != ZONE_DIGEST_NONE && !dnssec); // in case of DNSSEC, digest is part of signing routine
 	if (do_digest && !(update->flags & UPDATE_FULL) && zone_update_to(update) == NULL) {
 		// cold start, decide if (digest & bump SOA) or NOOP
-		if (zone_contents_digest_exists(update->new_cont, digest_alg)) { // yes, computing hash twice, but in rare situation: cold start & exists & invalid
+		// yes, computing hash twice, but in rare situation: cold start & exists & invalid
+		if (zone_contents_digest_exists(update->new_cont, digest_alg, false)) {
 			do_digest = false;
 		} else {
 			ret = zone_update_increment_soa(update, conf);
diff --git a/src/knot/zone/digest.c b/src/knot/zone/digest.c
index 81f44e0240..ebb3bbb6e0 100644
--- a/src/knot/zone/digest.c
+++ b/src/knot/zone/digest.c
@@ -173,13 +173,21 @@ static int verify_zonemd(const knot_rdata_t *zonemd, const zone_contents_t *cont
 	return ret;
 }
 
-bool zone_contents_digest_exists(const zone_contents_t *contents, uint8_t alg)
+bool zone_contents_digest_exists(const zone_contents_t *contents, uint8_t alg, bool no_verify)
 {
+	if (alg == 0) {
+		return true;
+	}
+
 	knot_rdataset_t *zonemd = node_rdataset(contents->apex, KNOT_RRTYPE_ZONEMD);
 	if (zonemd == NULL || zonemd->count != 1 || knot_zonemd_algorithm(zonemd->rdata) != alg) {
 		return false;
 	}
 
+	if (no_verify) {
+		return true;
+	}
+
 	return verify_zonemd(zonemd->rdata, contents) == KNOT_EOK;
 }
 
diff --git a/src/knot/zone/digest.h b/src/knot/zone/digest.h
index 64f33acbda..e2910f33f2 100644
--- a/src/knot/zone/digest.h
+++ b/src/knot/zone/digest.h
@@ -36,8 +36,9 @@ int zone_contents_digest(const zone_contents_t *contents, int algorithm,
  *
  * \param contents   Zone contents to be verified.
  * \param alg        Required algorithm of the ZONEMD.
+ * \param no_verify  Don't verify the validness of the digest in ZONEMD.
  */
-bool zone_contents_digest_exists(const zone_contents_t *contents, uint8_t alg);
+bool zone_contents_digest_exists(const zone_contents_t *contents, uint8_t alg, bool no_verify);
 
 /*!
  * \brief Verify zone dgest in ZONEMD record.
diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c
index a8152f28d1..1d056ed6cc 100644
--- a/src/knot/zone/zonedb-load.c
+++ b/src/knot/zone/zonedb-load.c
@@ -23,6 +23,7 @@
 #include "knot/conf/module.h"
 #include "knot/events/replan.h"
 #include "knot/journal/journal_metadata.h"
+#include "knot/zone/digest.h"
 #include "knot/zone/timers.h"
 #include "knot/zone/zone-load.h"
 #include "knot/zone/zone.h"
@@ -100,6 +101,11 @@ static zone_t *create_zone_reload(conf_t *conf, const knot_dname_t *name,
 
 	bool conf_updated = (old_zone->change_type & CONF_IO_TRELOAD);
 
+	conf_val_t digest = conf_zone_get(conf, C_ZONEMD_GENERATE, name);
+	if (zone->contents != NULL && !zone_contents_digest_exists(zone->contents, conf_opt(&digest), true)) {
+		conf_updated = true;
+	}
+
 	if ((zone_file_updated(conf, old_zone, name) || conf_updated) && !zone_expired(zone)) {
 		replan_load_updated(zone, old_zone);
 	} else {
diff --git a/tests-extra/tests/zone/zonemd_flush/test.py b/tests-extra/tests/zone/zonemd_flush/test.py
index 210c7b3b00..7af8d7ef4b 100644
--- a/tests-extra/tests/zone/zonemd_flush/test.py
+++ b/tests-extra/tests/zone/zonemd_flush/test.py
@@ -31,8 +31,15 @@ master.zonemd_generate = "zonemd-sha384"
 
 t.start()
 
-master.zones_wait(zone)
+serial = master.zones_wait(zone)
 t.sleep(4)
 check_zonemd(master, zone, "1")
 
+master.zonemd_generate = "zonemd-sha512"
+master.gen_confile()
+master.reload()
+master.zones_wait(zone, serial)
+t.sleep(4)
+check_zonemd(master, zone, "2")
+
 t.end()
-- 
GitLab