1/* 2 * Copyright (C) 2008, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * 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. 7 * 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. 15 */ 16 17/* $Id$ */ 18 19/* 20 * Copyright (C) 2004 Nominet, Ltd. 21 * 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. 25 * 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. 33 */ 34 35/* RFC 5155 */ 36 37#ifndef RDATA_GENERIC_NSEC3_50_C 38#define RDATA_GENERIC_NSEC3_50_C 39 40#include <isc/iterated_hash.h> 41#include <isc/base32.h> 42 43#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC 44 45static inline isc_result_t 46fromtext_nsec3(ARGS_FROMTEXT) { 47 isc_token_t token; 48 unsigned char bm[8*1024]; /* 64k bits */ 49 dns_rdatatype_t covered; 50 int octet; 51 int window; 52 unsigned int flags; 53 unsigned char hashalg; 54 isc_buffer_t b; 55 56 REQUIRE(type == 50); 57 58 UNUSED(type); 59 UNUSED(rdclass); 60 UNUSED(callbacks); 61 UNUSED(origin); 62 UNUSED(options); 63 64 /* Hash. */ 65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 66 ISC_FALSE)); 67 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion)); 68 RETERR(uint8_tobuffer(hashalg, target)); 69 70 /* Flags. */ 71 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 72 ISC_FALSE)); 73 flags = token.value.as_ulong; 74 if (flags > 255U) 75 RETTOK(ISC_R_RANGE); 76 RETERR(uint8_tobuffer(flags, target)); 77 78 /* Iterations. */ 79 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 80 ISC_FALSE)); 81 if (token.value.as_ulong > 0xffffU) 82 RETTOK(ISC_R_RANGE); 83 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 84 85 /* salt */ 86 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 87 ISC_FALSE)); 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)); 92 } else { 93 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target)); 94 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target)); 95 } 96 97 /* 98 * Next hash a single base32hex word. 99 */ 100 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 101 ISC_FALSE)); 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) 105 RETTOK(ISC_R_RANGE); 106 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target)); 107 RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b))); 108 109 memset(bm, 0, sizeof(bm)); 110 do { 111 RETERR(isc_lex_getmastertoken(lexer, &token, 112 isc_tokentype_string, ISC_TRUE)); 113 if (token.type != isc_tokentype_string) 114 break; 115 RETTOK(dns_rdatatype_fromtext(&covered, 116 &token.value.as_textregion)); 117 bm[covered/8] |= (0x80>>(covered%8)); 118 } while (1); 119 isc_lex_ungettoken(lexer, &token); 120 for (window = 0; window < 256 ; window++) { 121 /* 122 * Find if we have a type in this window. 123 */ 124 for (octet = 31; octet >= 0; octet--) 125 if (bm[window * 32 + octet] != 0) 126 break; 127 if (octet < 0) 128 continue; 129 RETERR(uint8_tobuffer(window, target)); 130 RETERR(uint8_tobuffer(octet + 1, target)); 131 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1)); 132 } 133 return (ISC_R_SUCCESS); 134} 135 136static inline isc_result_t 137totext_nsec3(ARGS_TOTEXT) { 138 isc_region_t sr; 139 unsigned int i, j, k; 140 unsigned int window, len; 141 unsigned char hash; 142 unsigned char flags; 143 char buf[sizeof("65535 ")]; 144 isc_uint32_t iterations; 145 146 REQUIRE(rdata->type == 50); 147 REQUIRE(rdata->length != 0); 148 149 UNUSED(tctx); 150 151 dns_rdata_toregion(rdata, &sr); 152 153 hash = uint8_fromregion(&sr); 154 isc_region_consume(&sr, 1); 155 156 flags = uint8_fromregion(&sr); 157 isc_region_consume(&sr, 1); 158 159 iterations = uint16_fromregion(&sr); 160 isc_region_consume(&sr, 2); 161 162 sprintf(buf, "%u ", hash); 163 RETERR(str_totext(buf, target)); 164 165 sprintf(buf, "%u ", flags); 166 RETERR(str_totext(buf, target)); 167 168 sprintf(buf, "%u ", iterations); 169 RETERR(str_totext(buf, target)); 170 171 j = uint8_fromregion(&sr); 172 isc_region_consume(&sr, 1); 173 INSIST(j <= sr.length); 174 175 if (j != 0) { 176 i = sr.length; 177 sr.length = j; 178 RETERR(isc_hex_totext(&sr, 1, "", target)); 179 sr.length = i - j; 180 RETERR(str_totext(" ", target)); 181 } else 182 RETERR(str_totext("- ", target)); 183 184 j = uint8_fromregion(&sr); 185 isc_region_consume(&sr, 1); 186 INSIST(j <= sr.length); 187 188 i = sr.length; 189 sr.length = j; 190 RETERR(isc_base32hex_totext(&sr, 1, "", target)); 191 sr.length = i - j; 192 193 for (i = 0; i < sr.length; i += len) { 194 INSIST(i + 2 <= sr.length); 195 window = sr.base[i]; 196 len = sr.base[i + 1]; 197 INSIST(len > 0 && len <= 32); 198 i += 2; 199 INSIST(i + len <= sr.length); 200 for (j = 0; j < len; j++) { 201 dns_rdatatype_t t; 202 if (sr.base[i + j] == 0) 203 continue; 204 for (k = 0; k < 8; k++) { 205 if ((sr.base[i + j] & (0x80 >> k)) == 0) 206 continue; 207 t = window * 256 + j * 8 + k; 208 RETERR(str_totext(" ", target)); 209 if (dns_rdatatype_isknown(t)) { 210 RETERR(dns_rdatatype_totext(t, target)); 211 } else { 212 char buf[sizeof("TYPE65535")]; 213 sprintf(buf, "TYPE%u", t); 214 RETERR(str_totext(buf, target)); 215 } 216 } 217 } 218 } 219 return (ISC_R_SUCCESS); 220} 221 222static inline isc_result_t 223fromwire_nsec3(ARGS_FROMWIRE) { 224 isc_region_t sr, rr; 225 unsigned int window, lastwindow = 0; 226 unsigned int len; 227 unsigned int saltlen, hashlen; 228 isc_boolean_t first = ISC_TRUE; 229 unsigned int i; 230 231 REQUIRE(type == 50); 232 233 UNUSED(type); 234 UNUSED(rdclass); 235 UNUSED(options); 236 UNUSED(dctx); 237 238 isc_buffer_activeregion(source, &sr); 239 rr = sr; 240 241 /* hash(1), flags(1), iteration(2), saltlen(1) */ 242 if (sr.length < 5U) 243 RETERR(DNS_R_FORMERR); 244 saltlen = sr.base[4]; 245 isc_region_consume(&sr, 5); 246 247 if (sr.length < saltlen) 248 RETERR(DNS_R_FORMERR); 249 isc_region_consume(&sr, saltlen); 250 251 if (sr.length < 1U) 252 RETERR(DNS_R_FORMERR); 253 hashlen = sr.base[0]; 254 isc_region_consume(&sr, 1); 255 256 if (sr.length < hashlen) 257 RETERR(DNS_R_FORMERR); 258 isc_region_consume(&sr, hashlen); 259 260 for (i = 0; i < sr.length; i += len) { 261 /* 262 * Check for overflow. 263 */ 264 if (i + 2 > sr.length) 265 RETERR(DNS_R_FORMERR); 266 window = sr.base[i]; 267 len = sr.base[i + 1]; 268 i += 2; 269 /* 270 * Check that bitmap windows are in the correct order. 271 */ 272 if (!first && window <= lastwindow) 273 RETERR(DNS_R_FORMERR); 274 /* 275 * Check for legal lengths. 276 */ 277 if (len < 1 || len > 32) 278 RETERR(DNS_R_FORMERR); 279 /* 280 * Check for overflow. 281 */ 282 if (i + len > sr.length) 283 RETERR(DNS_R_FORMERR); 284 /* 285 * The last octet of the bitmap must be non zero. 286 */ 287 if (sr.base[i + len - 1] == 0) 288 RETERR(DNS_R_FORMERR); 289 lastwindow = window; 290 first = ISC_FALSE; 291 } 292 if (i != sr.length) 293 return (DNS_R_EXTRADATA); 294 RETERR(mem_tobuffer(target, rr.base, rr.length)); 295 isc_buffer_forward(source, rr.length); 296 return (ISC_R_SUCCESS); 297} 298 299static inline isc_result_t 300towire_nsec3(ARGS_TOWIRE) { 301 isc_region_t sr; 302 303 REQUIRE(rdata->type == 50); 304 REQUIRE(rdata->length != 0); 305 306 UNUSED(cctx); 307 308 dns_rdata_toregion(rdata, &sr); 309 return (mem_tobuffer(target, sr.base, sr.length)); 310} 311 312static inline int 313compare_nsec3(ARGS_COMPARE) { 314 isc_region_t r1; 315 isc_region_t r2; 316 317 REQUIRE(rdata1->type == rdata2->type); 318 REQUIRE(rdata1->rdclass == rdata2->rdclass); 319 REQUIRE(rdata1->type == 50); 320 REQUIRE(rdata1->length != 0); 321 REQUIRE(rdata2->length != 0); 322 323 dns_rdata_toregion(rdata1, &r1); 324 dns_rdata_toregion(rdata2, &r2); 325 return (isc_region_compare(&r1, &r2)); 326} 327 328static inline isc_result_t 329fromstruct_nsec3(ARGS_FROMSTRUCT) { 330 dns_rdata_nsec3_t *nsec3 = source; 331 unsigned int i, len, window, lastwindow = 0; 332 isc_boolean_t first = ISC_TRUE; 333 334 REQUIRE(type == 50); 335 REQUIRE(source != NULL); 336 REQUIRE(nsec3->common.rdtype == type); 337 REQUIRE(nsec3->common.rdclass == rdclass); 338 REQUIRE(nsec3->typebits != NULL || nsec3->len == 0); 339 REQUIRE(nsec3->hash == dns_hash_sha1); 340 341 UNUSED(type); 342 UNUSED(rdclass); 343 344 RETERR(uint8_tobuffer(nsec3->hash, target)); 345 RETERR(uint8_tobuffer(nsec3->flags, target)); 346 RETERR(uint16_tobuffer(nsec3->iterations, target)); 347 RETERR(uint8_tobuffer(nsec3->salt_length, target)); 348 RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length)); 349 RETERR(uint8_tobuffer(nsec3->next_length, target)); 350 RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length)); 351 352 /* 353 * Perform sanity check. 354 */ 355 for (i = 0; i < nsec3->len ; i += len) { 356 INSIST(i + 2 <= nsec3->len); 357 window = nsec3->typebits[i]; 358 len = nsec3->typebits[i+1]; 359 i += 2; 360 INSIST(first || window > lastwindow); 361 INSIST(len > 0 && len <= 32); 362 INSIST(i + len <= nsec3->len); 363 INSIST(nsec3->typebits[i + len - 1] != 0); 364 lastwindow = window; 365 first = ISC_FALSE; 366 } 367 return (mem_tobuffer(target, nsec3->typebits, nsec3->len)); 368} 369 370static inline isc_result_t 371tostruct_nsec3(ARGS_TOSTRUCT) { 372 isc_region_t region; 373 dns_rdata_nsec3_t *nsec3 = target; 374 375 REQUIRE(rdata->type == 50); 376 REQUIRE(target != NULL); 377 REQUIRE(rdata->length != 0); 378 379 nsec3->common.rdclass = rdata->rdclass; 380 nsec3->common.rdtype = rdata->type; 381 ISC_LINK_INIT(&nsec3->common, link); 382 383 region.base = rdata->data; 384 region.length = rdata->length; 385 nsec3->hash = uint8_consume_fromregion(®ion); 386 nsec3->flags = uint8_consume_fromregion(®ion); 387 nsec3->iterations = uint16_consume_fromregion(®ion); 388 389 nsec3->salt_length = uint8_consume_fromregion(®ion); 390 nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length); 391 if (nsec3->salt == NULL) 392 return (ISC_R_NOMEMORY); 393 isc_region_consume(®ion, nsec3->salt_length); 394 395 nsec3->next_length = uint8_consume_fromregion(®ion); 396 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length); 397 if (nsec3->next == NULL) 398 goto cleanup; 399 isc_region_consume(®ion, nsec3->next_length); 400 401 nsec3->len = region.length; 402 nsec3->typebits = mem_maybedup(mctx, region.base, region.length); 403 if (nsec3->typebits == NULL) 404 goto cleanup; 405 406 nsec3->mctx = mctx; 407 return (ISC_R_SUCCESS); 408 409 cleanup: 410 if (nsec3->next != NULL) 411 isc_mem_free(mctx, nsec3->next); 412 isc_mem_free(mctx, nsec3->salt); 413 return (ISC_R_NOMEMORY); 414} 415 416static inline void 417freestruct_nsec3(ARGS_FREESTRUCT) { 418 dns_rdata_nsec3_t *nsec3 = source; 419 420 REQUIRE(source != NULL); 421 REQUIRE(nsec3->common.rdtype == 50); 422 423 if (nsec3->mctx == NULL) 424 return; 425 426 if (nsec3->salt != NULL) 427 isc_mem_free(nsec3->mctx, nsec3->salt); 428 if (nsec3->next != NULL) 429 isc_mem_free(nsec3->mctx, nsec3->next); 430 if (nsec3->typebits != NULL) 431 isc_mem_free(nsec3->mctx, nsec3->typebits); 432 nsec3->mctx = NULL; 433} 434 435static inline isc_result_t 436additionaldata_nsec3(ARGS_ADDLDATA) { 437 REQUIRE(rdata->type == 50); 438 439 UNUSED(rdata); 440 UNUSED(add); 441 UNUSED(arg); 442 443 return (ISC_R_SUCCESS); 444} 445 446static inline isc_result_t 447digest_nsec3(ARGS_DIGEST) { 448 isc_region_t r; 449 450 REQUIRE(rdata->type == 50); 451 452 dns_rdata_toregion(rdata, &r); 453 return ((digest)(arg, &r)); 454} 455 456static inline isc_boolean_t 457checkowner_nsec3(ARGS_CHECKOWNER) { 458 459 REQUIRE(type == 50); 460 461 UNUSED(name); 462 UNUSED(type); 463 UNUSED(rdclass); 464 UNUSED(wildcard); 465 466 return (ISC_TRUE); 467} 468 469static inline isc_boolean_t 470checknames_nsec3(ARGS_CHECKNAMES) { 471 472 REQUIRE(rdata->type == 50); 473 474 UNUSED(rdata); 475 UNUSED(owner); 476 UNUSED(bad); 477 478 return (ISC_TRUE); 479} 480 481static inline int 482casecompare_nsec3(ARGS_COMPARE) { 483 return (compare_nsec3(rdata1, rdata2)); 484} 485 486#endif /* RDATA_GENERIC_NSEC3_50_C */ 487