1 /* $OpenBSD: print.c,v 1.58 2024/11/13 12:51:04 tb Exp $ */ 2 /* 3 * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> 4 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <arpa/inet.h> 22 23 #include <err.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <time.h> 27 28 #include <openssl/evp.h> 29 30 #include "extern.h" 31 #include "json.h" 32 33 static const char * 34 pretty_key_id(const char *hex) 35 { 36 static char buf[128]; /* bigger than SHA_DIGEST_LENGTH * 3 */ 37 size_t i; 38 39 for (i = 0; i < sizeof(buf) && *hex != '\0'; i++) { 40 if (i % 3 == 2) 41 buf[i] = ':'; 42 else 43 buf[i] = *hex++; 44 } 45 if (i == sizeof(buf)) 46 memcpy(buf + sizeof(buf) - 4, "...", 4); 47 else 48 buf[i] = '\0'; 49 return buf; 50 } 51 52 char * 53 nid2str(int nid) 54 { 55 static char buf[128]; 56 const char *name; 57 58 if ((name = OBJ_nid2ln(nid)) == NULL) 59 name = OBJ_nid2sn(nid); 60 if (name == NULL) 61 name = "unknown"; 62 63 snprintf(buf, sizeof(buf), "nid %d (%s)", nid, name); 64 65 return buf; 66 } 67 68 const char * 69 purpose2str(enum cert_purpose purpose) 70 { 71 switch (purpose) { 72 case CERT_PURPOSE_INVALID: 73 return "invalid cert"; 74 case CERT_PURPOSE_TA: 75 return "TA cert"; 76 case CERT_PURPOSE_CA: 77 return "CA cert"; 78 case CERT_PURPOSE_EE: 79 return "EE cert"; 80 case CERT_PURPOSE_BGPSEC_ROUTER: 81 return "BGPsec Router cert"; 82 default: 83 return "unknown certificate purpose"; 84 } 85 } 86 87 char * 88 time2str(time_t t) 89 { 90 static char buf[64]; 91 struct tm tm; 92 93 if (gmtime_r(&t, &tm) == NULL) 94 return "could not convert time"; 95 96 strftime(buf, sizeof(buf), "%a %d %b %Y %T %z", &tm); 97 98 return buf; 99 } 100 101 void 102 tal_print(const struct tal *p) 103 { 104 char *ski; 105 const unsigned char *der; 106 X509_PUBKEY *pubkey; 107 size_t i; 108 109 der = p->pkey; 110 if ((pubkey = d2i_X509_PUBKEY(NULL, &der, p->pkeysz)) == NULL) 111 errx(1, "d2i_X509_PUBKEY failed"); 112 113 if ((ski = x509_pubkey_get_ski(pubkey, p->descr)) == NULL) 114 errx(1, "x509_pubkey_get_ski failed"); 115 116 if (outformats & FORMAT_JSON) { 117 json_do_string("type", "tal"); 118 json_do_string("name", p->descr); 119 json_do_string("ski", pretty_key_id(ski)); 120 json_do_array("trust_anchor_locations"); 121 for (i = 0; i < p->num_uris; i++) 122 json_do_string("tal", p->uri[i]); 123 json_do_end(); 124 } else { 125 printf("Trust anchor name: %s\n", p->descr); 126 printf("Subject key identifier: %s\n", pretty_key_id(ski)); 127 printf("Trust anchor locations: "); 128 for (i = 0; i < p->num_uris; i++) { 129 if (i > 0) 130 printf("%26s", ""); 131 printf("%s\n", p->uri[i]); 132 } 133 } 134 135 X509_PUBKEY_free(pubkey); 136 free(ski); 137 } 138 139 void 140 x509_print(const X509 *x) 141 { 142 const ASN1_INTEGER *xserial; 143 const X509_NAME *xissuer; 144 char *issuer = NULL; 145 char *serial = NULL; 146 147 if ((xissuer = X509_get_issuer_name(x)) == NULL) { 148 warnx("X509_get_issuer_name failed"); 149 goto out; 150 } 151 152 if ((issuer = X509_NAME_oneline(xissuer, NULL, 0)) == NULL) { 153 warnx("X509_NAME_oneline failed"); 154 goto out; 155 } 156 157 if ((xserial = X509_get0_serialNumber(x)) == NULL) { 158 warnx("X509_get0_serialNumber failed"); 159 goto out; 160 } 161 162 if ((serial = x509_convert_seqnum(__func__, "serial number", 163 xserial)) == NULL) 164 goto out; 165 166 if (outformats & FORMAT_JSON) { 167 json_do_string("cert_issuer", issuer); 168 json_do_string("cert_serial", serial); 169 } else { 170 printf("Certificate issuer: %s\n", issuer); 171 printf("Certificate serial: %s\n", serial); 172 } 173 174 out: 175 free(issuer); 176 free(serial); 177 } 178 179 static void 180 as_resources_print(struct cert_as *ases, size_t num_ases) 181 { 182 size_t i; 183 184 for (i = 0; i < num_ases; i++) { 185 if (outformats & FORMAT_JSON) 186 json_do_object("resource", 1); 187 switch (ases[i].type) { 188 case CERT_AS_ID: 189 if (outformats & FORMAT_JSON) { 190 json_do_uint("asid", ases[i].id); 191 } else { 192 if (i > 0) 193 printf("%26s", ""); 194 printf("AS: %u", ases[i].id); 195 } 196 break; 197 case CERT_AS_INHERIT: 198 if (outformats & FORMAT_JSON) { 199 json_do_bool("asid_inherit", 1); 200 } else { 201 if (i > 0) 202 printf("%26s", ""); 203 printf("AS: inherit"); 204 } 205 break; 206 case CERT_AS_RANGE: 207 if (outformats & FORMAT_JSON) { 208 json_do_object("asrange", 1); 209 json_do_uint("min", ases[i].range.min); 210 json_do_uint("max", ases[i].range.max); 211 json_do_end(); 212 } else { 213 if (i > 0) 214 printf("%26s", ""); 215 printf("AS: %u -- %u", ases[i].range.min, 216 ases[i].range.max); 217 } 218 break; 219 } 220 if (outformats & FORMAT_JSON) 221 json_do_end(); 222 else 223 printf("\n"); 224 } 225 } 226 227 static void 228 ip_resources_print(struct cert_ip *ips, size_t num_ips, size_t num_ases) 229 { 230 char buf1[64], buf2[64]; 231 size_t i; 232 int sockt; 233 234 for (i = 0; i < num_ips; i++) { 235 if (outformats & FORMAT_JSON) 236 json_do_object("resource", 1); 237 switch (ips[i].type) { 238 case CERT_IP_INHERIT: 239 if (outformats & FORMAT_JSON) { 240 json_do_bool("ip_inherit", 1); 241 } else { 242 if (i > 0 || num_ases > 0) 243 printf("%26s", ""); 244 printf("IP: inherit"); 245 } 246 break; 247 case CERT_IP_ADDR: 248 ip_addr_print(&ips[i].ip, ips[i].afi, buf1, 249 sizeof(buf1)); 250 if (outformats & FORMAT_JSON) { 251 json_do_string("ip_prefix", buf1); 252 } else { 253 if (i > 0 || num_ases > 0) 254 printf("%26s", ""); 255 printf("IP: %s", buf1); 256 } 257 break; 258 case CERT_IP_RANGE: 259 sockt = (ips[i].afi == AFI_IPV4) ? 260 AF_INET : AF_INET6; 261 inet_ntop(sockt, ips[i].min, buf1, sizeof(buf1)); 262 inet_ntop(sockt, ips[i].max, buf2, sizeof(buf2)); 263 if (outformats & FORMAT_JSON) { 264 json_do_object("ip_range", 1); 265 json_do_string("min", buf1); 266 json_do_string("max", buf2); 267 json_do_end(); 268 } else { 269 if (i > 0 || num_ases > 0) 270 printf("%26s", ""); 271 printf("IP: %s -- %s", buf1, buf2); 272 } 273 break; 274 } 275 if (outformats & FORMAT_JSON) 276 json_do_end(); 277 else 278 printf("\n"); 279 } 280 } 281 282 void 283 cert_print(const struct cert *p) 284 { 285 if (outformats & FORMAT_JSON) { 286 if (p->pubkey != NULL) 287 json_do_string("type", "router_key"); 288 else 289 json_do_string("type", "ca_cert"); 290 json_do_string("ski", pretty_key_id(p->ski)); 291 if (p->aki != NULL) 292 json_do_string("aki", pretty_key_id(p->aki)); 293 x509_print(p->x509); 294 if (p->aia != NULL) 295 json_do_string("aia", p->aia); 296 if (p->mft != NULL) 297 json_do_string("manifest", p->mft); 298 if (p->repo != NULL) 299 json_do_string("carepository", p->repo); 300 if (p->notify != NULL) 301 json_do_string("notify_url", p->notify); 302 if (p->pubkey != NULL) 303 json_do_string("router_key", p->pubkey); 304 json_do_int("valid_since", p->notbefore); 305 json_do_int("valid_until", p->notafter); 306 if (p->expires) 307 json_do_int("expires", p->expires); 308 json_do_array("subordinate_resources"); 309 } else { 310 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 311 if (p->aki != NULL) 312 printf("Authority key identifier: %s\n", 313 pretty_key_id(p->aki)); 314 x509_print(p->x509); 315 if (p->aia != NULL) 316 printf("Authority info access: %s\n", p->aia); 317 if (p->mft != NULL) 318 printf("Manifest: %s\n", p->mft); 319 if (p->repo != NULL) 320 printf("caRepository: %s\n", p->repo); 321 if (p->notify != NULL) 322 printf("Notify URL: %s\n", p->notify); 323 if (p->pubkey != NULL) { 324 printf("BGPsec ECDSA public key: %s\n", 325 p->pubkey); 326 printf("Router key not before: %s\n", 327 time2str(p->notbefore)); 328 printf("Router key not after: %s\n", 329 time2str(p->notafter)); 330 } else { 331 printf("Certificate not before: %s\n", 332 time2str(p->notbefore)); 333 printf("Certificate not after: %s\n", 334 time2str(p->notafter)); 335 } 336 printf("Subordinate resources: "); 337 } 338 339 as_resources_print(p->ases, p->num_ases); 340 ip_resources_print(p->ips, p->num_ips, p->num_ases); 341 342 if (outformats & FORMAT_JSON) 343 json_do_end(); 344 } 345 346 static char * 347 crl_parse_number(const X509_CRL *x509_crl) 348 { 349 ASN1_INTEGER *aint = NULL; 350 int crit; 351 char *s = NULL; 352 353 aint = X509_CRL_get_ext_d2i(x509_crl, NID_crl_number, &crit, NULL); 354 if (aint == NULL) { 355 if (crit != -1) 356 warnx("%s: RFC 6487, section 5: " 357 "failed to parse CRL number", __func__); 358 else 359 warnx("%s: RFC 6487, section 5: missing CRL number", 360 __func__); 361 goto out; 362 } 363 if (crit != 0) { 364 warnx("%s: RFC 6487, section 5: CRL number not non-critical", 365 __func__); 366 goto out; 367 } 368 369 s = x509_convert_seqnum(__func__, "CRL Number", aint); 370 371 out: 372 ASN1_INTEGER_free(aint); 373 return s; 374 } 375 376 void 377 crl_print(const struct crl *p) 378 { 379 STACK_OF(X509_REVOKED) *revlist; 380 X509_REVOKED *rev; 381 X509_NAME *xissuer; 382 int i; 383 char *issuer, *serial; 384 time_t t; 385 386 if (outformats & FORMAT_JSON) { 387 json_do_string("type", "crl"); 388 json_do_string("aki", pretty_key_id(p->aki)); 389 } else 390 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 391 392 xissuer = X509_CRL_get_issuer(p->x509_crl); 393 issuer = X509_NAME_oneline(xissuer, NULL, 0); 394 if (issuer != NULL) { 395 char *number; 396 397 if ((number = crl_parse_number(p->x509_crl)) != NULL) { 398 if (outformats & FORMAT_JSON) { 399 json_do_string("crl_issuer", issuer); 400 json_do_string("crl_serial", number); 401 } else { 402 printf("CRL issuer: %s\n", 403 issuer); 404 printf("CRL serial number: %s\n", 405 number); 406 } 407 free(number); 408 } 409 } 410 free(issuer); 411 412 if (outformats & FORMAT_JSON) { 413 json_do_int("valid_since", p->thisupdate); 414 json_do_int("valid_until", p->nextupdate); 415 json_do_array("revoked_certs"); 416 } else { 417 printf("CRL this update: %s\n", 418 time2str(p->thisupdate)); 419 printf("CRL next update: %s\n", 420 time2str(p->nextupdate)); 421 printf("Revoked Certificates:\n"); 422 } 423 424 revlist = X509_CRL_get_REVOKED(p->x509_crl); 425 for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) { 426 rev = sk_X509_REVOKED_value(revlist, i); 427 serial = x509_convert_seqnum(__func__, "serial number", 428 X509_REVOKED_get0_serialNumber(rev)); 429 x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t); 430 if (serial != NULL) { 431 if (outformats & FORMAT_JSON) { 432 json_do_object("cert", 1); 433 json_do_string("serial", serial); 434 json_do_string("date", time2str(t)); 435 json_do_end(); 436 } else 437 printf("%25s Serial: %8s Revocation Date: %s" 438 "\n", "", serial, time2str(t)); 439 } 440 free(serial); 441 } 442 443 if (outformats & FORMAT_JSON) 444 json_do_end(); 445 else if (i == 0) 446 printf("No Revoked Certificates\n"); 447 } 448 449 void 450 mft_print(const X509 *x, const struct mft *p) 451 { 452 size_t i; 453 char *hash; 454 455 if (outformats & FORMAT_JSON) { 456 json_do_string("type", "manifest"); 457 json_do_string("ski", pretty_key_id(p->ski)); 458 x509_print(x); 459 json_do_string("aki", pretty_key_id(p->aki)); 460 json_do_string("aia", p->aia); 461 json_do_string("sia", p->sia); 462 json_do_string("manifest_number", p->seqnum); 463 if (p->signtime != 0) 464 json_do_int("signing_time", p->signtime); 465 json_do_int("valid_since", p->thisupdate); 466 json_do_int("valid_until", p->nextupdate); 467 if (p->expires) 468 json_do_int("expires", p->expires); 469 } else { 470 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 471 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 472 x509_print(x); 473 printf("Authority info access: %s\n", p->aia); 474 printf("Subject info access: %s\n", p->sia); 475 printf("Manifest number: %s\n", p->seqnum); 476 if (p->signtime != 0) 477 printf("Signing time: %s\n", 478 time2str(p->signtime)); 479 printf("Manifest this update: %s\n", time2str(p->thisupdate)); 480 printf("Manifest next update: %s\n", time2str(p->nextupdate)); 481 printf("Files and hashes: "); 482 } 483 484 if (outformats & FORMAT_JSON) 485 json_do_array("filesandhashes"); 486 for (i = 0; i < p->filesz; i++) { 487 if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash), 488 &hash) == -1) 489 errx(1, "base64_encode failure"); 490 491 if (outformats & FORMAT_JSON) { 492 json_do_object("filehash", 1); 493 json_do_string("filename", p->files[i].file); 494 json_do_string("hash", hash); 495 json_do_end(); 496 } else { 497 if (i > 0) 498 printf("%26s", ""); 499 printf("%zu: %s (hash: %s)\n", i + 1, p->files[i].file, 500 hash); 501 } 502 503 free(hash); 504 } 505 if (outformats & FORMAT_JSON) 506 json_do_end(); 507 } 508 509 void 510 roa_print(const X509 *x, const struct roa *p) 511 { 512 char buf[128]; 513 size_t i; 514 515 if (outformats & FORMAT_JSON) { 516 json_do_string("type", "roa"); 517 json_do_string("ski", pretty_key_id(p->ski)); 518 x509_print(x); 519 json_do_string("aki", pretty_key_id(p->aki)); 520 json_do_string("aia", p->aia); 521 json_do_string("sia", p->sia); 522 if (p->signtime != 0) 523 json_do_int("signing_time", p->signtime); 524 json_do_int("valid_since", p->notbefore); 525 json_do_int("valid_until", p->notafter); 526 if (p->expires) 527 json_do_int("expires", p->expires); 528 } else { 529 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 530 x509_print(x); 531 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 532 printf("Authority info access: %s\n", p->aia); 533 printf("Subject info access: %s\n", p->sia); 534 if (p->signtime != 0) 535 printf("Signing time: %s\n", 536 time2str(p->signtime)); 537 printf("ROA not before: %s\n", 538 time2str(p->notbefore)); 539 printf("ROA not after: %s\n", time2str(p->notafter)); 540 printf("asID: %u\n", p->asid); 541 printf("IP address blocks: "); 542 } 543 544 if (outformats & FORMAT_JSON) 545 json_do_array("vrps"); 546 for (i = 0; i < p->num_ips; i++) { 547 ip_addr_print(&p->ips[i].addr, p->ips[i].afi, buf, sizeof(buf)); 548 549 if (outformats & FORMAT_JSON) { 550 json_do_object("vrp", 1); 551 json_do_string("prefix", buf); 552 json_do_uint("asid", p->asid); 553 json_do_uint("maxlen", p->ips[i].maxlength); 554 json_do_end(); 555 } else { 556 if (i > 0) 557 printf("%26s", ""); 558 printf("%s maxlen: %hhu\n", buf, p->ips[i].maxlength); 559 } 560 } 561 if (outformats & FORMAT_JSON) 562 json_do_end(); 563 } 564 565 void 566 spl_print(const X509 *x, const struct spl *s) 567 { 568 char buf[128]; 569 size_t i; 570 571 if (outformats & FORMAT_JSON) { 572 json_do_string("type", "spl"); 573 json_do_string("ski", pretty_key_id(s->ski)); 574 x509_print(x); 575 json_do_string("aki", pretty_key_id(s->aki)); 576 json_do_string("aia", s->aia); 577 json_do_string("sia", s->sia); 578 if (s->signtime != 0) 579 json_do_int("signing_time", s->signtime); 580 json_do_int("valid_since", s->notbefore); 581 json_do_int("valid_until", s->notafter); 582 if (s->expires) 583 json_do_int("expires", s->expires); 584 json_do_int("asid", s->asid); 585 } else { 586 printf("Subject key identifier: %s\n", pretty_key_id(s->ski)); 587 x509_print(x); 588 printf("Authority key identifier: %s\n", pretty_key_id(s->aki)); 589 printf("Authority info access: %s\n", s->aia); 590 printf("Subject info access: %s\n", s->sia); 591 if (s->signtime != 0) 592 printf("Signing time: %s\n", 593 time2str(s->signtime)); 594 printf("SPL not before: %s\n", 595 time2str(s->notbefore)); 596 printf("SPL not after: %s\n", time2str(s->notafter)); 597 printf("asID: %u\n", s->asid); 598 printf("Originated IP Prefixes: "); 599 } 600 601 if (outformats & FORMAT_JSON) 602 json_do_array("prefixes"); 603 for (i = 0; i < s->num_prefixes; i++) { 604 ip_addr_print(&s->prefixes[i].prefix, s->prefixes[i].afi, buf, 605 sizeof(buf)); 606 607 if (outformats & FORMAT_JSON) { 608 json_do_string("prefix", buf); 609 } else { 610 if (i > 0) 611 printf("%26s", ""); 612 printf("%s\n", buf); 613 } 614 } 615 if (outformats & FORMAT_JSON) 616 json_do_end(); 617 } 618 619 void 620 gbr_print(const X509 *x, const struct gbr *p) 621 { 622 if (outformats & FORMAT_JSON) { 623 json_do_string("type", "gbr"); 624 json_do_string("ski", pretty_key_id(p->ski)); 625 x509_print(x); 626 json_do_string("aki", pretty_key_id(p->aki)); 627 json_do_string("aia", p->aia); 628 json_do_string("sia", p->sia); 629 if (p->signtime != 0) 630 json_do_int("signing_time", p->signtime); 631 json_do_int("valid_since", p->notbefore); 632 json_do_int("valid_until", p->notafter); 633 if (p->expires) 634 json_do_int("expires", p->expires); 635 json_do_string("vcard", p->vcard); 636 } else { 637 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 638 x509_print(x); 639 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 640 printf("Authority info access: %s\n", p->aia); 641 printf("Subject info access: %s\n", p->sia); 642 if (p->signtime != 0) 643 printf("Signing time: %s\n", 644 time2str(p->signtime)); 645 printf("GBR not before: %s\n", 646 time2str(p->notbefore)); 647 printf("GBR not after: %s\n", time2str(p->notafter)); 648 printf("vcard:\n%s", p->vcard); 649 } 650 } 651 652 void 653 rsc_print(const X509 *x, const struct rsc *p) 654 { 655 char *hash; 656 size_t i; 657 658 if (outformats & FORMAT_JSON) { 659 json_do_string("type", "rsc"); 660 json_do_string("ski", pretty_key_id(p->ski)); 661 x509_print(x); 662 json_do_string("aki", pretty_key_id(p->aki)); 663 json_do_string("aia", p->aia); 664 if (p->signtime != 0) 665 json_do_int("signing_time", p->signtime); 666 json_do_int("valid_since", p->notbefore); 667 json_do_int("valid_until", p->notafter); 668 if (p->expires) 669 json_do_int("expires", p->expires); 670 json_do_array("signed_with_resources"); 671 } else { 672 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 673 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 674 x509_print(x); 675 printf("Authority info access: %s\n", p->aia); 676 if (p->signtime != 0) 677 printf("Signing time: %s\n", 678 time2str(p->signtime)); 679 printf("RSC not before: %s\n", 680 time2str(p->notbefore)); 681 printf("RSC not after: %s\n", time2str(p->notafter)); 682 printf("Signed with resources: "); 683 } 684 685 as_resources_print(p->ases, p->num_ases); 686 ip_resources_print(p->ips, p->num_ips, p->num_ases); 687 688 if (outformats & FORMAT_JSON) { 689 json_do_end(); 690 json_do_array("filenamesandhashes"); 691 } else 692 printf("Filenames and hashes: "); 693 694 for (i = 0; i < p->num_files; i++) { 695 if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash), 696 &hash) == -1) 697 errx(1, "base64_encode failure"); 698 699 if (outformats & FORMAT_JSON) { 700 json_do_object("filehash", 1); 701 if (p->files[i].filename) 702 json_do_string("filename", 703 p->files[i].filename); 704 json_do_string("hash_digest", hash); 705 json_do_end(); 706 } else { 707 if (i > 0) 708 printf("%26s", ""); 709 printf("%zu: %s (hash: %s)\n", i + 1, 710 p->files[i].filename ? p->files[i].filename 711 : "no filename", hash); 712 } 713 714 free(hash); 715 } 716 717 if (outformats & FORMAT_JSON) 718 json_do_end(); 719 } 720 721 void 722 aspa_print(const X509 *x, const struct aspa *p) 723 { 724 size_t i; 725 726 if (outformats & FORMAT_JSON) { 727 json_do_string("type", "aspa"); 728 json_do_string("ski", pretty_key_id(p->ski)); 729 x509_print(x); 730 json_do_string("aki", pretty_key_id(p->aki)); 731 json_do_string("aia", p->aia); 732 json_do_string("sia", p->sia); 733 if (p->signtime != 0) 734 json_do_int("signing_time", p->signtime); 735 json_do_int("valid_since", p->notbefore); 736 json_do_int("valid_until", p->notafter); 737 if (p->expires) 738 json_do_int("expires", p->expires); 739 json_do_uint("customer_asid", p->custasid); 740 json_do_array("providers"); 741 } else { 742 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 743 x509_print(x); 744 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 745 printf("Authority info access: %s\n", p->aia); 746 printf("Subject info access: %s\n", p->sia); 747 if (p->signtime != 0) 748 printf("Signing time: %s\n", 749 time2str(p->signtime)); 750 printf("ASPA not before: %s\n", 751 time2str(p->notbefore)); 752 printf("ASPA not after: %s\n", time2str(p->notafter)); 753 printf("Customer ASID: %u\n", p->custasid); 754 printf("Providers: "); 755 } 756 757 for (i = 0; i < p->num_providers; i++) { 758 if (outformats & FORMAT_JSON) 759 json_do_uint("asid", p->providers[i]); 760 else { 761 if (i > 0) 762 printf("%26s", ""); 763 printf("AS: %u\n", p->providers[i]); 764 } 765 } 766 767 if (outformats & FORMAT_JSON) 768 json_do_end(); 769 } 770 771 static void 772 takey_print(char *name, const struct takey *t) 773 { 774 char *spki = NULL; 775 size_t i, j = 0; 776 777 if (base64_encode(t->pubkey, t->pubkeysz, &spki) != 0) 778 errx(1, "base64_encode failed in %s", __func__); 779 780 if (outformats & FORMAT_JSON) { 781 json_do_object("takey", 0); 782 json_do_string("name", name); 783 json_do_array("comments"); 784 for (i = 0; i < t->num_comments; i++) 785 json_do_string("comment", t->comments[i]); 786 json_do_end(); 787 json_do_array("uris"); 788 for (i = 0; i < t->num_uris; i++) 789 json_do_string("uri", t->uris[i]); 790 json_do_end(); 791 json_do_string("spki", spki); 792 json_do_end(); 793 } else { 794 printf("TAL derived from the '%s' Trust Anchor Key:\n\n", name); 795 796 for (i = 0; i < t->num_comments; i++) 797 printf("\t# %s\n", t->comments[i]); 798 if (t->num_comments > 0) 799 printf("\n"); 800 for (i = 0; i < t->num_uris; i++) 801 printf("\t%s\n", t->uris[i]); 802 printf("\n\t"); 803 for (i = 0; i < strlen(spki); i++) { 804 printf("%c", spki[i]); 805 if ((++j % 64) == 0) 806 printf("\n\t"); 807 } 808 printf("\n\n"); 809 } 810 811 free(spki); 812 } 813 814 void 815 tak_print(const X509 *x, const struct tak *p) 816 { 817 if (outformats & FORMAT_JSON) { 818 json_do_string("type", "tak"); 819 json_do_string("ski", pretty_key_id(p->ski)); 820 x509_print(x); 821 json_do_string("aki", pretty_key_id(p->aki)); 822 json_do_string("aia", p->aia); 823 json_do_string("sia", p->sia); 824 if (p->signtime != 0) 825 json_do_int("signing_time", p->signtime); 826 json_do_int("valid_since", p->notbefore); 827 json_do_int("valid_until", p->notafter); 828 if (p->expires) 829 json_do_int("expires", p->expires); 830 json_do_array("takeys"); 831 } else { 832 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 833 x509_print(x); 834 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 835 printf("Authority info access: %s\n", p->aia); 836 printf("Subject info access: %s\n", p->sia); 837 if (p->signtime != 0) 838 printf("Signing time: %s\n", 839 time2str(p->signtime)); 840 printf("TAK not before: %s\n", 841 time2str(p->notbefore)); 842 printf("TAK not after: %s\n", time2str(p->notafter)); 843 } 844 845 takey_print("current", p->current); 846 if (p->predecessor != NULL) 847 takey_print("predecessor", p->predecessor); 848 if (p->successor != NULL) 849 takey_print("successor", p->successor); 850 851 if (outformats & FORMAT_JSON) 852 json_do_end(); 853 } 854 855 void 856 geofeed_print(const X509 *x, const struct geofeed *p) 857 { 858 char buf[128]; 859 size_t i; 860 861 if (outformats & FORMAT_JSON) { 862 json_do_string("type", "geofeed"); 863 json_do_string("ski", pretty_key_id(p->ski)); 864 x509_print(x); 865 json_do_string("aki", pretty_key_id(p->aki)); 866 json_do_string("aia", p->aia); 867 if (p->signtime != 0) 868 json_do_int("signing_time", p->signtime); 869 json_do_int("valid_since", p->notbefore); 870 json_do_int("valid_until", p->notafter); 871 if (p->expires) 872 json_do_int("expires", p->expires); 873 json_do_array("records"); 874 } else { 875 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 876 x509_print(x); 877 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 878 printf("Authority info access: %s\n", p->aia); 879 if (p->signtime != 0) 880 printf("Signing time: %s\n", 881 time2str(p->signtime)); 882 printf("Geofeed not before: %s\n", 883 time2str(p->notbefore)); 884 printf("Geofeed not after: %s\n", time2str(p->notafter)); 885 printf("Geofeed CSV records: "); 886 } 887 888 for (i = 0; i < p->num_geoips; i++) { 889 if (p->geoips[i].ip->type != CERT_IP_ADDR) 890 continue; 891 892 ip_addr_print(&p->geoips[i].ip->ip, p->geoips[i].ip->afi, buf, 893 sizeof(buf)); 894 if (outformats & FORMAT_JSON) { 895 json_do_object("geoip", 1); 896 json_do_string("prefix", buf); 897 json_do_string("location", p->geoips[i].loc); 898 json_do_end(); 899 } else { 900 if (i > 0) 901 printf("%26s", ""); 902 printf("IP: %s (%s)\n", buf, p->geoips[i].loc); 903 } 904 } 905 906 if (outformats & FORMAT_JSON) 907 json_do_end(); 908 } 909