Merge branch '4466-cds-is-stuck-on-an-old-key-bind-9.18' into 'bind-9.18'

[9.18] Resolve "CDS is stuck on an old key." !8565

See merge request isc-projects/bind9!8620
This commit is contained in:
Mark Andrews 2024-01-12 09:34:06 +00:00
commit 26fdc0fb80
19 changed files with 765 additions and 79 deletions

View file

@ -2,6 +2,11 @@
'host -C' commands when one of the name servers returns
SERVFAIL. [GL #4508]
6313. [bug] When dnssec-policy is in effect the DNSKEY's TTLs in
the zone where not being updated to match the policy.
This lead to failures when DNSKEYs where updated as the
TTLs mismatched. [GL #4466]
6312. [bug] Conversion from NSEC3 signed to NSEC signed could
temporarily put the zone into a state where it was
treated as unsigned until the NSEC chain was built.

View file

@ -9,7 +9,7 @@
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300 ; 5 minutes
$TTL 3600 ; 1 hour
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)

View file

@ -213,6 +213,7 @@ set_policy() {
POLICY=$1
NUM_KEYS=$2
DNSKEY_TTL=$3
KEYFILE_TTL=$3
CDS_DELETE="no"
}
# By default policies are considered to be secure.
@ -329,7 +330,7 @@ check_key() {
_alg_numpad=$(printf "%03d" "$_alg_num")
_alg_string=$(key_get "$1" ALG_STR)
_length=$(key_get "$1" "ALG_LEN")
_dnskey_ttl="$DNSKEY_TTL"
_dnskey_ttl="$KEYFILE_TTL"
_lifetime=$(key_get "$1" LIFETIME)
_legacy=$(key_get "$1" LEGACY)
_private=$(key_get "$1" PRIVATE)
@ -1055,7 +1056,7 @@ _find_dnskey() {
_flags="$(key_get $1 FLAGS)"
_key_file="$(key_get $1 BASEFILE).key"
awk '$1 == "'"$_owner"'" && $2 == "'"$DNSKEY_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' <"$_key_file"
awk '$1 == "'"$_owner"'" && $2 == "'"$KEYFILE_TTL"'" && $3 == "IN" && $4 == "DNSKEY" && $5 == "'"$_flags"'" && $6 == "3" && $7 == "'"$_alg"'" { print $8 }' <"$_key_file"
}
# Test DNSKEY query.

View file

@ -287,6 +287,16 @@ zone "expired-sigs.autosign" {
dnssec-policy "autosign";
};
/*
* Zone that has DNSKEY TTL mismatch with the dnssec-policy.
*/
zone "dnskey-ttl-mismatch.autosign" {
type primary;
file "dnskey-ttl-mismatch.autosign.db";
inline-signing yes;
dnssec-policy "autosign";
};
/*
* Zone that has valid, fresh signatures.
*/

View file

@ -198,6 +198,14 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
cp $infile $zonefile
$SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
# The DNSKEY's TTLs do not match the policy.
setup dnskey-ttl-mismatch.autosign
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 $zsktimes $zone 2>keygen.out.$zone.2)
cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile"
cp $infile $zonefile
$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
# These signatures are still good, and can be reused.
setup fresh-sigs.autosign
T="now-6mo"

View file

@ -1375,6 +1375,48 @@ check_rrsig_refresh() {
check_rrsig_refresh
#
# Zone: dnskey-ttl-mismatch.autosign
#
set_zone "dnskey-ttl-mismatch.autosign"
set_policy "autosign" "2" "300"
set_server "ns3" "10.53.0.3"
# Key properties.
key_clear "KEY1"
set_keyrole "KEY1" "ksk"
set_keylifetime "KEY1" "63072000"
set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
set_keysigning "KEY1" "yes"
set_zonesigning "KEY1" "no"
key_clear "KEY2"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "31536000"
set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "yes"
# Both KSK and ZSK stay OMNIPRESENT.
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY1" "STATE_DS" "omnipresent"
set_keystate "KEY2" "GOAL" "omnipresent"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
# Expect only two keys.
key_clear "KEY3"
key_clear "KEY4"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_autosign_policy
check_keytimes
check_apex
check_subdomain
dnssec_verify
#
# Zone: fresh-sigs.autosign.
#
@ -3970,7 +4012,7 @@ dnssec_verify
# Zone: step1.going-insecure.kasp
#
set_zone "step1.going-insecure.kasp"
set_policy "insecure" "2" "7200"
set_policy "insecure" "2" "3600"
set_server "ns6" "10.53.0.6"
# Expect a CDS/CDNSKEY Delete Record.
set_cdsdelete
@ -4007,7 +4049,7 @@ check_next_key_event 93600
# Zone: step2.going-insecure.kasp
#
set_zone "step2.going-insecure.kasp"
set_policy "insecure" "2" "7200"
set_policy "insecure" "2" "3600"
set_server "ns6" "10.53.0.6"
# The DS is long enough removed from the zone to be considered HIDDEN.
@ -4037,7 +4079,7 @@ check_next_key_event 7500
#
set_zone "step1.going-insecure-dynamic.kasp"
set_dynamic
set_policy "insecure" "2" "7200"
set_policy "insecure" "2" "3600"
set_server "ns6" "10.53.0.6"
# Expect a CDS/CDNSKEY Delete Record.
set_cdsdelete
@ -4075,7 +4117,7 @@ check_next_key_event 93600
#
set_zone "step2.going-insecure-dynamic.kasp"
set_dynamic
set_policy "insecure" "2" "7200"
set_policy "insecure" "2" "3600"
set_server "ns6" "10.53.0.6"
# The DS is long enough removed from the zone to be considered HIDDEN.

View file

@ -499,7 +499,7 @@ status=$((status + ret))
# Testing a good migration (CSK).
#
set_zone "csk.kasp"
set_policy "default" "1" "7200"
set_policy "default" "1" "3600"
set_server "ns3" "10.53.0.3"
key_clear "KEY1"
@ -549,7 +549,7 @@ status=$((status + ret))
# Testing a good migration (CSK, no SEP).
#
set_zone "csk-nosep.kasp"
set_policy "default" "1" "7200"
set_policy "default" "1" "3600"
set_server "ns3" "10.53.0.3"
key_clear "KEY1"

View file

@ -40,6 +40,7 @@ set_zone_policy() {
POLICY=$2
NUM_KEYS=$3
DNSKEY_TTL=$4
KEYFILE_TTL=$4
}
# Set expected NSEC3 parameters: flags ($1), iterations ($2), and
# salt length ($3).

View file

@ -19,8 +19,8 @@ set -e
zone=dnssec.
infile=dnssec.db.in
zonefile=dnssec.db.signed
ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" -f KSK "$zone")
zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" "$zone")
# Sign deliberately with a very short expiration date.
"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1
keyfile_to_key_id "$ksk" >dnssec.ksk.id
@ -29,12 +29,12 @@ keyfile_to_key_id "$zsk" >dnssec.zsk.id
zone=manykeys.
infile=manykeys.db.in
zonefile=manykeys.db.signed
ksk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 -f KSK "$zone")
zsk8=$("$KEYGEN" -q -a RSASHA256 -b 2048 "$zone")
ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 -f KSK "$zone")
zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -b 256 "$zone")
ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 -f KSK "$zone")
zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -b 384 "$zone")
ksk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 -f KSK "$zone")
zsk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 "$zone")
ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 -f KSK "$zone")
zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 "$zone")
ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 -f KSK "$zone")
zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 "$zone")
# Sign deliberately with a very short expiration date.
"$SIGNER" -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1
keyfile_to_key_id "$ksk8" >manykeys.ksk8.id

View file

@ -1846,9 +1846,9 @@ failure:
return (result);
}
static isc_result_t
make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
dns_rdata_t *target) {
isc_result_t
dns_dnssec_make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
dns_rdata_t *target) {
isc_result_t result;
isc_buffer_t b;
isc_region_t r;
@ -1904,7 +1904,7 @@ publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
dns_rdata_t dnskey = DNS_RDATA_INIT;
dns_rdata_reset(&dnskey);
RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
RETERR(dns_dnssec_make_dnskey(key->key, buf, sizeof(buf), &dnskey));
dst_key_format(key->key, keystr, sizeof(keystr));
report("Fetching %s (%s) from key %s.", keystr,
@ -1944,7 +1944,7 @@ remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
report("Removing %s key %s/%d/%s from DNSKEY RRset.", reason, namebuf,
dst_key_id(key->key), alg);
RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
RETERR(dns_dnssec_make_dnskey(key->key, buf, sizeof(buf), &dnskey));
result = delrdata(&dnskey, diff, origin, ttl, mctx);
failure:
@ -1983,6 +1983,19 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
unsigned char keybuf[DST_KEY_MAXSIZE];
isc_result_t result;
dns_dnsseckey_t *key;
dns_ttl_t cdsttl = ttl;
dns_ttl_t cdnskeyttl = ttl;
REQUIRE(keys != NULL);
REQUIRE(rmkeys != NULL);
if (dns_rdataset_isassociated(cds)) {
cdsttl = cds->ttl;
}
if (dns_rdataset_isassociated(cdnskey)) {
cdnskeyttl = cdnskey->ttl;
}
for (key = ISC_LIST_HEAD(*keys); key != NULL;
key = ISC_LIST_NEXT(key, link))
@ -1992,8 +2005,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
dns_name_t *origin = dst_key_name(key->key);
RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
/*
* We construct the SHA-1 version of the record so we can
@ -2030,7 +2043,7 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
"CDS for key %s is now published",
keystr);
RETERR(addrdata(&cdnskeyrdata, diff, origin,
ttl, mctx));
cdnskeyttl, mctx));
}
/* Only publish SHA-256 (SHA-1 is deprecated) */
if (!dns_rdataset_isassociated(cds) ||
@ -2041,8 +2054,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
"CDNSKEY for key %s is now published",
keystr);
RETERR(addrdata(&cds_sha256, diff, origin, ttl,
mctx));
RETERR(addrdata(&cds_sha256, diff, origin,
cdsttl, mctx));
}
}
@ -2114,8 +2127,8 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
char keystr[DST_KEY_FORMATSIZE];
dst_key_format(key->key, keystr, sizeof(keystr));
RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
if (dns_rdataset_isassociated(cds)) {
RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,

View file

@ -95,6 +95,23 @@ dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata,
*\li various errors from dns_name_totext
*/
isc_result_t
dns_dnssec_make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
dns_rdata_t *target);
/*%<
* Convert a DST key into a DNS record.
*
* Requires:
*\li 'key' is not NULL
*\li 'buf' is not NULL
*\li 'bufsize' equals DST_KEY_MAXSIZE
*\li 'target' is not NULL
*
* Returns:
*\li #ISC_R_SUCCESS
*\li various errors from dst_key_todns
*/
isc_result_t
dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
isc_stdtime_t *inception, isc_stdtime_t *expire,

View file

@ -572,6 +572,13 @@ dns_rdatatype_isdnssec(dns_rdatatype_t type);
* \li 'type' is a valid rdata type.
*/
bool
dns_rdatatype_iskeymaterial(dns_rdatatype_t type);
/*%<
* Return true iff the rdata type 'type' is a DNSSEC key
* related type, like DNSKEY, CDNSKEY, or CDS.
*/
bool
dns_rdatatype_iszonecutauth(dns_rdatatype_t type);
/*%<

View file

@ -392,6 +392,24 @@ dns_zone_unlock_keyfiles(dns_zone_t *zone);
*\li 'zone' to be a valid zone.
*/
isc_result_t
dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse);
/*%<
* Check if the DNSKEY record 'rdata' is used by 'zone' for zone signing.
* Store the result in 'inuse'.
*
* Require:
*\li 'zone' to be a valid zone.
*\li 'rdata' to represent a DNSKEY, CDNSKEY, or CDS record.
*
* Returns:
*\li #ISC_R_SUCCESS
*\li Any error result from dns_dnssec_keyfromrdata, dns_rdata_tostruct,
* dns_dnssec_make_dnskey, dns_ds_buildrdata, or
* dns_dnssec_findmatchingkeys.
*
*/
isc_result_t
dns_zone_load(dns_zone_t *zone, bool newonly);

View file

@ -2218,11 +2218,16 @@ 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 (dst_key_ismodified(dkey->key) && !dkey->purge) {
bool modified = dst_key_ismodified(dkey->key);
if (dst_key_getttl(dkey->key) != dns_kasp_dnskeyttl(kasp)) {
dst_key_setttl(dkey->key, dns_kasp_dnskeyttl(kasp));
modified = true;
}
if (modified && !dkey->purge) {
dns_dnssec_get_hints(dkey, now);
RETERR(dst_key_tofile(dkey->key, options, directory));
dst_key_setmodified(dkey->key, false);
}
dst_key_setmodified(dkey->key, false);
}
result = ISC_R_SUCCESS;

View file

@ -2262,6 +2262,12 @@ dns_rdatatype_isdnssec(dns_rdatatype_t type) {
return (false);
}
bool
dns_rdatatype_iskeymaterial(dns_rdatatype_t type) {
return (type == dns_rdatatype_dnskey || type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds);
}
bool
dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ZONECUTAUTH) !=

View file

@ -1205,10 +1205,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
}
}
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
/*
* DNSKEY RRset is signed with KSK.
* CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
@ -1242,10 +1239,7 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
/*
* CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
*/
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
if (!KSK(keys[i]) && keyset_kskonly) {
continue;
}
@ -1675,10 +1669,7 @@ next_state:
&flag));
if (flag) {
isc_stdtime_t exp;
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
exp = state->keyexpire;
} else if (type == dns_rdatatype_soa) {
exp = state->soaexpire;

View file

@ -6777,9 +6777,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
type != dns_rdatatype_cdnskey)
{
if (!dns_rdatatype_iskeymaterial(type)) {
bool warn = false, deleted = false;
if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
result = update_one_rr(db, ver, zonediff->diff,
@ -7097,10 +7095,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
both = have_ksk && have_zsk;
}
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
/*
* DNSKEY RRset is signed with KSK.
* CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
@ -7140,10 +7135,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
/*
* CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
*/
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey ||
type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
if (!KSK(keys[i]) && keyset_kskonly) {
continue;
}
@ -7545,9 +7537,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
}
KASP_UNLOCK(kasp);
if (type == dns_rdatatype_dnskey ||
type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(type)) {
/*
* CDS and CDNSKEY are signed with KSK like DNSKEY.
* (RFC 7344, section 4.1 specifies that they must
@ -7723,10 +7713,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
{
goto next_rdataset;
}
if (rdataset.type == dns_rdatatype_dnskey ||
rdataset.type == dns_rdatatype_cdnskey ||
rdataset.type == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(rdataset.type)) {
/*
* CDS and CDNSKEY are signed with KSK like DNSKEY.
* (RFC 7344, section 4.1 specifies that they must
@ -8324,9 +8311,7 @@ dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
isc_stdtime_t exp = expire;
if (keyexpire != 0 &&
(tuple->rdata.type == dns_rdatatype_dnskey ||
tuple->rdata.type == dns_rdatatype_cdnskey ||
tuple->rdata.type == dns_rdatatype_cds))
dns_rdatatype_iskeymaterial(tuple->rdata.type))
{
exp = keyexpire;
}
@ -16344,6 +16329,186 @@ update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
dns_zone_log(zone, level, "%s", message);
}
static isc_result_t
dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, isc_mem_t *mctx,
dns_dnsseckeylist_t *keylist, bool *inuse) {
isc_result_t result;
dst_key_t *dstkey = NULL;
result = dns_dnssec_keyfromrdata(dns_zone_getorigin(zone), rdata, mctx,
&dstkey);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_dnssec_keyfromrdata() failed: %s",
isc_result_totext(result));
return (result);
}
for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
k = ISC_LIST_NEXT(k, link))
{
if (dst_key_pubcompare(k->key, dstkey, false)) {
*inuse = true;
break;
}
}
dst_key_free(&dstkey);
return (ISC_R_SUCCESS);
}
static isc_result_t
cdnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata,
dns_dnsseckeylist_t *keylist, bool *inuse) {
isc_result_t result;
dns_rdata_cdnskey_t cdnskey;
result = dns_rdata_tostruct(rdata, &cdnskey, NULL);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_rdata_tostruct(cdnskey) failed: %s",
isc_result_totext(result));
return (result);
}
for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
k = ISC_LIST_NEXT(k, link))
{
dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
unsigned char keybuf[DST_KEY_MAXSIZE];
result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
&cdnskeyrdata);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_dnssec_make_dnskey() failed: %s",
isc_result_totext(result));
return (result);
}
cdnskeyrdata.type = dns_rdatatype_cdnskey;
if (dns_rdata_compare(rdata, &cdnskeyrdata) == 0) {
*inuse = true;
break;
}
}
return (ISC_R_SUCCESS);
}
static isc_result_t
cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
bool *inuse) {
isc_result_t result;
dns_rdata_ds_t cds;
result = dns_rdata_tostruct(rdata, &cds, NULL);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_rdata_tostruct(cds) failed: %s",
isc_result_totext(result));
return (result);
}
for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
k = ISC_LIST_NEXT(k, link))
{
dns_rdata_t dnskey = DNS_RDATA_INIT;
dns_rdata_t cdsrdata = DNS_RDATA_INIT;
unsigned char keybuf[DST_KEY_MAXSIZE];
unsigned char cdsbuf[DNS_DS_BUFFERSIZE];
if (dst_key_id(k->key) != cds.key_tag ||
dst_key_alg(k->key) != cds.algorithm)
{
continue;
}
result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
&dnskey);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_dnssec_make_dnskey() failed: %s",
isc_result_totext(result));
return (result);
}
result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
cds.digest_type, cdsbuf, &cdsrdata);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_ds_buildrdata(keytag=%d, algo=%d, "
"digest=%d) failed: %s",
cds.key_tag, cds.algorithm,
cds.digest_type,
isc_result_totext(result));
return (result);
}
cdsrdata.type = dns_rdatatype_cds;
if (dns_rdata_compare(rdata, &cdsrdata) == 0) {
*inuse = true;
break;
}
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) {
dns_dnsseckeylist_t keylist;
dns_dnsseckey_t *key = NULL;
isc_result_t result = ISC_R_SUCCESS;
isc_stdtime_t now = 0;
isc_mem_t *mctx;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(dns_rdatatype_iskeymaterial(rdata->type));
mctx = zone->mctx;
isc_stdtime_get(&now);
ISC_LIST_INIT(keylist);
*inuse = false;
dns_zone_lock_keyfiles(zone);
result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
dns_zone_getkeydirectory(zone),
now, mctx, &keylist);
dns_zone_unlock_keyfiles(zone);
if (result == ISC_R_NOTFOUND) {
return (ISC_R_SUCCESS);
} else if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"dns_dnssec_findmatchingkeys() failed: %s",
isc_result_totext(result));
return (result);
}
switch (rdata->type) {
case dns_rdatatype_dnskey:
result = dnskey_inuse(zone, rdata, mctx, &keylist, inuse);
break;
case dns_rdatatype_cdnskey:
result = cdnskey_inuse(zone, rdata, &keylist, inuse);
break;
case dns_rdatatype_cds:
result = cds_inuse(zone, rdata, &keylist, inuse);
break;
default:
UNREACHABLE();
break;
}
while (!ISC_LIST_EMPTY(keylist)) {
key = ISC_LIST_HEAD(keylist);
ISC_LIST_UNLINK(keylist, key, link);
dns_dnsseckey_destroy(mctx, &key);
}
return (result);
}
static isc_result_t
sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
@ -16423,6 +16588,77 @@ failure:
return (result);
}
/*
* Filter the key material preserving TTL changes. If kasp in effect honour the
* existing ttl. The lists returned by sync_secure_db/dns_db_diffx should be
* DNSSEC RRset order so we can process 'del' and 'add' in parallel rather than
* searching for TTL only changes first and processing them, then checking the
* 'in use' status on a subsequent pass.
*/
static void
filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del,
dns_difftuplelist_t *add, bool kasp, dns_ttl_t ttl) {
dns_difftuple_t *deltuple = ISC_LIST_HEAD(*del);
dns_difftuple_t *addtuple = ISC_LIST_HEAD(*add);
isc_result_t result;
while (deltuple != NULL || addtuple != NULL) {
dns_difftuple_t *delnext = NULL, *addnext = NULL;
bool inuse = false;
if (deltuple != NULL) {
delnext = ISC_LIST_NEXT(deltuple, link);
}
if (addtuple != NULL) {
addnext = ISC_LIST_NEXT(addtuple, link);
}
if (deltuple != NULL && addtuple != NULL) {
int n = dns_rdata_compare(&deltuple->rdata,
&addtuple->rdata);
if (n == 0) {
/*
* If the rdata is equal then the only
* difference will be a TTL change.
*/
if (kasp) {
/* TTL is managed by dnssec-policy */
ISC_LIST_UNLINK(*del, deltuple, link);
dns_difftuple_free(&deltuple);
ISC_LIST_UNLINK(*add, addtuple, link);
dns_difftuple_free(&addtuple);
}
deltuple = delnext;
addtuple = addnext;
continue;
}
if (n < 0) {
goto checkdel;
}
goto checkadd;
} else if (deltuple != NULL) {
checkdel:
result = dns_zone_dnskey_inuse(zone, &deltuple->rdata,
&inuse);
if (result == ISC_R_SUCCESS && inuse) {
ISC_LIST_UNLINK(*del, deltuple, link);
dns_difftuple_free(&deltuple);
}
deltuple = delnext;
} else {
checkadd:
result = dns_zone_dnskey_inuse(zone, &addtuple->rdata,
&inuse);
if (result == ISC_R_SUCCESS && inuse) {
ISC_LIST_UNLINK(*add, addtuple, link);
dns_difftuple_free(&addtuple);
} else if (kasp) {
addtuple->ttl = ttl;
}
addtuple = addnext;
}
}
}
static isc_result_t
sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
dns_dbversion_t *secver, dns_difftuple_t **soatuple,
@ -16433,6 +16669,22 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
dns_difftuple_t *tuple = NULL, *next;
dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
dns_rdata_soa_t oldsoa, newsoa;
dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
#if 0
dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER;
dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER;
#endif
dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER;
dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER;
dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER;
dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER;
dns_kasp_t *kasp = NULL;
#if 0
dns_ttl_t keyttl = 0;
#endif
dns_ttl_t ckeyttl = 0;
dns_ttl_t cdsttl = 0;
REQUIRE(DNS_ZONE_VALID(seczone));
REQUIRE(soatuple != NULL && *soatuple == NULL);
@ -16451,10 +16703,60 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
return (result);
}
/*
* If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS
* TTLs.
*/
kasp = seczone->kasp;
if (kasp != NULL) {
dns_rdataset_t rdataset;
dns_dbnode_t *node = NULL;
dns_ttl_t ttl = dns_kasp_dnskeyttl(kasp);
dns_rdataset_init(&rdataset);
result = dns_db_getoriginnode(secdb, &node);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
#if 0
result = dns_db_findrdataset(
secdb, node, secver, dns_rdatatype_dnskey,
dns_rdatatype_none, 0, &rdataset, NULL);
keyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
#endif
result = dns_db_findrdataset(
secdb, node, secver, dns_rdatatype_cdnskey,
dns_rdatatype_none, 0, &rdataset, NULL);
ckeyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
result = dns_db_findrdataset(
secdb, node, secver, dns_rdatatype_cds,
dns_rdatatype_none, 0, &rdataset, NULL);
cdsttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
dns_db_detachnode(secdb, &node);
}
for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
dns_difftuplelist_t *al = &add, *dl = &del;
next = ISC_LIST_NEXT(tuple, link);
/*
* Skip DNSSEC records that BIND maintains with inline-signing.
*/
if (tuple->rdata.type == dns_rdatatype_nsec ||
tuple->rdata.type == dns_rdatatype_rrsig ||
/* if dnskey is removed adjust switch below */
tuple->rdata.type == dns_rdatatype_dnskey ||
tuple->rdata.type == dns_rdatatype_nsec3 ||
tuple->rdata.type == dns_rdatatype_nsec3param)
@ -16463,6 +16765,34 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
dns_difftuple_free(&tuple);
continue;
}
/*
* Apex DNSKEY, CDNSKEY and CDS need special processing so
* split them out.
*/
if (dns_rdatatype_iskeymaterial(tuple->rdata.type) &&
dns_name_equal(&tuple->name, &seczone->origin))
{
switch (tuple->rdata.type) {
#if 0
case dns_rdatatype_dnskey:
al = &keyadd;
dl = &keydel;
break;
#endif
case dns_rdatatype_cdnskey:
al = &ckeyadd;
dl = &ckeydel;
break;
case dns_rdatatype_cds:
al = &cdsadd;
dl = &cdsdel;
break;
default:
UNREACHABLE();
}
}
if (tuple->rdata.type == dns_rdatatype_soa) {
if (tuple->op == DNS_DIFFOP_DEL) {
INSIST(oldtuple == NULL);
@ -16473,6 +16803,23 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
newtuple = tuple;
}
}
/*
* Split into deletions and additions.
*/
ISC_LIST_UNLINK(diff->tuples, tuple, link);
switch (tuple->op) {
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
ISC_LIST_APPEND(*dl, tuple, link);
break;
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
ISC_LIST_APPEND(*al, tuple, link);
break;
default:
UNREACHABLE();
}
}
if (oldtuple != NULL && newtuple != NULL) {
@ -16494,13 +16841,38 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
dns_name_equal(&oldsoa.contact, &newsoa.contact))
{
ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
ISC_LIST_UNLINK(del, oldtuple, link);
dns_difftuple_free(&oldtuple);
ISC_LIST_UNLINK(diff->tuples, newtuple, link);
ISC_LIST_UNLINK(add, newtuple, link);
dns_difftuple_free(&newtuple);
}
}
/*
* Filter out keys we manage but still allow TTL changes.
*/
#if 0
filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl);
#endif
filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl);
filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl);
/*
* Rebuild the diff now that we have filtered it
*/
ISC_LIST_APPENDLIST(diff->tuples, del, link);
#if 0
ISC_LIST_APPENDLIST(diff->tuples, keydel, link);
#endif
ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link);
ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link);
ISC_LIST_APPENDLIST(diff->tuples, add, link);
#if 0
ISC_LIST_APPENDLIST(diff->tuples, keyadd, link);
#endif
ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link);
ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link);
if (ISC_LIST_EMPTY(diff->tuples)) {
return (DNS_R_UNCHANGED);
}
@ -20382,7 +20754,8 @@ failure:
static isc_result_t
add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
dns_difftuple_t *tuple, *newtuple = NULL;
dns_difftuple_t *tuple = NULL, *newtuple = NULL, *next = NULL;
dns_difftuple_t *addtuple = NULL, *deltuple = NULL;
dns_rdata_dnskey_t dnskey;
dns_rdata_t rdata = DNS_RDATA_INIT;
bool flag;
@ -20391,11 +20764,20 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
uint16_t keyid;
unsigned char buf[5];
dns_name_t *name = dns_db_origin(db);
dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
dns_difftuplelist_t tuples = ISC_LIST_INITIALIZER;
/*
* Move non DNSKEY and not DNSSEC DNSKEY records to tuples
* and sort the remaining DNSKEY records to add and del.
*/
for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link))
tuple = ISC_LIST_HEAD(diff->tuples))
{
if (tuple->rdata.type != dns_rdatatype_dnskey) {
ISC_LIST_UNLINK(diff->tuples, tuple, link);
ISC_LIST_APPEND(tuples, tuple, link);
continue;
}
@ -20404,9 +20786,65 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
{
ISC_LIST_UNLINK(diff->tuples, tuple, link);
ISC_LIST_APPEND(tuples, tuple, link);
continue;
}
ISC_LIST_UNLINK(diff->tuples, tuple, link);
switch (tuple->op) {
case DNS_DIFFOP_DEL:
case DNS_DIFFOP_DELRESIGN:
ISC_LIST_APPEND(del, tuple, link);
break;
case DNS_DIFFOP_ADD:
case DNS_DIFFOP_ADDRESIGN:
ISC_LIST_APPEND(add, tuple, link);
break;
default:
UNREACHABLE();
}
}
/*
* Put the tuples that don't need more processing back onto
* diff->tuples.
*/
ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
/*
* Filter out DNSKEY TTL changes and put them back onto diff->tuples.
*/
for (deltuple = ISC_LIST_HEAD(del); deltuple != NULL; deltuple = next) {
next = ISC_LIST_NEXT(deltuple, link);
for (addtuple = ISC_LIST_HEAD(add); addtuple != NULL;
addtuple = ISC_LIST_NEXT(addtuple, link))
{
int n = dns_rdata_compare(&deltuple->rdata,
&addtuple->rdata);
if (n == 0) {
ISC_LIST_UNLINK(del, deltuple, link);
ISC_LIST_APPEND(diff->tuples, deltuple, link);
ISC_LIST_UNLINK(add, addtuple, link);
ISC_LIST_APPEND(diff->tuples, addtuple, link);
break;
}
}
}
/*
* Combine any remaining DNSKEY changes together.
*/
ISC_LIST_APPENDLIST(tuples, add, link);
ISC_LIST_APPENDLIST(tuples, del, link);
/*
* Add private records for keys that have been removed
* or added.
*/
for (tuple = ISC_LIST_HEAD(tuples); tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link))
{
dns_rdata_toregion(&tuple->rdata, &r);
keyid = dst_region_computeid(&r);
@ -20446,7 +20884,15 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
INSIST(newtuple == NULL);
}
}
failure:
/*
* Put the DNSKEY changes we cared about back on diff->tuples.
*/
ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
INSIST(ISC_LIST_EMPTY(add));
INSIST(ISC_LIST_EMPTY(del));
INSIST(ISC_LIST_EMPTY(tuples));
return (result);
}
@ -21437,6 +21883,55 @@ zone_checkds(dns_zone_t *zone) {
}
}
static isc_result_t
update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
dns_diff_t *diff) {
isc_result_t result;
/*
* Delete everything using the existing TTL.
*/
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset))
{
dns_difftuple_t *tuple = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(rdataset, &rdata);
result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
rdataset->ttl, &rdata, &tuple);
if (result != ISC_R_SUCCESS) {
return (result);
}
dns_diff_appendminimal(diff, &tuple);
}
if (result != ISC_R_NOMORE) {
return (result);
}
/*
* Add everything using the new TTL.
*/
for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset))
{
dns_difftuple_t *tuple = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(rdataset, &rdata);
result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
ttl, &rdata, &tuple);
if (result != ISC_R_SUCCESS) {
return (result);
}
dns_diff_appendminimal(diff, &tuple);
}
if (result != ISC_R_NOMORE) {
return (result);
}
return (ISC_R_SUCCESS);
}
static void
zone_rekey(dns_zone_t *zone) {
isc_result_t result;
@ -21494,11 +21989,39 @@ zone_rekey(dns_zone_t *zone) {
ttl = soaset.ttl;
dns_rdataset_disassociate(&soaset);
/*
* Only update DNSKEY TTL if we have a policy.
*/
if (kasp != NULL) {
ttl = dns_kasp_dnskeyttl(kasp);
}
/* Get the DNSKEY rdataset */
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
dns_rdatatype_none, 0, &keyset, &keysigs);
if (result == ISC_R_SUCCESS) {
ttl = keyset.ttl;
/*
* If we don't have a policy then use the DNSKEY ttl
* if it exists. Otherwise update the DNSKEY ttl if
* needed.
*/
if (kasp == NULL) {
ttl = keyset.ttl;
} else if (ttl != keyset.ttl) {
result = update_ttl(&keyset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"Updating DNSKEY TTL from %u to %u "
"failed: %s",
keyset.ttl, ttl,
isc_result_totext(result));
goto failure;
}
dnssec_log(zone, ISC_LOG_INFO,
"Updating DNSKEY TTL from %u to %u",
keyset.ttl, ttl);
keyset.ttl = ttl;
}
dns_zone_lock_keyfiles(zone);
@ -21520,6 +22043,18 @@ zone_rekey(dns_zone_t *zone) {
dns_rdatatype_none, 0, &cdsset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
dns_rdataset_disassociate(&cdsset);
} else if (result == ISC_R_SUCCESS && kasp != NULL && ttl != cdsset.ttl)
{
result = update_ttl(&cdsset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"Updating CDS TTL from %u to %u failed: %s",
cdsset.ttl, ttl, isc_result_totext(result));
goto failure;
}
dnssec_log(zone, ISC_LOG_INFO, "Updating CDS TTL from %u to %u",
cdsset.ttl, ttl);
cdsset.ttl = ttl;
}
/* Get the CDNSKEY rdataset */
@ -21527,6 +22062,21 @@ zone_rekey(dns_zone_t *zone) {
dns_rdatatype_none, 0, &cdnskeyset, NULL);
if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
dns_rdataset_disassociate(&cdnskeyset);
} else if (result == ISC_R_SUCCESS && kasp != NULL &&
ttl != cdnskeyset.ttl)
{
result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff);
if (result != ISC_R_SUCCESS) {
dnssec_log(
zone, ISC_LOG_ERROR,
"Updating CDNSKEY TTL from %u to %u failed: %s",
cdnskeyset.ttl, ttl, isc_result_totext(result));
goto failure;
}
dnssec_log(zone, ISC_LOG_INFO,
"Updating CDNSKEY TTL from %u to %u", cdnskeyset.ttl,
ttl);
cdnskeyset.ttl = ttl;
}
/*
@ -21659,13 +22209,6 @@ zone_rekey(dns_zone_t *zone) {
}
}
/*
* Only update DNSKEY TTL if we have a policy.
*/
if (kasp != NULL) {
ttl = dns_kasp_dnskeyttl(kasp);
}
result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
&zone->origin, ttl, &diff, mctx,
dnssec_report);

View file

@ -12352,9 +12352,7 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
/*
* Turn on minimal response for (C)DNSKEY and (C)DS queries.
*/
if (qtype == dns_rdatatype_dnskey || qtype == dns_rdatatype_ds ||
qtype == dns_rdatatype_cdnskey || qtype == dns_rdatatype_cds)
{
if (dns_rdatatype_iskeymaterial(qtype) || qtype == dns_rdatatype_ds) {
client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
NS_QUERYATTR_NOADDITIONAL);
} else if (qtype == dns_rdatatype_ns) {

View file

@ -3390,6 +3390,27 @@ update_action(isc_task_t *task, isc_event_t *event) {
continue;
}
}
/*
* Don't remove DNSKEY, CDNSKEY, CDS records
* that are in use (under our control).
*/
if (dns_rdatatype_iskeymaterial(rdata.type)) {
isc_result_t r;
bool inuse = false;
r = dns_zone_dnskey_inuse(zone, &rdata,
&inuse);
if (r != ISC_R_SUCCESS) {
FAIL(r);
}
if (inuse) {
update_log(client, zone,
LOGLEVEL_PROTOCOL,
"attempt to "
"delete in use "
"DNSKEY ignored");
continue;
}
}
}
dns_name_format(name, namestr, sizeof(namestr));
dns_rdatatype_format(rdata.type, typestr,