From bdb91e3825c194a0750ecf79f8acfd81de8c001d Mon Sep 17 00:00:00 2001
From: Matthijs Mekking <matthijs@isc.org>
Date: Tue, 7 Dec 2021 13:59:42 +0100
Subject: [PATCH] Fix bug introduced by #763 related to offline keys

In some cases we want to keep expired signatures. For example, if the
KSK is offline, we don't want to fall back to signing with the ZSK.
We could remove the signatures, but in any case we end up with a broken
zone.

The change made for GL #763 prevented the behavior to sign the DNSKEY
RRset with the ZSK if the KSK was offline (and signatures were expired).

The change causes the definition of "having both keys": if one key is
offline, we still consider having both keys, so we don't fallback
signing with the ZSK if KSK is offline.

That change also works the other way, if the ZSK is offline, we don't
fallback signing with the KSK.

This commit fixes that, so we only fallback signing zone RRsets with
the KSK, not signing key RRsets with the ZSK.

(cherry picked from commit beeefe35c4a05bb69e9730190039fdf3e9fea1ba)
Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/bdb91e3825c194a0750ecf79f8acfd81de8c001d
---
 lib/dns/update.c |  6 +++---
 lib/dns/zone.c   | 24 +++++++++++++++---------
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/lib/dns/update.c b/lib/dns/update.c
index 71ef7dde46..2a766dc6ba 100644
--- a/lib/dns/update.c
+++ b/lib/dns/update.c
@@ -1158,8 +1158,8 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
 				}
 
 				/* Don't consider inactive keys, however
-				 * the key may be temporary offline, so do
-				 * consider keys which private key files are
+				 * the KSK may be temporary offline, so do
+				 * consider KSKs which private key files are
 				 * unavailable.
 				 */
 				if (dst_key_inactive(keys[j])) {
@@ -1171,7 +1171,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
 				}
 				if (KSK(keys[j])) {
 					have_ksk = true;
-				} else {
+				} else if (dst_key_isprivate(keys[j])) {
 					have_nonksk = true;
 				}
 				both = have_ksk && have_nonksk;
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 27373b34fe..f8eb0aae82 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -3483,7 +3483,8 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
 		INSIST(result == ISC_R_SUCCESS);
 
-		/* RFC 3110, section 4: Performance Considerations:
+		/*
+		 * RFC 3110, section 4: Performance Considerations:
 		 *
 		 * A public exponent of 3 minimizes the effort needed to verify
 		 * a signature.  Use of 3 as the public exponent is weak for
@@ -7060,8 +7061,9 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
 					continue;
 				}
 
-				/* Don't consider inactive keys, however
-				 * the key may be temporary offline, so do
+				/*
+				 * Don't consider inactive keys, however
+				 * the KSK may be temporary offline, so do
 				 * consider keys which private key files are
 				 * unavailable.
 				 */
@@ -7074,7 +7076,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
 				}
 				if (KSK(keys[j])) {
 					have_ksk = true;
-				} else {
+				} else if (dst_key_isprivate(keys[j])) {
 					have_nonksk = true;
 				}
 				both = have_ksk && have_nonksk;
@@ -9705,9 +9707,10 @@ zone_sign(dns_zone_t *zone) {
 						       ALG(zone_keys[j]))) {
 						continue;
 					}
-					/* Don't consider inactive keys, however
+					/*
+					 * Don't consider inactive keys, however
 					 * the key may be temporary offline, so
-					 * do consider keys which private key
+					 * do consider KSKs which private key
 					 * files are unavailable.
 					 */
 					if (dst_key_inactive(zone_keys[j])) {
@@ -9718,7 +9721,8 @@ zone_sign(dns_zone_t *zone) {
 					}
 					if (KSK(zone_keys[j])) {
 						have_ksk = true;
-					} else {
+					} else if (dst_key_isprivate(
+							   zone_keys[j])) {
 						have_nonksk = true;
 					}
 					both = have_ksk && have_nonksk;
@@ -14744,8 +14748,10 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
 		timeout = 30;
 	}
 
-	/* Save request parameters so we can reuse them later on
-	   for resolving missing glue A/AAAA records. */
+	/*
+	 * Save request parameters so we can reuse them later on
+	 * for resolving missing glue A/AAAA records.
+	 */
 	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
 	cb_args->stub = stub;
 	cb_args->tsig_key = key;
-- 
2.23.0

