1 /* $NetBSD: caa_257.c,v 1.8 2023/01/25 21:43:30 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef GENERIC_CAA_257_C 17 #define GENERIC_CAA_257_C 1 18 19 #define RRTYPE_CAA_ATTRIBUTES (0) 20 21 static unsigned char const alphanumeric[256] = { 22 /* 0x00-0x0f */ 0, 23 0, 24 0, 25 0, 26 0, 27 0, 28 0, 29 0, 30 0, 31 0, 32 0, 33 0, 34 0, 35 0, 36 0, 37 0, 38 /* 0x10-0x1f */ 0, 39 0, 40 0, 41 0, 42 0, 43 0, 44 0, 45 0, 46 0, 47 0, 48 0, 49 0, 50 0, 51 0, 52 0, 53 0, 54 /* 0x20-0x2f */ 0, 55 0, 56 0, 57 0, 58 0, 59 0, 60 0, 61 0, 62 0, 63 0, 64 0, 65 0, 66 0, 67 0, 68 0, 69 0, 70 /* 0x30-0x3f */ 1, 71 1, 72 1, 73 1, 74 1, 75 1, 76 1, 77 1, 78 1, 79 1, 80 0, 81 0, 82 0, 83 0, 84 0, 85 0, 86 /* 0x40-0x4f */ 0, 87 1, 88 1, 89 1, 90 1, 91 1, 92 1, 93 1, 94 1, 95 1, 96 1, 97 1, 98 1, 99 1, 100 1, 101 1, 102 /* 0x50-0x5f */ 1, 103 1, 104 1, 105 1, 106 1, 107 1, 108 1, 109 1, 110 1, 111 1, 112 1, 113 0, 114 0, 115 0, 116 0, 117 0, 118 /* 0x60-0x6f */ 0, 119 1, 120 1, 121 1, 122 1, 123 1, 124 1, 125 1, 126 1, 127 1, 128 1, 129 1, 130 1, 131 1, 132 1, 133 1, 134 /* 0x70-0x7f */ 1, 135 1, 136 1, 137 1, 138 1, 139 1, 140 1, 141 1, 142 1, 143 1, 144 1, 145 0, 146 0, 147 0, 148 0, 149 0, 150 /* 0x80-0x8f */ 0, 151 0, 152 0, 153 0, 154 0, 155 0, 156 0, 157 0, 158 0, 159 0, 160 0, 161 0, 162 0, 163 0, 164 0, 165 0, 166 /* 0x90-0x9f */ 0, 167 0, 168 0, 169 0, 170 0, 171 0, 172 0, 173 0, 174 0, 175 0, 176 0, 177 0, 178 0, 179 0, 180 0, 181 0, 182 /* 0xa0-0xaf */ 0, 183 0, 184 0, 185 0, 186 0, 187 0, 188 0, 189 0, 190 0, 191 0, 192 0, 193 0, 194 0, 195 0, 196 0, 197 0, 198 /* 0xb0-0xbf */ 0, 199 0, 200 0, 201 0, 202 0, 203 0, 204 0, 205 0, 206 0, 207 0, 208 0, 209 0, 210 0, 211 0, 212 0, 213 0, 214 /* 0xc0-0xcf */ 0, 215 0, 216 0, 217 0, 218 0, 219 0, 220 0, 221 0, 222 0, 223 0, 224 0, 225 0, 226 0, 227 0, 228 0, 229 0, 230 /* 0xd0-0xdf */ 0, 231 0, 232 0, 233 0, 234 0, 235 0, 236 0, 237 0, 238 0, 239 0, 240 0, 241 0, 242 0, 243 0, 244 0, 245 0, 246 /* 0xe0-0xef */ 0, 247 0, 248 0, 249 0, 250 0, 251 0, 252 0, 253 0, 254 0, 255 0, 256 0, 257 0, 258 0, 259 0, 260 0, 261 0, 262 /* 0xf0-0xff */ 0, 263 0, 264 0, 265 0, 266 0, 267 0, 268 0, 269 0, 270 0, 271 0, 272 0, 273 0, 274 0, 275 0, 276 0, 277 0, 278 }; 279 280 static isc_result_t 281 fromtext_caa(ARGS_FROMTEXT) { 282 isc_token_t token; 283 isc_textregion_t tr; 284 uint8_t flags; 285 unsigned int i; 286 287 REQUIRE(type == dns_rdatatype_caa); 288 289 UNUSED(type); 290 UNUSED(rdclass); 291 UNUSED(origin); 292 UNUSED(options); 293 UNUSED(callbacks); 294 295 /* Flags. */ 296 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 297 false)); 298 if (token.value.as_ulong > 255U) { 299 RETTOK(ISC_R_RANGE); 300 } 301 flags = (uint8_t)(token.value.as_ulong & 255U); 302 RETERR(uint8_tobuffer(flags, target)); 303 304 /* 305 * Tag 306 */ 307 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 308 false)); 309 tr = token.value.as_textregion; 310 for (i = 0; i < tr.length; i++) { 311 if (!alphanumeric[(unsigned char)tr.base[i]]) { 312 RETTOK(DNS_R_SYNTAX); 313 } 314 } 315 RETERR(uint8_tobuffer(tr.length, target)); 316 RETERR(mem_tobuffer(target, tr.base, tr.length)); 317 318 /* 319 * Value 320 */ 321 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 322 false)); 323 if (token.type != isc_tokentype_qstring && 324 token.type != isc_tokentype_string) 325 { 326 RETERR(DNS_R_SYNTAX); 327 } 328 RETERR(multitxt_fromtext(&token.value.as_textregion, target)); 329 return (ISC_R_SUCCESS); 330 } 331 332 static isc_result_t 333 totext_caa(ARGS_TOTEXT) { 334 isc_region_t region; 335 uint8_t flags; 336 char buf[256]; 337 338 UNUSED(tctx); 339 340 REQUIRE(rdata->type == dns_rdatatype_caa); 341 REQUIRE(rdata->length >= 3U); 342 REQUIRE(rdata->data != NULL); 343 344 dns_rdata_toregion(rdata, ®ion); 345 346 /* 347 * Flags 348 */ 349 flags = uint8_consume_fromregion(®ion); 350 snprintf(buf, sizeof(buf), "%u ", flags); 351 RETERR(str_totext(buf, target)); 352 353 /* 354 * Tag 355 */ 356 RETERR(txt_totext(®ion, false, target)); 357 RETERR(str_totext(" ", target)); 358 359 /* 360 * Value 361 */ 362 RETERR(multitxt_totext(®ion, target)); 363 return (ISC_R_SUCCESS); 364 } 365 366 static isc_result_t 367 fromwire_caa(ARGS_FROMWIRE) { 368 isc_region_t sr; 369 unsigned int len, i; 370 371 REQUIRE(type == dns_rdatatype_caa); 372 373 UNUSED(type); 374 UNUSED(rdclass); 375 UNUSED(dctx); 376 UNUSED(options); 377 378 /* 379 * Flags 380 */ 381 isc_buffer_activeregion(source, &sr); 382 if (sr.length < 2) { 383 return (ISC_R_UNEXPECTEDEND); 384 } 385 386 /* 387 * Flags, tag length 388 */ 389 RETERR(mem_tobuffer(target, sr.base, 2)); 390 len = sr.base[1]; 391 isc_region_consume(&sr, 2); 392 isc_buffer_forward(source, 2); 393 394 /* 395 * Zero length tag fields are illegal. 396 */ 397 if (sr.length < len || len == 0) { 398 RETERR(DNS_R_FORMERR); 399 } 400 401 /* Check the Tag's value */ 402 for (i = 0; i < len; i++) { 403 if (!alphanumeric[sr.base[i]]) { 404 RETERR(DNS_R_FORMERR); 405 /* 406 * Tag + Value 407 */ 408 } 409 } 410 /* 411 * Tag + Value 412 */ 413 isc_buffer_forward(source, sr.length); 414 return (mem_tobuffer(target, sr.base, sr.length)); 415 } 416 417 static isc_result_t 418 towire_caa(ARGS_TOWIRE) { 419 isc_region_t region; 420 421 REQUIRE(rdata->type == dns_rdatatype_caa); 422 REQUIRE(rdata->length >= 3U); 423 REQUIRE(rdata->data != NULL); 424 425 UNUSED(cctx); 426 427 dns_rdata_toregion(rdata, ®ion); 428 return (mem_tobuffer(target, region.base, region.length)); 429 } 430 431 static int 432 compare_caa(ARGS_COMPARE) { 433 isc_region_t r1, r2; 434 435 REQUIRE(rdata1->type == rdata2->type); 436 REQUIRE(rdata1->rdclass == rdata2->rdclass); 437 REQUIRE(rdata1->type == dns_rdatatype_caa); 438 REQUIRE(rdata1->length >= 3U); 439 REQUIRE(rdata2->length >= 3U); 440 REQUIRE(rdata1->data != NULL); 441 REQUIRE(rdata2->data != NULL); 442 443 dns_rdata_toregion(rdata1, &r1); 444 dns_rdata_toregion(rdata2, &r2); 445 return (isc_region_compare(&r1, &r2)); 446 } 447 448 static isc_result_t 449 fromstruct_caa(ARGS_FROMSTRUCT) { 450 dns_rdata_caa_t *caa = source; 451 isc_region_t region; 452 unsigned int i; 453 454 REQUIRE(type == dns_rdatatype_caa); 455 REQUIRE(caa != NULL); 456 REQUIRE(caa->common.rdtype == type); 457 REQUIRE(caa->common.rdclass == rdclass); 458 REQUIRE(caa->tag != NULL && caa->tag_len != 0); 459 REQUIRE(caa->value != NULL); 460 461 UNUSED(type); 462 UNUSED(rdclass); 463 464 /* 465 * Flags 466 */ 467 RETERR(uint8_tobuffer(caa->flags, target)); 468 469 /* 470 * Tag length 471 */ 472 RETERR(uint8_tobuffer(caa->tag_len, target)); 473 474 /* 475 * Tag 476 */ 477 region.base = caa->tag; 478 region.length = caa->tag_len; 479 for (i = 0; i < region.length; i++) { 480 if (!alphanumeric[region.base[i]]) { 481 RETERR(DNS_R_SYNTAX); 482 } 483 } 484 RETERR(isc_buffer_copyregion(target, ®ion)); 485 486 /* 487 * Value 488 */ 489 region.base = caa->value; 490 region.length = caa->value_len; 491 return (isc_buffer_copyregion(target, ®ion)); 492 } 493 494 static isc_result_t 495 tostruct_caa(ARGS_TOSTRUCT) { 496 dns_rdata_caa_t *caa = target; 497 isc_region_t sr; 498 499 REQUIRE(rdata->type == dns_rdatatype_caa); 500 REQUIRE(caa != NULL); 501 REQUIRE(rdata->length >= 3U); 502 REQUIRE(rdata->data != NULL); 503 504 caa->common.rdclass = rdata->rdclass; 505 caa->common.rdtype = rdata->type; 506 ISC_LINK_INIT(&caa->common, link); 507 508 dns_rdata_toregion(rdata, &sr); 509 510 /* 511 * Flags 512 */ 513 if (sr.length < 1) { 514 return (ISC_R_UNEXPECTEDEND); 515 } 516 caa->flags = uint8_fromregion(&sr); 517 isc_region_consume(&sr, 1); 518 519 /* 520 * Tag length 521 */ 522 if (sr.length < 1) { 523 return (ISC_R_UNEXPECTEDEND); 524 } 525 caa->tag_len = uint8_fromregion(&sr); 526 isc_region_consume(&sr, 1); 527 528 /* 529 * Tag 530 */ 531 if (sr.length < caa->tag_len) { 532 return (ISC_R_UNEXPECTEDEND); 533 } 534 caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len); 535 if (caa->tag == NULL) { 536 return (ISC_R_NOMEMORY); 537 } 538 isc_region_consume(&sr, caa->tag_len); 539 540 /* 541 * Value 542 */ 543 caa->value_len = sr.length; 544 caa->value = mem_maybedup(mctx, sr.base, sr.length); 545 if (caa->value == NULL) { 546 return (ISC_R_NOMEMORY); 547 } 548 549 caa->mctx = mctx; 550 return (ISC_R_SUCCESS); 551 } 552 553 static void 554 freestruct_caa(ARGS_FREESTRUCT) { 555 dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source; 556 557 REQUIRE(caa != NULL); 558 REQUIRE(caa->common.rdtype == dns_rdatatype_caa); 559 560 if (caa->mctx == NULL) { 561 return; 562 } 563 564 if (caa->tag != NULL) { 565 isc_mem_free(caa->mctx, caa->tag); 566 } 567 if (caa->value != NULL) { 568 isc_mem_free(caa->mctx, caa->value); 569 } 570 caa->mctx = NULL; 571 } 572 573 static isc_result_t 574 additionaldata_caa(ARGS_ADDLDATA) { 575 REQUIRE(rdata->type == dns_rdatatype_caa); 576 REQUIRE(rdata->data != NULL); 577 REQUIRE(rdata->length >= 3U); 578 579 UNUSED(rdata); 580 UNUSED(add); 581 UNUSED(arg); 582 583 return (ISC_R_SUCCESS); 584 } 585 586 static isc_result_t 587 digest_caa(ARGS_DIGEST) { 588 isc_region_t r; 589 590 REQUIRE(rdata->type == dns_rdatatype_caa); 591 REQUIRE(rdata->data != NULL); 592 REQUIRE(rdata->length >= 3U); 593 594 dns_rdata_toregion(rdata, &r); 595 596 return ((digest)(arg, &r)); 597 } 598 599 static bool 600 checkowner_caa(ARGS_CHECKOWNER) { 601 REQUIRE(type == dns_rdatatype_caa); 602 603 UNUSED(name); 604 UNUSED(type); 605 UNUSED(rdclass); 606 UNUSED(wildcard); 607 608 return (true); 609 } 610 611 static bool 612 checknames_caa(ARGS_CHECKNAMES) { 613 REQUIRE(rdata->type == dns_rdatatype_caa); 614 REQUIRE(rdata->data != NULL); 615 REQUIRE(rdata->length >= 3U); 616 617 UNUSED(rdata); 618 UNUSED(owner); 619 UNUSED(bad); 620 621 return (true); 622 } 623 624 static int 625 casecompare_caa(ARGS_COMPARE) { 626 return (compare_caa(rdata1, rdata2)); 627 } 628 629 #endif /* GENERIC_CAA_257_C */ 630