1 /* $NetBSD: rrsig_46.c,v 1.7 2015/07/08 17:28:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007, 2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id */ 21 22 /* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */ 23 24 /* RFC2535 */ 25 26 #ifndef RDATA_GENERIC_RRSIG_46_C 27 #define RDATA_GENERIC_RRSIG_46_C 28 29 #define RRTYPE_RRSIG_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) 30 31 static inline isc_result_t 32 fromtext_rrsig(ARGS_FROMTEXT) { 33 isc_token_t token; 34 unsigned char c; 35 long i; 36 dns_rdatatype_t covered; 37 char *e; 38 isc_result_t result; 39 dns_name_t name; 40 isc_buffer_t buffer; 41 isc_uint32_t time_signed, time_expire; 42 43 REQUIRE(type == 46); 44 45 UNUSED(type); 46 UNUSED(rdclass); 47 UNUSED(callbacks); 48 49 /* 50 * Type covered. 51 */ 52 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 53 ISC_FALSE)); 54 result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion); 55 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { 56 i = strtol(DNS_AS_STR(token), &e, 10); 57 if (i < 0 || i > 65535) 58 RETTOK(ISC_R_RANGE); 59 if (*e != 0) 60 RETTOK(result); 61 covered = (dns_rdatatype_t)i; 62 } 63 RETERR(uint16_tobuffer(covered, target)); 64 65 /* 66 * Algorithm. 67 */ 68 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 69 ISC_FALSE)); 70 RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); 71 RETERR(mem_tobuffer(target, &c, 1)); 72 73 /* 74 * Labels. 75 */ 76 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 77 ISC_FALSE)); 78 if (token.value.as_ulong > 0xffU) 79 RETTOK(ISC_R_RANGE); 80 c = (unsigned char)token.value.as_ulong; 81 RETERR(mem_tobuffer(target, &c, 1)); 82 83 /* 84 * Original ttl. 85 */ 86 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 87 ISC_FALSE)); 88 RETERR(uint32_tobuffer(token.value.as_ulong, target)); 89 90 /* 91 * Signature expiration. 92 */ 93 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 94 ISC_FALSE)); 95 if (strlen(DNS_AS_STR(token)) <= 10U && 96 *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') { 97 char *end; 98 unsigned long u; 99 isc_uint64_t u64; 100 101 u64 = u = strtoul(DNS_AS_STR(token), &end, 10); 102 if (u == ULONG_MAX || *end != 0) 103 RETTOK(DNS_R_SYNTAX); 104 if (u64 > 0xffffffffUL) 105 RETTOK(ISC_R_RANGE); 106 time_expire = u; 107 } else 108 RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire)); 109 RETERR(uint32_tobuffer(time_expire, target)); 110 111 /* 112 * Time signed. 113 */ 114 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 115 ISC_FALSE)); 116 if (strlen(DNS_AS_STR(token)) <= 10U && 117 *DNS_AS_STR(token) != '-' && *DNS_AS_STR(token) != '+') { 118 char *end; 119 unsigned long u; 120 isc_uint64_t u64; 121 122 u64 = u = strtoul(DNS_AS_STR(token), &end, 10); 123 if (u == ULONG_MAX || *end != 0) 124 RETTOK(DNS_R_SYNTAX); 125 if (u64 > 0xffffffffUL) 126 RETTOK(ISC_R_RANGE); 127 time_signed = u; 128 } else 129 RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed)); 130 RETERR(uint32_tobuffer(time_signed, target)); 131 132 /* 133 * Key footprint. 134 */ 135 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 136 ISC_FALSE)); 137 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 138 139 /* 140 * Signer. 141 */ 142 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 143 ISC_FALSE)); 144 dns_name_init(&name, NULL); 145 buffer_fromregion(&buffer, &token.value.as_region); 146 origin = (origin != NULL) ? origin : dns_rootname; 147 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 148 149 /* 150 * Sig. 151 */ 152 return (isc_base64_tobuffer(lexer, target, -1)); 153 } 154 155 static inline isc_result_t 156 totext_rrsig(ARGS_TOTEXT) { 157 isc_region_t sr; 158 char buf[sizeof("4294967295")]; 159 dns_rdatatype_t covered; 160 unsigned long ttl; 161 unsigned long when; 162 unsigned long exp; 163 unsigned long foot; 164 dns_name_t name; 165 166 REQUIRE(rdata->type == 46); 167 REQUIRE(rdata->length != 0); 168 169 dns_rdata_toregion(rdata, &sr); 170 171 /* 172 * Type covered. 173 */ 174 covered = uint16_fromregion(&sr); 175 isc_region_consume(&sr, 2); 176 /* 177 * XXXAG We should have something like dns_rdatatype_isknown() 178 * that does the right thing with type 0. 179 */ 180 if (dns_rdatatype_isknown(covered) && covered != 0) { 181 RETERR(dns_rdatatype_totext(covered, target)); 182 } else { 183 sprintf(buf, "TYPE%u", covered); 184 RETERR(str_totext(buf, target)); 185 } 186 RETERR(str_totext(" ", target)); 187 188 /* 189 * Algorithm. 190 */ 191 sprintf(buf, "%u", sr.base[0]); 192 isc_region_consume(&sr, 1); 193 RETERR(str_totext(buf, target)); 194 RETERR(str_totext(" ", target)); 195 196 /* 197 * Labels. 198 */ 199 sprintf(buf, "%u", sr.base[0]); 200 isc_region_consume(&sr, 1); 201 RETERR(str_totext(buf, target)); 202 RETERR(str_totext(" ", target)); 203 204 /* 205 * Ttl. 206 */ 207 ttl = uint32_fromregion(&sr); 208 isc_region_consume(&sr, 4); 209 sprintf(buf, "%lu", ttl); 210 RETERR(str_totext(buf, target)); 211 212 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 213 RETERR(str_totext(" (", target)); 214 RETERR(str_totext(tctx->linebreak, target)); 215 216 /* 217 * Sig exp. 218 */ 219 exp = uint32_fromregion(&sr); 220 isc_region_consume(&sr, 4); 221 RETERR(dns_time32_totext(exp, target)); 222 RETERR(str_totext(" ", target)); 223 224 /* 225 * Time signed. 226 */ 227 when = uint32_fromregion(&sr); 228 isc_region_consume(&sr, 4); 229 RETERR(dns_time32_totext(when, target)); 230 RETERR(str_totext(" ", target)); 231 232 /* 233 * Footprint. 234 */ 235 foot = uint16_fromregion(&sr); 236 isc_region_consume(&sr, 2); 237 sprintf(buf, "%lu", foot); 238 RETERR(str_totext(buf, target)); 239 RETERR(str_totext(" ", target)); 240 241 /* 242 * Signer. 243 */ 244 dns_name_init(&name, NULL); 245 dns_name_fromregion(&name, &sr); 246 isc_region_consume(&sr, name_length(&name)); 247 RETERR(dns_name_totext(&name, ISC_FALSE, target)); 248 249 /* 250 * Sig. 251 */ 252 RETERR(str_totext(tctx->linebreak, target)); 253 if ((tctx->flags & DNS_STYLEFLAG_NOCRYPTO) == 0) { 254 if (tctx->width == 0) /* No splitting */ 255 RETERR(isc_base64_totext(&sr, 60, "", target)); 256 else 257 RETERR(isc_base64_totext(&sr, tctx->width - 2, 258 tctx->linebreak, target)); 259 } else 260 RETERR(str_totext("[omitted]", target)); 261 262 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) 263 RETERR(str_totext(" )", target)); 264 265 return (ISC_R_SUCCESS); 266 } 267 268 static inline isc_result_t 269 fromwire_rrsig(ARGS_FROMWIRE) { 270 isc_region_t sr; 271 dns_name_t name; 272 273 REQUIRE(type == 46); 274 275 UNUSED(type); 276 UNUSED(rdclass); 277 278 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 279 280 isc_buffer_activeregion(source, &sr); 281 /* 282 * type covered: 2 283 * algorithm: 1 284 * labels: 1 285 * original ttl: 4 286 * signature expiration: 4 287 * time signed: 4 288 * key footprint: 2 289 */ 290 if (sr.length < 18) 291 return (ISC_R_UNEXPECTEDEND); 292 293 isc_buffer_forward(source, 18); 294 RETERR(mem_tobuffer(target, sr.base, 18)); 295 296 /* 297 * Signer. 298 */ 299 dns_name_init(&name, NULL); 300 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 301 302 /* 303 * Sig. 304 */ 305 isc_buffer_activeregion(source, &sr); 306 isc_buffer_forward(source, sr.length); 307 return (mem_tobuffer(target, sr.base, sr.length)); 308 } 309 310 static inline isc_result_t 311 towire_rrsig(ARGS_TOWIRE) { 312 isc_region_t sr; 313 dns_name_t name; 314 dns_offsets_t offsets; 315 316 REQUIRE(rdata->type == 46); 317 REQUIRE(rdata->length != 0); 318 319 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 320 dns_rdata_toregion(rdata, &sr); 321 /* 322 * type covered: 2 323 * algorithm: 1 324 * labels: 1 325 * original ttl: 4 326 * signature expiration: 4 327 * time signed: 4 328 * key footprint: 2 329 */ 330 RETERR(mem_tobuffer(target, sr.base, 18)); 331 isc_region_consume(&sr, 18); 332 333 /* 334 * Signer. 335 */ 336 dns_name_init(&name, offsets); 337 dns_name_fromregion(&name, &sr); 338 isc_region_consume(&sr, name_length(&name)); 339 RETERR(dns_name_towire(&name, cctx, target)); 340 341 /* 342 * Signature. 343 */ 344 return (mem_tobuffer(target, sr.base, sr.length)); 345 } 346 347 static inline int 348 compare_rrsig(ARGS_COMPARE) { 349 isc_region_t r1; 350 isc_region_t r2; 351 352 REQUIRE(rdata1->type == rdata2->type); 353 REQUIRE(rdata1->rdclass == rdata2->rdclass); 354 REQUIRE(rdata1->type == 46); 355 REQUIRE(rdata1->length != 0); 356 REQUIRE(rdata2->length != 0); 357 358 dns_rdata_toregion(rdata1, &r1); 359 dns_rdata_toregion(rdata2, &r2); 360 return (isc_region_compare(&r1, &r2)); 361 } 362 363 static inline isc_result_t 364 fromstruct_rrsig(ARGS_FROMSTRUCT) { 365 dns_rdata_rrsig_t *sig = source; 366 367 REQUIRE(type == 46); 368 REQUIRE(source != NULL); 369 REQUIRE(sig->common.rdtype == type); 370 REQUIRE(sig->common.rdclass == rdclass); 371 REQUIRE(sig->signature != NULL || sig->siglen == 0); 372 373 UNUSED(type); 374 UNUSED(rdclass); 375 376 /* 377 * Type covered. 378 */ 379 RETERR(uint16_tobuffer(sig->covered, target)); 380 381 /* 382 * Algorithm. 383 */ 384 RETERR(uint8_tobuffer(sig->algorithm, target)); 385 386 /* 387 * Labels. 388 */ 389 RETERR(uint8_tobuffer(sig->labels, target)); 390 391 /* 392 * Original TTL. 393 */ 394 RETERR(uint32_tobuffer(sig->originalttl, target)); 395 396 /* 397 * Expire time. 398 */ 399 RETERR(uint32_tobuffer(sig->timeexpire, target)); 400 401 /* 402 * Time signed. 403 */ 404 RETERR(uint32_tobuffer(sig->timesigned, target)); 405 406 /* 407 * Key ID. 408 */ 409 RETERR(uint16_tobuffer(sig->keyid, target)); 410 411 /* 412 * Signer name. 413 */ 414 RETERR(name_tobuffer(&sig->signer, target)); 415 416 /* 417 * Signature. 418 */ 419 return (mem_tobuffer(target, sig->signature, sig->siglen)); 420 } 421 422 static inline isc_result_t 423 tostruct_rrsig(ARGS_TOSTRUCT) { 424 isc_region_t sr; 425 dns_rdata_rrsig_t *sig = target; 426 dns_name_t signer; 427 428 REQUIRE(rdata->type == 46); 429 REQUIRE(target != NULL); 430 REQUIRE(rdata->length != 0); 431 432 sig->common.rdclass = rdata->rdclass; 433 sig->common.rdtype = rdata->type; 434 ISC_LINK_INIT(&sig->common, link); 435 436 dns_rdata_toregion(rdata, &sr); 437 438 /* 439 * Type covered. 440 */ 441 sig->covered = uint16_fromregion(&sr); 442 isc_region_consume(&sr, 2); 443 444 /* 445 * Algorithm. 446 */ 447 sig->algorithm = uint8_fromregion(&sr); 448 isc_region_consume(&sr, 1); 449 450 /* 451 * Labels. 452 */ 453 sig->labels = uint8_fromregion(&sr); 454 isc_region_consume(&sr, 1); 455 456 /* 457 * Original TTL. 458 */ 459 sig->originalttl = uint32_fromregion(&sr); 460 isc_region_consume(&sr, 4); 461 462 /* 463 * Expire time. 464 */ 465 sig->timeexpire = uint32_fromregion(&sr); 466 isc_region_consume(&sr, 4); 467 468 /* 469 * Time signed. 470 */ 471 sig->timesigned = uint32_fromregion(&sr); 472 isc_region_consume(&sr, 4); 473 474 /* 475 * Key ID. 476 */ 477 sig->keyid = uint16_fromregion(&sr); 478 isc_region_consume(&sr, 2); 479 480 dns_name_init(&signer, NULL); 481 dns_name_fromregion(&signer, &sr); 482 dns_name_init(&sig->signer, NULL); 483 RETERR(name_duporclone(&signer, mctx, &sig->signer)); 484 isc_region_consume(&sr, name_length(&sig->signer)); 485 486 /* 487 * Signature. 488 */ 489 sig->siglen = sr.length; 490 sig->signature = mem_maybedup(mctx, sr.base, sig->siglen); 491 if (sig->signature == NULL) 492 goto cleanup; 493 494 495 sig->mctx = mctx; 496 return (ISC_R_SUCCESS); 497 498 cleanup: 499 if (mctx != NULL) 500 dns_name_free(&sig->signer, mctx); 501 return (ISC_R_NOMEMORY); 502 } 503 504 static inline void 505 freestruct_rrsig(ARGS_FREESTRUCT) { 506 dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *) source; 507 508 REQUIRE(source != NULL); 509 REQUIRE(sig->common.rdtype == 46); 510 511 if (sig->mctx == NULL) 512 return; 513 514 dns_name_free(&sig->signer, sig->mctx); 515 if (sig->signature != NULL) 516 isc_mem_free(sig->mctx, sig->signature); 517 sig->mctx = NULL; 518 } 519 520 static inline isc_result_t 521 additionaldata_rrsig(ARGS_ADDLDATA) { 522 REQUIRE(rdata->type == 46); 523 524 UNUSED(rdata); 525 UNUSED(add); 526 UNUSED(arg); 527 528 return (ISC_R_SUCCESS); 529 } 530 531 static inline isc_result_t 532 digest_rrsig(ARGS_DIGEST) { 533 534 REQUIRE(rdata->type == 46); 535 536 UNUSED(rdata); 537 UNUSED(digest); 538 UNUSED(arg); 539 540 return (ISC_R_NOTIMPLEMENTED); 541 } 542 543 static inline dns_rdatatype_t 544 covers_rrsig(dns_rdata_t *rdata) { 545 dns_rdatatype_t type; 546 isc_region_t r; 547 548 REQUIRE(rdata->type == 46); 549 550 dns_rdata_toregion(rdata, &r); 551 type = uint16_fromregion(&r); 552 553 return (type); 554 } 555 556 static inline isc_boolean_t 557 checkowner_rrsig(ARGS_CHECKOWNER) { 558 559 REQUIRE(type == 46); 560 561 UNUSED(name); 562 UNUSED(type); 563 UNUSED(rdclass); 564 UNUSED(wildcard); 565 566 return (ISC_TRUE); 567 } 568 569 static inline isc_boolean_t 570 checknames_rrsig(ARGS_CHECKNAMES) { 571 572 REQUIRE(rdata->type == 46); 573 574 UNUSED(rdata); 575 UNUSED(owner); 576 UNUSED(bad); 577 578 return (ISC_TRUE); 579 } 580 581 static inline int 582 casecompare_rrsig(ARGS_COMPARE) { 583 isc_region_t r1; 584 isc_region_t r2; 585 dns_name_t name1; 586 dns_name_t name2; 587 int order; 588 589 REQUIRE(rdata1->type == rdata2->type); 590 REQUIRE(rdata1->rdclass == rdata2->rdclass); 591 REQUIRE(rdata1->type == 46); 592 REQUIRE(rdata1->length != 0); 593 REQUIRE(rdata2->length != 0); 594 595 dns_rdata_toregion(rdata1, &r1); 596 dns_rdata_toregion(rdata2, &r2); 597 598 INSIST(r1.length > 18); 599 INSIST(r2.length > 18); 600 r1.length = 18; 601 r2.length = 18; 602 order = isc_region_compare(&r1, &r2); 603 if (order != 0) 604 return (order); 605 606 dns_name_init(&name1, NULL); 607 dns_name_init(&name2, NULL); 608 dns_rdata_toregion(rdata1, &r1); 609 dns_rdata_toregion(rdata2, &r2); 610 isc_region_consume(&r1, 18); 611 isc_region_consume(&r2, 18); 612 dns_name_fromregion(&name1, &r1); 613 dns_name_fromregion(&name2, &r2); 614 order = dns_name_rdatacompare(&name1, &name2); 615 if (order != 0) 616 return (order); 617 618 isc_region_consume(&r1, name_length(&name1)); 619 isc_region_consume(&r2, name_length(&name2)); 620 621 return (isc_region_compare(&r1, &r2)); 622 } 623 624 #endif /* RDATA_GENERIC_RRSIG_46_C */ 625