Merge branch '1706-dnssec-policy-migration' into 'master'

Resolve "Changing from auto-dnssec maintain to dnssec-policy x immediately deletes existing keys"

Closes #1706

See merge request isc-projects/bind9!3322
This commit is contained in:
Matthijs Mekking 2020-04-03 06:54:46 +00:00
commit 157eb5cd30
8 changed files with 699 additions and 117 deletions

View file

@ -1,3 +1,6 @@
5372. [bug] Fix migration from existing DNSSEC key files using
auto-dnssec maintain to dnssec-policy. [GL #1706]
5371. [bug] Improve incremental updates of the RPZ summary
database to reduce delays that could occur when
a policy zone update included a large number of

View file

@ -24,6 +24,7 @@ options {
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
};
key rndc_key {
@ -35,6 +36,35 @@ controls {
inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
/* These are zones that migrate to dnssec-policy. */
zone "migrate.kasp" {
type master;
file "migrate.kasp.db";
auto-dnssec maintain;
allow-update { any; };
dnssec-dnskey-kskonly yes;
update-check-ksk yes;
};
zone "migrate-nomatch-algnum.kasp" {
type master;
file "migrate-nomatch-algnum.kasp.db";
auto-dnssec maintain;
allow-update { any; };
dnssec-dnskey-kskonly yes;
update-check-ksk yes;
};
zone "migrate-nomatch-alglen.kasp" {
type master;
file "migrate-nomatch-alglen.kasp.db";
auto-dnssec maintain;
allow-update { any; };
dnssec-dnskey-kskonly yes;
update-check-ksk yes;
};
/* These are alorithm rollover test zones. */
zone "step1.algorithm-roll.kasp" {
type master;
file "step1.algorithm-roll.kasp.db";

View file

@ -35,6 +35,31 @@ controls {
inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
/* These are zones that migrate to dnssec-policy. */
zone "migrate.kasp" {
type master;
file "migrate.kasp.db";
allow-update { any; };
dnssec-policy "migrate";
};
zone "migrate-nomatch-algnum.kasp" {
type master;
file "migrate-nomatch-algnum.kasp.db";
allow-update { any; };
dnssec-policy "migrate-nomatch-algnum";
};
zone "migrate-nomatch-alglen.kasp" {
type master;
file "migrate-nomatch-alglen.kasp.db";
allow-update { any; };
dnssec-policy "migrate-nomatch-alglen";
};
/*
* Zones for testing KSK/ZSK algorithm roll.
*/
zone "step1.algorithm-roll.kasp" {
type master;
file "step1.algorithm-roll.kasp.db";

View file

@ -48,3 +48,56 @@ dnssec-policy "ecdsa256" {
parent-propagation-delay pt1h;
parent-ds-ttl 7200;
};
dnssec-policy "migrate" {
dnskey-ttl 300;
keys {
ksk key-directory lifetime unlimited algorithm ECDSAP256SHA256;
zsk key-directory lifetime P60D algorithm ECDSAP256SHA256;
};
};
/*
* This policy tests migration from existing keys with 1024 bits RSASHA1 keys
* to ECDSAP256SHA256 keys.
*/
dnssec-policy "migrate-nomatch-algnum" {
dnskey-ttl 300;
keys {
ksk key-directory lifetime unlimited algorithm ecdsa256;
zsk key-directory lifetime P60D algorithm ecdsa256;
};
// Together 12h
zone-propagation-delay 3600;
max-zone-ttl 11h;
// Together 24h
parent-registration-delay 21h;
parent-propagation-delay pt1h;
parent-ds-ttl 7200;
};
/*
* This policy tests migration from existing keys with 1024 bits RSASHA1 keys
* to 2048 bits RSASHA1 keys.
*/
dnssec-policy "migrate-nomatch-alglen" {
dnskey-ttl 300;
keys {
ksk key-directory lifetime unlimited algorithm rsasha1 2048;
zsk key-directory lifetime P60D algorithm rsasha1 2048;
};
// Together 12h
zone-propagation-delay 3600;
max-zone-ttl 11h;
// Together 24h
parent-registration-delay 21h;
parent-propagation-delay pt1h;
parent-ds-ttl 7200;
};

View file

@ -39,6 +39,54 @@ R="RUMOURED"
O="OMNIPRESENT"
U="UNRETENTIVE"
# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy.
setup migrate.kasp
echo "$zone" >> zones
KSK=$($KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2)
$SETTIME -P now -P sync now -A now "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -P now -A now "$ZSK" > settime.out.$zone.2 2>&1
cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
private_type_record $zone 5 "$KSK" >> "$infile"
private_type_record $zone 5 "$ZSK" >> "$infile"
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy, but this
# time the existing keys do not match the policy. The existing keys are
# RSASHA1 keys, and will be migrated to a dnssec-policy that dictates
# ECDSAP256SHA256 keys.
setup migrate-nomatch-algnum.kasp
echo "$zone" >> zones
KSK=$($KEYGEN -a RSASHA1 -b 2048 -f KSK -L 300 $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a RSASHA1 -b 1024 -L 300 $zone 2> keygen.out.$zone.2)
Tds="now-24h" # Time according to dnssec-policy that DS will be OMNIPRESENT
Tkey="now-3900s" # DNSKEY TTL + propagation delay
Tsig="now-12h" # Zone's maximum TTL + propagation delay
$SETTIME -P $Tkey -P sync $Tds -A $Tkey "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -P $Tsig -A $Tsig "$ZSK" > settime.out.$zone.2 2>&1
cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
private_type_record $zone 5 "$KSK" >> "$infile"
private_type_record $zone 5 "$ZSK" >> "$infile"
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
# Set up a zone with auto-dnssec maintain to migrate to dnssec-policy, but this
# time the existing keys do not match the policy. The existing keys are
# 1024 bits RSASHA1 keys, and will be migrated to a dnssec-policy that
# dictates 2048 bits RSASHA1 keys.
setup migrate-nomatch-alglen.kasp
echo "$zone" >> zones
KSK=$($KEYGEN -a RSASHA1 -b 1024 -f KSK -L 300 $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a RSASHA1 -b 1024 -L 300 $zone 2> keygen.out.$zone.2)
Tds="now-24h" # Time according to dnssec-policy that DS will be OMNIPRESENT
Tkey="now-3900s" # DNSKEY TTL + propagation delay
Tsig="now-12h" # Zone's maximum TTL + propagation delay
$SETTIME -P $Tkey -P sync $Tds -A $Tkey "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -P $Tsig -A $Tsig "$ZSK" > settime.out.$zone.2 2>&1
cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile"
private_type_record $zone 5 "$KSK" >> "$infile"
private_type_record $zone 5 "$ZSK" >> "$infile"
$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
#
# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK
# algorithm rollover.
@ -47,6 +95,7 @@ U="UNRETENTIVE"
# Step 1:
# Introduce the first key. This will immediately be active.
setup step1.algorithm-roll.kasp
echo "$zone" >> zones
KSK=$($KEYGEN -a RSASHA1 -f KSK -L 3600 $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a RSASHA1 -L 3600 $zone 2> keygen.out.$zone.2)
TactN="now"

View file

@ -55,6 +55,7 @@ VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8="
# STATE_DS=18
# EXPECT_ZRRSIG=19
# EXPECT_KRRSIG=20
# LEGACY=21
key_key() {
echo "${1}__${2}"
@ -77,7 +78,7 @@ key_clear() {
key_set "$1" "ROLE" 'none'
key_set "$1" "KSK" 'no'
key_set "$1" "ZSK" 'no'
key_set "$1" "LIFETIME" '0'
key_set "$1" "LIFETIME" 'none'
key_set "$1" "ALG_NUM" '0'
key_set "$1" "ALG_STR" 'none'
key_set "$1" "ALG_LEN" '0'
@ -93,6 +94,7 @@ key_clear() {
key_set "$1" "STATE_DS" 'none'
key_set "$1" "EXPECT_ZRRSIG" 'no'
key_set "$1" "EXPECT_KRRSIG" 'no'
key_set "$1" "LEGACY" 'no'
}
# Start clear.
@ -238,6 +240,7 @@ check_key() {
_length=$(key_get "$1" "ALG_LEN")
_dnskey_ttl="$DNSKEY_TTL"
_lifetime=$(key_get "$1" LIFETIME)
_legacy=$(key_get "$1" LEGACY)
_published=$(key_get "$1" PUBLISHED)
_active=$(key_get "$1" ACTIVE)
@ -277,10 +280,13 @@ check_key() {
# Check file existence.
[ -s "$KEY_FILE" ] || ret=1
[ -s "$PRIVATE_FILE" ] || ret=1
[ -s "$STATE_FILE" ] || ret=1
if [ "$_legacy" == "no" ]; then
[ -s "$STATE_FILE" ] || ret=1
fi
[ "$ret" -eq 0 ] || log_error "${BASE_FILE} files missing"
[ "$ret" -eq 0 ] || return
test $_log -eq 1 && echo_i "check key $BASE_FILE"
test $_log -eq 1 && echo_i "check key file $BASE_FILE"
# Check the public key file.
grep "This is a ${_role2} key, keyid ${_key_id}, for ${_zone}." "$KEY_FILE" > /dev/null || log_error "mismatch top comment in $KEY_FILE"
@ -289,106 +295,134 @@ check_key() {
grep "Private-key-format: v1.3" "$PRIVATE_FILE" > /dev/null || log_error "mismatch private key format in $PRIVATE_FILE"
grep "Algorithm: ${_alg_num} (${_alg_string})" "$PRIVATE_FILE" > /dev/null || log_error "mismatch algorithm in $PRIVATE_FILE"
# Now check the key state file.
grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || log_error "mismatch top comment in $STATE_FILE"
grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
grep "Length: ${_length}" "$STATE_FILE" > /dev/null || log_error "mismatch length in $STATE_FILE"
grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || log_error "mismatch ksk in $STATE_FILE"
grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || log_error "mismatch zsk in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || log_error "mismatch top comment in $STATE_FILE"
if [ "$_lifetime" == "none" ]; then
grep "Lifetime: " "$STATE_FILE" > /dev/null && log_error "unexpected lifetime in $STATE_FILE"
else
grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
fi
grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
grep "Length: ${_length}" "$STATE_FILE" > /dev/null || log_error "mismatch length in $STATE_FILE"
grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || log_error "mismatch ksk in $STATE_FILE"
grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || log_error "mismatch zsk in $STATE_FILE"
# Check key states.
if [ "$_goal" = "none" ]; then
grep "GoalState: " "$STATE_FILE" > /dev/null && log_error "unexpected goal state in $STATE_FILE"
else
grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || log_error "mismatch goal state in $STATE_FILE"
fi
# Check key states.
if [ "$_goal" = "none" ]; then
grep "GoalState: " "$STATE_FILE" > /dev/null && log_error "unexpected goal state in $STATE_FILE"
else
grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || log_error "mismatch goal state in $STATE_FILE"
fi
if [ "$_state_dnskey" = "none" ]; then
grep "DNSKEYState: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey state in $STATE_FILE"
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey change in $STATE_FILE"
else
grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || log_error "mismatch dnskey state in $STATE_FILE"
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || log_error "mismatch dnskey change in $STATE_FILE"
fi
if [ "$_state_dnskey" = "none" ]; then
grep "DNSKEYState: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey state in $STATE_FILE"
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey change in $STATE_FILE"
else
grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || log_error "mismatch dnskey state in $STATE_FILE"
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || log_error "mismatch dnskey change in $STATE_FILE"
fi
if [ "$_state_zrrsig" = "none" ]; then
grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig state in $STATE_FILE"
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig change in $STATE_FILE"
else
grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig state in $STATE_FILE"
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig change in $STATE_FILE"
fi
if [ "$_state_zrrsig" = "none" ]; then
grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig state in $STATE_FILE"
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig change in $STATE_FILE"
else
grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig state in $STATE_FILE"
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig change in $STATE_FILE"
fi
if [ "$_state_krrsig" = "none" ]; then
grep "KRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig state in $STATE_FILE"
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig change in $STATE_FILE"
else
grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch krrsig state in $STATE_FILE"
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch krrsig change in $STATE_FILE"
fi
if [ "$_state_krrsig" = "none" ]; then
grep "KRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig state in $STATE_FILE"
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig change in $STATE_FILE"
else
grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch krrsig state in $STATE_FILE"
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch krrsig change in $STATE_FILE"
fi
if [ "$_state_ds" = "none" ]; then
grep "DSState: " "$STATE_FILE" > /dev/null && log_error "unexpected ds state in $STATE_FILE"
grep "DSChange: " "$STATE_FILE" > /dev/null && log_error "unexpected ds change in $STATE_FILE"
else
grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || log_error "mismatch ds state in $STATE_FILE"
grep "DSChange: " "$STATE_FILE" > /dev/null || log_error "mismatch ds change in $STATE_FILE"
if [ "$_state_ds" = "none" ]; then
grep "DSState: " "$STATE_FILE" > /dev/null && log_error "unexpected ds state in $STATE_FILE"
grep "DSChange: " "$STATE_FILE" > /dev/null && log_error "unexpected ds change in $STATE_FILE"
else
grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || log_error "mismatch ds state in $STATE_FILE"
grep "DSChange: " "$STATE_FILE" > /dev/null || log_error "mismatch ds change in $STATE_FILE"
fi
fi
# Check timing metadata.
if [ "$_published" = "none" ]; then
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
fi
else
grep "; Publish:" "$KEY_FILE" > /dev/null || log_error "mismatch publish comment in $KEY_FILE ($KEY_PUBLISHED)"
grep "Publish:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch publish in $PRIVATE_FILE ($KEY_PUBLISHED)"
grep "Published:" "$STATE_FILE" > /dev/null || log_error "mismatch publish in $STATE_FILE ($KEY_PUBLISHED)"
grep "; Publish:" "$KEY_FILE" > /dev/null || log_error "mismatch publish comment in $KEY_FILE"
grep "Publish:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch publish in $PRIVATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Published:" "$STATE_FILE" > /dev/null || log_error "mismatch publish in $STATE_FILE"
fi
fi
if [ "$_active" = "none" ]; then
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
fi
else
grep "; Activate:" "$KEY_FILE" > /dev/null || log_error "mismatch active comment in $KEY_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch active in $PRIVATE_FILE"
grep "Active: " "$STATE_FILE" > /dev/null || log_error "mismatch active in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Active: " "$STATE_FILE" > /dev/null || log_error "mismatch active in $STATE_FILE"
fi
fi
if [ "$_retired" = "none" ]; then
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
fi
else
grep "; Inactive:" "$KEY_FILE" > /dev/null || log_error "mismatch retired comment in $KEY_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch retired in $PRIVATE_FILE"
grep "Retired: " "$STATE_FILE" > /dev/null || log_error "mismatch retired in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Retired: " "$STATE_FILE" > /dev/null || log_error "mismatch retired in $STATE_FILE"
fi
fi
if [ "$_revoked" = "none" ]; then
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
fi
else
grep "; Revoke:" "$KEY_FILE" > /dev/null || log_error "mismatch revoked comment in $KEY_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch revoked in $PRIVATE_FILE"
grep "Revoked: " "$STATE_FILE" > /dev/null || log_error "mismatch revoked in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Revoked: " "$STATE_FILE" > /dev/null || log_error "mismatch revoked in $STATE_FILE"
fi
fi
if [ "$_removed" = "none" ]; then
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
fi
else
grep "; Delete:" "$KEY_FILE" > /dev/null || log_error "mismatch removed comment in $KEY_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch removed in $PRIVATE_FILE"
grep "Removed: " "$STATE_FILE" > /dev/null || log_error "mismatch removed in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Removed: " "$STATE_FILE" > /dev/null || log_error "mismatch removed in $STATE_FILE"
fi
fi
grep "; Created:" "$KEY_FILE" > /dev/null || log_error "mismatch created comment in $KEY_FILE"
grep "Created:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch created in $PRIVATE_FILE"
grep "Generated: " "$STATE_FILE" > /dev/null || log_error "mismatch generated in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Generated: " "$STATE_FILE" > /dev/null || log_error "mismatch generated in $STATE_FILE"
fi
}
# Check the key with key id $1 and see if it is unused.
@ -424,20 +458,24 @@ key_unused() {
# Check timing metadata.
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
if [ "$_legacy" == "no" ]; then
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
fi
}
# Test: dnssec-verify zone $1.
@ -848,7 +886,7 @@ check_keys()
for _id in $_ids; do
# There are three key files with the same algorithm.
# Check them until a match is found.
echo_i "check key $_id"
echo_i "check key id $_id"
if [ "no" = "$(key_get KEY1 ID)" ] && [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
ret=0
@ -863,19 +901,19 @@ check_keys()
if [ "no" = "$(key_get KEY3 ID)" ] && [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
ret=0
check_key "KEY3" "$_id"
test "$ret" -eq 0 && key_set KEY3 ID "$KEY_ID" && continue
test "$ret" -eq 0 && key_set KEY3 "ID" "$KEY_ID" && continue
fi
if [ "no" = "$(key_get KEY4 ID)" ] && [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
ret=0
check_key "KEY4" "$_id"
test "$ret" -eq 0 && key_set KEY4 ID "$KEY_ID" && continue
test "$ret" -eq 0 && key_set KEY4 "ID" "$KEY_ID" && continue
fi
# This may be an unused key. Assume algorithm of KEY1.
ret=0 && key_unused "$_id" "$(key_get KEY1 ALG_NUM)"
test "$ret" -eq 0 && continue
# If ret is still non-zero, non of the files matched.
# If ret is still non-zero, none of the files matched.
test "$ret" -eq 0 || echo_i "failed"
status=$((status+1))
done
@ -885,15 +923,19 @@ check_keys()
ret=0
if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
echo_i "KEY1 ID $(key_get KEY1 ID)"
test "no" = "$(key_get KEY1 ID)" && log_error "No KEY1 found for zone ${ZONE}"
fi
if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
echo_i "KEY2 ID $(key_get KEY2 ID)"
test "no" = "$(key_get KEY2 ID)" && log_error "No KEY2 found for zone ${ZONE}"
fi
if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
echo_i "KEY3 ID $(key_get KEY3 ID)"
test "no" = "$(key_get KEY3 ID)" && log_error "No KEY3 found for zone ${ZONE}"
fi
if [ "$(key_get KEY4 EXPECT)" = "yes" ]; then
echo_i "KEY4 ID $(key_get KEY4 ID)"
test "no" = "$(key_get KEY4 ID)" && log_error "No KEY4 found for zone ${ZONE}"
fi
test "$ret" -eq 0 || echo_i "failed"
@ -2821,7 +2863,166 @@ dnssec_verify
# interval.
check_next_key_event 3600
# Reconfig dnssec-policy (triggering algorithm roll).
#
# Testing good migration.
#
set_zone "migrate.kasp"
set_policy "none" "2" "300"
set_server "ns6" "10.53.0.6"
init_migration_match() {
key_clear "KEY1"
key_set "KEY1" "LEGACY" "yes"
set_keyrole "KEY1" "ksk"
set_keylifetime "KEY1" "0"
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY1" "yes"
set_zonesigning "KEY1" "no"
key_clear "KEY2"
key_set "KEY2" "LEGACY" "yes"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "5184000"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "yes"
key_clear "KEY3"
key_clear "KEY4"
set_keytime "KEY1" "PUBLISHED" "yes"
set_keytime "KEY1" "ACTIVE" "yes"
set_keytime "KEY1" "RETIRED" "none"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "rumoured"
set_keystate "KEY1" "STATE_KRRSIG" "rumoured"
set_keystate "KEY1" "STATE_DS" "rumoured"
set_keytime "KEY2" "PUBLISHED" "yes"
set_keytime "KEY2" "ACTIVE" "yes"
set_keytime "KEY2" "RETIRED" "none"
set_keystate "KEY2" "GOAL" "omnipresent"
set_keystate "KEY2" "STATE_DNSKEY" "rumoured"
set_keystate "KEY2" "STATE_ZRRSIG" "rumoured"
}
init_migration_match
# Make sure the zone is signed with legacy keys.
check_keys
check_apex
check_subdomain
dnssec_verify
# Remember legacy key tags.
_migrate_ksk=$(key_get KEY1 ID)
_migrate_zsk=$(key_get KEY2 ID)
#
# Testing migration with unmatched existing keys (different algorithm).
#
set_zone "migrate-nomatch-algnum.kasp"
set_policy "none" "2" "300"
set_server "ns6" "10.53.0.6"
init_migration_nomatch_algnum() {
key_clear "KEY1"
key_set "KEY1" "LEGACY" "yes"
set_keyrole "KEY1" "ksk"
set_keyalgorithm "KEY1" "5" "RSASHA1" "2048"
set_keysigning "KEY1" "yes"
set_zonesigning "KEY1" "no"
key_clear "KEY2"
key_set "KEY2" "LEGACY" "yes"
set_keyrole "KEY2" "zsk"
set_keyalgorithm "KEY2" "5" "RSASHA1" "1024"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "yes"
key_clear "KEY3"
key_clear "KEY4"
set_keytime "KEY1" "PUBLISHED" "yes"
set_keytime "KEY1" "ACTIVE" "yes"
set_keytime "KEY1" "RETIRED" "none"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY1" "STATE_DS" "omnipresent"
set_keytime "KEY2" "PUBLISHED" "yes"
set_keytime "KEY2" "ACTIVE" "yes"
set_keytime "KEY2" "RETIRED" "none"
set_keystate "KEY2" "GOAL" "omnipresent"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
}
init_migration_nomatch_algnum
# Make sure the zone is signed with legacy keys.
check_keys
check_apex
check_subdomain
dnssec_verify
# Remember legacy key tags.
_migratenomatch_algnum_ksk=$(key_get KEY1 ID)
_migratenomatch_algnum_zsk=$(key_get KEY2 ID)
#
# Testing migration with unmatched existing keys (different length).
#
set_zone "migrate-nomatch-alglen.kasp"
set_policy "none" "2" "300"
set_server "ns6" "10.53.0.6"
init_migration_nomatch_alglen() {
key_clear "KEY1"
key_set "KEY1" "LEGACY" "yes"
set_keyrole "KEY1" "ksk"
set_keyalgorithm "KEY1" "5" "RSASHA1" "1024"
set_keysigning "KEY1" "yes"
set_zonesigning "KEY1" "no"
key_clear "KEY2"
key_set "KEY2" "LEGACY" "yes"
set_keyrole "KEY2" "zsk"
set_keyalgorithm "KEY2" "5" "RSASHA1" "1024"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "yes"
key_clear "KEY3"
key_clear "KEY4"
set_keytime "KEY1" "PUBLISHED" "yes"
set_keytime "KEY1" "ACTIVE" "yes"
set_keytime "KEY1" "RETIRED" "none"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY1" "STATE_DS" "omnipresent"
set_keytime "KEY2" "PUBLISHED" "yes"
set_keytime "KEY2" "ACTIVE" "yes"
set_keytime "KEY2" "RETIRED" "none"
set_keystate "KEY2" "GOAL" "omnipresent"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
}
init_migration_nomatch_alglen
# Make sure the zone is signed with legacy keys.
check_keys
check_apex
check_subdomain
dnssec_verify
# Remember legacy key tags.
_migratenomatch_alglen_ksk=$(key_get KEY1 ID)
_migratenomatch_alglen_zsk=$(key_get KEY2 ID)
# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy
# changes).
echo_i "reconfig dnssec-policy to trigger algorithm rollover"
copy_setports ns6/named2.conf.in ns6/named.conf
rndc_reconfig ns6 10.53.0.6
@ -2854,6 +3055,150 @@ status=$((status+ret))
next_key_event_threshold=$((next_key_event_threshold+i))
#
# Testing migration.
#
set_zone "migrate.kasp"
set_policy "migrate" "2" "300"
set_server "ns6" "10.53.0.6"
# Key properties, timings and metadata should be the same as legacy keys above.
# However, because the zsk has a lifetime, kasp will set the retired time.
init_migration_match
key_set "KEY1" "LEGACY" "no"
key_set "KEY2" "LEGACY" "no"
set_keytime "KEY2" "RETIRED" "yes"
check_keys
check_apex
check_subdomain
dnssec_verify
# Check key tags, should be the same.
n=$((n+1))
echo_i "check that of zone ${ZONE} migration to dnssec-policy uses the same keys ($n)"
ret=0
[ $_migrate_ksk == $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
[ $_migrate_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
status=$((status+ret))
# Test migration to dnssec-policy, existing keys do not match key algorithm.
set_zone "migrate-nomatch-algnum.kasp"
set_policy "migrate-nomatch-algnum" "4" "300"
set_server "ns6" "10.53.0.6"
# The legacy keys need to be retired, but otherwise stay present until the
# new keys are omnipresent, and can be used to construct a chain of trust.
init_migration_nomatch_algnum
key_set "KEY1" "LEGACY" "no"
set_keytime "KEY1" "RETIRED" "yes"
set_keystate "KEY1" "GOAL" "hidden"
key_set "KEY2" "LEGACY" "no"
set_keytime "KEY2" "RETIRED" "yes"
set_keystate "KEY2" "GOAL" "hidden"
set_keyrole "KEY3" "ksk"
set_keylifetime "KEY3" "0"
set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY3" "yes"
set_zonesigning "KEY3" "no"
set_keyrole "KEY4" "zsk"
set_keylifetime "KEY4" "5184000"
set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY4" "no"
set_zonesigning "KEY4" "yes"
set_keytime "KEY3" "PUBLISHED" "yes"
set_keytime "KEY3" "ACTIVE" "yes"
set_keytime "KEY3" "RETIRED" "none"
set_keystate "KEY3" "GOAL" "omnipresent"
set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
set_keystate "KEY3" "STATE_DS" "hidden"
set_keytime "KEY4" "PUBLISHED" "yes"
set_keytime "KEY4" "ACTIVE" "yes"
set_keytime "KEY4" "RETIRED" "yes"
set_keystate "KEY4" "GOAL" "omnipresent"
set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
set_keystate "KEY4" "STATE_ZRRSIG" "rumoured"
check_keys
check_apex
check_subdomain
dnssec_verify
# Check key tags, should be the same.
n=$((n+1))
echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)"
ret=0
[ $_migratenomatch_algnum_ksk == $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
[ $_migratenomatch_algnum_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
status=$((status+ret))
# Test migration to dnssec-policy, existing keys do not match key length.
set_zone "migrate-nomatch-alglen.kasp"
set_policy "migrate-nomatch-alglen" "4" "300"
set_server "ns6" "10.53.0.6"
# The legacy keys need to be retired, but otherwise stay present until the
# new keys are omnipresent, and can be used to construct a chain of trust.
init_migration_nomatch_alglen
key_set "KEY1" "LEGACY" "no"
set_keytime "KEY1" "RETIRED" "yes"
set_keystate "KEY1" "GOAL" "hidden"
key_set "KEY2" "LEGACY" "no"
set_keytime "KEY2" "RETIRED" "yes"
set_keystate "KEY2" "GOAL" "hidden"
set_keyrole "KEY3" "ksk"
set_keylifetime "KEY3" "0"
set_keyalgorithm "KEY3" "5" "RSASHA1" "2048"
set_keysigning "KEY3" "yes"
set_zonesigning "KEY3" "no"
set_keyrole "KEY4" "zsk"
set_keylifetime "KEY4" "5184000"
set_keyalgorithm "KEY4" "5" "RSASHA1" "2048"
set_keysigning "KEY4" "no"
# This key is considered to be prepublished, so it is not yet signing.
set_zonesigning "KEY4" "no"
set_keytime "KEY3" "PUBLISHED" "yes"
set_keytime "KEY3" "ACTIVE" "yes"
set_keytime "KEY3" "RETIRED" "none"
set_keystate "KEY3" "GOAL" "omnipresent"
set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
set_keystate "KEY3" "STATE_KRRSIG" "rumoured"
set_keystate "KEY3" "STATE_DS" "hidden"
set_keytime "KEY4" "PUBLISHED" "yes"
set_keytime "KEY4" "ACTIVE" "yes"
set_keytime "KEY4" "RETIRED" "yes"
set_keystate "KEY4" "GOAL" "omnipresent"
set_keystate "KEY4" "STATE_DNSKEY" "rumoured"
set_keystate "KEY4" "STATE_ZRRSIG" "hidden"
check_keys
check_apex
check_subdomain
dnssec_verify
# Check key tags, should be the same.
n=$((n+1))
echo_i "check that of zone ${ZONE} migration to dnssec-policy keeps existing keys ($n)"
ret=0
[ $_migratenomatch_alglen_ksk == $(key_get KEY1 ID) ] || log_error "mismatch ksk tag"
[ $_migratenomatch_alglen_zsk == $(key_get KEY2 ID) ] || log_error "mismatch zsk tag"
status=$((status+ret))
#
# Testing KSK/ZSK algorithm rollover.
#

View file

@ -63,6 +63,14 @@
reducing such delays. [GL #1447]
</para>
</listitem>
<listitem>
<para>
Migration to dnssec-policy from existing DNSSEC strategy with
auto-dnssec maintain did not work due to bad initializing of the
key states. Fixed by looking closely at the time metadata to
set the key states to the correct values. [GL #1706]
</para>
</listitem>
</itemizedlist>
</section>

View file

@ -43,13 +43,13 @@
* Set key state to HIDDEN and change last changed to now,
* only if key state has not been set before.
*/
#define INITIALIZE_STATE(key, state, time) \
#define INITIALIZE_STATE(key, state, time, target) \
do { \
dst_key_state_t s; \
if (dst_key_getstate((key), (state), &s) == ISC_R_NOTFOUND) { \
isc_stdtime_t t; \
dst_key_gettime((key), DST_TIME_CREATED, &t); \
dst_key_setstate((key), (state), HIDDEN); \
dst_key_setstate((key), (state), target); \
dst_key_settime((key), (time), t); \
} \
} while (0)
@ -105,7 +105,7 @@ static isc_stdtime_t
keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
uint32_t lifetime, isc_stdtime_t now) {
isc_result_t ret;
isc_stdtime_t active, retire, prepub;
isc_stdtime_t active, retire, pub, prepub;
bool ksk = false;
REQUIRE(key != NULL);
@ -125,7 +125,8 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
if (ret != ISC_R_SUCCESS) {
uint32_t klifetime = 0;
/*
* An active key must have an activate timing metadata.
* An active key must have publish and activate timing
* metadata.
*/
ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
if (ret != ISC_R_SUCCESS) {
@ -133,6 +134,12 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
dst_key_settime(key->key, DST_TIME_ACTIVATE, now);
active = now;
}
ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
if (ret != ISC_R_SUCCESS) {
/* Super weird, but if it happens, set it to now. */
dst_key_settime(key->key, DST_TIME_PUBLISH, now);
pub = now;
}
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
if (ret != ISC_R_SUCCESS) {
@ -1214,19 +1221,25 @@ transition:
}
/*
* See if this key needs to be initialized with a role. A key created and
* derived from a dnssec-policy will have the required metadata available,
* otherwise these may be missing and need to be initialized.
* See if this key needs to be initialized with properties. A key created
* and derived from a dnssec-policy will have the required metadata available,
* otherwise these may be missing and need to be initialized. The key states
* will be initialized according to existing timing metadata.
*
*/
static void
keymgr_key_init_role(dns_dnsseckey_t *key) {
keymgr_key_init(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) {
bool ksk, zsk;
isc_result_t ret;
isc_stdtime_t active = 0, pub = 0, syncpub = 0;
dst_key_state_t dnskey_state = HIDDEN;
dst_key_state_t ds_state = HIDDEN;
dst_key_state_t zrrsig_state = HIDDEN;
REQUIRE(key != NULL);
REQUIRE(key->key != NULL);
/* Initialize role. */
ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk);
if (ret != ISC_R_SUCCESS) {
ksk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) != 0);
@ -1237,6 +1250,52 @@ keymgr_key_init_role(dns_dnsseckey_t *key) {
zsk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) == 0);
dst_key_setbool(key->key, DST_BOOL_ZSK, zsk);
}
/* Get time metadata. */
ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
if (active <= now && ret == ISC_R_SUCCESS) {
dns_ttl_t key_ttl = dst_key_getttl(key->key);
key_ttl += dns_kasp_zonepropagationdelay(kasp);
if ((active + key_ttl) <= now) {
dnskey_state = OMNIPRESENT;
} else {
dnskey_state = RUMOURED;
}
}
ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub);
if (pub <= now && ret == ISC_R_SUCCESS) {
dns_ttl_t zone_ttl = dns_kasp_zonemaxttl(kasp);
zone_ttl += dns_kasp_zonepropagationdelay(kasp);
if ((pub + zone_ttl) <= now) {
zrrsig_state = OMNIPRESENT;
} else {
zrrsig_state = RUMOURED;
}
}
ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub);
if (syncpub <= now && ret == ISC_R_SUCCESS) {
dns_ttl_t ds_ttl = dns_kasp_dsttl(kasp);
ds_ttl += dns_kasp_parentregistrationdelay(kasp);
ds_ttl += dns_kasp_parentpropagationdelay(kasp);
if ((syncpub + ds_ttl) <= now) {
ds_state = OMNIPRESENT;
} else {
ds_state = RUMOURED;
}
}
/* Set key states for all keys that do not have them. */
INITIALIZE_STATE(key->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY,
dnskey_state);
if (ksk) {
INITIALIZE_STATE(key->key, DST_KEY_KRRSIG, DST_TIME_KRRSIG,
dnskey_state);
INITIALIZE_STATE(key->key, DST_KEY_DS, DST_TIME_DS, ds_state);
}
if (zsk) {
INITIALIZE_STATE(key->key, DST_KEY_ZRRSIG, DST_TIME_ZRRSIG,
zrrsig_state);
}
}
/*
@ -1302,23 +1361,13 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
{
bool found_match = false;
/* Make sure this key knows about roles. */
keymgr_key_init_role(dkey);
keymgr_key_init(dkey, kasp, now);
for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
kkey = ISC_LIST_NEXT(kkey, link))
{
if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) {
found_match = true;
dst_key_format(dkey->key, keystr,
sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC,
ISC_LOG_DEBUG(1),
"keymgr: DNSKEY %s (%s) matches "
"policy %s",
keystr, keymgr_keyrole(dkey->key),
dns_kasp_getname(kasp));
break;
}
}
@ -1343,8 +1392,17 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
{
if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) {
/* Found a match. */
dst_key_format(dkey->key, keystr,
sizeof(keystr));
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC,
ISC_LOG_DEBUG(1),
"keymgr: DNSKEY %s (%s) matches "
"policy %s",
keystr, keymgr_keyrole(dkey->key),
dns_kasp_getname(kasp));
/* Initialize lifetime. */
/* Initialize lifetime if not set. */
uint32_t l;
if (dst_key_getnum(dkey->key, DST_NUM_LIFETIME,
&l) != ISC_R_SUCCESS) {
@ -1353,18 +1411,49 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
lifetime);
}
if (dst_key_goal(dkey->key) == OMNIPRESENT) {
if (active_key != NULL) {
if (active_key) {
/* We already have an active key that
* matches the kasp policy.
*/
if (!dst_key_is_unused(dkey->key) &&
(dst_key_goal(dkey->key) ==
OMNIPRESENT) &&
!keymgr_key_is_successor(
dkey->key,
active_key->key) &&
!keymgr_key_is_successor(
active_key->key, dkey->key))
{
/*
* Multiple signing keys match
* the kasp key configuration.
* Retire excess keys.
* Retire excess keys in use.
*/
keymgr_key_retire(dkey, now);
} else {
/* Save the matched key. */
active_key = dkey;
}
continue;
}
/*
* This is possibly an active key created
* outside dnssec-policy. Initialize goal,
* if not set.
*/
dst_key_state_t goal;
if (dst_key_getstate(dkey->key, DST_KEY_GOAL,
&goal) != ISC_R_SUCCESS) {
dst_key_setstate(dkey->key,
DST_KEY_GOAL,
OMNIPRESENT);
}
/*
* Save the matched key only if it is active
* or desires to be active.
*/
if (dst_key_goal(dkey->key) == OMNIPRESENT ||
dst_key_is_active(dkey->key, now)) {
active_key = dkey;
}
}
}
@ -1377,7 +1466,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
isc_log_write(
dns_lctx, DNS_LOGCATEGORY_DNSSEC,
DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
"keymgr: DNSKEY %s (%s) matches "
"keymgr: DNSKEY %s (%s) is active in "
"policy %s",
keystr, keymgr_keyrole(active_key->key),
dns_kasp_getname(kasp));
@ -1446,6 +1535,7 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
dst_key_setttl(dst_key, dns_kasp_dnskeyttl(kasp));
dst_key_settime(dst_key, DST_TIME_CREATED, now);
RETERR(dns_dnsseckey_create(mctx, &dst_key, &newkey));
keymgr_key_init(newkey, kasp, now);
} else {
newkey = candidate;
dst_key_setnum(newkey->key, DST_NUM_LIFETIME, lifetime);
@ -1512,27 +1602,6 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
ISC_LIST_APPENDLIST(*keyring, newkeys, link);
}
/* Initialize key states (for keys that don't have them yet). */
for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL;
dkey = ISC_LIST_NEXT(dkey, link))
{
bool ksk = false, zsk = false;
/* Set key states for all keys that do not have them. */
INITIALIZE_STATE(dkey->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY);
(void)dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk);
if (ksk) {
INITIALIZE_STATE(dkey->key, DST_KEY_KRRSIG,
DST_TIME_KRRSIG);
INITIALIZE_STATE(dkey->key, DST_KEY_DS, DST_TIME_DS);
}
(void)dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk);
if (zsk) {
INITIALIZE_STATE(dkey->key, DST_KEY_ZRRSIG,
DST_TIME_ZRRSIG);
}
}
/* Read to update key states. */
keymgr_update(keyring, kasp, now, nexttime);