4127. [protocol] CDS and CDNSKEY need to be signed by the key signing

key as per RFC 7344, Section 4.1. [RT #37215]

(cherry picked from commit 598b502695)
This commit is contained in:
Mark Andrews 2015-05-27 15:25:45 +10:00
parent 15203066d1
commit f381cb86da
21 changed files with 717 additions and 75 deletions

View file

@ -1,3 +1,6 @@
4127. [protocol] CDS and CDNSKEY need to be signed by the key signing
key as per RFC 7344, Section 4.1. [RT #37215]
4123. [port] Added %z (size_t) format options to the portable
internal printf/sprintf implementation. [RT #39586]

View file

@ -238,7 +238,7 @@ logkey(dns_rdata_t *rdata)
static void
emit(unsigned int dtype, isc_boolean_t showall, char *lookaside,
dns_rdata_t *rdata)
isc_boolean_t cds, dns_rdata_t *rdata)
{
isc_result_t result;
unsigned char buf[DNS_DS_BUFFERSIZE];
@ -302,9 +302,12 @@ emit(unsigned int dtype, isc_boolean_t showall, char *lookaside,
isc_buffer_usedregion(&classb, &r);
printf("%.*s", (int)r.length, r.base);
if (lookaside == NULL)
printf(" DS ");
else
if (lookaside == NULL) {
if (cds)
printf(" CDS ");
else
printf(" DS ");
} else
printf(" DLV ");
isc_buffer_usedregion(&textb, &r);
@ -332,6 +335,7 @@ usage(void) {
"(SHA-1, SHA-256, GOST or SHA-384)\n");
fprintf(stderr, " -1: use SHA-1\n");
fprintf(stderr, " -2: use SHA-256\n");
fprintf(stderr, " -C: print CDS record\n");
fprintf(stderr, " -l: add lookaside zone and print DLV records\n");
fprintf(stderr, " -s: read keyset from keyset-<dnsname> file\n");
fprintf(stderr, " -c class: rdata class for DS set (default: IN)\n");
@ -352,6 +356,7 @@ main(int argc, char **argv) {
char *endp;
int ch;
unsigned int dtype = DNS_DSDIGEST_SHA1;
isc_boolean_t cds = ISC_FALSE;
isc_boolean_t both = ISC_TRUE;
isc_boolean_t usekeyset = ISC_FALSE;
isc_boolean_t showall = ISC_FALSE;
@ -374,8 +379,8 @@ main(int argc, char **argv) {
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv,
"12Aa:c:d:Ff:K:l:sT:v:hV")) != -1) {
#define OPTIONS "12Aa:Cc:d:Ff:K:l:sT:v:hV"
while ((ch = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
switch (ch) {
case '1':
dtype = DNS_DSDIGEST_SHA1;
@ -392,6 +397,12 @@ main(int argc, char **argv) {
algname = isc_commandline_argument;
both = ISC_FALSE;
break;
case 'C':
if (lookaside != NULL)
fatal("lookaside and CDS are mutually"
" exclusive");
cds = ISC_TRUE;
break;
case 'c':
classname = isc_commandline_argument;
break;
@ -408,6 +419,9 @@ main(int argc, char **argv) {
filename = isc_commandline_argument;
break;
case 'l':
if (cds)
fatal("lookaside and CDS are mutually"
" exclusive");
lookaside = isc_commandline_argument;
if (strlen(lookaside) == 0U)
fatal("lookaside must be a non-empty string");
@ -526,11 +540,11 @@ main(int argc, char **argv) {
if (both) {
emit(DNS_DSDIGEST_SHA1, showall, lookaside,
&rdata);
cds, &rdata);
emit(DNS_DSDIGEST_SHA256, showall, lookaside,
&rdata);
cds, &rdata);
} else
emit(dtype, showall, lookaside, &rdata);
emit(dtype, showall, lookaside, cds, &rdata);
}
} else {
unsigned char key_buf[DST_KEY_MAXSIZE];
@ -539,10 +553,12 @@ main(int argc, char **argv) {
DST_KEY_MAXSIZE, &rdata);
if (both) {
emit(DNS_DSDIGEST_SHA1, showall, lookaside, &rdata);
emit(DNS_DSDIGEST_SHA256, showall, lookaside, &rdata);
emit(DNS_DSDIGEST_SHA1, showall, lookaside, cds,
&rdata);
emit(DNS_DSDIGEST_SHA256, showall, lookaside, cds,
&rdata);
} else
emit(dtype, showall, lookaside, &rdata);
emit(dtype, showall, lookaside, cds, &rdata);
}
if (dns_rdataset_isassociated(&rdataset))

View file

@ -41,6 +41,7 @@
<year>2011</year>
<year>2012</year>
<year>2014</year>
<year>2015</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
@ -52,6 +53,7 @@
<arg><option>-1</option></arg>
<arg><option>-2</option></arg>
<arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
<arg><option>-C</option></arg>
<arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
<arg><option>-T <replaceable class="parameter">TTL</replaceable></option></arg>
<arg choice="req">keyfile</arg>
@ -122,6 +124,16 @@
</listitem>
</varlistentry>
<varlistentry>
<term>-C</term>
<listitem>
<para>
Generate CDS records rather than DS records. This is mutually
exclusive with generating lookaside records.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-T <replaceable class="parameter">TTL</replaceable></term>
<listitem>
@ -182,7 +194,8 @@
<option>domain</option> is appended to the name for each
record in the set.
The DNSSEC Lookaside Validation (DLV) RR is described
in RFC 4431.
in RFC 4431. This is mutually exclusive with generating
CDS records.
</para>
</listitem>
</varlistentry>

View file

@ -681,7 +681,9 @@ 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 (iszsk(key)) {
} else if (set->type == dns_rdatatype_cds ||
set->type == dns_rdatatype_cdnskey ||
iszsk(key)) {
signwithkey(name, set, key->key, ttl, add,
"signing with dnskey");
}

View file

@ -3017,6 +3017,19 @@ update_action(isc_task_t *task, isc_event_t *event) {
goto failure;
}
}
if (! ISC_LIST_EMPTY(diff.tuples)) {
result = dns_zone_cdscheck(zone, db, ver);
if (result == DNS_R_BADCDS || result == DNS_R_BADCDNSKEY) {
update_log(client, zone, LOGLEVEL_PROTOCOL,
"update rejected: bad %s RRset",
result == DNS_R_BADCDS ? "CDS" : "CDNSKEY");
result = DNS_R_REFUSED;
goto failure;
}
if (result != ISC_R_SUCCESS)
goto failure;
}
/*
* If any changes were made, increment the SOA serial number,

View file

@ -16,68 +16,81 @@
# PERFORMANCE OF THIS SOFTWARE.
rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed
rm -f */trusted.conf */managed.conf */revoked.conf
rm -f */tmp* */*.jnl */*.bk */*.jbk
rm -f ns1/root.db ns2/example.db ns3/secure.example.db
rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db
rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl
rm -f ns3/rsasha256.example.db ns3/rsasha512.example.db
rm -f ns3/split-dnssec.example.db
rm -f ns3/expiring.example.db ns3/nosign.example.db
rm -f ns2/private.secure.example.db
rm -f ns2/badparam.db ns2/badparam.db.bad
rm -f ns2/single-nsec3.db
rm -f ns2/nsec3chain-test.db
rm -f ns2/in-addr.arpa.db
rm -f */example.bk
rm -f dig.out.*
rm -f sample.out*
rm -f ns2/dlv.db
rm -f ns3/multiple.example.db ns3/nsec3-unknown.example.db ns3/nsec3.example.db
rm -f ns3/optout-unknown.example.db ns3/optout.example.db
rm -f ns3/expired.example.db ns3/update-nsec3.example.db
rm -f ns7/multiple.example.bk ns7/nsec3.example.bk ns7/optout.example.bk
rm -f */named.memstats
rm -f */named.run
rm -f ns3/nsec3.nsec3.example.db
rm -f ns3/nsec3.optout.example.db
rm -f ns3/optout.nsec3.example.db
rm -f ns3/optout.optout.example.db
rm -f ns3/secure.nsec3.example.db
rm -f ns3/secure.optout.example.db
rm -f */named.secroots
rm -f ns1/managed.key.id
rm -f signer/*.db
rm -f signer/signer.out.*
rm -f ns2/algroll.db
rm -f ns3/kskonly.example.db
rm -f ns4/named.conf ns5/named.conf
rm -f ns4/managed-keys.bind*
rm -f ns3/auto-nsec.example.db ns3/auto-nsec3.example.db
rm -f ns3/secure.below-cname.example.db
rm -f ns3/publish-inactive.example.db
rm -f signer/example.db.after signer/example.db.before
rm -f signer/example.db.changed
rm -f signer/nsec3param.out
rm -f ns3/ttlpatch.example.db ns3/ttlpatch.example.db.signed
rm -f ns3/ttlpatch.example.db.patched
rm -f ns3/split-smart.example.db
rm -f ns3/siginterval.example.db
rm -f ns3/inline.example.db.signed
rm -f ns3/lower.example.db ns3/upper.example.db ns3/upper.example.db.lower
rm -f ns6/optout-tld.db
rm -f nosign.before
rm -f signing.out*
rm -f canonical?.*
rm -f ns1/resolve.key
rm -f ns3/siginterval.conf
rm -f ns4/named_dump.db
rm -f ns7/split-rrsig.db ns7/split-rrsig.db.unsplit
rm -f */tmp* */*.jnl */*.bk */*.jbk
rm -f */trusted.conf */managed.conf */revoked.conf
rm -f Kexample.*
rm -f canonical?.*
rm -f delv.out*
rm -f delve.out*
rm -f dig.out.*
rm -f keygen.err
rm -f ns3/future.example.db ns3/trusted-future.key
rm -f named.secroots.test*
rm -f nosign.before
rm -f ns*/*.nta
rm -f ns*/named.lock
rm -f ns1/managed.key.id
rm -f ns1/resolve.key
rm -f ns1/root.db ns2/example.db ns3/secure.example.db
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/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/dlv.db
rm -f ns2/in-addr.arpa.db
rm -f ns2/nsec3chain-test.db
rm -f ns2/private.secure.example.db
rm -f ns2/single-nsec3.db
rm -f ns3/auto-nsec.example.db ns3/auto-nsec3.example.db
rm -f ns3/badds.example.db
rm -f ns3/dnskey-nsec3-unknown.example.db
rm -f ns3/dnskey-nsec3-unknown.example.db.tmp
rm -f ns3/dnskey-unknown.example.db
rm -f ns3/dnskey-unknown.example.db.tmp
rm -f named.secroots.test*
rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl
rm -f ns3/expired.example.db ns3/update-nsec3.example.db
rm -f ns3/expiring.example.db ns3/nosign.example.db
rm -f ns3/future.example.db ns3/trusted-future.key
rm -f ns3/inline.example.db.signed
rm -f ns3/kskonly.example.db
rm -f ns3/lower.example.db ns3/upper.example.db ns3/upper.example.db.lower
rm -f ns3/multiple.example.db ns3/nsec3-unknown.example.db ns3/nsec3.example.db
rm -f ns3/nsec3.nsec3.example.db
rm -f ns3/nsec3.optout.example.db
rm -f ns3/optout-unknown.example.db ns3/optout.example.db
rm -f ns3/optout.nsec3.example.db
rm -f ns3/optout.optout.example.db
rm -f ns3/publish-inactive.example.db
rm -f ns3/rsasha256.example.db ns3/rsasha512.example.db
rm -f ns3/secure.below-cname.example.db
rm -f ns3/secure.nsec3.example.db
rm -f ns3/secure.optout.example.db
rm -f ns3/siginterval.conf
rm -f ns3/siginterval.example.db
rm -f ns3/split-dnssec.example.db
rm -f ns3/split-smart.example.db
rm -f ns3/ttlpatch.example.db ns3/ttlpatch.example.db.signed
rm -f ns3/ttlpatch.example.db.patched
rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db
rm -f ns4/managed-keys.bind*
rm -f ns4/named.conf
rm -f ns4/named.conf ns5/named.conf
rm -f ns4/named_dump.db
rm -f ns6/optout-tld.db
rm -f ns7/multiple.example.bk ns7/nsec3.example.bk ns7/optout.example.bk
rm -f ns7/split-rrsig.db ns7/split-rrsig.db.unsplit
rm -f nsupdate.out*
rm -f rndc.out.*
rm -f sample.out*
rm -f signer/*.db
rm -f signer/example.db.after signer/example.db.before
rm -f signer/example.db.changed
rm -f signer/nsec3param.out
rm -f signer/signer.out.*
rm -f signing.out*

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -0,0 +1,17 @@
; Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
$TTL 3600
@ SOA ns2.example. . 1 3600 1200 86400 1200
@ NS ns2.example.

View file

@ -107,4 +107,40 @@ zone "in-addr.arpa" {
file "in-addr.arpa.db.signed";
};
zone "cds.secure" {
type master;
file "cds.secure.db.signed";
};
zone "cds-update.secure" {
type master;
file "cds-update.secure.db.signed";
allow-update { any; };
};
zone "cds-auto.secure" {
type master;
file "cds-auto.secure.db.signed";
auto-dnssec maintain;
allow-update { any; };
};
zone "cdnskey.secure" {
type master;
file "cdnskey.secure.db.signed";
};
zone "cdnskey-update.secure" {
type master;
file "cdnskey-update.secure.db.signed";
allow-update { any; };
};
zone "cdnskey-auto.secure" {
type master;
file "cdnskey-auto.secure.db.signed";
auto-dnssec maintain;
allow-update { any; };
};
include "trusted.conf";

View file

@ -193,3 +193,53 @@ key1=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone -fk $zone`
key2=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 1024 -n zone $zone`
cat $key1.key $key2.key >> $zonefile
$SIGNER -P -3 - -A -H 1 -g -r $RANDFILE -o $zone -k $key1 $zonefile $key2 > /dev/null
zone=cds.secure
infile=cds.secure.db.in
zonefile=cds.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 $zone`
$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-update.secure
infile=cds-update.secure.db.in
zonefile=cds-update.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 $zone`
cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
zone=cds-auto.secure
infile=cds-auto.secure.db.in
zonefile=cds-auto.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 $zone`
$DSFROMKEY -C $key1.key > $key1.cds
cat $infile $key1.cds > $zonefile.signed
zone=cdnskey.secure
infile=cdnskey.secure.db.in
zonefile=cdnskey.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 $zone`
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-update.secure
infile=cdnskey-update.secure.db.in
zonefile=cdnskey-update.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 $zone`
cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -r $RANDFILE -o $zone $zonefile > /dev/null
zone=cdnskey-auto.secure
infile=cdnskey-auto.secure.db.in
zonefile=cdnskey-auto.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 $zone`
sed 's/DNSKEY/CDNSKEY/' $key1.key > $key1.cds
cat $infile $key1.cds > $zonefile.signed

View file

@ -2415,6 +2415,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDS records are signed using KSK by dnssec-signzone ($n)"
ret=0
$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$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`
#
# Test for +sigchase with a null set of trusted keys.
#
@ -2450,6 +2459,57 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDS records are signed using KSK by with dnssec-auto ($n)"
ret=0
$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds-auto.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$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:check that a lone non matching CDS record is rejected ($n)"
ret=0
(
echo zone cds-update.secure
echo server 10.53.0.2 5300
echo update delete cds-update.secure CDS
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE > nsupdate.out.test$n 2>&1
grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
lines=`awk '$4 == "CDS" {print}' dig.out.test$n | wc -l`
test ${lines:-10} -eq 0 || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDS records are signed using KSK when added by nsupdate ($n)"
ret=0
(
echo zone cds-update.secure
echo server 10.53.0.2 5300
echo update delete cds-update.secure CDS
echo send
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" |
$DSFROMKEY -C -f - -T 1 cds-update.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE
$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l`
test ${lines:-0} -eq 2 || ret=1
lines=`awk '$4 == "CDS" {print}' dig.out.test$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:checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 optout-unknown.example SOA > dig.out.ns3.test$n
@ -2462,6 +2522,32 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that a non matching CDS record is accepted with a matching CDS record ($n)"
ret=0
(
echo zone cds-update.secure
echo server 10.53.0.2 5300
echo update delete cds-update.secure CDS
echo send
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" |
$DSFROMKEY -C -f - -T 1 cds-update.secure |
sed "s/^/update add /"
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cds-update.secure |
grep "DNSKEY.257" | sed 's/DNSKEY.257/DNSKEY 258/' |
$DSFROMKEY -C -A -f - -T 1 cds-update.secure |
sed "s/^/update add /"
echo send
) | $NSUPDATE
$DIG $DIGOPTS +noall +answer @10.53.0.2 cds cds-update.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDS" {print}' dig.out.test$n | wc -l`
test ${lines:-0} -eq 2 || ret=1
lines=`awk '$4 == "CDS" {print}' dig.out.test$n | wc -l`
test ${lines:-0} -eq 4 || 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 does not validate ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 nsec3-unknown.example A > dig.out.ns3.test$n
@ -2472,6 +2558,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
ret=0
$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$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: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
@ -2482,6 +2577,15 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
ret=0
$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$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:checking that unknown DNSKEY algorithm validates as insecure ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 dnskey-unknown.example A > dig.out.ns3.test$n
@ -2493,6 +2597,25 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that a lone non matching CDNSKEY record is rejected ($n)"
ret=0
(
echo zone cdnskey-update.secure
echo server 10.53.0.2 5300
echo update delete cdnskey-update.secure CDNSKEY
echo send
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
echo send
) | $NSUPDATE > nsupdate.out.test$n 2>&1
grep "update failed: REFUSED" nsupdate.out.test$n > /dev/null || ret=1
$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
lines=`awk '$4 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
test ${lines:-10} -eq 0 || ret=1
n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
ret=0
$DIG $DIGOPTS +noauth +noadd +nodnssec +adflag -p 5300 @10.53.0.3 dnskey-nsec3-unknown.example A > dig.out.ns3.test$n
@ -2504,6 +2627,25 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that CDNSKEY records are signed using KSK when added by nsupdate ($n)"
ret=0
(
echo zone cdnskey-update.secure
echo server 10.53.0.2 5300
echo update delete cdnskey-update.secure CDNSKEY
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
echo send
) | $NSUPDATE
$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
test ${lines:-0} -eq 2 || ret=1
lines=`awk '$4 == "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 initialization with a revoked managed key ($n)"
ret=0
cp ns5/named2.conf ns5/named.conf
@ -2515,5 +2657,26 @@ n=`expr $n + 1`
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:check that a non matching CDNSKEY record is accepted with a matching CDNSKEY record ($n)"
ret=0
(
echo zone cdnskey-update.secure
echo server 10.53.0.2 5300
echo update delete cdnskey-update.secure CDNSKEY
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 257/p'
$DIG $DIGOPTS +noall +answer @10.53.0.2 dnskey cdnskey-update.secure |
sed -n -e "s/^/update add /" -e 's/DNSKEY.257/CDNSKEY 258/p'
echo send
) | $NSUPDATE
$DIG $DIGOPTS +noall +answer @10.53.0.2 cdnskey cdnskey-update.secure > dig.out.test$n
lines=`awk '$4 == "RRSIG" && $5 == "CDNSKEY" {print}' dig.out.test$n | wc -l`
test ${lines:-0} -eq 2 || ret=1
lines=`awk '$4 == "CDNSKEY" {print}' dig.out.test$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:exit status: $status"
exit $status

51
doc/design/cds-child Normal file
View file

@ -0,0 +1,51 @@
CDS / CDNSKEY Child side processing.
* We need a mechanism to say that key should have a cds publish
start/end dates.
* We need a mechanism to say that key should have a cdnskey publish
start/end dates
- update dnssec-settime, dnssec-keygen, dnssec-keyfromlabel
- update K* files
* dnssec-signzone should add cds and/or cdnskey to zone apex iff the
DNSKEY is published and is signing the DNSKEY RRset. CDS and CDNSKEY
records are only removed if there is a deletion date set (implicit on
matching DNSKEY going inactive / unpublished or explict).
Non-matching CDS and CDNSKEY are removed.
* auto-dnssec maintain should cds and/or cdnskey to zone apex iff the
DNSKEY is published and is signing the DNSKEY RRset. CDS and CDNSKEY
records are only removed if there is a deletion date set (implicit on
matching DNSKEY going inactive / unpublished or explict).
* UPDATE should check that CDS and CDNSKEY match a active DNSKEY that
is signing the DNSKEY RRset and ignore otherwise. This should be
done after all the update section records have been processed.
? how will this tie in with CDS/CDNSKEY sanity checks? Only on fail?
* UPDATE should remove CDS and CDNSKEY records that match a DNSKEY
that is being removed. This should be done after all the update
section records have been processed.
? how will this tie in with CDS/CDNSKEY sanity checks? Only on fail?
* Zone loading should perform sanity checks on CDS and CDNSKEY
records against the DNSKEY records. This will flow through into
dnssec-checkzone and "dnssec-checkconf -z". ignore/warn/fail
* rndc add the ability to say generate CDS / CDNSKEY along with a key list /
all / all SEP
* rndc add the ability to say remove CDS / CDNSKEY.
* inline zones need to check CDS and CDNSKEY records in the raw zone and
filter non matching.
* CDS and CDNSKEY must be signed by a DNSKEY which matches parent DS record.
This is is different to how non DNSKEY RRsets are usually signed
RFC 7344, 4.1.

View file

@ -153,8 +153,11 @@
#define DNS_R_EXPIRED (ISC_RESULTCLASS_DNS + 107)
#define DNS_R_NOTDYNAMIC (ISC_RESULTCLASS_DNS + 108)
#define DNS_R_BADEUI (ISC_RESULTCLASS_DNS + 109)
#define DNS_R_NTACOVERED (ISC_RESULTCLASS_DNS + 110)
#define DNS_R_BADCDS (ISC_RESULTCLASS_DNS + 111)
#define DNS_R_BADCDNSKEY (ISC_RESULTCLASS_DNS + 112)
#define DNS_R_NRESULTS 110 /*%< Number of results */
#define DNS_R_NRESULTS 113 /*%< Number of results */
/*
* DNS wire format rcodes.

View file

@ -1961,6 +1961,23 @@ dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
* ISC_R_SUCCESS if there were no errors examining the zone contents.
*/
isc_result_t
dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version);
/*%
* Check if CSD, CDNSKEY and DNSKEY are consistent.
*
* Requires:
* \li 'zone' to be valid.
* \li 'db' to be valid.
* \li 'version' to be valid or NULL.
*
* Returns:
*\li #ISC_R_SUCCESS
*\li #DNS_R_BADCDS
*\li #DNS_R_BADCDNSKEY
* Others
*/
void
dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added);
/*%

View file

@ -162,7 +162,11 @@ static const char *text[DNS_R_NRESULTS] = {
"broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */
"expired", /*%< 107 DNS_R_EXPIRED */
"not dynamic", /*%< 108 DNS_R_NOTDYNAMIC */
"bad EUI" /*%< 109 DNS_R_BADEUI */
"bad EUI", /*%< 109 DNS_R_BADEUI */
"covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */
"bad CDS", /*%< 111 DNS_R_BADCSD */
"bad CDNSKEY" /*%< 112 DNS_R_BADCDNSKEY */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {

View file

@ -1139,8 +1139,15 @@ add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
if (type == dns_rdatatype_dnskey) {
if (!KSK(keys[i]) && keyset_kskonly)
continue;
} else if (KSK(keys[i]))
continue;
} else if (KSK(keys[i])) {
/*
* CDS and CDNSKEY are signed with KSK
* (RFC 7344, 4.1).
*/
if (type != dns_rdatatype_cds &&
type != dns_rdatatype_cdnskey)
continue;
}
} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
continue;

View file

@ -46,6 +46,7 @@
#include <dns/db.h>
#include <dns/dbiterator.h>
#include <dns/dnssec.h>
#include <dns/ds.h>
#include <dns/events.h>
#include <dns/journal.h>
#include <dns/keydata.h>
@ -6114,8 +6115,14 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
if (rdataset.type == dns_rdatatype_dnskey) {
if (!is_ksk && keyset_kskonly)
goto next_rdataset;
} else if (is_ksk)
goto next_rdataset;
} else if (is_ksk) {
/*
* CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
*/
if (rdataset.type != dns_rdatatype_cds &&
rdataset.type != dns_rdatatype_cdnskey)
goto next_rdataset;
}
if (*delegation &&
rdataset.type != dns_rdatatype_ds &&
rdataset.type != dns_rdatatype_nsec)
@ -16950,6 +16957,148 @@ dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
return (result);
}
isc_result_t
dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdataset_t dnskey, cds, cdnskey;
unsigned char buffer[DNS_DS_BUFFERSIZE];
unsigned char algorithms[256];
unsigned int i;
REQUIRE(DNS_ZONE_VALID(zone));
result = dns_db_getoriginnode(db, &node);
if (result != ISC_R_SUCCESS)
return (result);
dns_rdataset_init(&cds);
dns_rdataset_init(&dnskey);
dns_rdataset_init(&cdnskey);
result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
dns_rdatatype_none, 0, &cds, NULL);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
goto failure;
result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
dns_rdatatype_none, 0, &cdnskey, NULL);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
goto failure;
if (!dns_rdataset_isassociated(&cds) &&
!dns_rdataset_isassociated(&cdnskey)) {
result = ISC_R_SUCCESS;
goto failure;
}
result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
dns_rdatatype_none, 0, &dnskey, NULL);
if (result == ISC_R_NOTFOUND) {
if (dns_rdataset_isassociated(&cds))
result = DNS_R_BADCDS;
else
result = DNS_R_BADCDNSKEY;
goto failure;
}
if (result != ISC_R_SUCCESS)
goto failure;
/*
* For each DNSSEC algorithm in the CDS RRset there must be
* a matching DNSKEY record.
*/
if (dns_rdataset_isassociated(&cds)) {
memset(algorithms, 0, sizeof(algorithms));
for (result = dns_rdataset_first(&cds);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&cds)) {
dns_rdata_t crdata = DNS_RDATA_INIT;
dns_rdata_cds_t structcds;
dns_rdataset_current(&cds, &crdata);
CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
if (algorithms[structcds.algorithm] == 0)
algorithms[structcds.algorithm] = 1;
for (result = dns_rdataset_first(&dnskey);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&dnskey)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdataset_current(&dnskey, &rdata);
CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
structcds.digest_type,
buffer, &dsrdata));
if (crdata.length == dsrdata.length &&
memcmp(crdata.data, dsrdata.data,
dsrdata.length) == 0) {
algorithms[structcds.algorithm] = 2;
}
}
if (result != ISC_R_NOMORE)
goto failure;
}
for (i = 0; i < sizeof(algorithms); i++) {
if (algorithms[i] == 1) {
result = DNS_R_BADCDNSKEY;
goto failure;
}
}
}
/*
* For each DNSSEC algorithm in the CDNSKEY RRset there must be
* a matching DNSKEY record.
*/
if (dns_rdataset_isassociated(&cdnskey)) {
memset(algorithms, 0, sizeof(algorithms));
for (result = dns_rdataset_first(&cdnskey);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&cdnskey)) {
dns_rdata_t crdata = DNS_RDATA_INIT;
dns_rdata_cdnskey_t structcdnskey;
dns_rdataset_current(&cdnskey, &crdata);
CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
NULL));
if (algorithms[structcdnskey.algorithm] == 0)
algorithms[structcdnskey.algorithm] = 1;
for (result = dns_rdataset_first(&dnskey);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&dnskey)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(&dnskey, &rdata);
if (crdata.length == rdata.length &&
memcmp(crdata.data, rdata.data,
rdata.length) == 0) {
algorithms[structcdnskey.algorithm] = 2;
}
}
if (result != ISC_R_NOMORE)
goto failure;
}
for (i = 0; i < sizeof(algorithms); i++) {
if (algorithms[i] == 1) {
result = DNS_R_BADCDS;
goto failure;
}
}
}
result = ISC_R_SUCCESS;
failure:
if (dns_rdataset_isassociated(&cds))
dns_rdataset_disassociate(&cds);
if (dns_rdataset_isassociated(&dnskey))
dns_rdataset_disassociate(&dnskey);
if (dns_rdataset_isassociated(&cdnskey))
dns_rdataset_disassociate(&cdnskey);
dns_db_detachnode(db, &node);
return (result);
}
void
dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
REQUIRE(DNS_ZONE_VALID(zone));