1 /* $NetBSD: tkey_249.c,v 1.5 2020/05/24 19:46:24 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 /* draft-ietf-dnsext-tkey-01.txt */ 15 16 #ifndef RDATA_GENERIC_TKEY_249_C 17 #define RDATA_GENERIC_TKEY_249_C 18 19 #define RRTYPE_TKEY_ATTRIBUTES (DNS_RDATATYPEATTR_META) 20 21 static inline isc_result_t 22 fromtext_tkey(ARGS_FROMTEXT) { 23 isc_token_t token; 24 dns_rcode_t rcode; 25 dns_name_t name; 26 isc_buffer_t buffer; 27 long i; 28 char *e; 29 30 REQUIRE(type == dns_rdatatype_tkey); 31 32 UNUSED(type); 33 UNUSED(rdclass); 34 UNUSED(callbacks); 35 36 /* 37 * Algorithm. 38 */ 39 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 40 false)); 41 dns_name_init(&name, NULL); 42 buffer_fromregion(&buffer, &token.value.as_region); 43 if (origin == NULL) { 44 origin = dns_rootname; 45 } 46 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 47 48 /* 49 * Inception. 50 */ 51 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 52 false)); 53 RETERR(uint32_tobuffer(token.value.as_ulong, target)); 54 55 /* 56 * Expiration. 57 */ 58 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 59 false)); 60 RETERR(uint32_tobuffer(token.value.as_ulong, target)); 61 62 /* 63 * Mode. 64 */ 65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 66 false)); 67 if (token.value.as_ulong > 0xffffU) { 68 RETTOK(ISC_R_RANGE); 69 } 70 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 71 72 /* 73 * Error. 74 */ 75 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 76 false)); 77 if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion) != 78 ISC_R_SUCCESS) { 79 i = strtol(DNS_AS_STR(token), &e, 10); 80 if (*e != 0) { 81 RETTOK(DNS_R_UNKNOWN); 82 } 83 if (i < 0 || i > 0xffff) { 84 RETTOK(ISC_R_RANGE); 85 } 86 rcode = (dns_rcode_t)i; 87 } 88 RETERR(uint16_tobuffer(rcode, target)); 89 90 /* 91 * Key Size. 92 */ 93 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 94 false)); 95 if (token.value.as_ulong > 0xffffU) { 96 RETTOK(ISC_R_RANGE); 97 } 98 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 99 100 /* 101 * Key Data. 102 */ 103 RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); 104 105 /* 106 * Other Size. 107 */ 108 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 109 false)); 110 if (token.value.as_ulong > 0xffffU) { 111 RETTOK(ISC_R_RANGE); 112 } 113 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 114 115 /* 116 * Other Data. 117 */ 118 return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong)); 119 } 120 121 static inline isc_result_t 122 totext_tkey(ARGS_TOTEXT) { 123 isc_region_t sr, dr; 124 char buf[sizeof("4294967295 ")]; 125 unsigned long n; 126 dns_name_t name; 127 dns_name_t prefix; 128 bool sub; 129 130 REQUIRE(rdata->type == dns_rdatatype_tkey); 131 REQUIRE(rdata->length != 0); 132 133 dns_rdata_toregion(rdata, &sr); 134 135 /* 136 * Algorithm. 137 */ 138 dns_name_init(&name, NULL); 139 dns_name_init(&prefix, NULL); 140 dns_name_fromregion(&name, &sr); 141 sub = name_prefix(&name, tctx->origin, &prefix); 142 RETERR(dns_name_totext(&prefix, sub, target)); 143 RETERR(str_totext(" ", target)); 144 isc_region_consume(&sr, name_length(&name)); 145 146 /* 147 * Inception. 148 */ 149 n = uint32_fromregion(&sr); 150 isc_region_consume(&sr, 4); 151 snprintf(buf, sizeof(buf), "%lu ", n); 152 RETERR(str_totext(buf, target)); 153 154 /* 155 * Expiration. 156 */ 157 n = uint32_fromregion(&sr); 158 isc_region_consume(&sr, 4); 159 snprintf(buf, sizeof(buf), "%lu ", n); 160 RETERR(str_totext(buf, target)); 161 162 /* 163 * Mode. 164 */ 165 n = uint16_fromregion(&sr); 166 isc_region_consume(&sr, 2); 167 snprintf(buf, sizeof(buf), "%lu ", n); 168 RETERR(str_totext(buf, target)); 169 170 /* 171 * Error. 172 */ 173 n = uint16_fromregion(&sr); 174 isc_region_consume(&sr, 2); 175 if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS) { 176 RETERR(str_totext(" ", target)); 177 } else { 178 snprintf(buf, sizeof(buf), "%lu ", n); 179 RETERR(str_totext(buf, target)); 180 } 181 182 /* 183 * Key Size. 184 */ 185 n = uint16_fromregion(&sr); 186 isc_region_consume(&sr, 2); 187 snprintf(buf, sizeof(buf), "%lu", n); 188 RETERR(str_totext(buf, target)); 189 190 /* 191 * Key Data. 192 */ 193 REQUIRE(n <= sr.length); 194 dr = sr; 195 dr.length = n; 196 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 197 RETERR(str_totext(" (", target)); 198 } 199 RETERR(str_totext(tctx->linebreak, target)); 200 if (tctx->width == 0) { /* No splitting */ 201 RETERR(isc_base64_totext(&dr, 60, "", target)); 202 } else { 203 RETERR(isc_base64_totext(&dr, tctx->width - 2, tctx->linebreak, 204 target)); 205 } 206 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 207 RETERR(str_totext(" ) ", target)); 208 } else { 209 RETERR(str_totext(" ", target)); 210 } 211 isc_region_consume(&sr, n); 212 213 /* 214 * Other Size. 215 */ 216 n = uint16_fromregion(&sr); 217 isc_region_consume(&sr, 2); 218 snprintf(buf, sizeof(buf), "%lu", n); 219 RETERR(str_totext(buf, target)); 220 221 /* 222 * Other Data. 223 */ 224 REQUIRE(n <= sr.length); 225 if (n != 0U) { 226 dr = sr; 227 dr.length = n; 228 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 229 RETERR(str_totext(" (", target)); 230 } 231 RETERR(str_totext(tctx->linebreak, target)); 232 if (tctx->width == 0) { /* No splitting */ 233 RETERR(isc_base64_totext(&dr, 60, "", target)); 234 } else { 235 RETERR(isc_base64_totext(&dr, tctx->width - 2, 236 tctx->linebreak, target)); 237 } 238 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 239 RETERR(str_totext(" )", target)); 240 } 241 } 242 return (ISC_R_SUCCESS); 243 } 244 245 static inline isc_result_t 246 fromwire_tkey(ARGS_FROMWIRE) { 247 isc_region_t sr; 248 unsigned long n; 249 dns_name_t name; 250 251 REQUIRE(type == dns_rdatatype_tkey); 252 253 UNUSED(type); 254 UNUSED(rdclass); 255 256 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 257 258 /* 259 * Algorithm. 260 */ 261 dns_name_init(&name, NULL); 262 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 263 264 /* 265 * Inception: 4 266 * Expiration: 4 267 * Mode: 2 268 * Error: 2 269 */ 270 isc_buffer_activeregion(source, &sr); 271 if (sr.length < 12) { 272 return (ISC_R_UNEXPECTEDEND); 273 } 274 RETERR(mem_tobuffer(target, sr.base, 12)); 275 isc_region_consume(&sr, 12); 276 isc_buffer_forward(source, 12); 277 278 /* 279 * Key Length + Key Data. 280 */ 281 if (sr.length < 2) { 282 return (ISC_R_UNEXPECTEDEND); 283 } 284 n = uint16_fromregion(&sr); 285 if (sr.length < n + 2) { 286 return (ISC_R_UNEXPECTEDEND); 287 } 288 RETERR(mem_tobuffer(target, sr.base, n + 2)); 289 isc_region_consume(&sr, n + 2); 290 isc_buffer_forward(source, n + 2); 291 292 /* 293 * Other Length + Other Data. 294 */ 295 if (sr.length < 2) { 296 return (ISC_R_UNEXPECTEDEND); 297 } 298 n = uint16_fromregion(&sr); 299 if (sr.length < n + 2) { 300 return (ISC_R_UNEXPECTEDEND); 301 } 302 isc_buffer_forward(source, n + 2); 303 return (mem_tobuffer(target, sr.base, n + 2)); 304 } 305 306 static inline isc_result_t 307 towire_tkey(ARGS_TOWIRE) { 308 isc_region_t sr; 309 dns_name_t name; 310 dns_offsets_t offsets; 311 312 REQUIRE(rdata->type == dns_rdatatype_tkey); 313 REQUIRE(rdata->length != 0); 314 315 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 316 /* 317 * Algorithm. 318 */ 319 dns_rdata_toregion(rdata, &sr); 320 dns_name_init(&name, offsets); 321 dns_name_fromregion(&name, &sr); 322 RETERR(dns_name_towire(&name, cctx, target)); 323 isc_region_consume(&sr, name_length(&name)); 324 325 return (mem_tobuffer(target, sr.base, sr.length)); 326 } 327 328 static inline int 329 compare_tkey(ARGS_COMPARE) { 330 isc_region_t r1; 331 isc_region_t r2; 332 dns_name_t name1; 333 dns_name_t name2; 334 int order; 335 336 REQUIRE(rdata1->type == rdata2->type); 337 REQUIRE(rdata1->rdclass == rdata2->rdclass); 338 REQUIRE(rdata1->type == dns_rdatatype_tkey); 339 REQUIRE(rdata1->length != 0); 340 REQUIRE(rdata2->length != 0); 341 342 /* 343 * Algorithm. 344 */ 345 dns_rdata_toregion(rdata1, &r1); 346 dns_rdata_toregion(rdata2, &r2); 347 dns_name_init(&name1, NULL); 348 dns_name_init(&name2, NULL); 349 dns_name_fromregion(&name1, &r1); 350 dns_name_fromregion(&name2, &r2); 351 if ((order = dns_name_rdatacompare(&name1, &name2)) != 0) { 352 return (order); 353 } 354 isc_region_consume(&r1, name_length(&name1)); 355 isc_region_consume(&r2, name_length(&name2)); 356 return (isc_region_compare(&r1, &r2)); 357 } 358 359 static inline isc_result_t 360 fromstruct_tkey(ARGS_FROMSTRUCT) { 361 dns_rdata_tkey_t *tkey = source; 362 363 REQUIRE(type == dns_rdatatype_tkey); 364 REQUIRE(tkey != NULL); 365 REQUIRE(tkey->common.rdtype == type); 366 REQUIRE(tkey->common.rdclass == rdclass); 367 368 UNUSED(type); 369 UNUSED(rdclass); 370 371 /* 372 * Algorithm Name. 373 */ 374 RETERR(name_tobuffer(&tkey->algorithm, target)); 375 376 /* 377 * Inception: 32 bits. 378 */ 379 RETERR(uint32_tobuffer(tkey->inception, target)); 380 381 /* 382 * Expire: 32 bits. 383 */ 384 RETERR(uint32_tobuffer(tkey->expire, target)); 385 386 /* 387 * Mode: 16 bits. 388 */ 389 RETERR(uint16_tobuffer(tkey->mode, target)); 390 391 /* 392 * Error: 16 bits. 393 */ 394 RETERR(uint16_tobuffer(tkey->error, target)); 395 396 /* 397 * Key size: 16 bits. 398 */ 399 RETERR(uint16_tobuffer(tkey->keylen, target)); 400 401 /* 402 * Key. 403 */ 404 RETERR(mem_tobuffer(target, tkey->key, tkey->keylen)); 405 406 /* 407 * Other size: 16 bits. 408 */ 409 RETERR(uint16_tobuffer(tkey->otherlen, target)); 410 411 /* 412 * Other data. 413 */ 414 return (mem_tobuffer(target, tkey->other, tkey->otherlen)); 415 } 416 417 static inline isc_result_t 418 tostruct_tkey(ARGS_TOSTRUCT) { 419 dns_rdata_tkey_t *tkey = target; 420 dns_name_t alg; 421 isc_region_t sr; 422 423 REQUIRE(rdata->type == dns_rdatatype_tkey); 424 REQUIRE(tkey != NULL); 425 REQUIRE(rdata->length != 0); 426 427 tkey->common.rdclass = rdata->rdclass; 428 tkey->common.rdtype = rdata->type; 429 ISC_LINK_INIT(&tkey->common, link); 430 431 dns_rdata_toregion(rdata, &sr); 432 433 /* 434 * Algorithm Name. 435 */ 436 dns_name_init(&alg, NULL); 437 dns_name_fromregion(&alg, &sr); 438 dns_name_init(&tkey->algorithm, NULL); 439 RETERR(name_duporclone(&alg, mctx, &tkey->algorithm)); 440 isc_region_consume(&sr, name_length(&tkey->algorithm)); 441 442 /* 443 * Inception. 444 */ 445 tkey->inception = uint32_fromregion(&sr); 446 isc_region_consume(&sr, 4); 447 448 /* 449 * Expire. 450 */ 451 tkey->expire = uint32_fromregion(&sr); 452 isc_region_consume(&sr, 4); 453 454 /* 455 * Mode. 456 */ 457 tkey->mode = uint16_fromregion(&sr); 458 isc_region_consume(&sr, 2); 459 460 /* 461 * Error. 462 */ 463 tkey->error = uint16_fromregion(&sr); 464 isc_region_consume(&sr, 2); 465 466 /* 467 * Key size. 468 */ 469 tkey->keylen = uint16_fromregion(&sr); 470 isc_region_consume(&sr, 2); 471 472 /* 473 * Key. 474 */ 475 INSIST(tkey->keylen + 2U <= sr.length); 476 tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen); 477 if (tkey->key == NULL) { 478 goto cleanup; 479 } 480 isc_region_consume(&sr, tkey->keylen); 481 482 /* 483 * Other size. 484 */ 485 tkey->otherlen = uint16_fromregion(&sr); 486 isc_region_consume(&sr, 2); 487 488 /* 489 * Other. 490 */ 491 INSIST(tkey->otherlen <= sr.length); 492 tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen); 493 if (tkey->other == NULL) { 494 goto cleanup; 495 } 496 497 tkey->mctx = mctx; 498 return (ISC_R_SUCCESS); 499 500 cleanup: 501 if (mctx != NULL) { 502 dns_name_free(&tkey->algorithm, mctx); 503 } 504 if (mctx != NULL && tkey->key != NULL) { 505 isc_mem_free(mctx, tkey->key); 506 } 507 return (ISC_R_NOMEMORY); 508 } 509 510 static inline void 511 freestruct_tkey(ARGS_FREESTRUCT) { 512 dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *)source; 513 514 REQUIRE(tkey != NULL); 515 516 if (tkey->mctx == NULL) { 517 return; 518 } 519 520 dns_name_free(&tkey->algorithm, tkey->mctx); 521 if (tkey->key != NULL) { 522 isc_mem_free(tkey->mctx, tkey->key); 523 } 524 if (tkey->other != NULL) { 525 isc_mem_free(tkey->mctx, tkey->other); 526 } 527 tkey->mctx = NULL; 528 } 529 530 static inline isc_result_t 531 additionaldata_tkey(ARGS_ADDLDATA) { 532 UNUSED(rdata); 533 UNUSED(add); 534 UNUSED(arg); 535 536 REQUIRE(rdata->type == dns_rdatatype_tkey); 537 538 return (ISC_R_SUCCESS); 539 } 540 541 static inline isc_result_t 542 digest_tkey(ARGS_DIGEST) { 543 UNUSED(rdata); 544 UNUSED(digest); 545 UNUSED(arg); 546 547 REQUIRE(rdata->type == dns_rdatatype_tkey); 548 549 return (ISC_R_NOTIMPLEMENTED); 550 } 551 552 static inline bool 553 checkowner_tkey(ARGS_CHECKOWNER) { 554 REQUIRE(type == dns_rdatatype_tkey); 555 556 UNUSED(name); 557 UNUSED(type); 558 UNUSED(rdclass); 559 UNUSED(wildcard); 560 561 return (true); 562 } 563 564 static inline bool 565 checknames_tkey(ARGS_CHECKNAMES) { 566 REQUIRE(rdata->type == dns_rdatatype_tkey); 567 568 UNUSED(rdata); 569 UNUSED(owner); 570 UNUSED(bad); 571 572 return (true); 573 } 574 575 static inline int 576 casecompare_tkey(ARGS_COMPARE) { 577 return (compare_tkey(rdata1, rdata2)); 578 } 579 #endif /* RDATA_GENERIC_TKEY_249_C */ 580