1 /* $OpenBSD: print.c,v 1.56 2024/09/12 10:33:25 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 *
pretty_key_id(const char * hex)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 *
nid2str(int nid)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 *
purpose2str(enum cert_purpose purpose)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 *
time2str(time_t t)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
tal_print(const struct tal * p)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->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
139 void
x509_print(const X509 * x)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
as_resources_print(struct cert_as * as,size_t asz)180 as_resources_print(struct cert_as *as, size_t asz)
181 {
182 size_t i;
183
184 for (i = 0; i < asz; i++) {
185 if (outformats & FORMAT_JSON)
186 json_do_object("resource", 1);
187 switch (as[i].type) {
188 case CERT_AS_ID:
189 if (outformats & FORMAT_JSON) {
190 json_do_uint("asid", as[i].id);
191 } else {
192 if (i > 0)
193 printf("%26s", "");
194 printf("AS: %u", as[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", as[i].range.min);
210 json_do_uint("max", as[i].range.max);
211 json_do_end();
212 } else {
213 if (i > 0)
214 printf("%26s", "");
215 printf("AS: %u -- %u", as[i].range.min,
216 as[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
ip_resources_print(struct cert_ip * ips,size_t ipsz,size_t asz)228 ip_resources_print(struct cert_ip *ips, size_t ipsz, size_t asz)
229 {
230 char buf1[64], buf2[64];
231 size_t i;
232 int sockt;
233
234 for (i = 0; i < ipsz; 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 || asz > 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 || asz > 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 || asz > 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
cert_print(const struct cert * p)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->as, p->asz);
340 ip_resources_print(p->ips, p->ipsz, p->asz);
341
342 if (outformats & FORMAT_JSON)
343 json_do_end();
344 }
345
346 static char *
crl_parse_number(const X509_CRL * x509_crl)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
crl_print(const struct crl * p)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
mft_print(const X509 * x,const struct mft * p)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
roa_print(const X509 * x,const struct roa * p)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->ipsz; i++) {
547 ip_addr_print(&p->ips[i].addr,
548 p->ips[i].afi, buf, sizeof(buf));
549
550 if (outformats & FORMAT_JSON) {
551 json_do_object("vrp", 1);
552 json_do_string("prefix", buf);
553 json_do_uint("asid", p->asid);
554 json_do_uint("maxlen", p->ips[i].maxlength);
555 json_do_end();
556 } else {
557 if (i > 0)
558 printf("%26s", "");
559 printf("%s maxlen: %hhu\n", buf, p->ips[i].maxlength);
560 }
561 }
562 if (outformats & FORMAT_JSON)
563 json_do_end();
564 }
565
566 void
spl_print(const X509 * x,const struct spl * s)567 spl_print(const X509 *x, const struct spl *s)
568 {
569 char buf[128];
570 size_t i;
571
572 if (outformats & FORMAT_JSON) {
573 json_do_string("type", "spl");
574 json_do_string("ski", pretty_key_id(s->ski));
575 x509_print(x);
576 json_do_string("aki", pretty_key_id(s->aki));
577 json_do_string("aia", s->aia);
578 json_do_string("sia", s->sia);
579 if (s->signtime != 0)
580 json_do_int("signing_time", s->signtime);
581 json_do_int("valid_since", s->notbefore);
582 json_do_int("valid_until", s->notafter);
583 if (s->expires)
584 json_do_int("expires", s->expires);
585 json_do_int("asid", s->asid);
586 } else {
587 printf("Subject key identifier: %s\n", pretty_key_id(s->ski));
588 x509_print(x);
589 printf("Authority key identifier: %s\n", pretty_key_id(s->aki));
590 printf("Authority info access: %s\n", s->aia);
591 printf("Subject info access: %s\n", s->sia);
592 if (s->signtime != 0)
593 printf("Signing time: %s\n",
594 time2str(s->signtime));
595 printf("SPL not before: %s\n",
596 time2str(s->notbefore));
597 printf("SPL not after: %s\n", time2str(s->notafter));
598 printf("asID: %u\n", s->asid);
599 printf("Originated IP Prefixes: ");
600 }
601
602 if (outformats & FORMAT_JSON)
603 json_do_array("prefixes");
604 for (i = 0; i < s->pfxsz; i++) {
605 ip_addr_print(&s->pfxs[i].prefix, s->pfxs[i].afi, buf,
606 sizeof(buf));
607
608 if (outformats & FORMAT_JSON) {
609 json_do_string("prefix", buf);
610 } else {
611 if (i > 0)
612 printf("%26s", "");
613 printf("%s\n", buf);
614 }
615 }
616 if (outformats & FORMAT_JSON)
617 json_do_end();
618 }
619
620 void
gbr_print(const X509 * x,const struct gbr * p)621 gbr_print(const X509 *x, const struct gbr *p)
622 {
623 if (outformats & FORMAT_JSON) {
624 json_do_string("type", "gbr");
625 json_do_string("ski", pretty_key_id(p->ski));
626 x509_print(x);
627 json_do_string("aki", pretty_key_id(p->aki));
628 json_do_string("aia", p->aia);
629 json_do_string("sia", p->sia);
630 if (p->signtime != 0)
631 json_do_int("signing_time", p->signtime);
632 json_do_int("valid_since", p->notbefore);
633 json_do_int("valid_until", p->notafter);
634 if (p->expires)
635 json_do_int("expires", p->expires);
636 json_do_string("vcard", p->vcard);
637 } else {
638 printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
639 x509_print(x);
640 printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
641 printf("Authority info access: %s\n", p->aia);
642 printf("Subject info access: %s\n", p->sia);
643 if (p->signtime != 0)
644 printf("Signing time: %s\n",
645 time2str(p->signtime));
646 printf("GBR not before: %s\n",
647 time2str(p->notbefore));
648 printf("GBR not after: %s\n", time2str(p->notafter));
649 printf("vcard:\n%s", p->vcard);
650 }
651 }
652
653 void
rsc_print(const X509 * x,const struct rsc * p)654 rsc_print(const X509 *x, const struct rsc *p)
655 {
656 char *hash;
657 size_t i;
658
659 if (outformats & FORMAT_JSON) {
660 json_do_string("type", "rsc");
661 json_do_string("ski", pretty_key_id(p->ski));
662 x509_print(x);
663 json_do_string("aki", pretty_key_id(p->aki));
664 json_do_string("aia", p->aia);
665 if (p->signtime != 0)
666 json_do_int("signing_time", p->signtime);
667 json_do_int("valid_since", p->notbefore);
668 json_do_int("valid_until", p->notafter);
669 if (p->expires)
670 json_do_int("expires", p->expires);
671 json_do_array("signed_with_resources");
672 } else {
673 printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
674 printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
675 x509_print(x);
676 printf("Authority info access: %s\n", p->aia);
677 if (p->signtime != 0)
678 printf("Signing time: %s\n",
679 time2str(p->signtime));
680 printf("RSC not before: %s\n",
681 time2str(p->notbefore));
682 printf("RSC not after: %s\n", time2str(p->notafter));
683 printf("Signed with resources: ");
684 }
685
686 as_resources_print(p->as, p->asz);
687 ip_resources_print(p->ips, p->ipsz, p->asz);
688
689 if (outformats & FORMAT_JSON) {
690 json_do_end();
691 json_do_array("filenamesandhashes");
692 } else
693 printf("Filenames and hashes: ");
694
695 for (i = 0; i < p->filesz; i++) {
696 if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash),
697 &hash) == -1)
698 errx(1, "base64_encode failure");
699
700 if (outformats & FORMAT_JSON) {
701 json_do_object("filehash", 1);
702 if (p->files[i].filename)
703 json_do_string("filename",
704 p->files[i].filename);
705 json_do_string("hash_digest", hash);
706 json_do_end();
707 } else {
708 if (i > 0)
709 printf("%26s", "");
710 printf("%zu: %s (hash: %s)\n", i + 1,
711 p->files[i].filename ? p->files[i].filename
712 : "no filename", hash);
713 }
714
715 free(hash);
716 }
717
718 if (outformats & FORMAT_JSON)
719 json_do_end();
720 }
721
722 void
aspa_print(const X509 * x,const struct aspa * p)723 aspa_print(const X509 *x, const struct aspa *p)
724 {
725 size_t i;
726
727 if (outformats & FORMAT_JSON) {
728 json_do_string("type", "aspa");
729 json_do_string("ski", pretty_key_id(p->ski));
730 x509_print(x);
731 json_do_string("aki", pretty_key_id(p->aki));
732 json_do_string("aia", p->aia);
733 json_do_string("sia", p->sia);
734 if (p->signtime != 0)
735 json_do_int("signing_time", p->signtime);
736 json_do_int("valid_since", p->notbefore);
737 json_do_int("valid_until", p->notafter);
738 if (p->expires)
739 json_do_int("expires", p->expires);
740 json_do_uint("customer_asid", p->custasid);
741 json_do_array("providers");
742 } else {
743 printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
744 x509_print(x);
745 printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
746 printf("Authority info access: %s\n", p->aia);
747 printf("Subject info access: %s\n", p->sia);
748 if (p->signtime != 0)
749 printf("Signing time: %s\n",
750 time2str(p->signtime));
751 printf("ASPA not before: %s\n",
752 time2str(p->notbefore));
753 printf("ASPA not after: %s\n", time2str(p->notafter));
754 printf("Customer ASID: %u\n", p->custasid);
755 printf("Providers: ");
756 }
757
758 for (i = 0; i < p->providersz; i++) {
759 if (outformats & FORMAT_JSON)
760 json_do_uint("asid", p->providers[i]);
761 else {
762 if (i > 0)
763 printf("%26s", "");
764 printf("AS: %u\n", p->providers[i]);
765 }
766 }
767
768 if (outformats & FORMAT_JSON)
769 json_do_end();
770 }
771
772 static void
takey_print(char * name,const struct takey * t)773 takey_print(char *name, const struct takey *t)
774 {
775 char *spki = NULL;
776 size_t i, j = 0;
777
778 if (base64_encode(t->pubkey, t->pubkeysz, &spki) != 0)
779 errx(1, "base64_encode failed in %s", __func__);
780
781 if (outformats & FORMAT_JSON) {
782 json_do_object("takey", 0);
783 json_do_string("name", name);
784 json_do_array("comments");
785 for (i = 0; i < t->commentsz; i++)
786 json_do_string("comment", t->comments[i]);
787 json_do_end();
788 json_do_array("uris");
789 for (i = 0; i < t->urisz; i++)
790 json_do_string("uri", t->uris[i]);
791 json_do_end();
792 json_do_string("spki", spki);
793 json_do_end();
794 } else {
795 printf("TAL derived from the '%s' Trust Anchor Key:\n\n", name);
796
797 for (i = 0; i < t->commentsz; i++)
798 printf("\t# %s\n", t->comments[i]);
799 if (t->commentsz > 0)
800 printf("\n");
801 for (i = 0; i < t->urisz; i++)
802 printf("\t%s\n", t->uris[i]);
803 printf("\n\t");
804 for (i = 0; i < strlen(spki); i++) {
805 printf("%c", spki[i]);
806 if ((++j % 64) == 0)
807 printf("\n\t");
808 }
809 printf("\n\n");
810 }
811
812 free(spki);
813 }
814
815 void
tak_print(const X509 * x,const struct tak * p)816 tak_print(const X509 *x, const struct tak *p)
817 {
818 if (outformats & FORMAT_JSON) {
819 json_do_string("type", "tak");
820 json_do_string("ski", pretty_key_id(p->ski));
821 x509_print(x);
822 json_do_string("aki", pretty_key_id(p->aki));
823 json_do_string("aia", p->aia);
824 json_do_string("sia", p->sia);
825 if (p->signtime != 0)
826 json_do_int("signing_time", p->signtime);
827 json_do_int("valid_since", p->notbefore);
828 json_do_int("valid_until", p->notafter);
829 if (p->expires)
830 json_do_int("expires", p->expires);
831 json_do_array("takeys");
832 } else {
833 printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
834 x509_print(x);
835 printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
836 printf("Authority info access: %s\n", p->aia);
837 printf("Subject info access: %s\n", p->sia);
838 if (p->signtime != 0)
839 printf("Signing time: %s\n",
840 time2str(p->signtime));
841 printf("TAK not before: %s\n",
842 time2str(p->notbefore));
843 printf("TAK not after: %s\n", time2str(p->notafter));
844 }
845
846 takey_print("current", p->current);
847 if (p->predecessor != NULL)
848 takey_print("predecessor", p->predecessor);
849 if (p->successor != NULL)
850 takey_print("successor", p->successor);
851
852 if (outformats & FORMAT_JSON)
853 json_do_end();
854 }
855
856 void
geofeed_print(const X509 * x,const struct geofeed * p)857 geofeed_print(const X509 *x, const struct geofeed *p)
858 {
859 char buf[128];
860 size_t i;
861
862 if (outformats & FORMAT_JSON) {
863 json_do_string("type", "geofeed");
864 json_do_string("ski", pretty_key_id(p->ski));
865 x509_print(x);
866 json_do_string("aki", pretty_key_id(p->aki));
867 json_do_string("aia", p->aia);
868 if (p->signtime != 0)
869 json_do_int("signing_time", p->signtime);
870 json_do_int("valid_since", p->notbefore);
871 json_do_int("valid_until", p->notafter);
872 if (p->expires)
873 json_do_int("expires", p->expires);
874 json_do_array("records");
875 } else {
876 printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
877 x509_print(x);
878 printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
879 printf("Authority info access: %s\n", p->aia);
880 if (p->signtime != 0)
881 printf("Signing time: %s\n",
882 time2str(p->signtime));
883 printf("Geofeed not before: %s\n",
884 time2str(p->notbefore));
885 printf("Geofeed not after: %s\n", time2str(p->notafter));
886 printf("Geofeed CSV records: ");
887 }
888
889 for (i = 0; i < p->geoipsz; i++) {
890 if (p->geoips[i].ip->type != CERT_IP_ADDR)
891 continue;
892
893 ip_addr_print(&p->geoips[i].ip->ip, p->geoips[i].ip->afi, buf,
894 sizeof(buf));
895 if (outformats & FORMAT_JSON) {
896 json_do_object("geoip", 1);
897 json_do_string("prefix", buf);
898 json_do_string("location", p->geoips[i].loc);
899 json_do_end();
900 } else {
901 if (i > 0)
902 printf("%26s", "");
903 printf("IP: %s (%s)\n", buf, p->geoips[i].loc);
904 }
905 }
906
907 if (outformats & FORMAT_JSON)
908 json_do_end();
909 }
910