diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 7d4c910917..5b8f14c3f2 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -6438,7 +6438,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; @@ -6482,12 +6482,27 @@ 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 (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) { - return (true); + if (kasp && have_pzsk) { + return (true); + } + return (!kasp); } /* @@ -6521,6 +6536,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; @@ -6563,7 +6579,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, @@ -6807,6 +6823,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) { @@ -6821,6 +6839,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) @@ -6836,7 +6904,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)) { /*