1 /* $NetBSD: keydata_65533.c,v 1.10 2024/02/21 22:52:13 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_KEYDATA_65533_C 17 #define GENERIC_KEYDATA_65533_C 1 18 19 #include <isc/stdtime.h> 20 #include <isc/time.h> 21 22 #include <dst/dst.h> 23 24 #define RRTYPE_KEYDATA_ATTRIBUTES (0) 25 26 static isc_result_t 27 fromtext_keydata(ARGS_FROMTEXT) { 28 isc_token_t token; 29 dns_secalg_t alg; 30 dns_secproto_t proto; 31 dns_keyflags_t flags; 32 uint32_t refresh, addhd, removehd; 33 34 REQUIRE(type == dns_rdatatype_keydata); 35 36 UNUSED(type); 37 UNUSED(rdclass); 38 UNUSED(origin); 39 UNUSED(options); 40 UNUSED(callbacks); 41 42 /* refresh timer */ 43 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 44 false)); 45 RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &refresh)); 46 RETERR(uint32_tobuffer(refresh, target)); 47 48 /* add hold-down */ 49 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 50 false)); 51 RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &addhd)); 52 RETERR(uint32_tobuffer(addhd, target)); 53 54 /* remove hold-down */ 55 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 56 false)); 57 RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &removehd)); 58 RETERR(uint32_tobuffer(removehd, target)); 59 60 /* flags */ 61 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 62 false)); 63 RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); 64 RETERR(uint16_tobuffer(flags, target)); 65 66 /* protocol */ 67 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 68 false)); 69 RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); 70 RETERR(mem_tobuffer(target, &proto, 1)); 71 72 /* algorithm */ 73 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 74 false)); 75 RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); 76 RETERR(mem_tobuffer(target, &alg, 1)); 77 78 /* Do we have a placeholder KEYDATA record? */ 79 if (flags == 0 && proto == 0 && alg == 0) { 80 return (ISC_R_SUCCESS); 81 } 82 83 /* No Key? */ 84 if ((flags & 0xc000) == 0xc000) { 85 return (ISC_R_SUCCESS); 86 } 87 88 return (isc_base64_tobuffer(lexer, target, -2)); 89 } 90 91 static isc_result_t 92 totext_keydata(ARGS_TOTEXT) { 93 isc_region_t sr; 94 char buf[sizeof("64000")]; 95 unsigned int flags; 96 unsigned char proto, algorithm; 97 unsigned long refresh, add, deltime; 98 char algbuf[DNS_NAME_FORMATSIZE]; 99 const char *keyinfo; 100 101 REQUIRE(rdata->type == dns_rdatatype_keydata); 102 103 if ((tctx->flags & DNS_STYLEFLAG_KEYDATA) == 0 || rdata->length < 16) { 104 return (unknown_totext(rdata, tctx, target)); 105 } 106 107 dns_rdata_toregion(rdata, &sr); 108 109 /* refresh timer */ 110 refresh = uint32_fromregion(&sr); 111 isc_region_consume(&sr, 4); 112 RETERR(dns_time32_totext(refresh, target)); 113 RETERR(str_totext(" ", target)); 114 115 /* add hold-down */ 116 add = uint32_fromregion(&sr); 117 isc_region_consume(&sr, 4); 118 RETERR(dns_time32_totext(add, target)); 119 RETERR(str_totext(" ", target)); 120 121 /* remove hold-down */ 122 deltime = uint32_fromregion(&sr); 123 isc_region_consume(&sr, 4); 124 RETERR(dns_time32_totext(deltime, target)); 125 RETERR(str_totext(" ", target)); 126 127 /* flags */ 128 flags = uint16_fromregion(&sr); 129 isc_region_consume(&sr, 2); 130 snprintf(buf, sizeof(buf), "%u", flags); 131 RETERR(str_totext(buf, target)); 132 RETERR(str_totext(" ", target)); 133 if ((flags & DNS_KEYFLAG_KSK) != 0) { 134 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 135 keyinfo = "revoked KSK"; 136 } else { 137 keyinfo = "KSK"; 138 } 139 } else { 140 keyinfo = "ZSK"; 141 } 142 143 /* protocol */ 144 proto = sr.base[0]; 145 snprintf(buf, sizeof(buf), "%u", proto); 146 isc_region_consume(&sr, 1); 147 RETERR(str_totext(buf, target)); 148 RETERR(str_totext(" ", target)); 149 150 /* algorithm */ 151 algorithm = sr.base[0]; 152 snprintf(buf, sizeof(buf), "%u", algorithm); 153 isc_region_consume(&sr, 1); 154 RETERR(str_totext(buf, target)); 155 156 /* Do we have a placeholder KEYDATA record? */ 157 if (flags == 0 && proto == 0 && algorithm == 0) { 158 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { 159 RETERR(str_totext(" ; placeholder", target)); 160 } 161 return (ISC_R_SUCCESS); 162 } 163 164 /* No Key? */ 165 if ((flags & 0xc000) == 0xc000) { 166 return (ISC_R_SUCCESS); 167 } 168 169 /* key */ 170 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 171 RETERR(str_totext(" (", target)); 172 } 173 RETERR(str_totext(tctx->linebreak, target)); 174 if (tctx->width == 0) { /* No splitting */ 175 RETERR(isc_base64_totext(&sr, 60, "", target)); 176 } else { 177 RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak, 178 target)); 179 } 180 181 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { 182 RETERR(str_totext(tctx->linebreak, target)); 183 } else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 184 RETERR(str_totext(" ", target)); 185 } 186 187 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 188 RETERR(str_totext(")", target)); 189 } 190 191 if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { 192 isc_region_t tmpr; 193 char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 194 char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 195 char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; 196 isc_time_t t; 197 198 RETERR(str_totext(" ; ", target)); 199 RETERR(str_totext(keyinfo, target)); 200 dns_secalg_format((dns_secalg_t)algorithm, algbuf, 201 sizeof(algbuf)); 202 RETERR(str_totext("; alg = ", target)); 203 RETERR(str_totext(algbuf, target)); 204 RETERR(str_totext("; key id = ", target)); 205 dns_rdata_toregion(rdata, &tmpr); 206 /* Skip over refresh, addhd, and removehd */ 207 isc_region_consume(&tmpr, 12); 208 snprintf(buf, sizeof(buf), "%u", dst_region_computeid(&tmpr)); 209 RETERR(str_totext(buf, target)); 210 211 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { 212 isc_stdtime_t now; 213 214 isc_stdtime_get(&now); 215 216 RETERR(str_totext(tctx->linebreak, target)); 217 RETERR(str_totext("; next refresh: ", target)); 218 isc_time_set(&t, refresh, 0); 219 isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf)); 220 RETERR(str_totext(rbuf, target)); 221 222 if (add == 0U) { 223 RETERR(str_totext(tctx->linebreak, target)); 224 RETERR(str_totext("; no trust", target)); 225 } else { 226 RETERR(str_totext(tctx->linebreak, target)); 227 if (add < now) { 228 RETERR(str_totext("; trusted since: ", 229 target)); 230 } else { 231 RETERR(str_totext("; trust pending: ", 232 target)); 233 } 234 isc_time_set(&t, add, 0); 235 isc_time_formathttptimestamp(&t, abuf, 236 sizeof(abuf)); 237 RETERR(str_totext(abuf, target)); 238 } 239 240 if (deltime != 0U) { 241 RETERR(str_totext(tctx->linebreak, target)); 242 RETERR(str_totext("; removal pending: ", 243 target)); 244 isc_time_set(&t, deltime, 0); 245 isc_time_formathttptimestamp(&t, dbuf, 246 sizeof(dbuf)); 247 RETERR(str_totext(dbuf, target)); 248 } 249 } 250 } 251 return (ISC_R_SUCCESS); 252 } 253 254 static isc_result_t 255 fromwire_keydata(ARGS_FROMWIRE) { 256 isc_region_t sr; 257 258 REQUIRE(type == dns_rdatatype_keydata); 259 260 UNUSED(type); 261 UNUSED(rdclass); 262 UNUSED(dctx); 263 UNUSED(options); 264 265 isc_buffer_activeregion(source, &sr); 266 isc_buffer_forward(source, sr.length); 267 return (mem_tobuffer(target, sr.base, sr.length)); 268 } 269 270 static isc_result_t 271 towire_keydata(ARGS_TOWIRE) { 272 isc_region_t sr; 273 274 REQUIRE(rdata->type == dns_rdatatype_keydata); 275 276 UNUSED(cctx); 277 278 dns_rdata_toregion(rdata, &sr); 279 return (mem_tobuffer(target, sr.base, sr.length)); 280 } 281 282 static int 283 compare_keydata(ARGS_COMPARE) { 284 isc_region_t r1; 285 isc_region_t r2; 286 287 REQUIRE(rdata1->type == rdata2->type); 288 REQUIRE(rdata1->rdclass == rdata2->rdclass); 289 REQUIRE(rdata1->type == dns_rdatatype_keydata); 290 291 dns_rdata_toregion(rdata1, &r1); 292 dns_rdata_toregion(rdata2, &r2); 293 return (isc_region_compare(&r1, &r2)); 294 } 295 296 static isc_result_t 297 fromstruct_keydata(ARGS_FROMSTRUCT) { 298 dns_rdata_keydata_t *keydata = source; 299 300 REQUIRE(type == dns_rdatatype_keydata); 301 REQUIRE(keydata != NULL); 302 REQUIRE(keydata->common.rdtype == type); 303 REQUIRE(keydata->common.rdclass == rdclass); 304 305 UNUSED(type); 306 UNUSED(rdclass); 307 308 /* Refresh timer */ 309 RETERR(uint32_tobuffer(keydata->refresh, target)); 310 311 /* Add hold-down */ 312 RETERR(uint32_tobuffer(keydata->addhd, target)); 313 314 /* Remove hold-down */ 315 RETERR(uint32_tobuffer(keydata->removehd, target)); 316 317 /* Flags */ 318 RETERR(uint16_tobuffer(keydata->flags, target)); 319 320 /* Protocol */ 321 RETERR(uint8_tobuffer(keydata->protocol, target)); 322 323 /* Algorithm */ 324 RETERR(uint8_tobuffer(keydata->algorithm, target)); 325 326 /* Data */ 327 return (mem_tobuffer(target, keydata->data, keydata->datalen)); 328 } 329 330 static isc_result_t 331 tostruct_keydata(ARGS_TOSTRUCT) { 332 dns_rdata_keydata_t *keydata = target; 333 isc_region_t sr; 334 335 REQUIRE(rdata->type == dns_rdatatype_keydata); 336 REQUIRE(keydata != NULL); 337 338 keydata->common.rdclass = rdata->rdclass; 339 keydata->common.rdtype = rdata->type; 340 ISC_LINK_INIT(&keydata->common, link); 341 342 dns_rdata_toregion(rdata, &sr); 343 344 /* Refresh timer */ 345 if (sr.length < 4) { 346 return (ISC_R_UNEXPECTEDEND); 347 } 348 keydata->refresh = uint32_fromregion(&sr); 349 isc_region_consume(&sr, 4); 350 351 /* Add hold-down */ 352 if (sr.length < 4) { 353 return (ISC_R_UNEXPECTEDEND); 354 } 355 keydata->addhd = uint32_fromregion(&sr); 356 isc_region_consume(&sr, 4); 357 358 /* Remove hold-down */ 359 if (sr.length < 4) { 360 return (ISC_R_UNEXPECTEDEND); 361 } 362 keydata->removehd = uint32_fromregion(&sr); 363 isc_region_consume(&sr, 4); 364 365 /* Flags */ 366 if (sr.length < 2) { 367 return (ISC_R_UNEXPECTEDEND); 368 } 369 keydata->flags = uint16_fromregion(&sr); 370 isc_region_consume(&sr, 2); 371 372 /* Protocol */ 373 if (sr.length < 1) { 374 return (ISC_R_UNEXPECTEDEND); 375 } 376 keydata->protocol = uint8_fromregion(&sr); 377 isc_region_consume(&sr, 1); 378 379 /* Algorithm */ 380 if (sr.length < 1) { 381 return (ISC_R_UNEXPECTEDEND); 382 } 383 keydata->algorithm = uint8_fromregion(&sr); 384 isc_region_consume(&sr, 1); 385 386 /* Data */ 387 keydata->datalen = sr.length; 388 keydata->data = mem_maybedup(mctx, sr.base, keydata->datalen); 389 if (keydata->data == NULL) { 390 return (ISC_R_NOMEMORY); 391 } 392 393 keydata->mctx = mctx; 394 return (ISC_R_SUCCESS); 395 } 396 397 static void 398 freestruct_keydata(ARGS_FREESTRUCT) { 399 dns_rdata_keydata_t *keydata = (dns_rdata_keydata_t *)source; 400 401 REQUIRE(keydata != NULL); 402 REQUIRE(keydata->common.rdtype == dns_rdatatype_keydata); 403 404 if (keydata->mctx == NULL) { 405 return; 406 } 407 408 if (keydata->data != NULL) { 409 isc_mem_free(keydata->mctx, keydata->data); 410 } 411 keydata->mctx = NULL; 412 } 413 414 static isc_result_t 415 additionaldata_keydata(ARGS_ADDLDATA) { 416 REQUIRE(rdata->type == dns_rdatatype_keydata); 417 418 UNUSED(rdata); 419 UNUSED(owner); 420 UNUSED(add); 421 UNUSED(arg); 422 423 return (ISC_R_SUCCESS); 424 } 425 426 static isc_result_t 427 digest_keydata(ARGS_DIGEST) { 428 isc_region_t r; 429 430 REQUIRE(rdata->type == dns_rdatatype_keydata); 431 432 dns_rdata_toregion(rdata, &r); 433 434 return ((digest)(arg, &r)); 435 } 436 437 static bool 438 checkowner_keydata(ARGS_CHECKOWNER) { 439 REQUIRE(type == dns_rdatatype_keydata); 440 441 UNUSED(name); 442 UNUSED(type); 443 UNUSED(rdclass); 444 UNUSED(wildcard); 445 446 return (true); 447 } 448 449 static bool 450 checknames_keydata(ARGS_CHECKNAMES) { 451 REQUIRE(rdata->type == dns_rdatatype_keydata); 452 453 UNUSED(rdata); 454 UNUSED(owner); 455 UNUSED(bad); 456 457 return (true); 458 } 459 460 static int 461 casecompare_keydata(ARGS_COMPARE) { 462 return (compare_keydata(rdata1, rdata2)); 463 } 464 465 #endif /* GENERIC_KEYDATA_65533_C */ 466