1 /* $NetBSD: tkey_249.c,v 1.10 2025/01/26 16:25:33 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 23 static isc_result_t 24 fromtext_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 124 static isc_result_t 125 totext_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 unsigned int opts; 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 opts = name_prefix(&name, tctx->origin, &prefix) ? DNS_NAME_OMITFINALDOT 145 : 0; 146 RETERR(dns_name_totext(&prefix, opts, target)); 147 RETERR(str_totext(" ", target)); 148 isc_region_consume(&sr, name_length(&name)); 149 150 /* 151 * Inception. 152 */ 153 n = uint32_fromregion(&sr); 154 isc_region_consume(&sr, 4); 155 snprintf(buf, sizeof(buf), "%lu ", n); 156 RETERR(str_totext(buf, target)); 157 158 /* 159 * Expiration. 160 */ 161 n = uint32_fromregion(&sr); 162 isc_region_consume(&sr, 4); 163 snprintf(buf, sizeof(buf), "%lu ", n); 164 RETERR(str_totext(buf, target)); 165 166 /* 167 * Mode. 168 */ 169 n = uint16_fromregion(&sr); 170 isc_region_consume(&sr, 2); 171 snprintf(buf, sizeof(buf), "%lu ", n); 172 RETERR(str_totext(buf, target)); 173 174 /* 175 * Error. 176 */ 177 n = uint16_fromregion(&sr); 178 isc_region_consume(&sr, 2); 179 if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS) { 180 RETERR(str_totext(" ", target)); 181 } else { 182 snprintf(buf, sizeof(buf), "%lu ", n); 183 RETERR(str_totext(buf, target)); 184 } 185 186 /* 187 * Key Size. 188 */ 189 n = uint16_fromregion(&sr); 190 isc_region_consume(&sr, 2); 191 snprintf(buf, sizeof(buf), "%lu", n); 192 RETERR(str_totext(buf, target)); 193 194 /* 195 * Key Data. 196 */ 197 REQUIRE(n <= sr.length); 198 dr = sr; 199 dr.length = n; 200 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 201 RETERR(str_totext(" (", target)); 202 } 203 RETERR(str_totext(tctx->linebreak, target)); 204 if (tctx->width == 0) { /* No splitting */ 205 RETERR(isc_base64_totext(&dr, 60, "", target)); 206 } else { 207 RETERR(isc_base64_totext(&dr, tctx->width - 2, tctx->linebreak, 208 target)); 209 } 210 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 211 RETERR(str_totext(" ) ", target)); 212 } else { 213 RETERR(str_totext(" ", target)); 214 } 215 isc_region_consume(&sr, n); 216 217 /* 218 * Other Size. 219 */ 220 n = uint16_fromregion(&sr); 221 isc_region_consume(&sr, 2); 222 snprintf(buf, sizeof(buf), "%lu", n); 223 RETERR(str_totext(buf, target)); 224 225 /* 226 * Other Data. 227 */ 228 REQUIRE(n <= sr.length); 229 if (n != 0U) { 230 dr = sr; 231 dr.length = n; 232 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 233 RETERR(str_totext(" (", target)); 234 } 235 RETERR(str_totext(tctx->linebreak, target)); 236 if (tctx->width == 0) { /* No splitting */ 237 RETERR(isc_base64_totext(&dr, 60, "", target)); 238 } else { 239 RETERR(isc_base64_totext(&dr, tctx->width - 2, 240 tctx->linebreak, target)); 241 } 242 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 243 RETERR(str_totext(" )", target)); 244 } 245 } 246 return ISC_R_SUCCESS; 247 } 248 249 static isc_result_t 250 fromwire_tkey(ARGS_FROMWIRE) { 251 isc_region_t sr; 252 unsigned long n; 253 dns_name_t name; 254 255 REQUIRE(type == dns_rdatatype_tkey); 256 257 UNUSED(type); 258 UNUSED(rdclass); 259 260 dctx = dns_decompress_setpermitted(dctx, false); 261 262 /* 263 * Algorithm. 264 */ 265 dns_name_init(&name, NULL); 266 RETERR(dns_name_fromwire(&name, source, dctx, target)); 267 268 /* 269 * Inception: 4 270 * Expiration: 4 271 * Mode: 2 272 * Error: 2 273 */ 274 isc_buffer_activeregion(source, &sr); 275 if (sr.length < 12) { 276 return ISC_R_UNEXPECTEDEND; 277 } 278 RETERR(mem_tobuffer(target, sr.base, 12)); 279 isc_region_consume(&sr, 12); 280 isc_buffer_forward(source, 12); 281 282 /* 283 * Key Length + Key Data. 284 */ 285 if (sr.length < 2) { 286 return ISC_R_UNEXPECTEDEND; 287 } 288 n = uint16_fromregion(&sr); 289 if (sr.length < n + 2) { 290 return ISC_R_UNEXPECTEDEND; 291 } 292 RETERR(mem_tobuffer(target, sr.base, n + 2)); 293 isc_region_consume(&sr, n + 2); 294 isc_buffer_forward(source, n + 2); 295 296 /* 297 * Other Length + Other Data. 298 */ 299 if (sr.length < 2) { 300 return ISC_R_UNEXPECTEDEND; 301 } 302 n = uint16_fromregion(&sr); 303 if (sr.length < n + 2) { 304 return ISC_R_UNEXPECTEDEND; 305 } 306 isc_buffer_forward(source, n + 2); 307 return mem_tobuffer(target, sr.base, n + 2); 308 } 309 310 static isc_result_t 311 towire_tkey(ARGS_TOWIRE) { 312 isc_region_t sr; 313 dns_name_t name; 314 dns_offsets_t offsets; 315 316 REQUIRE(rdata->type == dns_rdatatype_tkey); 317 REQUIRE(rdata->length != 0); 318 319 dns_compress_setpermitted(cctx, false); 320 /* 321 * Algorithm. 322 */ 323 dns_rdata_toregion(rdata, &sr); 324 dns_name_init(&name, offsets); 325 dns_name_fromregion(&name, &sr); 326 RETERR(dns_name_towire(&name, cctx, target, NULL)); 327 isc_region_consume(&sr, name_length(&name)); 328 329 return mem_tobuffer(target, sr.base, sr.length); 330 } 331 332 static int 333 compare_tkey(ARGS_COMPARE) { 334 isc_region_t r1; 335 isc_region_t r2; 336 dns_name_t name1; 337 dns_name_t name2; 338 int order; 339 340 REQUIRE(rdata1->type == rdata2->type); 341 REQUIRE(rdata1->rdclass == rdata2->rdclass); 342 REQUIRE(rdata1->type == dns_rdatatype_tkey); 343 REQUIRE(rdata1->length != 0); 344 REQUIRE(rdata2->length != 0); 345 346 /* 347 * Algorithm. 348 */ 349 dns_rdata_toregion(rdata1, &r1); 350 dns_rdata_toregion(rdata2, &r2); 351 dns_name_init(&name1, NULL); 352 dns_name_init(&name2, NULL); 353 dns_name_fromregion(&name1, &r1); 354 dns_name_fromregion(&name2, &r2); 355 if ((order = dns_name_rdatacompare(&name1, &name2)) != 0) { 356 return order; 357 } 358 isc_region_consume(&r1, name_length(&name1)); 359 isc_region_consume(&r2, name_length(&name2)); 360 return isc_region_compare(&r1, &r2); 361 } 362 363 static isc_result_t 364 fromstruct_tkey(ARGS_FROMSTRUCT) { 365 dns_rdata_tkey_t *tkey = source; 366 367 REQUIRE(type == dns_rdatatype_tkey); 368 REQUIRE(tkey != NULL); 369 REQUIRE(tkey->common.rdtype == type); 370 REQUIRE(tkey->common.rdclass == rdclass); 371 372 UNUSED(type); 373 UNUSED(rdclass); 374 375 /* 376 * Algorithm Name. 377 */ 378 RETERR(name_tobuffer(&tkey->algorithm, target)); 379 380 /* 381 * Inception: 32 bits. 382 */ 383 RETERR(uint32_tobuffer(tkey->inception, target)); 384 385 /* 386 * Expire: 32 bits. 387 */ 388 RETERR(uint32_tobuffer(tkey->expire, target)); 389 390 /* 391 * Mode: 16 bits. 392 */ 393 RETERR(uint16_tobuffer(tkey->mode, target)); 394 395 /* 396 * Error: 16 bits. 397 */ 398 RETERR(uint16_tobuffer(tkey->error, target)); 399 400 /* 401 * Key size: 16 bits. 402 */ 403 RETERR(uint16_tobuffer(tkey->keylen, target)); 404 405 /* 406 * Key. 407 */ 408 RETERR(mem_tobuffer(target, tkey->key, tkey->keylen)); 409 410 /* 411 * Other size: 16 bits. 412 */ 413 RETERR(uint16_tobuffer(tkey->otherlen, target)); 414 415 /* 416 * Other data. 417 */ 418 return mem_tobuffer(target, tkey->other, tkey->otherlen); 419 } 420 421 static isc_result_t 422 tostruct_tkey(ARGS_TOSTRUCT) { 423 dns_rdata_tkey_t *tkey = target; 424 dns_name_t alg; 425 isc_region_t sr; 426 427 REQUIRE(rdata->type == dns_rdatatype_tkey); 428 REQUIRE(tkey != NULL); 429 REQUIRE(rdata->length != 0); 430 431 tkey->common.rdclass = rdata->rdclass; 432 tkey->common.rdtype = rdata->type; 433 ISC_LINK_INIT(&tkey->common, link); 434 435 dns_rdata_toregion(rdata, &sr); 436 437 /* 438 * Algorithm Name. 439 */ 440 dns_name_init(&alg, NULL); 441 dns_name_fromregion(&alg, &sr); 442 dns_name_init(&tkey->algorithm, NULL); 443 name_duporclone(&alg, mctx, &tkey->algorithm); 444 isc_region_consume(&sr, name_length(&tkey->algorithm)); 445 446 /* 447 * Inception. 448 */ 449 tkey->inception = uint32_fromregion(&sr); 450 isc_region_consume(&sr, 4); 451 452 /* 453 * Expire. 454 */ 455 tkey->expire = uint32_fromregion(&sr); 456 isc_region_consume(&sr, 4); 457 458 /* 459 * Mode. 460 */ 461 tkey->mode = uint16_fromregion(&sr); 462 isc_region_consume(&sr, 2); 463 464 /* 465 * Error. 466 */ 467 tkey->error = uint16_fromregion(&sr); 468 isc_region_consume(&sr, 2); 469 470 /* 471 * Key size. 472 */ 473 tkey->keylen = uint16_fromregion(&sr); 474 isc_region_consume(&sr, 2); 475 476 /* 477 * Key. 478 */ 479 INSIST(tkey->keylen + 2U <= sr.length); 480 tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen); 481 isc_region_consume(&sr, tkey->keylen); 482 483 /* 484 * Other size. 485 */ 486 tkey->otherlen = uint16_fromregion(&sr); 487 isc_region_consume(&sr, 2); 488 489 /* 490 * Other. 491 */ 492 INSIST(tkey->otherlen <= sr.length); 493 tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen); 494 tkey->mctx = mctx; 495 return ISC_R_SUCCESS; 496 } 497 498 static void 499 freestruct_tkey(ARGS_FREESTRUCT) { 500 dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *)source; 501 502 REQUIRE(tkey != NULL); 503 504 if (tkey->mctx == NULL) { 505 return; 506 } 507 508 dns_name_free(&tkey->algorithm, tkey->mctx); 509 if (tkey->key != NULL) { 510 isc_mem_free(tkey->mctx, tkey->key); 511 } 512 if (tkey->other != NULL) { 513 isc_mem_free(tkey->mctx, tkey->other); 514 } 515 tkey->mctx = NULL; 516 } 517 518 static isc_result_t 519 additionaldata_tkey(ARGS_ADDLDATA) { 520 REQUIRE(rdata->type == dns_rdatatype_tkey); 521 522 UNUSED(rdata); 523 UNUSED(owner); 524 UNUSED(add); 525 UNUSED(arg); 526 527 return ISC_R_SUCCESS; 528 } 529 530 static isc_result_t 531 digest_tkey(ARGS_DIGEST) { 532 UNUSED(rdata); 533 UNUSED(digest); 534 UNUSED(arg); 535 536 REQUIRE(rdata->type == dns_rdatatype_tkey); 537 538 return ISC_R_NOTIMPLEMENTED; 539 } 540 541 static bool 542 checkowner_tkey(ARGS_CHECKOWNER) { 543 REQUIRE(type == dns_rdatatype_tkey); 544 545 UNUSED(name); 546 UNUSED(type); 547 UNUSED(rdclass); 548 UNUSED(wildcard); 549 550 return true; 551 } 552 553 static bool 554 checknames_tkey(ARGS_CHECKNAMES) { 555 REQUIRE(rdata->type == dns_rdatatype_tkey); 556 557 UNUSED(rdata); 558 UNUSED(owner); 559 UNUSED(bad); 560 561 return true; 562 } 563 564 static int 565 casecompare_tkey(ARGS_COMPARE) { 566 return compare_tkey(rdata1, rdata2); 567 } 568 #endif /* RDATA_GENERIC_TKEY_249_C */ 569