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 *
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->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
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 * ases,size_t num_ases)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
ip_resources_print(struct cert_ip * ips,size_t num_ips,size_t num_ases)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
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->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 *
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->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
spl_print(const X509 * x,const struct spl * s)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
gbr_print(const X509 * x,const struct gbr * p)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
rsc_print(const X509 * x,const struct rsc * p)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
aspa_print(const X509 * x,const struct aspa * p)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
takey_print(char * name,const struct takey * t)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
tak_print(const X509 * x,const struct tak * p)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
geofeed_print(const X509 * x,const struct geofeed * p)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