diff --git a/CHANGES b/CHANGES
index a27f2fab3a..b00baff4d9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4721. [func] 'dnssec-signzone -x' and 'dnssec-dnskey-kskonly'
+ options now apply to CDNSKEY and DS records as well
+ as DNSKEY. Thanks to Tony Finch. [RT #45689]
+
4720. [func] Added a statistics counter to track prefetch
queries. [RT #45847]
diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
index 47759558e5..5d278a18a8 100644
--- a/bin/dnssec/dnssec-signzone.c
+++ b/bin/dnssec/dnssec-signzone.c
@@ -659,7 +659,9 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
if (!issigningkey(key))
continue;
- if (set->type == dns_rdatatype_dnskey &&
+ if ((set->type == dns_rdatatype_cds ||
+ set->type == dns_rdatatype_cdnskey ||
+ set->type == dns_rdatatype_dnskey) &&
dns_name_equal(name, gorigin)) {
isc_boolean_t have_ksk;
dns_dnsseckey_t *tmpkey;
@@ -680,9 +682,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
(iszsk(key) && !keyset_kskonly))
signwithkey(name, set, key->key, ttl, add,
"signing with dnskey");
- } else if (set->type == dns_rdatatype_cds ||
- set->type == dns_rdatatype_cdnskey ||
- iszsk(key)) {
+ } else if (iszsk(key)) {
signwithkey(name, set, key->key, ttl, add,
"signing with dnskey");
}
diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook
index 82089a9613..79e5d25fab 100644
--- a/bin/dnssec/dnssec-signzone.docbook
+++ b/bin/dnssec/dnssec-signzone.docbook
@@ -705,8 +705,9 @@
-x
- Only sign the DNSKEY RRset with key-signing keys, and omit
- signatures from zone-signing keys. (This is similar to the
+ Only sign the DNSKEY, CDNSKEY, and CDS RRsets with
+ key-signing keys, and omit signatures from zone-signing
+ keys. (This is similar to the
dnssec-dnskey-kskonly yes; zone option in
named.)
diff --git a/bin/tests/system/autosign/clean.sh b/bin/tests/system/autosign/clean.sh
index 1033cbdbc2..ac393db64d 100644
--- a/bin/tests/system/autosign/clean.sh
+++ b/bin/tests/system/autosign/clean.sh
@@ -7,27 +7,29 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
rm -f */K* */dsset-* */*.signed */tmp* */*.jnl */*.bk
-rm -f */trusted.conf */private.conf
rm -f */core
rm -f */example.bk
rm -f */named.memstats
rm -f */named.run
+rm -f */trusted.conf */private.conf
rm -f activate-now-publish-1day.key
rm -f active.key inact.key del.key unpub.key standby.key rev.key
-rm -f sync.key
rm -f delayksk.key delayzsk.key autoksk.key autozsk.key
rm -f dig.out.*
rm -f digcomp.out.test*
+rm -f digcomp.out.test*
rm -f missingzsk.key inactivezsk.key
rm -f nopriv.key vanishing.key del1.key del2.key
rm -f ns*/named.lock
+rm -f ns*/named.lock
rm -f ns1/root.db
rm -f ns2/example.db
rm -f ns2/private.secure.example.db ns2/bar.db
+rm -f ns3/*.nzd ns3/*.nzd-lock ns3/*.nzf
rm -f ns3/*.nzf
rm -f ns3/autonsec3.example.db
-rm -f ns3/sync.example.db
rm -f ns3/kg.out ns3/s.out ns3/st.out
+rm -f ns3/kskonly.example.db
rm -f ns3/nozsk.example.db ns3/inaczsk.example.db
rm -f ns3/nsec.example.db
rm -f ns3/nsec3-to-nsec.example.db
@@ -47,10 +49,9 @@ rm -f ns3/secure-to-insecure2.example.db
rm -f ns3/secure.example.db
rm -f ns3/secure.nsec3.example.db
rm -f ns3/secure.optout.example.db
+rm -f ns3/sync.example.db
rm -f ns3/ttl*.db
rm -f nsupdate.out
-rm -f signing.out.*
rm -f settime.out.*
-rm -f ns3/*.nzd ns3/*.nzd-lock ns3/*.nzf
-rm -f digcomp.out.test*
-rm -f ns*/named.lock
+rm -f signing.out.*
+rm -f sync.key
diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh
index 769171e645..b3ded65eb6 100644
--- a/bin/tests/system/autosign/ns3/keygen.sh
+++ b/bin/tests/system/autosign/ns3/keygen.sh
@@ -248,7 +248,7 @@ echo $zsk > ../inactivezsk.key
$SETTIME -I now $zsk > st.out 2>&1 || dumpit st.out
#
-# A zone that is set to 'auto-dnssec maintain' during a recofnig
+# A zone that is set to 'auto-dnssec maintain' during a reconfig
#
setup reconf.example
cp secure.example.db.in $zonefile
@@ -256,7 +256,7 @@ $KEYGEN -q -a RSASHA1 -3 -r $RANDFILE -fk $zone > kg.out 2>&1 || dumpit kg.out
$KEYGEN -q -a RSASHA1 -3 -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
#
-# A zone which generates a CDS and CDNSEY RRsets automatically
+# A zone which generates CDS and CDNSEY RRsets automatically
#
setup sync.example
cp $infile $zonefile
@@ -264,3 +264,12 @@ ksk=`$KEYGEN -a RSASHA1 -3 -q -r $RANDFILE -fk -P sync now $zone 2> kg.out` || d
$KEYGEN -a RSASHA1 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
$DSFROMKEY $ksk.key > dsset-${zone}$TP
echo ns3/$ksk > ../sync.key
+
+#
+# A zone that generates CDS and CDNSKEY and uses dnssec-dnskey-kskonly
+#
+setup kskonly.example
+cp $infile $zonefile
+ksk=`$KEYGEN -a RSASHA1 -3 -q -r $RANDFILE -fk -P sync now $zone 2> kg.out` || dumpit kg.out
+$KEYGEN -a RSASHA1 -3 -q -r $RANDFILE $zone > kg.out 2>&1 || dumpit kg.out
+$DSFROMKEY $ksk.key > dsset-${zone}$TP
diff --git a/bin/tests/system/autosign/ns3/kskonly.example.db.in b/bin/tests/system/autosign/ns3/kskonly.example.db.in
new file mode 100644
index 0000000000..b8e46a6599
--- /dev/null
+++ b/bin/tests/system/autosign/ns3/kskonly.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) 2015, 2016 Internet Systems Consortium, Inc. ("ISC")
+;
+; 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 http://mozilla.org/MPL/2.0/.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
diff --git a/bin/tests/system/autosign/ns3/named.conf b/bin/tests/system/autosign/ns3/named.conf
index b45de3d7f6..add46e5d06 100644
--- a/bin/tests/system/autosign/ns3/named.conf
+++ b/bin/tests/system/autosign/ns3/named.conf
@@ -6,8 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-/* $Id: named.conf,v 1.15 2012/02/06 23:46:47 tbox Exp $ */
-
// NS3
controls { /* empty */ };
@@ -243,4 +241,12 @@ zone "sync.example" {
auto-dnssec maintain;
};
+zone "kskonly.example" {
+ type master;
+ file "kskonly.example.db";
+ allow-update { any; };
+ dnssec-dnskey-kskonly yes;
+ auto-dnssec maintain;
+};
+
include "trusted.conf";
diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh
index 7cd19084e6..e30d06306b 100644
--- a/bin/tests/system/autosign/tests.sh
+++ b/bin/tests/system/autosign/tests.sh
@@ -1166,8 +1166,38 @@ if [ "$lret" != 0 ]; then ret=$lret; fi
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:test 'dnssec-dnskey-kskonly no' affects DNSKEY/CDS/CDNSKEY ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 sync.example dnskey > dig.out.ns3.dnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 sync.example cdnskey > dig.out.ns3.cdnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 sync.example cds > dig.out.ns3.cdstest$n
+lines=`awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l`
+test ${lines:-0} -eq 2 || ret=1
+lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l`
+test ${lines:-0} -eq 2 || ret=1
+lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l`
+test ${lines:-0} -eq 2 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:test 'dnssec-dnskey-kskonly yes' affects DNSKEY/CDS/CDNSKEY ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.3 kskonly.example dnskey > dig.out.ns3.dnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 kskonly.example cdnskey > dig.out.ns3.cdnskeytest$n
+$DIG $DIGOPTS @10.53.0.3 kskonly.example cds > dig.out.ns3.cdstest$n
+lines=`awk '$4 == "RRSIG" && $5 == "DNSKEY" {print}' dig.out.ns3.dnskeytest$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.ns3.cdnskeytest$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.ns3.cdstest$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:setting CDS and CDNSKEY deletion times and calling 'rndc loadkeys'"
-$SETTIME -D sync now+2 `cat sync.key`
+$SETTIME -D sync now+2 `cat sync.key` > /dev/null
$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys sync.example
echo "I:waiting for deletion to occur"
sleep 3
diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh
index acb139904f..d4549dc266 100644
--- a/bin/tests/system/dnssec/clean.sh
+++ b/bin/tests/system/dnssec/clean.sh
@@ -30,9 +30,10 @@ rm -f ns2/algroll.db
rm -f ns2/badparam.db ns2/badparam.db.bad
rm -f ns2/cdnskey-update.secure.db
rm -f ns2/cdnskey.secure.db
+rm -f ns2/cdnskey-x.secure.db
rm -f ns2/cds-auto.secure.db ns2/cds-auto.secure.db.jnl
rm -f ns2/cds-update.secure.db ns2/cds-update.secure.db.jnl
-rm -f ns2/cds.secure.db
+rm -f ns2/cds.secure.db ns2/cds-x.secure.db
rm -f ns2/dlv.db
rm -f ns2/in-addr.arpa.db
rm -f ns2/nsec3chain-test.db
diff --git a/bin/tests/system/dnssec/ns2/named.conf b/bin/tests/system/dnssec/ns2/named.conf
index 5233f1ec69..b76f7f3777 100644
--- a/bin/tests/system/dnssec/ns2/named.conf
+++ b/bin/tests/system/dnssec/ns2/named.conf
@@ -102,6 +102,11 @@ zone "cds.secure" {
file "cds.secure.db.signed";
};
+zone "cds-x.secure" {
+ type master;
+ file "cds-x.secure.db.signed";
+};
+
zone "cds-update.secure" {
type master;
file "cds-update.secure.db.signed";
@@ -120,6 +125,11 @@ zone "cdnskey.secure" {
file "cdnskey.secure.db.signed";
};
+zone "cdnskey-x.secure" {
+ type master;
+ file "cdnskey-x.secure.db.signed";
+};
+
zone "cdnskey-update.secure" {
type master;
file "cdnskey-update.secure.db.signed";
diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh
index b7264f6d8c..fb4744d3e4 100644
--- a/bin/tests/system/dnssec/ns2/sign.sh
+++ b/bin/tests/system/dnssec/ns2/sign.sh
@@ -194,6 +194,16 @@ $DSFROMKEY -C $key1.key > $key1.cds
cat $infile $key1.key $key2.key $key1.cds >$zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+zone=cds-x.secure
+infile=cds.secure.db.in
+zonefile=cds-x.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key3=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+$DSFROMKEY -C $key2.key > $key2.cds
+cat $infile $key1.key $key3.key $key2.cds >$zonefile
+$SIGNER -P -g -x -r $RANDFILE -o $zone $zonefile > /dev/null
+
zone=cds-update.secure
infile=cds-update.secure.db.in
zonefile=cds-update.secure.db
@@ -219,6 +229,16 @@ sed 's/DNSKEY/CDNSKEY/' $key1.key > $key1.cds
cat $infile $key1.key $key2.key $key1.cds >$zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
+zone=cdnskey-x.secure
+infile=cdnskey.secure.db.in
+zonefile=cdnskey-x.secure.db
+key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key2=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone -fk $zone`
+key3=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone`
+sed 's/DNSKEY/CDNSKEY/' $key1.key > $key1.cds
+cat $infile $key2.key $key3.key $key1.cds >$zonefile
+$SIGNER -P -g -x -r $RANDFILE -o $zone $zonefile > /dev/null
+
zone=cdnskey-update.secure
infile=cdnskey-update.secure.db.in
zonefile=cdnskey-update.secure.db
diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh
index 3a1cd1027e..e02b44cf45 100644
--- a/bin/tests/system/dnssec/tests.sh
+++ b/bin/tests/system/dnssec/tests.sh
@@ -3002,6 +3002,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:check that CDS records are not signed using ZSK by dnssec-signzone -x ($n)"
+ret=0
+$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds-x.secure > dig.out.test$n
+lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:checking that positive unknown NSEC3 hash algorithm does validate ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 nsec3-unknown.example SOA > dig.out.ns3.test$n
@@ -3122,6 +3131,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:check that CDNSKEY records are not signed using ZSK by dnssec-signzone -x ($n)"
+ret=0
+$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey-x.secure > dig.out.test$n
+lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
+test ${lines:-0} -eq 1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 optout-unknown.example A > dig.out.ns3.test$n
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index d0afb11fda..2058484908 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -7139,9 +7139,9 @@ options {
When this option and update-check-ksk
are both set to yes, only key-signing
keys (that is, keys with the KSK bit set) will be used
- to sign the DNSKEY RRset at the zone apex. Zone-signing
- keys (keys without the KSK bit set) will be used to sign
- the remainder of the zone, but not the DNSKEY RRset.
+ to sign the DNSKEY, CDNSKEY, and CDS RRsets at the zone apex.
+ Zone-signing keys (keys without the KSK bit set) will be used
+ to sign the remainder of the zone, but not the DNSKEY RRset.
This is similar to the
dnssec-signzone -x command line option.
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 22be2e53b2..645ac46cff 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -482,6 +482,16 @@
queries. [RT #45847]
+
+
+ The dnssec-signzone -x flag and the
+ dnssec-dnskey-kskonly option in
+ named.conf, which suppress the use of
+ the ZSK when signing DNSKEY records, now also apply to
+ CDNSKEY and CDS records. Thanks to Tony Finch for the
+ contribution. [RT #45689]
+
+
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 85a171f40a..c15d31540d 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -6234,7 +6234,10 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
}
}
if (both) {
- if (type == dns_rdatatype_dnskey) {
+ if (type == dns_rdatatype_dnskey ||
+ type == dns_rdatatype_cdnskey ||
+ type == dns_rdatatype_cds)
+ {
if (!KSK(keys[i]) && keyset_kskonly)
continue;
} else if (KSK(keys[i]))
@@ -6652,24 +6655,34 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
dns_rdatasetiter_current(iterator, &rdataset);
if (rdataset.type == dns_rdatatype_soa ||
rdataset.type == dns_rdatatype_rrsig)
+ {
goto next_rdataset;
- if (rdataset.type == dns_rdatatype_dnskey) {
- if (!is_ksk && keyset_kskonly)
- goto next_rdataset;
- } else if (is_ksk) {
+ }
+ if (rdataset.type == dns_rdatatype_dnskey ||
+ rdataset.type == dns_rdatatype_cdnskey ||
+ rdataset.type == dns_rdatatype_cds)
+ {
/*
- * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
+ * CDS and CDNSKEY are signed with KSK like DNSKEY.
+ * (RFC 7344, section 4.1 specifies that they must
+ * be signed with a key in the current DS RRset,
+ * which would only include KSK's.)
*/
- if (rdataset.type != dns_rdatatype_cds &&
- rdataset.type != dns_rdatatype_cdnskey)
+ if (!is_ksk && keyset_kskonly) {
goto next_rdataset;
+ }
+ } else if (is_ksk) {
+ goto next_rdataset;
}
if (*delegation &&
rdataset.type != dns_rdatatype_ds &&
rdataset.type != dns_rdatatype_nsec)
+ {
goto next_rdataset;
- if (signed_with_key(db, node, version, rdataset.type, key))
+ }
+ if (signed_with_key(db, node, version, rdataset.type, key)) {
goto next_rdataset;
+ }
/* Calculate the signature, creating a RRSIG RDATA. */
isc_buffer_clear(&buffer);
CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,