2 * Copyright (C) 2008, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
20 * Copyright (C) 2004 Nominet, Ltd.
22 * Permission to use, copy, modify, and distribute this software for any
23 * purpose with or without fee is hereby granted, provided that the above
24 * copyright notice and this permission notice appear in all copies.
26 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
27 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
28 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
29 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
30 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
31 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
32 * PERFORMANCE OF THIS SOFTWARE.
37 #ifndef RDATA_GENERIC_NSEC3_50_C
38 #define RDATA_GENERIC_NSEC3_50_C
40 #include <isc/iterated_hash.h>
41 #include <isc/base32.h>
43 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
45 static inline isc_result_t
46 fromtext_nsec3(ARGS_FROMTEXT) {
48 unsigned char bm[8*1024]; /* 64k bits */
49 dns_rdatatype_t covered;
53 unsigned char hashalg;
65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
67 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
68 RETERR(uint8_tobuffer(hashalg, target));
71 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
73 flags = token.value.as_ulong;
76 RETERR(uint8_tobuffer(flags, target));
79 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
81 if (token.value.as_ulong > 0xffffU)
83 RETERR(uint16_tobuffer(token.value.as_ulong, target));
86 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
88 if (token.value.as_textregion.length > (255*2))
89 RETTOK(DNS_R_TEXTTOOLONG);
90 if (strcmp(DNS_AS_STR(token), "-") == 0) {
91 RETERR(uint8_tobuffer(0, target));
93 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
94 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
98 * Next hash a single base32hex word.
100 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
102 isc_buffer_init(&b, bm, sizeof(bm));
103 RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
104 if (isc_buffer_usedlength(&b) > 0xffU)
106 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
107 RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
109 memset(bm, 0, sizeof(bm));
111 RETERR(isc_lex_getmastertoken(lexer, &token,
112 isc_tokentype_string, ISC_TRUE));
113 if (token.type != isc_tokentype_string)
115 RETTOK(dns_rdatatype_fromtext(&covered,
116 &token.value.as_textregion));
117 bm[covered/8] |= (0x80>>(covered%8));
119 isc_lex_ungettoken(lexer, &token);
120 for (window = 0; window < 256 ; window++) {
122 * Find if we have a type in this window.
124 for (octet = 31; octet >= 0; octet--)
125 if (bm[window * 32 + octet] != 0)
129 RETERR(uint8_tobuffer(window, target));
130 RETERR(uint8_tobuffer(octet + 1, target));
131 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
133 return (ISC_R_SUCCESS);
136 static inline isc_result_t
137 totext_nsec3(ARGS_TOTEXT) {
139 unsigned int i, j, k;
140 unsigned int window, len;
143 char buf[sizeof("65535 ")];
144 isc_uint32_t iterations;
147 REQUIRE(rdata->type == 50);
148 REQUIRE(rdata->length != 0);
150 dns_rdata_toregion(rdata, &sr);
153 hash = uint8_fromregion(&sr);
154 isc_region_consume(&sr, 1);
155 sprintf(buf, "%u ", hash);
156 RETERR(str_totext(buf, target));
159 flags = uint8_fromregion(&sr);
160 isc_region_consume(&sr, 1);
161 sprintf(buf, "%u ", flags);
162 RETERR(str_totext(buf, target));
165 iterations = uint16_fromregion(&sr);
166 isc_region_consume(&sr, 2);
167 sprintf(buf, "%u ", iterations);
168 RETERR(str_totext(buf, target));
171 j = uint8_fromregion(&sr);
172 isc_region_consume(&sr, 1);
173 INSIST(j <= sr.length);
178 RETERR(isc_hex_totext(&sr, 1, "", target));
181 RETERR(str_totext("-", target));
183 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
184 RETERR(str_totext(" (", target));
185 RETERR(str_totext(tctx->linebreak, target));
188 j = uint8_fromregion(&sr);
189 isc_region_consume(&sr, 1);
190 INSIST(j <= sr.length);
194 RETERR(isc_base32hex_totext(&sr, 1, "", target));
197 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0)
198 RETERR(str_totext(" ", target));
202 for (i = 0; i < sr.length; i += len) {
203 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
204 RETERR(str_totext(tctx->linebreak, target));
207 INSIST(i + 2 <= sr.length);
209 len = sr.base[i + 1];
210 INSIST(len > 0 && len <= 32);
212 INSIST(i + len <= sr.length);
213 for (j = 0; j < len; j++) {
215 if (sr.base[i + j] == 0)
217 for (k = 0; k < 8; k++) {
218 if ((sr.base[i + j] & (0x80 >> k)) == 0)
220 t = window * 256 + j * 8 + k;
222 RETERR(str_totext(" ", target));
224 if (dns_rdatatype_isknown(t)) {
225 RETERR(dns_rdatatype_totext(t, target));
227 char buf[sizeof("TYPE65535")];
228 sprintf(buf, "TYPE%u", t);
229 RETERR(str_totext(buf, target));
235 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
236 RETERR(str_totext(" )", target));
238 return (ISC_R_SUCCESS);
241 static inline isc_result_t
242 fromwire_nsec3(ARGS_FROMWIRE) {
244 unsigned int window, lastwindow = 0;
246 unsigned int saltlen, hashlen;
247 isc_boolean_t first = ISC_TRUE;
257 isc_buffer_activeregion(source, &sr);
260 /* hash(1), flags(1), iteration(2), saltlen(1) */
262 RETERR(DNS_R_FORMERR);
263 saltlen = sr.base[4];
264 isc_region_consume(&sr, 5);
266 if (sr.length < saltlen)
267 RETERR(DNS_R_FORMERR);
268 isc_region_consume(&sr, saltlen);
271 RETERR(DNS_R_FORMERR);
272 hashlen = sr.base[0];
273 isc_region_consume(&sr, 1);
275 if (sr.length < hashlen)
276 RETERR(DNS_R_FORMERR);
277 isc_region_consume(&sr, hashlen);
279 for (i = 0; i < sr.length; i += len) {
281 * Check for overflow.
283 if (i + 2 > sr.length)
284 RETERR(DNS_R_FORMERR);
286 len = sr.base[i + 1];
289 * Check that bitmap windows are in the correct order.
291 if (!first && window <= lastwindow)
292 RETERR(DNS_R_FORMERR);
294 * Check for legal lengths.
296 if (len < 1 || len > 32)
297 RETERR(DNS_R_FORMERR);
299 * Check for overflow.
301 if (i + len > sr.length)
302 RETERR(DNS_R_FORMERR);
304 * The last octet of the bitmap must be non zero.
306 if (sr.base[i + len - 1] == 0)
307 RETERR(DNS_R_FORMERR);
312 return (DNS_R_EXTRADATA);
313 RETERR(mem_tobuffer(target, rr.base, rr.length));
314 isc_buffer_forward(source, rr.length);
315 return (ISC_R_SUCCESS);
318 static inline isc_result_t
319 towire_nsec3(ARGS_TOWIRE) {
322 REQUIRE(rdata->type == 50);
323 REQUIRE(rdata->length != 0);
327 dns_rdata_toregion(rdata, &sr);
328 return (mem_tobuffer(target, sr.base, sr.length));
332 compare_nsec3(ARGS_COMPARE) {
336 REQUIRE(rdata1->type == rdata2->type);
337 REQUIRE(rdata1->rdclass == rdata2->rdclass);
338 REQUIRE(rdata1->type == 50);
339 REQUIRE(rdata1->length != 0);
340 REQUIRE(rdata2->length != 0);
342 dns_rdata_toregion(rdata1, &r1);
343 dns_rdata_toregion(rdata2, &r2);
344 return (isc_region_compare(&r1, &r2));
347 static inline isc_result_t
348 fromstruct_nsec3(ARGS_FROMSTRUCT) {
349 dns_rdata_nsec3_t *nsec3 = source;
350 unsigned int i, len, window, lastwindow = 0;
351 isc_boolean_t first = ISC_TRUE;
354 REQUIRE(source != NULL);
355 REQUIRE(nsec3->common.rdtype == type);
356 REQUIRE(nsec3->common.rdclass == rdclass);
357 REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
358 REQUIRE(nsec3->hash == dns_hash_sha1);
363 RETERR(uint8_tobuffer(nsec3->hash, target));
364 RETERR(uint8_tobuffer(nsec3->flags, target));
365 RETERR(uint16_tobuffer(nsec3->iterations, target));
366 RETERR(uint8_tobuffer(nsec3->salt_length, target));
367 RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
368 RETERR(uint8_tobuffer(nsec3->next_length, target));
369 RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
372 * Perform sanity check.
374 for (i = 0; i < nsec3->len ; i += len) {
375 INSIST(i + 2 <= nsec3->len);
376 window = nsec3->typebits[i];
377 len = nsec3->typebits[i+1];
379 INSIST(first || window > lastwindow);
380 INSIST(len > 0 && len <= 32);
381 INSIST(i + len <= nsec3->len);
382 INSIST(nsec3->typebits[i + len - 1] != 0);
386 return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
389 static inline isc_result_t
390 tostruct_nsec3(ARGS_TOSTRUCT) {
392 dns_rdata_nsec3_t *nsec3 = target;
394 REQUIRE(rdata->type == 50);
395 REQUIRE(target != NULL);
396 REQUIRE(rdata->length != 0);
398 nsec3->common.rdclass = rdata->rdclass;
399 nsec3->common.rdtype = rdata->type;
400 ISC_LINK_INIT(&nsec3->common, link);
402 region.base = rdata->data;
403 region.length = rdata->length;
404 nsec3->hash = uint8_consume_fromregion(®ion);
405 nsec3->flags = uint8_consume_fromregion(®ion);
406 nsec3->iterations = uint16_consume_fromregion(®ion);
408 nsec3->salt_length = uint8_consume_fromregion(®ion);
409 nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
410 if (nsec3->salt == NULL)
411 return (ISC_R_NOMEMORY);
412 isc_region_consume(®ion, nsec3->salt_length);
414 nsec3->next_length = uint8_consume_fromregion(®ion);
415 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
416 if (nsec3->next == NULL)
418 isc_region_consume(®ion, nsec3->next_length);
420 nsec3->len = region.length;
421 nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
422 if (nsec3->typebits == NULL)
426 return (ISC_R_SUCCESS);
429 if (nsec3->next != NULL)
430 isc_mem_free(mctx, nsec3->next);
431 isc_mem_free(mctx, nsec3->salt);
432 return (ISC_R_NOMEMORY);
436 freestruct_nsec3(ARGS_FREESTRUCT) {
437 dns_rdata_nsec3_t *nsec3 = source;
439 REQUIRE(source != NULL);
440 REQUIRE(nsec3->common.rdtype == 50);
442 if (nsec3->mctx == NULL)
445 if (nsec3->salt != NULL)
446 isc_mem_free(nsec3->mctx, nsec3->salt);
447 if (nsec3->next != NULL)
448 isc_mem_free(nsec3->mctx, nsec3->next);
449 if (nsec3->typebits != NULL)
450 isc_mem_free(nsec3->mctx, nsec3->typebits);
454 static inline isc_result_t
455 additionaldata_nsec3(ARGS_ADDLDATA) {
456 REQUIRE(rdata->type == 50);
462 return (ISC_R_SUCCESS);
465 static inline isc_result_t
466 digest_nsec3(ARGS_DIGEST) {
469 REQUIRE(rdata->type == 50);
471 dns_rdata_toregion(rdata, &r);
472 return ((digest)(arg, &r));
475 static inline isc_boolean_t
476 checkowner_nsec3(ARGS_CHECKOWNER) {
488 static inline isc_boolean_t
489 checknames_nsec3(ARGS_CHECKNAMES) {
491 REQUIRE(rdata->type == 50);
501 casecompare_nsec3(ARGS_COMPARE) {
502 return (compare_nsec3(rdata1, rdata2));
505 #endif /* RDATA_GENERIC_NSEC3_50_C */