2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

Merge branch '2710-fix-inline-signing-multisigner-bugs-matthijs' into 'main'

Make multisigner server capabilities work with inline-signing

Closes #2710

See merge request isc-projects/bind9!6901
This commit is contained in:
Matthijs Mekking 2023-05-23 12:05:46 +00:00
commit bf6fbf9ee5
27 changed files with 1475 additions and 64 deletions

View File

@ -1,10 +1,12 @@
6178. [func] Add support for the multi-signer model 2 (RFC 8901) when
using inline-signing. [GL #2710]
6177. [placeholder]
6176. [test] Add support for using pytest & pytest-xdist to
execute the system test suite. [GL #3978]
6175. [test] Fix the `upforwd` system test to be more reliable,
especially when using thread sanitizer. [GL #4069]
6174. [placeholder]

View File

@ -201,7 +201,7 @@ endif HAVE_PERLMOD_NET_DNS_NAMESERVER
endif HAVE_PERLMOD_NET_DNS
if HAVE_PYTHON
TESTS += kasp keymgr2kasp tcp pipelined
TESTS += kasp keymgr2kasp multisigner tcp pipelined
if HAVE_PYTEST
TESTS += checkds dispatch rpzextra shutdown timeouts

View File

@ -108,6 +108,7 @@ keyfromlabel
keymgr2kasp
legacy
logfileconfig
multisigner
nzd2nzf
pipelined
qmin

View File

@ -209,6 +209,7 @@ zone "expired.example" {
zone "update-nsec3.example" {
type primary;
auto-dnssec maintain;
allow-update { any; };
file "update-nsec3.example.db.signed";
};

View File

@ -0,0 +1,43 @@
#!/bin/sh
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
set -e
rm -f *.created
rm -f cdnskey.ns*
rm -f cds.ns*
rm -f secondary.cdnskey.ns*
rm -f secondary.cds.ns*
rm -f created.key-*
rm -f dig.out.*
rm -f python.out.*
rm -f rndc.dnssec.status.out.*
rm -f unused.key-*
rm -f verify.out.*
rm -f ns*/*.jbk
rm -f ns*/*.jnl
rm -f ns*/*.journal.out.test*
rm -f ns*/*.signed
rm -f ns*/*.signed.jnl
rm -f ns*/*.zsk
rm -f ns*/db-*
rm -f ns*/K*
rm -f ns*/keygen.out.*
rm -f ns*/managed-keys*
rm -f ns*/model2.secondary.db
rm -f ns*/model2.secondary.db
rm -f ns*/named.conf
rm -f ns*/named.memstats
rm -f ns*/named.run
rm -f ns*/settime.out.*

View File

@ -0,0 +1,19 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-policy "model2" {
keys {
ksk lifetime unlimited algorithm ecdsap256sha256;
zsk lifetime unlimited algorithm ecdsap256sha256;
};
};

View File

@ -0,0 +1,27 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns3
ns3 A 10.53.0.3
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
// NS3
include "../kasp.conf";
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "model2.multisigner." {
type primary;
allow-update { any; };
file "model2.multisigner.db";
dnssec-policy model2;
inline-signing no;
};
zone "model2.secondary." {
type secondary;
primaries { 10.53.0.5; };
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
};

View File

@ -0,0 +1,44 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
echo_i "ns3/setup.sh"
O="OMNIPRESENT"
ksktimes="-P now -A now -P sync now"
zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" > settime.out.$zone.2 2>&1
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" > "${zone}.zsk"
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" > settime.out.$zone.2 2>&1
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" > "${zone}.zsk"

View File

@ -0,0 +1,26 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns4
ns4 A 10.53.0.4
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
// NS4
include "../kasp.conf";
options {
query-source address 10.53.0.4;
notify-source 10.53.0.4;
transfer-source 10.53.0.4;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "model2.multisigner." {
type primary;
allow-update { any; };
file "model2.multisigner.db";
dnssec-policy model2;
inline-signing yes;
};
zone "model2.secondary." {
type secondary;
primaries { 10.53.0.5; };
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
};

View File

@ -0,0 +1,44 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
echo_i "ns4/setup.sh"
O="OMNIPRESENT"
ksktimes="-P now -A now -P sync now"
zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" > settime.out.$zone.2 2>&1
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" > "${zone}.zsk"
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2> keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2> keygen.out.$zone.2)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" > settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" > settime.out.$zone.2 2>&1
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" > "${zone}.zsk"

View File

@ -0,0 +1,29 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns3
NS ns4
ns3 A 10.53.0.3
ns4 A 10.53.0.4
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
// NS5
include "../kasp.conf";
options {
query-source address 10.53.0.5;
notify-source 10.53.0.5;
transfer-source 10.53.0.5;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "model2.secondary." {
type primary;
allow-update { any; };
file "model2.secondary.db";
};

View File

@ -0,0 +1,22 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
echo_i "ns5/setup.sh"
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "${zonefile}.in" "$zonefile"

View File

@ -0,0 +1,36 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../conf.sh
set -e
$SHELL clean.sh
copy_setports ns3/named.conf.in ns3/named.conf
copy_setports ns4/named.conf.in ns4/named.conf
copy_setports ns5/named.conf.in ns5/named.conf
(
cd ns3
$SHELL setup.sh
)
(
cd ns4
$SHELL setup.sh
)
(
cd ns5
$SHELL setup.sh
)

View File

@ -0,0 +1,664 @@
#!/bin/sh
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../conf.sh
# shellcheck source=kasp.sh
. ../kasp.sh
dig_with_opts() {
$DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p $PORT "$@"
}
start_time="$(TZ=UTC date +%s)"
status=0
n=0
set_zone "model2.multisigner"
set_policy "model2" "2" "3600"
# Key properties and states.
key_clear "KEY1"
set_keyrole "KEY1" "ksk"
set_keylifetime "KEY1" "0"
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY1" "yes"
set_zonesigning "KEY1" "no"
set_keystate "KEY1" "GOAL" "omnipresent"
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
set_keystate "KEY1" "STATE_DS" "omnipresent"
key_clear "KEY2"
set_keyrole "KEY2" "zsk"
set_keylifetime "KEY2" "0"
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
set_keysigning "KEY2" "no"
set_zonesigning "KEY2" "yes"
set_keystate "KEY2" "GOAL" "omnipresent"
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
key_clear "KEY3"
key_clear "KEY4"
set_keytimes_model2() {
# The first KSK is immediately published and activated.
created=$(key_get KEY1 CREATED)
set_keytime "KEY1" "PUBLISHED" "${created}"
set_keytime "KEY1" "ACTIVE" "${created}"
set_keytime "KEY1" "SYNCPUBLISH" "${created}"
# The first ZSKs are immediately published and activated.
created=$(key_get KEY2 CREATED)
set_keytime "KEY2" "PUBLISHED" "${created}"
set_keytime "KEY2" "ACTIVE" "${created}"
}
set_server "ns3" "10.53.0.3"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_model2
check_keytimes
check_apex
dnssec_verify
set_server "ns4" "10.53.0.4"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_model2
check_keytimes
check_apex
dnssec_verify
#
# Update DNSKEY RRset.
#
# Check that the ZSKs from the other provider are published.
zsks_are_published() {
dig_with_opts "$ZONE" "@${SERVER}" DNSKEY > "dig.out.$DIR.test$n" || return 1
cat dig.out.$DIR.test$n | tr [:blank:] ' ' > dig.out.$DIR.test$n.tr || return 1
# We should have two ZSKs.
lines=$(grep "256 3 13" dig.out.$DIR.test$n.tr | wc -l)
test "$lines" -eq 2 || return 1
# Both ZSKs are published.
grep "$(cat ns3/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr > /dev/null || return 1
grep "$(cat ns4/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr > /dev/null || return 1
# And one KSK.
lines=$(grep "257 3 13" dig.out.$DIR.test$n.tr | wc -l)
test "$lines" -eq 1 || return 1
}
# Test to make sure no DNSSEC records end up in the raw journal.
no_dnssec_in_journal() {
n=$((n+1))
ret=0
echo_i "check zone ${ZONE} raw journal has no DNSSEC ($n)"
$JOURNALPRINT "${DIR}/${ZONE}.db.jnl" > "${DIR}/${ZONE}.journal.out.test$n"
rrset_exists NSEC "${DIR}/${ZONE}.journal.out.test$n" && ret=1
rrset_exists NSEC3 "${DIR}/${ZONE}.journal.out.test$n" && ret=1
rrset_exists NSEC3PARAM "${DIR}/${ZONE}.journal.out.test$n" && ret=1
rrset_exists RRSIG "${DIR}/${ZONE}.journal.out.test$n" && ret= 1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
}
# Check if a certain RRtype is present in the journal file.
rrset_exists() (
rrtype=$1
file=$2
lines=$(awk -v rt="${rrtype}" '$5 == rt {print}' ${file} | wc -l)
test "$lines" -gt 0
)
n=$((n+1))
echo_i "add dnskey record: update zone ${ZONE} at ns3 with ZSK from provider ns4 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Verify again.
dnssec_verify
n=$((n+1))
echo_i "add dnskey record: - update zone ${ZONE} at ns4 with ZSK from provider ns3 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "ns3/${ZONE}.zsk")
echo send
) | $NSUPDATE
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Verify again.
dnssec_verify
no_dnssec_in_journal
n=$((n+1))
echo_i "remove dnskey record: - try to remove ns3 ZSK from provider ns3 (should fail) ($n)"
ret=0
set_server "ns3" "10.53.0.3"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "ns3/${ZONE}.zsk")
echo send
) | $NSUPDATE
# Both ZSKs should still be published.
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "remove dnskey record: remove ns4 ZSK from provider ns3 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
check_keys
check_apex
dnssec_verify
n=$((n+1))
echo_i "remove dnskey record: try to remove ns4 ZSK from provider ns4 (should fail) ($n)"
ret=0
set_server "ns4" "10.53.0.4"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
# Both ZSKs should still be published.
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "remove dnskey record: remove ns3 ZSK from provider ns4 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "ns3/${ZONE}.zsk")
echo send
) | $NSUPDATE
check_keys
check_apex
dnssec_verify
no_dnssec_in_journal
#
# Update CDNSKEY RRset.
#
# Check that the CDNSKEY from both providers are published.
records_published() {
_rrtype=$1
_expect=$2
dig_with_opts "$ZONE" "@${SERVER}" "${_rrtype}" > "dig.out.$DIR.test$n" || return 1
lines=$(awk -v rt="${_rrtype}" '$4 == rt {print}' dig.out.$DIR.test$n | wc -l)
test "$lines" -eq "$_expect" || return 1
}
# Retrieve CDNSKEY records from the other provider.
dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY > dig.out.ns3.cdnskey
awk '$4 == "CDNSKEY" {print}' dig.out.ns3.cdnskey > cdnskey.ns3
dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY > dig.out.ns4.cdnskey
awk '$4 == "CDNSKEY" {print}' dig.out.ns4.cdnskey > cdnskey.ns4
n=$((n+1))
echo_i "add cdnskey record: update zone ${ZONE} at ns3 with CDNSKEY from provider ns4 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
# Initially there should be one CDNSKEY.
retry_quiet 10 records_published CDNSKEY 1 || ret=1
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "cdnskey.ns4")
echo send
) | $NSUPDATE
# Now there should be two CDNSKEY records (we test that BIND does not
# skip it during DNSSEC maintenance).
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "add cdnskey record: update zone ${ZONE} at ns4 with CDNSKEY from provider ns3 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
# Initially there should be one CDNSKEY.
retry_quiet 10 records_published CDNSKEY 1 || ret=1
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "cdnskey.ns3")
echo send
) | $NSUPDATE
# Now there should be two CDNSKEY records (we test that BIND does not
# skip it during DNSSEC maintenance).
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# No DNSSEC in raw journal.
no_dnssec_in_journal
n=$((n+1))
echo_i "remove cdnskey record: remove ns4 CDNSKEY from provider ns3 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "cdnskey.ns4")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDNSKEY record again.
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "remove cdnskey record: remove ns3 CDNSKEY from provider ns4 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "cdnskey.ns3")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDNSKEY record again.
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# No DNSSEC in raw journal.
no_dnssec_in_journal
#
# Update CDS RRset.
#
# Retrieve CDS records from the other provider.
dig_with_opts ${ZONE} @10.53.0.3 CDS > dig.out.ns3.cds
awk '$4 == "CDS" {print}' dig.out.ns3.cds > cds.ns3
dig_with_opts ${ZONE} @10.53.0.4 CDS > dig.out.ns4.cds
awk '$4 == "CDS" {print}' dig.out.ns4.cds > cds.ns4
n=$((n+1))
echo_i "add cds record: update zone ${ZONE} at ns3 with CDS from provider ns4 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
# Initially there should be one CDS.
retry_quiet 10 records_published CDS 1 || ret=1
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "cds.ns4")
echo send
) | $NSUPDATE
# Now there should be two CDS records (we test that BIND does not
# skip it during DNSSEC maintenance).
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "add cds record: update zone ${ZONE} at ns4 with CDS from provider ns3 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
# Initially there should be one CDS.
retry_quiet 10 records_published CDS 1 || ret=1
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "cds.ns3")
echo send
) | $NSUPDATE
# Now there should be two CDS records (we test that BIND does not
# skip it during DNSSEC maintenance).
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# No DNSSEC in raw journal.
no_dnssec_in_journal
n=$((n+1))
echo_i "remove cds record: remove ns4 CDS from provider ns3 ($n)"
ret=0
set_server "ns3" "10.53.0.3"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "cds.ns4")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDS record again.
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "remove cds record: remove ns3 CDS from provider ns4 ($n)"
ret=0
set_server "ns4" "10.53.0.4"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "cds.ns3")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDS record again.
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# No DNSSEC in raw journal.
no_dnssec_in_journal
#
# Check secondary server behaviour.
#
set_zone "model2.secondary"
set_policy "model2" "2" "3600"
set_server "ns3" "10.53.0.3"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_model2
check_keytimes
check_apex
dnssec_verify
set_server "ns4" "10.53.0.4"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_model2
check_keytimes
check_apex
dnssec_verify
#
# Update DNSKEY RRset.
#
n=$((n+1))
echo_i "add dnskey record: update zone ${ZONE} at ns5 with ZSKs from providers ns3 and ns4 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "ns3/${ZONE}.zsk")
echo update add $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
retry_quiet 10 zsks_are_published || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
n=$((n+1))
echo_i "remove dnskey record: remove ns3 and ns4 DNSKEY records from primary ns5 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "ns3/${ZONE}.zsk")
echo update del $(cat "ns4/${ZONE}.zsk")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one DNSKEY record again.
# While we did remove both DNSKEY records, the bump in the wire signer, i.e
# the secondary inline-signing zone, should add back the DNSKEY belonging to
# its own KSK when re-signing the zone.
#
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
check_keys
check_apex
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
check_keys
check_apex
dnssec_verify
no_dnssec_in_journal
#
# Update CDNSKEY RRset.
#
# Retrieve CDNSKEY records from the providers.
n=$((n+1))
echo_i "check initial CDSNKEY response for zone ${ZONE} at ns3 and ns4 ($n)"
ret=0
dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY > dig.out.ns3.secondary.cdnskey
awk '$4 == "CDNSKEY" {print}' dig.out.ns3.secondary.cdnskey > secondary.cdnskey.ns3
dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY > dig.out.ns4.secondary.cdnskey
awk '$4 == "CDNSKEY" {print}' dig.out.ns4.secondary.cdnskey > secondary.cdnskey.ns4
# Initially there should be one CDNSKEY.
set_server "ns3" "10.53.0.3"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
set_server "ns4" "10.53.0.4"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "add cdnskey record: update zone ${ZONE} at ns5 with CDNSKEY records from providers ns3 and ns4 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "secondary.cdnskey.ns3")
echo update add $(cat "secondary.cdnskey.ns4")
echo send
) | $NSUPDATE
# Now there should be two CDNSKEY records (we test that BIND does not
# skip it during DNSSEC maintenance).
#
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
n=$((n+1))
echo_i "remove cdnskey record: remove ns3 and ns4 CDNSKEY records from primary ns5 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "secondary.cdnskey.ns3")
echo update del $(cat "secondary.cdnskey.ns4")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDNSKEY record again.
# While we did remove both CDNSKEY records, the bump in the wire signer, i.e
# the secondary inline-signing zone, should add back the CDNSKEY belonging to
# its own KSK when re-signing the zone.
#
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
retry_quiet 10 records_published CDNSKEY 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
#
# Update CDS RRset.
#
# Retrieve CDS records from the other provider.
n=$((n+1))
echo_i "check initial CDS response for zone ${ZONE} at ns3 and ns4 ($n)"
ret=0
dig_with_opts ${ZONE} @10.53.0.3 CDS > dig.out.ns3.secondary.cds
awk '$4 == "CDS" {print}' dig.out.ns3.secondary.cds > secondary.cds.ns3
dig_with_opts ${ZONE} @10.53.0.4 CDS > dig.out.ns4.secondary.cds
awk '$4 == "CDS" {print}' dig.out.ns4.secondary.cds > secondary.cds.ns4
# Initially there should be one CDS.
set_server "ns3" "10.53.0.3"
retry_quiet 10 records_published CDS 1 || ret=1
set_server "ns4" "10.53.0.4"
retry_quiet 10 records_published CDS 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
n=$((n+1))
echo_i "add cds record: update zone ${ZONE} at ns5 with CDS from provider ns4 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update add $(cat "secondary.cds.ns3")
echo update add $(cat "secondary.cds.ns4")
echo send
) | $NSUPDATE
# Now there should be two CDS records (we test that BIND does not
# skip it during DNSSEC maintenance).
#
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 2 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
n=$((n+1))
echo_i "remove cds record: remove ns3 and ns4 CDS records from primary ns5 ($n)"
ret=0
set_server "ns5" "10.53.0.5"
(
echo zone "${ZONE}"
echo server "${SERVER}" "${PORT}"
echo update del $(cat "secondary.cds.ns3")
echo update del $(cat "secondary.cds.ns4")
echo send
) | $NSUPDATE
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
# Now there should be one CDS record again.
# While we did remove both CDS records, the bump in the wire signer, i.e
# the secondary inline-signing zone, should add back the CDS belonging to
# its own KSK when re-signing the zone.
#
# NS3
set_server "ns3" "10.53.0.3"
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
# NS4
set_server "ns4" "10.53.0.4"
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
retry_quiet 10 records_published CDS 1 || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status+ret))
dnssec_verify
no_dnssec_in_journal
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1

View File

@ -20,6 +20,9 @@ Security Fixes
New Features
~~~~~~~~~~~~
- Add support for multi-signer model 2 (RFC 8901) when using
``inline-signing``. :gl:`#2710`
- A new option to :any:`dnssec-policy` has been added, :any:`cdnskey`, that
allows you to enable or disable the publication of CDNSKEY records.
:gl:`#4050`

View File

@ -1835,8 +1835,8 @@ failure:
return (result);
}
static isc_result_t
make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
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;
@ -1893,7 +1893,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,
@ -1933,7 +1933,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:
@ -2045,7 +2045,7 @@ 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),
RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
cdnskeyrdata.type = dns_rdatatype_cdnskey;
@ -2127,7 +2127,7 @@ 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),
RETERR(dns_dnssec_make_dnskey(key->key, keybuf, sizeof(keybuf),
&cdnskeyrdata));
if (dns_rdataset_isassociated(cds)) {

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

@ -565,6 +565,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

@ -395,6 +395,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);
@ -2299,6 +2317,12 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw);
void
dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw);
bool
dns_zone_israw(dns_zone_t *zone);
bool
dns_zone_issecure(dns_zone_t *zone);
isc_result_t
dns_zone_keydone(dns_zone_t *zone, const char *data);
/*%<

View File

@ -2272,6 +2272,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

@ -1201,10 +1201,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).
@ -1238,10 +1235,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;
}
@ -1670,10 +1664,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

@ -5739,9 +5739,19 @@ dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
dns_kasp_t *
dns_zone_getkasp(dns_zone_t *zone) {
dns_kasp_t *kasp;
REQUIRE(DNS_ZONE_VALID(zone));
return (zone->kasp);
LOCK_ZONE(zone);
if (inline_raw(zone) && zone->secure != NULL) {
kasp = zone->secure->kasp;
} else {
kasp = zone->kasp;
}
UNLOCK_ZONE(zone);
return (kasp);
}
void
@ -6108,7 +6118,7 @@ dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
dns_dnsseckey_t *key, *key_next;
dns_dnsseckeylist_t dnskeys;
dns_name_t *origin = dns_zone_getorigin(zone);
dns_kasp_t *kasp = dns_zone_getkasp(zone);
dns_kasp_t *kasp = zone->kasp;
dns_rdataset_t keyset;
REQUIRE(DNS_ZONE_VALID(zone));
@ -6335,7 +6345,7 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdataset_t rdataset;
unsigned int i;
dns_rdata_rrsig_t rrsig;
bool kasp = (dns_zone_getkasp(zone) != NULL);
bool kasp = zone->kasp;
bool found;
int64_t timewarn = 0, timemaybe = 0;
@ -6374,9 +6384,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,
@ -6536,7 +6544,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
unsigned int i, j;
bool use_kasp = false;
if (dns_zone_getkasp(zone) != NULL) {
if (zone->kasp != NULL) {
check_ksk = false;
keyset_kskonly = true;
use_kasp = true;
@ -6693,10 +6701,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).
@ -6736,10 +6741,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;
}
@ -7095,7 +7097,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_rrsig_t rrsig;
int count = 0;
dns_kasp_t *kasp = dns_zone_getkasp(zone);
dns_kasp_t *kasp = zone->kasp;
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
@ -7122,7 +7124,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
dns_rdata_reset(&rdata);
}
if (dns_zone_getkasp(zone) != NULL) {
if (zone->kasp != NULL) {
dns_kasp_key_t *kkey;
int zsk_count = 0;
bool approved;
@ -7140,9 +7142,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
@ -7317,10 +7317,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
@ -7336,7 +7333,7 @@ sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
inception, &when))
{
/* Only applies to dnssec-policy. */
if (dns_zone_getkasp(zone) != NULL) {
if (zone->kasp != NULL) {
goto next_rdataset;
}
}
@ -7934,9 +7931,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;
}
@ -9057,7 +9052,7 @@ dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
/* Check kasp for NSEC3PARAM settings */
if (!nsec3) {
dns_kasp_t *kasp = dns_zone_getkasp(zone);
dns_kasp_t *kasp = zone->kasp;
if (kasp != NULL) {
nsec3 = dns_kasp_nsec3(kasp);
}
@ -9157,7 +9152,7 @@ zone_sign(dns_zone_t *zone) {
goto cleanup;
}
kasp = dns_zone_getkasp(zone);
kasp = zone->kasp;
sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
inception = now - 3600; /* Allow for clock skew. */
soaexpire = now + sigvalidityinterval;
@ -9194,7 +9189,7 @@ zone_sign(dns_zone_t *zone) {
signing = ISC_LIST_HEAD(zone->signing);
first = true;
if (dns_zone_getkasp(zone) != NULL) {
if (kasp != NULL) {
check_ksk = false;
keyset_kskonly = true;
use_kasp = true;
@ -15850,6 +15845,184 @@ 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 = isc_stdtime_now();
isc_mem_t *mctx;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(dns_rdatatype_iskeymaterial(rdata->type));
mctx = zone->mctx;
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,
@ -15906,14 +16079,29 @@ sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
continue;
}
/*
* Skip DNSSEC records that BIND maintains with inline-signing.
*/
if (rdata->type == dns_rdatatype_nsec ||
rdata->type == dns_rdatatype_rrsig ||
rdata->type == dns_rdatatype_nsec3 ||
rdata->type == dns_rdatatype_dnskey ||
rdata->type == dns_rdatatype_nsec3param)
{
continue;
}
/*
* Allow DNSKEY, CDNSKEY, CDS because users should be able to
* update the zone with these records from a different provider,
* but skip records that are under our control.
*/
if (dns_rdatatype_iskeymaterial(rdata->type)) {
bool inuse = false;
isc_result_t r = dns_zone_dnskey_inuse(zone, rdata,
&inuse);
if (r == ISC_R_SUCCESS && inuse) {
continue;
}
}
op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
@ -15959,9 +16147,11 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
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 ||
tuple->rdata.type == dns_rdatatype_dnskey ||
tuple->rdata.type == dns_rdatatype_nsec3 ||
tuple->rdata.type == dns_rdatatype_nsec3param)
{
@ -15969,6 +16159,23 @@ sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
dns_difftuple_free(&tuple);
continue;
}
/*
* Allow DNSKEY, CDNSKEY, CDS because users should be able to
* update the zone with these records from a different provider,
* but skip records that are under our control.
*/
if (dns_rdatatype_iskeymaterial(tuple->rdata.type)) {
bool inuse = false;
isc_result_t r = dns_zone_dnskey_inuse(
seczone, &tuple->rdata, &inuse);
if (r == ISC_R_SUCCESS && inuse) {
ISC_LIST_UNLINK(diff->tuples, tuple, link);
dns_difftuple_free(&tuple);
continue;
}
}
if (tuple->rdata.type == dns_rdatatype_soa) {
if (tuple->op == DNS_DIFFOP_DEL) {
INSIST(oldtuple == NULL);
@ -19710,7 +19917,7 @@ make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
static bool
do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
bool dspublish) {
dns_kasp_t *kasp = dns_zone_getkasp(zone);
dns_kasp_t *kasp = zone->kasp;
const char *dir = dns_zone_getkeydirectory(zone);
isc_result_t result;
uint32_t count = 0;
@ -20923,7 +21130,7 @@ zone_rekey(dns_zone_t *zone) {
timenow = isc_time_now();
now = isc_time_seconds(&timenow);
kasp = dns_zone_getkasp(zone);
kasp = zone->kasp;
dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
@ -21961,6 +22168,26 @@ dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
UNLOCK(&zone->lock);
}
bool
dns_zone_israw(dns_zone_t *zone) {
bool israw;
REQUIRE(DNS_ZONE_VALID(zone));
LOCK(&zone->lock);
israw = zone->secure != NULL;
UNLOCK(&zone->lock);
return (israw);
}
bool
dns_zone_issecure(dns_zone_t *zone) {
bool issecure;
REQUIRE(DNS_ZONE_VALID(zone));
LOCK(&zone->lock);
issecure = zone->raw != NULL;
UNLOCK(&zone->lock);
return (issecure);
}
struct keydone {
bool all;
unsigned char data[5];

View File

@ -11989,9 +11989,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

@ -2900,6 +2900,7 @@ update_action(void *arg) {
dns_ttl_t maxttl = 0;
uint32_t maxrecords;
uint64_t records;
bool is_inline, is_maintain, is_signing;
dns_diff_init(mctx, &diff);
dns_diff_init(mctx, &temp);
@ -2910,6 +2911,10 @@ update_action(void *arg) {
dns_zone_getssutable(zone, &ssutable);
options = dns_zone_getoptions(zone);
is_inline = (!dns_zone_israw(zone) && dns_zone_issecure(zone));
is_maintain = ((dns_zone_getkeyopts(zone) & DNS_ZONEKEY_MAINTAIN) != 0);
is_signing = is_inline || (!is_inline && is_maintain);
/*
* Get old and new versions now that queryacl has been checked.
*/
@ -3377,6 +3382,27 @@ update_action(void *arg) {
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,
@ -3411,7 +3437,7 @@ update_action(void *arg) {
goto failure;
}
}
if (!ISC_LIST_EMPTY(diff.tuples)) {
if (!ISC_LIST_EMPTY(diff.tuples) && is_signing) {
result = dns_zone_cdscheck(zone, db, ver);
if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) {
update_log(client, zone, LOGLEVEL_PROTOCOL,
@ -3457,11 +3483,13 @@ update_action(void *arg) {
CHECK(rollback_private(db, privatetype, ver, &diff));
if (is_signing) {
CHECK(add_signing_records(db, privatetype, ver, &diff));
}
CHECK(add_nsec3param_records(client, zone, db, ver, &diff));
if (had_dnskey && !has_dnskey) {
if (is_signing && had_dnskey && !has_dnskey) {
/*
* We are transitioning from secure to insecure.
* Cause all NSEC3 chains to be deleted. When the