diff --git a/CHANGES b/CHANGES index 72a416df41..833c57e38a 100644 --- 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] diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh index 1e90e0195f..67deb5f033 100644 --- a/bin/tests/system/genzone.sh +++ b/bin/tests/system/genzone.sh @@ -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. diff --git a/bin/tests/system/masterformat/ns1/example.db b/bin/tests/system/masterformat/ns1/example.db index c216706858..1d7043ec76 100644 --- a/bin/tests/system/masterformat/ns1/example.db +++ b/bin/tests/system/masterformat/ns1/example.db @@ -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 . diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh index a5cd6d450c..ee9cc1c3ba 100755 --- a/bin/tests/system/masterformat/tests.sh +++ b/bin/tests/system/masterformat/tests.sh @@ -57,7 +57,8 @@ echo "I:checking that master files in raw format loaded" ret=0 for zone in example example-explicit example-compat; do for server in 1 2; 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 diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good index b10153ea38..abf6e10649 100644 --- a/bin/tests/system/xfer/dig1.good +++ b/bin/tests/system/xfer/dig1.good @@ -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/bin/tests/system/xfer/dig2.good b/bin/tests/system/xfer/dig2.good index 8b63816968..9dd775b67a 100644 --- a/bin/tests/system/xfer/dig2.good +++ b/bin/tests/system/xfer/dig2.good @@ -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 index 0000000000..e295f485fa --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2009, 2011-2013 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. + */ + +/* $Id$ */ + +/* + * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_CDNSKEY_60_C +#define RDATA_GENERIC_CDNSKEY_60_C + +#include + +#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("64000")]; + unsigned int flags; + unsigned char algorithm; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; + + 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->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 0, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, 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) { + isc_region_t tmpr; + + 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 index 0000000000..692abb5b98 --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.h @@ -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 index 0000000000..da9a96e853 --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2009-2012 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. + */ + +/* $Id$ */ + +/* draft-ietf-dnsext-delegation-signer-05.txt */ + +#ifndef RDATA_GENERIC_CDS_59_C +#define RDATA_GENERIC_CDS_59_C + +#define RRTYPE_CDS_ATTRIBUTES \ + (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT) + +#include +#include + +#include + +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_number, + ISC_FALSE)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + c = (unsigned char) token.value.as_ulong; + + /* + * Digest. + */ + switch (c) { + case DNS_DSDIGEST_SHA1: + length = ISC_SHA1_DIGESTLENGTH; + break; + case DNS_DSDIGEST_SHA256: + length = ISC_SHA256_DIGESTLENGTH; + break; + case DNS_DSDIGEST_GOST: + length = ISC_GOST_DIGESTLENGTH; + break; + 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->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, 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) || + (sr.base[3] == DNS_DSDIGEST_GOST && + sr.length < 4 + ISC_GOST_DIGESTLENGTH) || + (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; + else if (sr.base[3] == DNS_DSDIGEST_GOST) + sr.length = 4 + ISC_GOST_DIGESTLENGTH; + 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; + case DNS_DSDIGEST_GOST: + REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH); + break; + 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, ®ion); + + ds->key_tag = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + ds->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + ds->digest_type = uint8_fromregion(®ion); + isc_region_consume(®ion, 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 index 0000000000..08d82c3cd4 --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.h @@ -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 */