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