mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
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:
commit
26fdc0fb80
19 changed files with 765 additions and 79 deletions
5
CHANGES
5
CHANGES
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) !=
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
609
lib/dns/zone.c
609
lib/dns/zone.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue