Home | History | Annotate | Line # | Download | only in generic
nsec3_50.c revision 1.1.1.1
      1 /*	$NetBSD: nsec3_50.c,v 1.1.1.1 2018/08/12 12:08:17 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 
     15 /*
     16  * Copyright (C) 2004  Nominet, Ltd.
     17  *
     18  * Permission to use, copy, modify, and distribute this software for any
     19  * purpose with or without fee is hereby granted, provided that the above
     20  * copyright notice and this permission notice appear in all copies.
     21  *
     22  * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
     23  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     24  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
     25  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     26  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     27  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     28  * PERFORMANCE OF THIS SOFTWARE.
     29  */
     30 
     31 /* RFC 5155 */
     32 
     33 #ifndef RDATA_GENERIC_NSEC3_50_C
     34 #define RDATA_GENERIC_NSEC3_50_C
     35 
     36 #include <isc/iterated_hash.h>
     37 #include <isc/base32.h>
     38 
     39 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
     40 
     41 static inline isc_result_t
     42 fromtext_nsec3(ARGS_FROMTEXT) {
     43 	isc_token_t token;
     44 	unsigned int flags;
     45 	unsigned char hashalg;
     46 	isc_buffer_t b;
     47 	unsigned char buf[256];
     48 
     49 	REQUIRE(type == dns_rdatatype_nsec3);
     50 
     51 	UNUSED(type);
     52 	UNUSED(rdclass);
     53 	UNUSED(callbacks);
     54 	UNUSED(origin);
     55 	UNUSED(options);
     56 
     57 	/* Hash. */
     58 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     59 				      ISC_FALSE));
     60 	RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
     61 	RETERR(uint8_tobuffer(hashalg, target));
     62 
     63 	/* Flags. */
     64 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     65 				      ISC_FALSE));
     66 	flags = token.value.as_ulong;
     67 	if (flags > 255U)
     68 		RETTOK(ISC_R_RANGE);
     69 	RETERR(uint8_tobuffer(flags, target));
     70 
     71 	/* Iterations. */
     72 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
     73 				      ISC_FALSE));
     74 	if (token.value.as_ulong > 0xffffU)
     75 		RETTOK(ISC_R_RANGE);
     76 	RETERR(uint16_tobuffer(token.value.as_ulong, target));
     77 
     78 	/* salt */
     79 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     80 				      ISC_FALSE));
     81 	if (token.value.as_textregion.length > (255*2))
     82 		RETTOK(DNS_R_TEXTTOOLONG);
     83 	if (strcmp(DNS_AS_STR(token), "-") == 0) {
     84 		RETERR(uint8_tobuffer(0, target));
     85 	} else {
     86 		RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
     87 		RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
     88 	}
     89 
     90 	/*
     91 	 * Next hash a single base32hex word.
     92 	 */
     93 	RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
     94 				      ISC_FALSE));
     95 	isc_buffer_init(&b, buf, sizeof(buf));
     96 	RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
     97 	if (isc_buffer_usedlength(&b) > 0xffU)
     98 		RETTOK(ISC_R_RANGE);
     99 	RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
    100 	RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b)));
    101 
    102 	return (typemap_fromtext(lexer, target, ISC_TRUE));
    103 }
    104 
    105 static inline isc_result_t
    106 totext_nsec3(ARGS_TOTEXT) {
    107 	isc_region_t sr;
    108 	unsigned int i, j;
    109 	unsigned char hash;
    110 	unsigned char flags;
    111 	char buf[sizeof("TYPE65535")];
    112 	isc_uint32_t iterations;
    113 
    114 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    115 	REQUIRE(rdata->length != 0);
    116 
    117 	dns_rdata_toregion(rdata, &sr);
    118 
    119 	/* Hash */
    120 	hash = uint8_fromregion(&sr);
    121 	isc_region_consume(&sr, 1);
    122 	snprintf(buf, sizeof(buf), "%u ", hash);
    123 	RETERR(str_totext(buf, target));
    124 
    125 	/* Flags */
    126 	flags = uint8_fromregion(&sr);
    127 	isc_region_consume(&sr, 1);
    128 	snprintf(buf, sizeof(buf), "%u ", flags);
    129 	RETERR(str_totext(buf, target));
    130 
    131 	/* Iterations */
    132 	iterations = uint16_fromregion(&sr);
    133 	isc_region_consume(&sr, 2);
    134 	snprintf(buf, sizeof(buf), "%u ", iterations);
    135 	RETERR(str_totext(buf, target));
    136 
    137 	/* Salt */
    138 	j = uint8_fromregion(&sr);
    139 	isc_region_consume(&sr, 1);
    140 	INSIST(j <= sr.length);
    141 
    142 	if (j != 0) {
    143 		i = sr.length;
    144 		sr.length = j;
    145 		RETERR(isc_hex_totext(&sr, 1, "", target));
    146 		sr.length = i - j;
    147 	} else
    148 		RETERR(str_totext("-", target));
    149 
    150 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
    151 		RETERR(str_totext(" (", target));
    152 	RETERR(str_totext(tctx->linebreak, target));
    153 
    154 	/* Next hash */
    155 	j = uint8_fromregion(&sr);
    156 	isc_region_consume(&sr, 1);
    157 	INSIST(j <= sr.length);
    158 
    159 	i = sr.length;
    160 	sr.length = j;
    161 	RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
    162 	sr.length = i - j;
    163 
    164 	/*
    165 	 * Don't leave a trailing space when there's no typemap present.
    166 	 */
    167 	if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
    168 		RETERR(str_totext(" ", target));
    169 	}
    170 	RETERR(typemap_totext(&sr, tctx, target));
    171 
    172 	if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
    173 		RETERR(str_totext(" )", target));
    174 
    175 	return (ISC_R_SUCCESS);
    176 }
    177 
    178 static inline isc_result_t
    179 fromwire_nsec3(ARGS_FROMWIRE) {
    180 	isc_region_t sr, rr;
    181 	unsigned int saltlen, hashlen;
    182 
    183 	REQUIRE(type == dns_rdatatype_nsec3);
    184 
    185 	UNUSED(type);
    186 	UNUSED(rdclass);
    187 	UNUSED(options);
    188 	UNUSED(dctx);
    189 
    190 	isc_buffer_activeregion(source, &sr);
    191 	rr = sr;
    192 
    193 	/* hash(1), flags(1), iteration(2), saltlen(1) */
    194 	if (sr.length < 5U)
    195 		RETERR(DNS_R_FORMERR);
    196 	saltlen = sr.base[4];
    197 	isc_region_consume(&sr, 5);
    198 
    199 	if (sr.length < saltlen)
    200 		RETERR(DNS_R_FORMERR);
    201 	isc_region_consume(&sr, saltlen);
    202 
    203 	if (sr.length < 1U)
    204 		RETERR(DNS_R_FORMERR);
    205 	hashlen = sr.base[0];
    206 	isc_region_consume(&sr, 1);
    207 
    208 	if (sr.length < hashlen)
    209 		RETERR(DNS_R_FORMERR);
    210 	isc_region_consume(&sr, hashlen);
    211 
    212 	RETERR(typemap_test(&sr, ISC_TRUE));
    213 
    214 	RETERR(mem_tobuffer(target, rr.base, rr.length));
    215 	isc_buffer_forward(source, rr.length);
    216 	return (ISC_R_SUCCESS);
    217 }
    218 
    219 static inline isc_result_t
    220 towire_nsec3(ARGS_TOWIRE) {
    221 	isc_region_t sr;
    222 
    223 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    224 	REQUIRE(rdata->length != 0);
    225 
    226 	UNUSED(cctx);
    227 
    228 	dns_rdata_toregion(rdata, &sr);
    229 	return (mem_tobuffer(target, sr.base, sr.length));
    230 }
    231 
    232 static inline int
    233 compare_nsec3(ARGS_COMPARE) {
    234 	isc_region_t r1;
    235 	isc_region_t r2;
    236 
    237 	REQUIRE(rdata1->type == rdata2->type);
    238 	REQUIRE(rdata1->rdclass == rdata2->rdclass);
    239 	REQUIRE(rdata1->type == dns_rdatatype_nsec3);
    240 	REQUIRE(rdata1->length != 0);
    241 	REQUIRE(rdata2->length != 0);
    242 
    243 	dns_rdata_toregion(rdata1, &r1);
    244 	dns_rdata_toregion(rdata2, &r2);
    245 	return (isc_region_compare(&r1, &r2));
    246 }
    247 
    248 static inline isc_result_t
    249 fromstruct_nsec3(ARGS_FROMSTRUCT) {
    250 	dns_rdata_nsec3_t *nsec3 = source;
    251 	isc_region_t region;
    252 
    253 	REQUIRE(type == dns_rdatatype_nsec3);
    254 	REQUIRE(source != NULL);
    255 	REQUIRE(nsec3->common.rdtype == type);
    256 	REQUIRE(nsec3->common.rdclass == rdclass);
    257 	REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
    258 	REQUIRE(nsec3->hash == dns_hash_sha1);
    259 
    260 	UNUSED(type);
    261 	UNUSED(rdclass);
    262 
    263 	RETERR(uint8_tobuffer(nsec3->hash, target));
    264 	RETERR(uint8_tobuffer(nsec3->flags, target));
    265 	RETERR(uint16_tobuffer(nsec3->iterations, target));
    266 	RETERR(uint8_tobuffer(nsec3->salt_length, target));
    267 	RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
    268 	RETERR(uint8_tobuffer(nsec3->next_length, target));
    269 	RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
    270 
    271 	region.base = nsec3->typebits;
    272 	region.length = nsec3->len;
    273 	RETERR(typemap_test(&region, ISC_TRUE));
    274 	return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
    275 }
    276 
    277 static inline isc_result_t
    278 tostruct_nsec3(ARGS_TOSTRUCT) {
    279 	isc_region_t region;
    280 	dns_rdata_nsec3_t *nsec3 = target;
    281 
    282 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    283 	REQUIRE(target != NULL);
    284 	REQUIRE(rdata->length != 0);
    285 
    286 	nsec3->common.rdclass = rdata->rdclass;
    287 	nsec3->common.rdtype = rdata->type;
    288 	ISC_LINK_INIT(&nsec3->common, link);
    289 
    290 	region.base = rdata->data;
    291 	region.length = rdata->length;
    292 	nsec3->hash = uint8_consume_fromregion(&region);
    293 	nsec3->flags = uint8_consume_fromregion(&region);
    294 	nsec3->iterations = uint16_consume_fromregion(&region);
    295 
    296 	nsec3->salt_length = uint8_consume_fromregion(&region);
    297 	nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
    298 	if (nsec3->salt == NULL)
    299 		return (ISC_R_NOMEMORY);
    300 	isc_region_consume(&region, nsec3->salt_length);
    301 
    302 	nsec3->next_length = uint8_consume_fromregion(&region);
    303 	nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
    304 	if (nsec3->next == NULL)
    305 		goto cleanup;
    306 	isc_region_consume(&region, nsec3->next_length);
    307 
    308 	nsec3->len = region.length;
    309 	nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
    310 	if (nsec3->typebits == NULL)
    311 		goto cleanup;
    312 
    313 	nsec3->mctx = mctx;
    314 	return (ISC_R_SUCCESS);
    315 
    316   cleanup:
    317 	if (nsec3->next != NULL)
    318 		isc_mem_free(mctx, nsec3->next);
    319 	isc_mem_free(mctx, nsec3->salt);
    320 	return (ISC_R_NOMEMORY);
    321 }
    322 
    323 static inline void
    324 freestruct_nsec3(ARGS_FREESTRUCT) {
    325 	dns_rdata_nsec3_t *nsec3 = source;
    326 
    327 	REQUIRE(source != NULL);
    328 	REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3);
    329 
    330 	if (nsec3->mctx == NULL)
    331 		return;
    332 
    333 	if (nsec3->salt != NULL)
    334 		isc_mem_free(nsec3->mctx, nsec3->salt);
    335 	if (nsec3->next != NULL)
    336 		isc_mem_free(nsec3->mctx, nsec3->next);
    337 	if (nsec3->typebits != NULL)
    338 		isc_mem_free(nsec3->mctx, nsec3->typebits);
    339 	nsec3->mctx = NULL;
    340 }
    341 
    342 static inline isc_result_t
    343 additionaldata_nsec3(ARGS_ADDLDATA) {
    344 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    345 
    346 	UNUSED(rdata);
    347 	UNUSED(add);
    348 	UNUSED(arg);
    349 
    350 	return (ISC_R_SUCCESS);
    351 }
    352 
    353 static inline isc_result_t
    354 digest_nsec3(ARGS_DIGEST) {
    355 	isc_region_t r;
    356 
    357 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    358 
    359 	dns_rdata_toregion(rdata, &r);
    360 	return ((digest)(arg, &r));
    361 }
    362 
    363 static inline isc_boolean_t
    364 checkowner_nsec3(ARGS_CHECKOWNER) {
    365 	unsigned char owner[NSEC3_MAX_HASH_LENGTH];
    366 	isc_buffer_t buffer;
    367 	dns_label_t label;
    368 
    369 	REQUIRE(type == dns_rdatatype_nsec3);
    370 
    371 	UNUSED(type);
    372 	UNUSED(rdclass);
    373 	UNUSED(wildcard);
    374 
    375 	/*
    376 	 * First label is a base32hex string without padding.
    377 	 */
    378 	dns_name_getlabel(name, 0, &label);
    379 	isc_region_consume(&label, 1);
    380 	isc_buffer_init(&buffer, owner, sizeof(owner));
    381 	if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
    382 		return (ISC_TRUE);
    383 
    384 	return (ISC_FALSE);
    385 }
    386 
    387 static inline isc_boolean_t
    388 checknames_nsec3(ARGS_CHECKNAMES) {
    389 
    390 	REQUIRE(rdata->type == dns_rdatatype_nsec3);
    391 
    392 	UNUSED(rdata);
    393 	UNUSED(owner);
    394 	UNUSED(bad);
    395 
    396 	return (ISC_TRUE);
    397 }
    398 
    399 static inline int
    400 casecompare_nsec3(ARGS_COMPARE) {
    401 	return (compare_nsec3(rdata1, rdata2));
    402 }
    403 
    404 #endif	/* RDATA_GENERIC_NSEC3_50_C */
    405