+4127. [protocol] CDS and CDNSKEY need to be signed by the key signing
+ key as per RFC 7344, Section 4.1. [RT #37215]
+
4126. [bug] Addressed a regression introduced in change #4121.
[RT #39611]
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];
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);
"(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");
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;
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;
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;
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");
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];
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))
<year>2011</year>
<year>2012</year>
<year>2014</year>
+ <year>2015</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
<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>
</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>
<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>
(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");
}
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,
# PERFORMANCE OF THIS SOFTWARE.
rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed
-rm -f */trusted.conf */managed.conf */revoked.conf
+rm -f */example.bk
+rm -f */named.memstats
+rm -f */named.run
+rm -f */named.secroots
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 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/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/algroll.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 rndc.out.*
-rm -f delv.out*
+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 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 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 ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl
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/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 */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 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 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 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 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 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 signer/signer.out.*
rm -f signing.out*
-rm -f canonical?.*
-rm -f ns3/siginterval.conf
-rm -f ns4/named_dump.db
-rm -f ns3/badds.example.db
-rm -f delve.out*
-rm -f ns7/split-rrsig.db ns7/split-rrsig.db.unsplit
-rm -f Kexample.*
-rm -f keygen.err
-rm -f ns3/future.example.db ns3/trusted-future.key
-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 ns*/named.lock
-rm -f ns*/*.nta
-rm -f named.secroots.test*
--- /dev/null
+; 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.
--- /dev/null
+; 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.
--- /dev/null
+; 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.
--- /dev/null
+; 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.
--- /dev/null
+; 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.
--- /dev/null
+; 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.
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";
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
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.
#
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
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
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
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
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
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
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
--- /dev/null
+
+ 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.
#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 111 /*%< Number of results */
+#define DNS_R_NRESULTS 113 /*%< Number of results */
/*
* DNS wire format rcodes.
* 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);
/*%
"not dynamic", /*%< 108 DNS_R_NOTDYNAMIC */
"bad EUI", /*%< 109 DNS_R_BADEUI */
- "covered by negative trust anchor" /*%< 110 DNS_R_NTACOVERED */
+ "covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */
+ "bad CDS", /*%< 111 DNS_R_BADCSD */
+ "bad CDNSKEY" /*%< 112 DNS_R_BADCDNSKEY */
};
static const char *ids[DNS_R_NRESULTS] = {
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;
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)
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_setautomatic(dns_zone_t *zone, isc_boolean_t automatic) {
REQUIRE(DNS_ZONE_VALID(zone));