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