]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[v9_10] CDS/CDNSKEY rrtypes
authorEvan Hunt <each@isc.org>
Thu, 19 Jun 2014 07:35:53 +0000 (00:35 -0700)
committerEvan Hunt <each@isc.org>
Thu, 19 Jun 2014 07:35:53 +0000 (00:35 -0700)
3884. [protocol] Add CDS and CDNSKEY record types. [RT #36333]

(cherry picked from commit cac2181160bdb3ccc89e3560addae5e38d4c05e3)

CHANGES
bin/tests/system/genzone.sh
bin/tests/system/masterformat/ns1/example.db
bin/tests/system/masterformat/tests.sh
bin/tests/system/rrchecker/typelist.good
bin/tests/system/xfer/dig1.good
bin/tests/system/xfer/dig2.good
lib/dns/rdata/generic/cdnskey_60.c [new file with mode: 0644]
lib/dns/rdata/generic/cdnskey_60.h [new file with mode: 0644]
lib/dns/rdata/generic/cds_59.c [new file with mode: 0644]
lib/dns/rdata/generic/cds_59.h [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 8756a229763646a99dd1c20605e7c0bff0e95bbe..3ce1495ffdab7ef01a38507213ad64c7ad60b9ed 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+3884.  [protocol]      Add CDS and CDNSKEY record types. [RT #36333]
+
 3881.  [bug]           Address memory leak with UPDATE error handling.
                        [RT #36303]
 
index 1e90e0195fc4c8db3762cd035bb1e268ef98a79b..67deb5f0331e68779e1084b5b53bf5c7c4b0a7bc 100644 (file)
@@ -238,6 +238,17 @@ dnskey01           DNSKEY  512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
                                sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
                                a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
 
+; type 59
+cds01                  CDS     30795 1 1 (
+                                       310D27F4D82C1FC2400704EA9939FE6E1CEA
+                                       A3B9 )
+
+; type 60
+cdnskey01              CDNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+                               9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+                               sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+                               a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
 ; type 249
 ; TKEY is a meta-type and should never occur in master files.
 ; The text representation is not specified in the draft.
index c21670685853cd8076445281165d505e94e7539e..1d7043ec7646d808c043bb616cd9a59aa46012f6 100644 (file)
@@ -45,6 +45,15 @@ dnskey                       300     DNSKEY  256 3 1 (
 ds                     300     DS      30795 1 1 (
                                        310D27F4D82C1FC2400704EA9939FE6E1CEA
                                        A3B9 )
+cdnskey                        300     CDNSKEY 256 3 1 (
+                                       AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+                                       +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+                                       Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+                                       b9VIE5x7KNHAYTvTO5d4S8M=
+                                       )
+cds                    300     CDS     30795 1 1 (
+                                       310D27F4D82C1FC2400704EA9939FE6E1CEA
+                                       A3B9 )
 nsec                   600     NSEC    nsecnext NS DS RRSIG NSEC
 rrsig                  300     RRSIG   SOA 1 0 300 20050714214747 (
                                        20050614214747 30795 .
index d50af8332de3105a50bb613749bc9ea75a158141..9dfdb29e0e98b09a347bfff7d536ea0b241b4bbc 100755 (executable)
@@ -82,7 +82,8 @@ ret=0
 set -- 1 2 3
 for zone in example example-explicit example-compat; do
     for server in $*; do
-       for name in ns mx a aaaa cname dname txt rrsig nsec dnskey ds; do
+       for name in ns mx a aaaa cname dname txt rrsig nsec \
+                   dnskey ds cdnskey cds; do
                $DIG $DIGOPTS $name.$zone. $name @10.53.0.$server -p 5300
                echo
        done > dig.out.$zone.$server
index 9b3b098499158cb9a4505f7b1ecbd55fb2362526..37f805ff7c5e8772e76f56179278849473c7fb13 100644 (file)
@@ -49,6 +49,8 @@ NSEC3
 NSEC3PARAM
 TLSA
 HIP
+CDS
+CDNSKEY
 SPF
 UINFO
 UID
index b10153ea3884356479574761acbcb26e671d4043..abf6e10649e671f001fccb09555b3bc07b43c13c 100644 (file)
@@ -9,6 +9,8 @@ a601.example.           3600    IN      A6      127 ::1 foo.
 a601.example.          3600    IN      A6      128  .
 afsdb01.example.       3600    IN      AFSDB   0 hostname.example.
 afsdb02.example.       3600    IN      AFSDB   65535 .
+cdnskey01.example.     3600    IN      CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example.         3600    IN      CDS     30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
 cert01.example.                3600    IN      CERT    65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
 cname01.example.       3600    IN      CNAME   cname-target.
 cname02.example.       3600    IN      CNAME   cname-target.example.
index 8b63816968df8a0db8b7c735b0ab3116333f71d7..9dd775b67a3c765ddc0d7b0ad18ce3724871934c 100644 (file)
@@ -9,6 +9,8 @@ a601.example.           3600    IN      A6      127 ::1 foo.
 a601.example.          3600    IN      A6      128  .
 afsdb01.example.       3600    IN      AFSDB   0 hostname.example.
 afsdb02.example.       3600    IN      AFSDB   65535 .
+cdnskey01.example.     3600    IN      CDNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+cds01.example.         3600    IN      CDS     30795 1 1 310D27F4D82C1FC2400704EA9939FE6E1CEAA3B9
 cert01.example.                3600    IN      CERT    65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
 cname01.example.       3600    IN      CNAME   cname-target.
 cname02.example.       3600    IN      CNAME   cname-target.example.
diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c
new file mode 100644 (file)
index 0000000..3e732d8
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * 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.
+ */
+
+/* draft-ietf-dnsop-delegation-trust-maintainance-14 */
+
+#ifndef RDATA_GENERIC_CDNSKEY_60_C
+#define RDATA_GENERIC_CDNSKEY_60_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_CDNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_cdnskey(ARGS_FROMTEXT) {
+       isc_result_t result;
+       isc_token_t token;
+       dns_secalg_t alg;
+       dns_secproto_t proto;
+       dns_keyflags_t flags;
+
+       REQUIRE(type == 60);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(origin);
+       UNUSED(options);
+       UNUSED(callbacks);
+
+       /* flags */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion));
+       RETERR(uint16_tobuffer(flags, target));
+
+       /* protocol */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &proto, 1));
+
+       /* algorithm */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &alg, 1));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       result = isc_base64_tobuffer(lexer, target, -1);
+       if (result != ISC_R_SUCCESS)
+               return (result);
+
+       /* Ensure there's at least enough data to compute a key ID for MD5 */
+       if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7)
+               return (ISC_R_UNEXPECTEDEND);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_cdnskey(ARGS_TOTEXT) {
+       isc_region_t sr;
+       char buf[sizeof("[key id = 64000]")];
+       unsigned int flags;
+       unsigned char algorithm;
+       char algbuf[DNS_NAME_FORMATSIZE];
+       const char *keyinfo;
+       isc_region_t tmpr;
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(rdata->length != 0);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* flags */
+       flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+       sprintf(buf, "%u", flags);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+       if ((flags & DNS_KEYFLAG_KSK) != 0) {
+               if (flags & DNS_KEYFLAG_REVOKE)
+                       keyinfo = "revoked KSK";
+               else
+                       keyinfo = "KSK";
+       } else
+               keyinfo = "ZSK";
+
+       /* protocol */
+       sprintf(buf, "%u", sr.base[0]);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+       RETERR(str_totext(" ", target));
+
+       /* algorithm */
+       algorithm = sr.base[0];
+       sprintf(buf, "%u", algorithm);
+       isc_region_consume(&sr, 1);
+       RETERR(str_totext(buf, target));
+
+       /* No Key? */
+       if ((flags & 0xc000) == 0xc000)
+               return (ISC_R_SUCCESS);
+
+       if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 &&
+            algorithm == DNS_KEYALG_PRIVATEDNS) {
+               dns_name_t name;
+               dns_name_init(&name, NULL);
+               dns_name_fromregion(&name, &sr);
+               dns_name_format(&name, algbuf, sizeof(algbuf));
+       } else {
+               dns_secalg_format((dns_secalg_t) algorithm, algbuf,
+                                 sizeof(algbuf));
+       }
+
+       /* key */
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" (", target));
+       RETERR(str_totext(tctx->linebreak, target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+               if (tctx->width == 0)   /* No splitting */
+                       RETERR(isc_base64_totext(&sr, 0, "", target));
+               else
+                       RETERR(isc_base64_totext(&sr, tctx->width - 2,
+                                                tctx->linebreak, target));
+       } else {
+               dns_rdata_toregion(rdata, &tmpr);
+               snprintf(buf, sizeof(buf), "[key id = %u]",
+                        dst_region_computeid(&tmpr, algorithm));
+               RETERR(str_totext(buf, target));
+       }
+
+       if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0)
+               RETERR(str_totext(tctx->linebreak, target));
+       else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" ", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(")", target));
+
+       if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) {
+
+               RETERR(str_totext(" ; ", target));
+               RETERR(str_totext(keyinfo, target));
+               RETERR(str_totext("; alg = ", target));
+               RETERR(str_totext(algbuf, target));
+               RETERR(str_totext("; key id = ", target));
+               dns_rdata_toregion(rdata, &tmpr);
+               sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+               RETERR(str_totext(buf, target));
+       }
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cdnskey(ARGS_FROMWIRE) {
+       unsigned char algorithm;
+       isc_region_t sr;
+
+       REQUIRE(type == 60);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(dctx);
+       UNUSED(options);
+
+       isc_buffer_activeregion(source, &sr);
+       if (sr.length < 4)
+               return (ISC_R_UNEXPECTEDEND);
+
+       algorithm = sr.base[3];
+       RETERR(mem_tobuffer(target, sr.base, 4));
+       isc_region_consume(&sr, 4);
+       isc_buffer_forward(source, 4);
+
+       if (algorithm == DNS_KEYALG_PRIVATEDNS) {
+               dns_name_t name;
+               dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+               dns_name_init(&name, NULL);
+               RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+       }
+
+       /*
+        * RSAMD5 computes key ID differently from other
+        * algorithms: we need to ensure there's enough data
+        * present for the computation
+        */
+       if (algorithm == DST_ALG_RSAMD5 && sr.length < 3)
+               return (ISC_R_UNEXPECTEDEND);
+
+       isc_buffer_activeregion(source, &sr);
+       isc_buffer_forward(source, sr.length);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cdnskey(ARGS_TOWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(cctx);
+
+       dns_rdata_toregion(rdata, &sr);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cdnskey(ARGS_COMPARE) {
+       isc_region_t r1;
+       isc_region_t r2;
+
+       REQUIRE(rdata1->type == rdata2->type);
+       REQUIRE(rdata1->rdclass == rdata2->rdclass);
+       REQUIRE(rdata1->type == 60);
+       REQUIRE(rdata1->length != 0);
+       REQUIRE(rdata2->length != 0);
+
+       dns_rdata_toregion(rdata1, &r1);
+       dns_rdata_toregion(rdata2, &r2);
+       return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_cdnskey(ARGS_FROMSTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = source;
+
+       REQUIRE(type == 60);
+       REQUIRE(source != NULL);
+       REQUIRE(dnskey->common.rdtype == type);
+       REQUIRE(dnskey->common.rdclass == rdclass);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+
+       /* Flags */
+       RETERR(uint16_tobuffer(dnskey->flags, target));
+
+       /* Protocol */
+       RETERR(uint8_tobuffer(dnskey->protocol, target));
+
+       /* Algorithm */
+       RETERR(uint8_tobuffer(dnskey->algorithm, target));
+
+       /* Data */
+       return (mem_tobuffer(target, dnskey->data, dnskey->datalen));
+}
+
+static inline isc_result_t
+tostruct_cdnskey(ARGS_TOSTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = target;
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 60);
+       REQUIRE(target != NULL);
+       REQUIRE(rdata->length != 0);
+
+       dnskey->common.rdclass = rdata->rdclass;
+       dnskey->common.rdtype = rdata->type;
+       ISC_LINK_INIT(&dnskey->common, link);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /* Flags */
+       if (sr.length < 2)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->flags = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+
+       /* Protocol */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->protocol = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Algorithm */
+       if (sr.length < 1)
+               return (ISC_R_UNEXPECTEDEND);
+       dnskey->algorithm = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+
+       /* Data */
+       dnskey->datalen = sr.length;
+       dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen);
+       if (dnskey->data == NULL)
+               return (ISC_R_NOMEMORY);
+
+       dnskey->mctx = mctx;
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cdnskey(ARGS_FREESTRUCT) {
+       dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source;
+
+       REQUIRE(source != NULL);
+       REQUIRE(dnskey->common.rdtype == 60);
+
+       if (dnskey->mctx == NULL)
+               return;
+
+       if (dnskey->data != NULL)
+               isc_mem_free(dnskey->mctx, dnskey->data);
+       dnskey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cdnskey(ARGS_ADDLDATA) {
+       REQUIRE(rdata->type == 60);
+
+       UNUSED(rdata);
+       UNUSED(add);
+       UNUSED(arg);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cdnskey(ARGS_DIGEST) {
+       isc_region_t r;
+
+       REQUIRE(rdata->type == 60);
+
+       dns_rdata_toregion(rdata, &r);
+
+       return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cdnskey(ARGS_CHECKOWNER) {
+
+       REQUIRE(type == 60);
+
+       UNUSED(name);
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
+
+       return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cdnskey(ARGS_CHECKNAMES) {
+
+       REQUIRE(rdata->type == 60);
+
+       UNUSED(rdata);
+       UNUSED(owner);
+       UNUSED(bad);
+
+       return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cdnskey(ARGS_COMPARE) {
+
+       /*
+        * Treat ALG 253 (private DNS) subtype name case sensistively.
+        */
+       return (compare_cdnskey(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDNSKEY_60_C */
diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h
new file mode 100644 (file)
index 0000000..692abb5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2003  Internet Software Consortium.
+ *
+ * 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.
+ */
+
+#ifndef GENERIC_CDNSKEY_60_H
+#define GENERIC_CDNSKEY_60_H 1
+
+/* CDNSKEY records have the same RDATA fields as DNSKEY records. */
+typedef struct dns_rdata_cdnskey {
+        dns_rdatacommon_t      common;
+        isc_mem_t *            mctx;
+        isc_uint16_t           flags;
+        isc_uint8_t            protocol;
+        isc_uint8_t            algorithm;
+        isc_uint16_t           datalen;
+        unsigned char *                data;
+} dns_rdata_cdnskey_t;
+
+
+#endif /* GENERIC_CDNSKEY_60_H */
diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c
new file mode 100644 (file)
index 0000000..f201003
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009-2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * 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.
+ */
+
+/* draft-ietf-dnsop-delegation-trust-maintainance-14 */
+
+#ifndef RDATA_GENERIC_CDS_59_C
+#define RDATA_GENERIC_CDS_59_C
+
+#define RRTYPE_CDS_ATTRIBUTES \
+       (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT)
+
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+
+#include <dns/ds.h>
+
+#include "dst_gost.h"
+
+static inline isc_result_t
+fromtext_cds(ARGS_FROMTEXT) {
+       isc_token_t token;
+       unsigned char c;
+       int length;
+
+       REQUIRE(type == 59);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(origin);
+       UNUSED(options);
+       UNUSED(callbacks);
+
+       /*
+        * Key tag.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+                                     ISC_FALSE));
+       if (token.value.as_ulong > 0xffffU)
+               RETTOK(ISC_R_RANGE);
+       RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+       /*
+        * Algorithm.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &c, 1));
+
+       /*
+        * Digest type.
+        */
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+                                     ISC_FALSE));
+       RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &c, 1));
+
+       /*
+        * Digest.
+        */
+       switch (c) {
+       case DNS_DSDIGEST_SHA1:
+               length = ISC_SHA1_DIGESTLENGTH;
+               break;
+       case DNS_DSDIGEST_SHA256:
+               length = ISC_SHA256_DIGESTLENGTH;
+               break;
+#ifdef ISC_GOST_DIGESTLENGTH
+       case DNS_DSDIGEST_GOST:
+               length = ISC_GOST_DIGESTLENGTH;
+               break;
+#endif
+       case DNS_DSDIGEST_SHA384:
+               length = ISC_SHA384_DIGESTLENGTH;
+               break;
+       default:
+               length = -1;
+               break;
+       }
+       return (isc_hex_tobuffer(lexer, target, length));
+}
+
+static inline isc_result_t
+totext_cds(ARGS_TOTEXT) {
+       isc_region_t sr;
+       char buf[sizeof("64000 ")];
+       unsigned int n;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(tctx);
+
+       dns_rdata_toregion(rdata, &sr);
+
+       /*
+        * Key tag.
+        */
+       n = uint16_fromregion(&sr);
+       isc_region_consume(&sr, 2);
+       sprintf(buf, "%u ", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Algorithm.
+        */
+       n = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+       sprintf(buf, "%u ", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Digest type.
+        */
+       n = uint8_fromregion(&sr);
+       isc_region_consume(&sr, 1);
+       sprintf(buf, "%u", n);
+       RETERR(str_totext(buf, target));
+
+       /*
+        * Digest.
+        */
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" (", target));
+       RETERR(str_totext(tctx->linebreak, target));
+       if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) {
+               if (tctx->width == 0) /* No splitting */
+                       RETERR(isc_hex_totext(&sr, 0, "", target));
+               else
+                       RETERR(isc_hex_totext(&sr, tctx->width - 2,
+                                             tctx->linebreak, target));
+       } else
+               RETERR(str_totext("[omitted]", target));
+       if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+               RETERR(str_totext(" )", target));
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cds(ARGS_FROMWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(type == 59);
+
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(dctx);
+       UNUSED(options);
+
+       isc_buffer_activeregion(source, &sr);
+
+       /*
+        * Check digest lengths if we know them.
+        */
+       if (sr.length < 4 ||
+           (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+            sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+           (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+            sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
+#ifdef ISC_GOST_DIGESTLENGTH
+           (sr.base[3] == DNS_DSDIGEST_GOST &&
+            sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
+#endif
+           (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+            sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+               return (ISC_R_UNEXPECTEDEND);
+
+       /*
+        * Only copy digest lengths if we know them.
+        * If there is extra data dns_rdata_fromwire() will
+        * detect that.
+        */
+       if (sr.base[3] == DNS_DSDIGEST_SHA1)
+               sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+       else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+               sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+#ifdef ISC_GOST_DIGESTLENGTH
+       else if (sr.base[3] == DNS_DSDIGEST_GOST)
+               sr.length = 4 + ISC_GOST_DIGESTLENGTH;
+#endif
+       else if (sr.base[3] == DNS_DSDIGEST_SHA384)
+               sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+
+       isc_buffer_forward(source, sr.length);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cds(ARGS_TOWIRE) {
+       isc_region_t sr;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(rdata->length != 0);
+
+       UNUSED(cctx);
+
+       dns_rdata_toregion(rdata, &sr);
+       return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cds(ARGS_COMPARE) {
+       isc_region_t r1;
+       isc_region_t r2;
+
+       REQUIRE(rdata1->type == rdata2->type);
+       REQUIRE(rdata1->rdclass == rdata2->rdclass);
+       REQUIRE(rdata1->type == 59);
+       REQUIRE(rdata1->length != 0);
+       REQUIRE(rdata2->length != 0);
+
+       dns_rdata_toregion(rdata1, &r1);
+       dns_rdata_toregion(rdata2, &r2);
+       return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_cds(ARGS_FROMSTRUCT) {
+       dns_rdata_cds_t *ds = source;
+
+       REQUIRE(type == 59);
+       REQUIRE(source != NULL);
+       REQUIRE(ds->common.rdtype == type);
+       REQUIRE(ds->common.rdclass == rdclass);
+       switch (ds->digest_type) {
+       case DNS_DSDIGEST_SHA1:
+               REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
+               break;
+       case DNS_DSDIGEST_SHA256:
+               REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+               break;
+#ifdef ISC_GOST_DIGESTLENGTH
+       case DNS_DSDIGEST_GOST:
+               REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
+               break;
+#endif
+       case DNS_DSDIGEST_SHA384:
+               REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
+               break;
+       }
+
+       UNUSED(type);
+       UNUSED(rdclass);
+
+       RETERR(uint16_tobuffer(ds->key_tag, target));
+       RETERR(uint8_tobuffer(ds->algorithm, target));
+       RETERR(uint8_tobuffer(ds->digest_type, target));
+
+       return (mem_tobuffer(target, ds->digest, ds->length));
+}
+
+static inline isc_result_t
+tostruct_cds(ARGS_TOSTRUCT) {
+       dns_rdata_cds_t *ds = target;
+       isc_region_t region;
+
+       REQUIRE(rdata->type == 59);
+       REQUIRE(target != NULL);
+       REQUIRE(rdata->length != 0);
+
+       ds->common.rdclass = rdata->rdclass;
+       ds->common.rdtype = rdata->type;
+       ISC_LINK_INIT(&ds->common, link);
+
+       dns_rdata_toregion(rdata, &region);
+
+       ds->key_tag = uint16_fromregion(&region);
+       isc_region_consume(&region, 2);
+       ds->algorithm = uint8_fromregion(&region);
+       isc_region_consume(&region, 1);
+       ds->digest_type = uint8_fromregion(&region);
+       isc_region_consume(&region, 1);
+       ds->length = region.length;
+
+       ds->digest = mem_maybedup(mctx, region.base, region.length);
+       if (ds->digest == NULL)
+               return (ISC_R_NOMEMORY);
+
+       ds->mctx = mctx;
+       return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cds(ARGS_FREESTRUCT) {
+       dns_rdata_cds_t *ds = source;
+
+       REQUIRE(ds != NULL);
+       REQUIRE(ds->common.rdtype == 59);
+
+       if (ds->mctx == NULL)
+               return;
+
+       if (ds->digest != NULL)
+               isc_mem_free(ds->mctx, ds->digest);
+       ds->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cds(ARGS_ADDLDATA) {
+       REQUIRE(rdata->type == 59);
+
+       UNUSED(rdata);
+       UNUSED(add);
+       UNUSED(arg);
+
+       return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cds(ARGS_DIGEST) {
+       isc_region_t r;
+
+       REQUIRE(rdata->type == 59);
+
+       dns_rdata_toregion(rdata, &r);
+
+       return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cds(ARGS_CHECKOWNER) {
+
+       REQUIRE(type == 59);
+
+       UNUSED(name);
+       UNUSED(type);
+       UNUSED(rdclass);
+       UNUSED(wildcard);
+
+       return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cds(ARGS_CHECKNAMES) {
+
+       REQUIRE(rdata->type == 59);
+
+       UNUSED(rdata);
+       UNUSED(owner);
+       UNUSED(bad);
+
+       return (ISC_TRUE);
+}
+
+static inline int
+casecompare_cds(ARGS_COMPARE) {
+       return (compare_cds(rdata1, rdata2));
+}
+
+#endif /* RDATA_GENERIC_CDS_59_C */
diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h
new file mode 100644 (file)
index 0000000..08d82c3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002  Internet Software Consortium.
+ *
+ * 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.
+ */
+
+#ifndef GENERIC_CDS_59_H
+#define GENERIC_CDS_59_H 1
+
+/* CDS records have the same RDATA fields as DS records. */
+typedef struct dns_rdata_cds {
+       dns_rdatacommon_t       common;
+       isc_mem_t               *mctx;
+       isc_uint16_t            key_tag;
+       isc_uint8_t             algorithm;
+       isc_uint8_t             digest_type;
+       isc_uint16_t            length;
+       unsigned char           *digest;
+} dns_rdata_cds_t;
+
+#endif /* GENERIC_CDS_59_H */