1/* $OpenBSD: print.c,v 1.55 2024/06/08 13:30:35 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 33static const char * 34pretty_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 52char * 53nid2str(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 68const char * 69purpose2str(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 87char * 88time2str(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 101void 102tal_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->urisz; 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->urisz; 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 139void 140x509_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__, xserial)) == NULL) 163 goto out; 164 165 if (outformats & FORMAT_JSON) { 166 json_do_string("cert_issuer", issuer); 167 json_do_string("cert_serial", serial); 168 } else { 169 printf("Certificate issuer: %s\n", issuer); 170 printf("Certificate serial: %s\n", serial); 171 } 172 173 out: 174 free(issuer); 175 free(serial); 176} 177 178static void 179as_resources_print(struct cert_as *as, size_t asz) 180{ 181 size_t i; 182 183 for (i = 0; i < asz; i++) { 184 if (outformats & FORMAT_JSON) 185 json_do_object("resource", 1); 186 switch (as[i].type) { 187 case CERT_AS_ID: 188 if (outformats & FORMAT_JSON) { 189 json_do_uint("asid", as[i].id); 190 } else { 191 if (i > 0) 192 printf("%26s", ""); 193 printf("AS: %u", as[i].id); 194 } 195 break; 196 case CERT_AS_INHERIT: 197 if (outformats & FORMAT_JSON) { 198 json_do_bool("asid_inherit", 1); 199 } else { 200 if (i > 0) 201 printf("%26s", ""); 202 printf("AS: inherit"); 203 } 204 break; 205 case CERT_AS_RANGE: 206 if (outformats & FORMAT_JSON) { 207 json_do_object("asrange", 1); 208 json_do_uint("min", as[i].range.min); 209 json_do_uint("max", as[i].range.max); 210 json_do_end(); 211 } else { 212 if (i > 0) 213 printf("%26s", ""); 214 printf("AS: %u -- %u", as[i].range.min, 215 as[i].range.max); 216 } 217 break; 218 } 219 if (outformats & FORMAT_JSON) 220 json_do_end(); 221 else 222 printf("\n"); 223 } 224} 225 226static void 227ip_resources_print(struct cert_ip *ips, size_t ipsz, size_t asz) 228{ 229 char buf1[64], buf2[64]; 230 size_t i; 231 int sockt; 232 233 for (i = 0; i < ipsz; i++) { 234 if (outformats & FORMAT_JSON) 235 json_do_object("resource", 1); 236 switch (ips[i].type) { 237 case CERT_IP_INHERIT: 238 if (outformats & FORMAT_JSON) { 239 json_do_bool("ip_inherit", 1); 240 } else { 241 if (i > 0 || asz > 0) 242 printf("%26s", ""); 243 printf("IP: inherit"); 244 } 245 break; 246 case CERT_IP_ADDR: 247 ip_addr_print(&ips[i].ip, ips[i].afi, buf1, 248 sizeof(buf1)); 249 if (outformats & FORMAT_JSON) { 250 json_do_string("ip_prefix", buf1); 251 } else { 252 if (i > 0 || asz > 0) 253 printf("%26s", ""); 254 printf("IP: %s", buf1); 255 } 256 break; 257 case CERT_IP_RANGE: 258 sockt = (ips[i].afi == AFI_IPV4) ? 259 AF_INET : AF_INET6; 260 inet_ntop(sockt, ips[i].min, buf1, sizeof(buf1)); 261 inet_ntop(sockt, ips[i].max, buf2, sizeof(buf2)); 262 if (outformats & FORMAT_JSON) { 263 json_do_object("ip_range", 1); 264 json_do_string("min", buf1); 265 json_do_string("max", buf2); 266 json_do_end(); 267 } else { 268 if (i > 0 || asz > 0) 269 printf("%26s", ""); 270 printf("IP: %s -- %s", buf1, buf2); 271 } 272 break; 273 } 274 if (outformats & FORMAT_JSON) 275 json_do_end(); 276 else 277 printf("\n"); 278 } 279} 280 281void 282cert_print(const struct cert *p) 283{ 284 if (outformats & FORMAT_JSON) { 285 if (p->pubkey != NULL) 286 json_do_string("type", "router_key"); 287 else 288 json_do_string("type", "ca_cert"); 289 json_do_string("ski", pretty_key_id(p->ski)); 290 if (p->aki != NULL) 291 json_do_string("aki", pretty_key_id(p->aki)); 292 x509_print(p->x509); 293 if (p->aia != NULL) 294 json_do_string("aia", p->aia); 295 if (p->mft != NULL) 296 json_do_string("manifest", p->mft); 297 if (p->repo != NULL) 298 json_do_string("carepository", p->repo); 299 if (p->notify != NULL) 300 json_do_string("notify_url", p->notify); 301 if (p->pubkey != NULL) 302 json_do_string("router_key", p->pubkey); 303 json_do_int("valid_since", p->notbefore); 304 json_do_int("valid_until", p->notafter); 305 if (p->expires) 306 json_do_int("expires", p->expires); 307 json_do_array("subordinate_resources"); 308 } else { 309 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 310 if (p->aki != NULL) 311 printf("Authority key identifier: %s\n", 312 pretty_key_id(p->aki)); 313 x509_print(p->x509); 314 if (p->aia != NULL) 315 printf("Authority info access: %s\n", p->aia); 316 if (p->mft != NULL) 317 printf("Manifest: %s\n", p->mft); 318 if (p->repo != NULL) 319 printf("caRepository: %s\n", p->repo); 320 if (p->notify != NULL) 321 printf("Notify URL: %s\n", p->notify); 322 if (p->pubkey != NULL) { 323 printf("BGPsec ECDSA public key: %s\n", 324 p->pubkey); 325 printf("Router key not before: %s\n", 326 time2str(p->notbefore)); 327 printf("Router key not after: %s\n", 328 time2str(p->notafter)); 329 } else { 330 printf("Certificate not before: %s\n", 331 time2str(p->notbefore)); 332 printf("Certificate not after: %s\n", 333 time2str(p->notafter)); 334 } 335 printf("Subordinate resources: "); 336 } 337 338 as_resources_print(p->as, p->asz); 339 ip_resources_print(p->ips, p->ipsz, p->asz); 340 341 if (outformats & FORMAT_JSON) 342 json_do_end(); 343} 344 345/* 346 * XXX - dedup with x509_convert_seqnum()? 347 */ 348static char * 349crl_parse_number(const X509_CRL *x509_crl) 350{ 351 ASN1_INTEGER *aint = NULL; 352 int crit; 353 BIGNUM *seqnum = NULL; 354 char *s = NULL; 355 356 aint = X509_CRL_get_ext_d2i(x509_crl, NID_crl_number, &crit, NULL); 357 if (aint == NULL) { 358 if (crit != -1) 359 warnx("failed to parse CRL Number"); 360 else 361 warnx("CRL Number missing"); 362 goto out; 363 } 364 365 if (ASN1_STRING_length(aint) > 20) 366 warnx("CRL Number should fit in 20 octets"); 367 368 seqnum = ASN1_INTEGER_to_BN(aint, NULL); 369 if (seqnum == NULL) { 370 warnx("CRL Number: ASN1_INTEGER_to_BN error"); 371 goto out; 372 } 373 374 if (BN_is_negative(seqnum)) 375 warnx("CRL Number should be positive"); 376 377 s = BN_bn2hex(seqnum); 378 if (s == NULL) 379 warnx("CRL Number: BN_bn2hex error"); 380 381 out: 382 ASN1_INTEGER_free(aint); 383 BN_free(seqnum); 384 return s; 385} 386 387void 388crl_print(const struct crl *p) 389{ 390 STACK_OF(X509_REVOKED) *revlist; 391 X509_REVOKED *rev; 392 X509_NAME *xissuer; 393 int i; 394 char *issuer, *serial; 395 time_t t; 396 397 if (outformats & FORMAT_JSON) { 398 json_do_string("type", "crl"); 399 json_do_string("aki", pretty_key_id(p->aki)); 400 } else 401 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 402 403 xissuer = X509_CRL_get_issuer(p->x509_crl); 404 issuer = X509_NAME_oneline(xissuer, NULL, 0); 405 if (issuer != NULL) { 406 char *number; 407 408 if ((number = crl_parse_number(p->x509_crl)) != NULL) { 409 if (outformats & FORMAT_JSON) { 410 json_do_string("crl_issuer", issuer); 411 json_do_string("crl_serial", number); 412 } else { 413 printf("CRL issuer: %s\n", 414 issuer); 415 printf("CRL serial number: %s\n", 416 number); 417 } 418 free(number); 419 } 420 } 421 free(issuer); 422 423 if (outformats & FORMAT_JSON) { 424 json_do_int("valid_since", p->thisupdate); 425 json_do_int("valid_until", p->nextupdate); 426 json_do_array("revoked_certs"); 427 } else { 428 printf("CRL this update: %s\n", 429 time2str(p->thisupdate)); 430 printf("CRL next update: %s\n", 431 time2str(p->nextupdate)); 432 printf("Revoked Certificates:\n"); 433 } 434 435 revlist = X509_CRL_get_REVOKED(p->x509_crl); 436 for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) { 437 rev = sk_X509_REVOKED_value(revlist, i); 438 serial = x509_convert_seqnum(__func__, 439 X509_REVOKED_get0_serialNumber(rev)); 440 x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t); 441 if (serial != NULL) { 442 if (outformats & FORMAT_JSON) { 443 json_do_object("cert", 1); 444 json_do_string("serial", serial); 445 json_do_string("date", time2str(t)); 446 json_do_end(); 447 } else 448 printf("%25s Serial: %8s Revocation Date: %s" 449 "\n", "", serial, time2str(t)); 450 } 451 free(serial); 452 } 453 454 if (outformats & FORMAT_JSON) 455 json_do_end(); 456 else if (i == 0) 457 printf("No Revoked Certificates\n"); 458} 459 460void 461mft_print(const X509 *x, const struct mft *p) 462{ 463 size_t i; 464 char *hash; 465 466 if (outformats & FORMAT_JSON) { 467 json_do_string("type", "manifest"); 468 json_do_string("ski", pretty_key_id(p->ski)); 469 x509_print(x); 470 json_do_string("aki", pretty_key_id(p->aki)); 471 json_do_string("aia", p->aia); 472 json_do_string("sia", p->sia); 473 json_do_string("manifest_number", p->seqnum); 474 if (p->signtime != 0) 475 json_do_int("signing_time", p->signtime); 476 json_do_int("valid_since", p->thisupdate); 477 json_do_int("valid_until", p->nextupdate); 478 if (p->expires) 479 json_do_int("expires", p->expires); 480 } else { 481 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 482 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 483 x509_print(x); 484 printf("Authority info access: %s\n", p->aia); 485 printf("Subject info access: %s\n", p->sia); 486 printf("Manifest number: %s\n", p->seqnum); 487 if (p->signtime != 0) 488 printf("Signing time: %s\n", 489 time2str(p->signtime)); 490 printf("Manifest this update: %s\n", time2str(p->thisupdate)); 491 printf("Manifest next update: %s\n", time2str(p->nextupdate)); 492 printf("Files and hashes: "); 493 } 494 495 if (outformats & FORMAT_JSON) 496 json_do_array("filesandhashes"); 497 for (i = 0; i < p->filesz; i++) { 498 if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash), 499 &hash) == -1) 500 errx(1, "base64_encode failure"); 501 502 if (outformats & FORMAT_JSON) { 503 json_do_object("filehash", 1); 504 json_do_string("filename", p->files[i].file); 505 json_do_string("hash", hash); 506 json_do_end(); 507 } else { 508 if (i > 0) 509 printf("%26s", ""); 510 printf("%zu: %s (hash: %s)\n", i + 1, p->files[i].file, 511 hash); 512 } 513 514 free(hash); 515 } 516 if (outformats & FORMAT_JSON) 517 json_do_end(); 518} 519 520void 521roa_print(const X509 *x, const struct roa *p) 522{ 523 char buf[128]; 524 size_t i; 525 526 if (outformats & FORMAT_JSON) { 527 json_do_string("type", "roa"); 528 json_do_string("ski", pretty_key_id(p->ski)); 529 x509_print(x); 530 json_do_string("aki", pretty_key_id(p->aki)); 531 json_do_string("aia", p->aia); 532 json_do_string("sia", p->sia); 533 if (p->signtime != 0) 534 json_do_int("signing_time", p->signtime); 535 json_do_int("valid_since", p->notbefore); 536 json_do_int("valid_until", p->notafter); 537 if (p->expires) 538 json_do_int("expires", p->expires); 539 } else { 540 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 541 x509_print(x); 542 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 543 printf("Authority info access: %s\n", p->aia); 544 printf("Subject info access: %s\n", p->sia); 545 if (p->signtime != 0) 546 printf("Signing time: %s\n", 547 time2str(p->signtime)); 548 printf("ROA not before: %s\n", 549 time2str(p->notbefore)); 550 printf("ROA not after: %s\n", time2str(p->notafter)); 551 printf("asID: %u\n", p->asid); 552 printf("IP address blocks: "); 553 } 554 555 if (outformats & FORMAT_JSON) 556 json_do_array("vrps"); 557 for (i = 0; i < p->ipsz; i++) { 558 ip_addr_print(&p->ips[i].addr, 559 p->ips[i].afi, buf, sizeof(buf)); 560 561 if (outformats & FORMAT_JSON) { 562 json_do_object("vrp", 1); 563 json_do_string("prefix", buf); 564 json_do_uint("asid", p->asid); 565 json_do_uint("maxlen", p->ips[i].maxlength); 566 json_do_end(); 567 } else { 568 if (i > 0) 569 printf("%26s", ""); 570 printf("%s maxlen: %hhu\n", buf, p->ips[i].maxlength); 571 } 572 } 573 if (outformats & FORMAT_JSON) 574 json_do_end(); 575} 576 577void 578spl_print(const X509 *x, const struct spl *s) 579{ 580 char buf[128]; 581 size_t i; 582 583 if (outformats & FORMAT_JSON) { 584 json_do_string("type", "spl"); 585 json_do_string("ski", pretty_key_id(s->ski)); 586 x509_print(x); 587 json_do_string("aki", pretty_key_id(s->aki)); 588 json_do_string("aia", s->aia); 589 json_do_string("sia", s->sia); 590 if (s->signtime != 0) 591 json_do_int("signing_time", s->signtime); 592 json_do_int("valid_since", s->notbefore); 593 json_do_int("valid_until", s->notafter); 594 if (s->expires) 595 json_do_int("expires", s->expires); 596 json_do_int("asid", s->asid); 597 } else { 598 printf("Subject key identifier: %s\n", pretty_key_id(s->ski)); 599 x509_print(x); 600 printf("Authority key identifier: %s\n", pretty_key_id(s->aki)); 601 printf("Authority info access: %s\n", s->aia); 602 printf("Subject info access: %s\n", s->sia); 603 if (s->signtime != 0) 604 printf("Signing time: %s\n", 605 time2str(s->signtime)); 606 printf("SPL not before: %s\n", 607 time2str(s->notbefore)); 608 printf("SPL not after: %s\n", time2str(s->notafter)); 609 printf("asID: %u\n", s->asid); 610 printf("Originated IP Prefixes: "); 611 } 612 613 if (outformats & FORMAT_JSON) 614 json_do_array("prefixes"); 615 for (i = 0; i < s->pfxsz; i++) { 616 ip_addr_print(&s->pfxs[i].prefix, s->pfxs[i].afi, buf, 617 sizeof(buf)); 618 619 if (outformats & FORMAT_JSON) { 620 json_do_string("prefix", buf); 621 } else { 622 if (i > 0) 623 printf("%26s", ""); 624 printf("%s\n", buf); 625 } 626 } 627 if (outformats & FORMAT_JSON) 628 json_do_end(); 629} 630 631void 632gbr_print(const X509 *x, const struct gbr *p) 633{ 634 if (outformats & FORMAT_JSON) { 635 json_do_string("type", "gbr"); 636 json_do_string("ski", pretty_key_id(p->ski)); 637 x509_print(x); 638 json_do_string("aki", pretty_key_id(p->aki)); 639 json_do_string("aia", p->aia); 640 json_do_string("sia", p->sia); 641 if (p->signtime != 0) 642 json_do_int("signing_time", p->signtime); 643 json_do_int("valid_since", p->notbefore); 644 json_do_int("valid_until", p->notafter); 645 if (p->expires) 646 json_do_int("expires", p->expires); 647 json_do_string("vcard", p->vcard); 648 } else { 649 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 650 x509_print(x); 651 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 652 printf("Authority info access: %s\n", p->aia); 653 printf("Subject info access: %s\n", p->sia); 654 if (p->signtime != 0) 655 printf("Signing time: %s\n", 656 time2str(p->signtime)); 657 printf("GBR not before: %s\n", 658 time2str(p->notbefore)); 659 printf("GBR not after: %s\n", time2str(p->notafter)); 660 printf("vcard:\n%s", p->vcard); 661 } 662} 663 664void 665rsc_print(const X509 *x, const struct rsc *p) 666{ 667 char *hash; 668 size_t i; 669 670 if (outformats & FORMAT_JSON) { 671 json_do_string("type", "rsc"); 672 json_do_string("ski", pretty_key_id(p->ski)); 673 x509_print(x); 674 json_do_string("aki", pretty_key_id(p->aki)); 675 json_do_string("aia", p->aia); 676 if (p->signtime != 0) 677 json_do_int("signing_time", p->signtime); 678 json_do_int("valid_since", p->notbefore); 679 json_do_int("valid_until", p->notafter); 680 if (p->expires) 681 json_do_int("expires", p->expires); 682 json_do_array("signed_with_resources"); 683 } else { 684 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 685 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 686 x509_print(x); 687 printf("Authority info access: %s\n", p->aia); 688 if (p->signtime != 0) 689 printf("Signing time: %s\n", 690 time2str(p->signtime)); 691 printf("RSC not before: %s\n", 692 time2str(p->notbefore)); 693 printf("RSC not after: %s\n", time2str(p->notafter)); 694 printf("Signed with resources: "); 695 } 696 697 as_resources_print(p->as, p->asz); 698 ip_resources_print(p->ips, p->ipsz, p->asz); 699 700 if (outformats & FORMAT_JSON) { 701 json_do_end(); 702 json_do_array("filenamesandhashes"); 703 } else 704 printf("Filenames and hashes: "); 705 706 for (i = 0; i < p->filesz; i++) { 707 if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash), 708 &hash) == -1) 709 errx(1, "base64_encode failure"); 710 711 if (outformats & FORMAT_JSON) { 712 json_do_object("filehash", 1); 713 if (p->files[i].filename) 714 json_do_string("filename", 715 p->files[i].filename); 716 json_do_string("hash_digest", hash); 717 json_do_end(); 718 } else { 719 if (i > 0) 720 printf("%26s", ""); 721 printf("%zu: %s (hash: %s)\n", i + 1, 722 p->files[i].filename ? p->files[i].filename 723 : "no filename", hash); 724 } 725 726 free(hash); 727 } 728 729 if (outformats & FORMAT_JSON) 730 json_do_end(); 731} 732 733void 734aspa_print(const X509 *x, const struct aspa *p) 735{ 736 size_t i; 737 738 if (outformats & FORMAT_JSON) { 739 json_do_string("type", "aspa"); 740 json_do_string("ski", pretty_key_id(p->ski)); 741 x509_print(x); 742 json_do_string("aki", pretty_key_id(p->aki)); 743 json_do_string("aia", p->aia); 744 json_do_string("sia", p->sia); 745 if (p->signtime != 0) 746 json_do_int("signing_time", p->signtime); 747 json_do_int("valid_since", p->notbefore); 748 json_do_int("valid_until", p->notafter); 749 if (p->expires) 750 json_do_int("expires", p->expires); 751 json_do_uint("customer_asid", p->custasid); 752 json_do_array("providers"); 753 } else { 754 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 755 x509_print(x); 756 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 757 printf("Authority info access: %s\n", p->aia); 758 printf("Subject info access: %s\n", p->sia); 759 if (p->signtime != 0) 760 printf("Signing time: %s\n", 761 time2str(p->signtime)); 762 printf("ASPA not before: %s\n", 763 time2str(p->notbefore)); 764 printf("ASPA not after: %s\n", time2str(p->notafter)); 765 printf("Customer ASID: %u\n", p->custasid); 766 printf("Providers: "); 767 } 768 769 for (i = 0; i < p->providersz; i++) { 770 if (outformats & FORMAT_JSON) 771 json_do_uint("asid", p->providers[i]); 772 else { 773 if (i > 0) 774 printf("%26s", ""); 775 printf("AS: %u\n", p->providers[i]); 776 } 777 } 778 779 if (outformats & FORMAT_JSON) 780 json_do_end(); 781} 782 783static void 784takey_print(char *name, const struct takey *t) 785{ 786 char *spki = NULL; 787 size_t i, j = 0; 788 789 if (base64_encode(t->pubkey, t->pubkeysz, &spki) != 0) 790 errx(1, "base64_encode failed in %s", __func__); 791 792 if (outformats & FORMAT_JSON) { 793 json_do_object("takey", 0); 794 json_do_string("name", name); 795 json_do_array("comments"); 796 for (i = 0; i < t->commentsz; i++) 797 json_do_string("comment", t->comments[i]); 798 json_do_end(); 799 json_do_array("uris"); 800 for (i = 0; i < t->urisz; i++) 801 json_do_string("uri", t->uris[i]); 802 json_do_end(); 803 json_do_string("spki", spki); 804 json_do_end(); 805 } else { 806 printf("TAL derived from the '%s' Trust Anchor Key:\n\n", name); 807 808 for (i = 0; i < t->commentsz; i++) 809 printf("\t# %s\n", t->comments[i]); 810 if (t->commentsz > 0) 811 printf("\n"); 812 for (i = 0; i < t->urisz; i++) 813 printf("\t%s\n", t->uris[i]); 814 printf("\n\t"); 815 for (i = 0; i < strlen(spki); i++) { 816 printf("%c", spki[i]); 817 if ((++j % 64) == 0) 818 printf("\n\t"); 819 } 820 printf("\n\n"); 821 } 822 823 free(spki); 824} 825 826void 827tak_print(const X509 *x, const struct tak *p) 828{ 829 if (outformats & FORMAT_JSON) { 830 json_do_string("type", "tak"); 831 json_do_string("ski", pretty_key_id(p->ski)); 832 x509_print(x); 833 json_do_string("aki", pretty_key_id(p->aki)); 834 json_do_string("aia", p->aia); 835 json_do_string("sia", p->sia); 836 if (p->signtime != 0) 837 json_do_int("signing_time", p->signtime); 838 json_do_int("valid_since", p->notbefore); 839 json_do_int("valid_until", p->notafter); 840 if (p->expires) 841 json_do_int("expires", p->expires); 842 json_do_array("takeys"); 843 } else { 844 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 845 x509_print(x); 846 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 847 printf("Authority info access: %s\n", p->aia); 848 printf("Subject info access: %s\n", p->sia); 849 if (p->signtime != 0) 850 printf("Signing time: %s\n", 851 time2str(p->signtime)); 852 printf("TAK not before: %s\n", 853 time2str(p->notbefore)); 854 printf("TAK not after: %s\n", time2str(p->notafter)); 855 } 856 857 takey_print("current", p->current); 858 if (p->predecessor != NULL) 859 takey_print("predecessor", p->predecessor); 860 if (p->successor != NULL) 861 takey_print("successor", p->successor); 862 863 if (outformats & FORMAT_JSON) 864 json_do_end(); 865} 866 867void 868geofeed_print(const X509 *x, const struct geofeed *p) 869{ 870 char buf[128]; 871 size_t i; 872 873 if (outformats & FORMAT_JSON) { 874 json_do_string("type", "geofeed"); 875 json_do_string("ski", pretty_key_id(p->ski)); 876 x509_print(x); 877 json_do_string("aki", pretty_key_id(p->aki)); 878 json_do_string("aia", p->aia); 879 if (p->signtime != 0) 880 json_do_int("signing_time", p->signtime); 881 json_do_int("valid_since", p->notbefore); 882 json_do_int("valid_until", p->notafter); 883 if (p->expires) 884 json_do_int("expires", p->expires); 885 json_do_array("records"); 886 } else { 887 printf("Subject key identifier: %s\n", pretty_key_id(p->ski)); 888 x509_print(x); 889 printf("Authority key identifier: %s\n", pretty_key_id(p->aki)); 890 printf("Authority info access: %s\n", p->aia); 891 if (p->signtime != 0) 892 printf("Signing time: %s\n", 893 time2str(p->signtime)); 894 printf("Geofeed not before: %s\n", 895 time2str(p->notbefore)); 896 printf("Geofeed not after: %s\n", time2str(p->notafter)); 897 printf("Geofeed CSV records: "); 898 } 899 900 for (i = 0; i < p->geoipsz; i++) { 901 if (p->geoips[i].ip->type != CERT_IP_ADDR) 902 continue; 903 904 ip_addr_print(&p->geoips[i].ip->ip, p->geoips[i].ip->afi, buf, 905 sizeof(buf)); 906 if (outformats & FORMAT_JSON) { 907 json_do_object("geoip", 1); 908 json_do_string("prefix", buf); 909 json_do_string("location", p->geoips[i].loc); 910 json_do_end(); 911 } else { 912 if (i > 0) 913 printf("%26s", ""); 914 printf("IP: %s (%s)\n", buf, p->geoips[i].loc); 915 } 916 } 917 918 if (outformats & FORMAT_JSON) 919 json_do_end(); 920} 921