]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update smart signing when key is offline
authorMatthijs Mekking <matthijs@isc.org>
Mon, 12 Apr 2021 12:45:31 +0000 (14:45 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 5 May 2021 10:50:00 +0000 (12:50 +0200)
BIND 9 is smart about when to sign with what key. If a key is offline,
BIND will delete the old signature anyway if there is another key to
sign the RRset with.

With KASP we don't want to fallback to the KSK if the ZSK is missing,
only for the SOA RRset. If the KSK is missing, but we do have a ZSK,
deleting the signature is fine. Otherwise it depends on if we use KASP
or not. Update the 'delsig_ok' function to reflect that.

(cherry picked from commit 6a60bf637d40c48520ec4c24c443f066b6464de3)

lib/dns/zone.c

index cdc151a5b01118fc7c746f8940547a0b19369890..a2e51a1b20fa8923d6c264aa7cc634735e0eb3ca 100644 (file)
@@ -6373,7 +6373,7 @@ set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
  */
 static bool
 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
-         bool *warn) {
+         bool kasp, bool *warn) {
        unsigned int i = 0;
        isc_result_t ret;
        bool have_ksk = false, have_zsk = false;
@@ -6417,14 +6417,29 @@ delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
                *warn = true;
        }
 
+       if (have_pksk && have_pzsk) {
+               return (true);
+       }
+
        /*
-        * It's okay to delete a signature if there is an active key
-        * with the same algorithm to replace it.
+        * Deleting the SOA RRSIG is always okay.
         */
-       if (have_pksk || have_pzsk) {
+       if (rrsig_ptr->covered == dns_rdatatype_soa) {
                return (true);
        }
 
+       /*
+        * It's okay to delete a signature if there is an active key with the
+        * same algorithm to replace it, unless that violates the DNSSEC
+        * policy.
+        */
+       if (have_pksk || have_pzsk) {
+               if (kasp && have_pzsk) {
+                       return (true);
+               }
+               return (!kasp);
+       }
+
        /*
         * Failing that, it is *not* okay to delete a signature
         * if the associated public key is still in the DNSKEY RRset
@@ -6456,6 +6471,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
        dns_rdataset_t rdataset;
        unsigned int i;
        dns_rdata_rrsig_t rrsig;
+       bool kasp = (dns_zone_getkasp(zone) != NULL);
        bool found;
        int64_t timewarn = 0, timemaybe = 0;
 
@@ -6498,7 +6514,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
                    type != dns_rdatatype_cdnskey)
                {
                        bool warn = false, deleted = false;
-                       if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
+                       if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
                                result = update_one_rr(db, ver, zonediff->diff,
                                                       DNS_DIFFOP_DELRESIGN,
                                                       name, rdataset.ttl,
@@ -6742,6 +6758,8 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
                        isc_stdtime_t when;
                        bool ksk = false;
                        bool zsk = false;
+                       bool have_ksk = false;
+                       bool have_zsk = false;
 
                        kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
                        if (kresult != ISC_R_SUCCESS) {
@@ -6756,6 +6774,56 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
                                }
                        }
 
+                       have_ksk = ksk;
+                       have_zsk = zsk;
+                       both = have_ksk && have_zsk;
+
+                       for (j = 0; j < nkeys; j++) {
+                               if (both) {
+                                       break;
+                               }
+
+                               if (j == i || ALG(keys[i]) != ALG(keys[j])) {
+                                       continue;
+                               }
+
+                               /*
+                                * Don't consider inactive keys or offline keys.
+                                */
+                               if (!dst_key_isprivate(keys[j])) {
+                                       continue;
+                               }
+                               if (dst_key_inactive(keys[j])) {
+                                       continue;
+                               }
+
+                               if (REVOKE(keys[j])) {
+                                       continue;
+                               }
+
+                               if (!have_ksk) {
+                                       kresult = dst_key_getbool(keys[j],
+                                                                 DST_BOOL_KSK,
+                                                                 &have_ksk);
+                                       if (kresult != ISC_R_SUCCESS) {
+                                               if (KSK(keys[j])) {
+                                                       have_ksk = true;
+                                               }
+                                       }
+                               }
+                               if (!have_zsk) {
+                                       kresult = dst_key_getbool(keys[j],
+                                                                 DST_BOOL_ZSK,
+                                                                 &have_zsk);
+                                       if (kresult != ISC_R_SUCCESS) {
+                                               if (!KSK(keys[j])) {
+                                                       have_zsk = true;
+                                               }
+                                       }
+                               }
+                               both = have_ksk && have_zsk;
+                       }
+
                        if (type == dns_rdatatype_dnskey ||
                            type == dns_rdatatype_cdnskey ||
                            type == dns_rdatatype_cds)
@@ -6771,7 +6839,13 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
                                /*
                                 * Other RRsets are signed with ZSK.
                                 */
-                               continue;
+                               if (type != dns_rdatatype_soa &&
+                                   type != zone->privatetype) {
+                                       continue;
+                               }
+                               if (have_zsk) {
+                                       continue;
+                               }
                        } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
                                                       inception, &when)) {
                                /*