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