1 /* $NetBSD: ipseckey_45.c,v 1.9 2022/09/23 12:15:31 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 RDATA_GENERIC_IPSECKEY_45_C 17 #define RDATA_GENERIC_IPSECKEY_45_C 18 19 #include <string.h> 20 21 #include <isc/net.h> 22 23 #define RRTYPE_IPSECKEY_ATTRIBUTES (0) 24 25 static isc_result_t 26 fromtext_ipseckey(ARGS_FROMTEXT) { 27 isc_token_t token; 28 dns_name_t name; 29 isc_buffer_t buffer; 30 unsigned int gateway; 31 struct in_addr addr; 32 unsigned char addr6[16]; 33 isc_region_t region; 34 35 REQUIRE(type == dns_rdatatype_ipseckey); 36 37 UNUSED(type); 38 UNUSED(rdclass); 39 UNUSED(callbacks); 40 41 /* 42 * Precedence. 43 */ 44 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 45 false)); 46 if (token.value.as_ulong > 0xffU) { 47 RETTOK(ISC_R_RANGE); 48 } 49 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 50 51 /* 52 * Gateway type. 53 */ 54 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 55 false)); 56 if (token.value.as_ulong > 0x3U) { 57 RETTOK(ISC_R_RANGE); 58 } 59 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 60 gateway = token.value.as_ulong; 61 62 /* 63 * Algorithm. 64 */ 65 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 66 false)); 67 if (token.value.as_ulong > 0xffU) { 68 RETTOK(ISC_R_RANGE); 69 } 70 RETERR(uint8_tobuffer(token.value.as_ulong, target)); 71 72 /* 73 * Gateway. 74 */ 75 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 76 false)); 77 78 switch (gateway) { 79 case 0: 80 if (strcmp(DNS_AS_STR(token), ".") != 0) { 81 RETTOK(DNS_R_SYNTAX); 82 } 83 break; 84 85 case 1: 86 if (inet_pton(AF_INET, DNS_AS_STR(token), &addr) != 1) { 87 RETTOK(DNS_R_BADDOTTEDQUAD); 88 } 89 isc_buffer_availableregion(target, ®ion); 90 if (region.length < 4) { 91 return (ISC_R_NOSPACE); 92 } 93 memmove(region.base, &addr, 4); 94 isc_buffer_add(target, 4); 95 break; 96 97 case 2: 98 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1) { 99 RETTOK(DNS_R_BADAAAA); 100 } 101 isc_buffer_availableregion(target, ®ion); 102 if (region.length < 16) { 103 return (ISC_R_NOSPACE); 104 } 105 memmove(region.base, addr6, 16); 106 isc_buffer_add(target, 16); 107 break; 108 109 case 3: 110 dns_name_init(&name, NULL); 111 buffer_fromregion(&buffer, &token.value.as_region); 112 if (origin == NULL) { 113 origin = dns_rootname; 114 } 115 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, 116 target)); 117 break; 118 } 119 120 /* 121 * Public key. 122 */ 123 return (isc_base64_tobuffer(lexer, target, -2)); 124 } 125 126 static isc_result_t 127 totext_ipseckey(ARGS_TOTEXT) { 128 isc_region_t region; 129 dns_name_t name; 130 char buf[sizeof("255 ")]; 131 unsigned short num; 132 unsigned short gateway; 133 134 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 135 REQUIRE(rdata->length >= 3); 136 137 dns_name_init(&name, NULL); 138 139 if (rdata->data[1] > 3U) { 140 return (ISC_R_NOTIMPLEMENTED); 141 } 142 143 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 144 RETERR(str_totext("( ", target)); 145 } 146 147 /* 148 * Precedence. 149 */ 150 dns_rdata_toregion(rdata, ®ion); 151 num = uint8_fromregion(®ion); 152 isc_region_consume(®ion, 1); 153 snprintf(buf, sizeof(buf), "%u ", num); 154 RETERR(str_totext(buf, target)); 155 156 /* 157 * Gateway type. 158 */ 159 gateway = uint8_fromregion(®ion); 160 isc_region_consume(®ion, 1); 161 snprintf(buf, sizeof(buf), "%u ", gateway); 162 RETERR(str_totext(buf, target)); 163 164 /* 165 * Algorithm. 166 */ 167 num = uint8_fromregion(®ion); 168 isc_region_consume(®ion, 1); 169 snprintf(buf, sizeof(buf), "%u ", num); 170 RETERR(str_totext(buf, target)); 171 172 /* 173 * Gateway. 174 */ 175 switch (gateway) { 176 case 0: 177 RETERR(str_totext(".", target)); 178 break; 179 180 case 1: 181 RETERR(inet_totext(AF_INET, tctx->flags, ®ion, target)); 182 isc_region_consume(®ion, 4); 183 break; 184 185 case 2: 186 RETERR(inet_totext(AF_INET6, tctx->flags, ®ion, target)); 187 isc_region_consume(®ion, 16); 188 break; 189 190 case 3: 191 dns_name_fromregion(&name, ®ion); 192 RETERR(dns_name_totext(&name, false, target)); 193 isc_region_consume(®ion, name_length(&name)); 194 break; 195 } 196 197 /* 198 * Key. 199 */ 200 if (region.length > 0U) { 201 RETERR(str_totext(tctx->linebreak, target)); 202 if (tctx->width == 0) { /* No splitting */ 203 RETERR(isc_base64_totext(®ion, 60, "", target)); 204 } else { 205 RETERR(isc_base64_totext(®ion, tctx->width - 2, 206 tctx->linebreak, target)); 207 } 208 } 209 210 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 211 RETERR(str_totext(" )", target)); 212 } 213 return (ISC_R_SUCCESS); 214 } 215 216 static isc_result_t 217 fromwire_ipseckey(ARGS_FROMWIRE) { 218 dns_name_t name; 219 isc_region_t region; 220 221 REQUIRE(type == dns_rdatatype_ipseckey); 222 223 UNUSED(type); 224 UNUSED(rdclass); 225 226 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 227 228 dns_name_init(&name, NULL); 229 230 isc_buffer_activeregion(source, ®ion); 231 if (region.length < 3) { 232 return (ISC_R_UNEXPECTEDEND); 233 } 234 235 switch (region.base[1]) { 236 case 0: 237 if (region.length < 4) { 238 return (ISC_R_UNEXPECTEDEND); 239 } 240 isc_buffer_forward(source, region.length); 241 return (mem_tobuffer(target, region.base, region.length)); 242 243 case 1: 244 if (region.length < 8) { 245 return (ISC_R_UNEXPECTEDEND); 246 } 247 isc_buffer_forward(source, region.length); 248 return (mem_tobuffer(target, region.base, region.length)); 249 250 case 2: 251 if (region.length < 20) { 252 return (ISC_R_UNEXPECTEDEND); 253 } 254 isc_buffer_forward(source, region.length); 255 return (mem_tobuffer(target, region.base, region.length)); 256 257 case 3: 258 RETERR(mem_tobuffer(target, region.base, 3)); 259 isc_buffer_forward(source, 3); 260 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 261 isc_buffer_activeregion(source, ®ion); 262 isc_buffer_forward(source, region.length); 263 if (region.length < 1) { 264 return (ISC_R_UNEXPECTEDEND); 265 } 266 return (mem_tobuffer(target, region.base, region.length)); 267 268 default: 269 return (ISC_R_NOTIMPLEMENTED); 270 } 271 } 272 273 static isc_result_t 274 towire_ipseckey(ARGS_TOWIRE) { 275 isc_region_t region; 276 277 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 278 REQUIRE(rdata->length != 0); 279 280 UNUSED(cctx); 281 282 dns_rdata_toregion(rdata, ®ion); 283 return (mem_tobuffer(target, region.base, region.length)); 284 } 285 286 static int 287 compare_ipseckey(ARGS_COMPARE) { 288 isc_region_t region1; 289 isc_region_t region2; 290 291 REQUIRE(rdata1->type == rdata2->type); 292 REQUIRE(rdata1->rdclass == rdata2->rdclass); 293 REQUIRE(rdata1->type == dns_rdatatype_ipseckey); 294 REQUIRE(rdata1->length >= 3); 295 REQUIRE(rdata2->length >= 3); 296 297 dns_rdata_toregion(rdata1, ®ion1); 298 dns_rdata_toregion(rdata2, ®ion2); 299 300 return (isc_region_compare(®ion1, ®ion2)); 301 } 302 303 static isc_result_t 304 fromstruct_ipseckey(ARGS_FROMSTRUCT) { 305 dns_rdata_ipseckey_t *ipseckey = source; 306 isc_region_t region; 307 uint32_t n; 308 309 REQUIRE(type == dns_rdatatype_ipseckey); 310 REQUIRE(ipseckey != NULL); 311 REQUIRE(ipseckey->common.rdtype == type); 312 REQUIRE(ipseckey->common.rdclass == rdclass); 313 314 UNUSED(type); 315 UNUSED(rdclass); 316 317 if (ipseckey->gateway_type > 3U) { 318 return (ISC_R_NOTIMPLEMENTED); 319 } 320 321 RETERR(uint8_tobuffer(ipseckey->precedence, target)); 322 RETERR(uint8_tobuffer(ipseckey->gateway_type, target)); 323 RETERR(uint8_tobuffer(ipseckey->algorithm, target)); 324 325 switch (ipseckey->gateway_type) { 326 case 0: 327 break; 328 329 case 1: 330 n = ntohl(ipseckey->in_addr.s_addr); 331 RETERR(uint32_tobuffer(n, target)); 332 break; 333 334 case 2: 335 RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16)); 336 break; 337 338 case 3: 339 dns_name_toregion(&ipseckey->gateway, ®ion); 340 RETERR(isc_buffer_copyregion(target, ®ion)); 341 break; 342 } 343 344 return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength)); 345 } 346 347 static isc_result_t 348 tostruct_ipseckey(ARGS_TOSTRUCT) { 349 isc_region_t region; 350 dns_rdata_ipseckey_t *ipseckey = target; 351 dns_name_t name; 352 uint32_t n; 353 354 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 355 REQUIRE(ipseckey != NULL); 356 REQUIRE(rdata->length >= 3); 357 358 if (rdata->data[1] > 3U) { 359 return (ISC_R_NOTIMPLEMENTED); 360 } 361 362 ipseckey->common.rdclass = rdata->rdclass; 363 ipseckey->common.rdtype = rdata->type; 364 ISC_LINK_INIT(&ipseckey->common, link); 365 366 dns_name_init(&name, NULL); 367 dns_rdata_toregion(rdata, ®ion); 368 369 ipseckey->precedence = uint8_fromregion(®ion); 370 isc_region_consume(®ion, 1); 371 372 ipseckey->gateway_type = uint8_fromregion(®ion); 373 isc_region_consume(®ion, 1); 374 375 ipseckey->algorithm = uint8_fromregion(®ion); 376 isc_region_consume(®ion, 1); 377 378 switch (ipseckey->gateway_type) { 379 case 0: 380 break; 381 382 case 1: 383 n = uint32_fromregion(®ion); 384 ipseckey->in_addr.s_addr = htonl(n); 385 isc_region_consume(®ion, 4); 386 break; 387 388 case 2: 389 memmove(ipseckey->in6_addr.s6_addr, region.base, 16); 390 isc_region_consume(®ion, 16); 391 break; 392 393 case 3: 394 dns_name_init(&ipseckey->gateway, NULL); 395 dns_name_fromregion(&name, ®ion); 396 RETERR(name_duporclone(&name, mctx, &ipseckey->gateway)); 397 isc_region_consume(®ion, name_length(&name)); 398 break; 399 } 400 401 ipseckey->keylength = region.length; 402 if (ipseckey->keylength != 0U) { 403 ipseckey->key = mem_maybedup(mctx, region.base, 404 ipseckey->keylength); 405 if (ipseckey->key == NULL) { 406 if (ipseckey->gateway_type == 3) { 407 dns_name_free(&ipseckey->gateway, 408 ipseckey->mctx); 409 } 410 return (ISC_R_NOMEMORY); 411 } 412 } else { 413 ipseckey->key = NULL; 414 } 415 416 ipseckey->mctx = mctx; 417 return (ISC_R_SUCCESS); 418 } 419 420 static void 421 freestruct_ipseckey(ARGS_FREESTRUCT) { 422 dns_rdata_ipseckey_t *ipseckey = source; 423 424 REQUIRE(ipseckey != NULL); 425 REQUIRE(ipseckey->common.rdtype == dns_rdatatype_ipseckey); 426 427 if (ipseckey->mctx == NULL) { 428 return; 429 } 430 431 if (ipseckey->gateway_type == 3) { 432 dns_name_free(&ipseckey->gateway, ipseckey->mctx); 433 } 434 435 if (ipseckey->key != NULL) { 436 isc_mem_free(ipseckey->mctx, ipseckey->key); 437 } 438 439 ipseckey->mctx = NULL; 440 } 441 442 static isc_result_t 443 additionaldata_ipseckey(ARGS_ADDLDATA) { 444 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 445 446 UNUSED(rdata); 447 UNUSED(add); 448 UNUSED(arg); 449 450 return (ISC_R_SUCCESS); 451 } 452 453 static isc_result_t 454 digest_ipseckey(ARGS_DIGEST) { 455 isc_region_t region; 456 457 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 458 459 dns_rdata_toregion(rdata, ®ion); 460 return ((digest)(arg, ®ion)); 461 } 462 463 static bool 464 checkowner_ipseckey(ARGS_CHECKOWNER) { 465 REQUIRE(type == dns_rdatatype_ipseckey); 466 467 UNUSED(name); 468 UNUSED(type); 469 UNUSED(rdclass); 470 UNUSED(wildcard); 471 472 return (true); 473 } 474 475 static bool 476 checknames_ipseckey(ARGS_CHECKNAMES) { 477 REQUIRE(rdata->type == dns_rdatatype_ipseckey); 478 479 UNUSED(rdata); 480 UNUSED(owner); 481 UNUSED(bad); 482 483 return (true); 484 } 485 486 static int 487 casecompare_ipseckey(ARGS_COMPARE) { 488 isc_region_t region1; 489 isc_region_t region2; 490 dns_name_t name1; 491 dns_name_t name2; 492 int order; 493 494 REQUIRE(rdata1->type == rdata2->type); 495 REQUIRE(rdata1->rdclass == rdata2->rdclass); 496 REQUIRE(rdata1->type == dns_rdatatype_ipseckey); 497 REQUIRE(rdata1->length >= 3); 498 REQUIRE(rdata2->length >= 3); 499 500 dns_rdata_toregion(rdata1, ®ion1); 501 dns_rdata_toregion(rdata2, ®ion2); 502 503 if (memcmp(region1.base, region2.base, 3) != 0 || region1.base[1] != 3) 504 { 505 return (isc_region_compare(®ion1, ®ion2)); 506 } 507 508 dns_name_init(&name1, NULL); 509 dns_name_init(&name2, NULL); 510 511 isc_region_consume(®ion1, 3); 512 isc_region_consume(®ion2, 3); 513 514 dns_name_fromregion(&name1, ®ion1); 515 dns_name_fromregion(&name2, ®ion2); 516 517 order = dns_name_rdatacompare(&name1, &name2); 518 if (order != 0) { 519 return (order); 520 } 521 522 isc_region_consume(®ion1, name_length(&name1)); 523 isc_region_consume(®ion2, name_length(&name2)); 524 525 return (isc_region_compare(®ion1, ®ion2)); 526 } 527 528 #endif /* RDATA_GENERIC_IPSECKEY_45_C */ 529