xref: /openbsd/usr.sbin/rpki-client/print.c (revision 254fd372)
1*254fd372Sclaudio /*	$OpenBSD: print.c,v 1.6 2022/03/21 10:39:51 claudio Exp $ */
2714f4e3fSclaudio /*
3714f4e3fSclaudio  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
4714f4e3fSclaudio  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
5714f4e3fSclaudio  *
6714f4e3fSclaudio  * Permission to use, copy, modify, and distribute this software for any
7714f4e3fSclaudio  * purpose with or without fee is hereby granted, provided that the above
8714f4e3fSclaudio  * copyright notice and this permission notice appear in all copies.
9714f4e3fSclaudio  *
10714f4e3fSclaudio  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11714f4e3fSclaudio  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12714f4e3fSclaudio  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13714f4e3fSclaudio  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14714f4e3fSclaudio  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15714f4e3fSclaudio  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16714f4e3fSclaudio  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17714f4e3fSclaudio  */
18714f4e3fSclaudio 
19714f4e3fSclaudio #include <sys/types.h>
20714f4e3fSclaudio #include <sys/socket.h>
21714f4e3fSclaudio #include <arpa/inet.h>
22714f4e3fSclaudio 
23714f4e3fSclaudio #include <err.h>
24714f4e3fSclaudio #include <stdio.h>
25714f4e3fSclaudio #include <string.h>
26714f4e3fSclaudio #include <time.h>
27714f4e3fSclaudio 
28714f4e3fSclaudio #include "extern.h"
29714f4e3fSclaudio 
30714f4e3fSclaudio static const char *
31*254fd372Sclaudio pretty_key_id(const char *hex)
32714f4e3fSclaudio {
33714f4e3fSclaudio 	static char buf[128];	/* bigger than SHA_DIGEST_LENGTH * 3 */
34714f4e3fSclaudio 	size_t i;
35714f4e3fSclaudio 
36714f4e3fSclaudio 	for (i = 0; i < sizeof(buf) && *hex != '\0'; i++) {
37*254fd372Sclaudio 		if  (i % 3 == 2)
38714f4e3fSclaudio 			buf[i] = ':';
39714f4e3fSclaudio 		else
40714f4e3fSclaudio 			buf[i] = *hex++;
41714f4e3fSclaudio 	}
42714f4e3fSclaudio 	if (i == sizeof(buf))
43714f4e3fSclaudio 		memcpy(buf + sizeof(buf) - 4, "...", 4);
44*254fd372Sclaudio 	else
45*254fd372Sclaudio 		buf[i] = '\0';
46714f4e3fSclaudio 	return buf;
47714f4e3fSclaudio }
48714f4e3fSclaudio 
49220c707cSclaudio char *
50220c707cSclaudio time2str(time_t t)
51220c707cSclaudio {
52220c707cSclaudio 	static char buf[64];
53220c707cSclaudio 	struct tm tm;
54220c707cSclaudio 
55220c707cSclaudio 	if (gmtime_r(&t, &tm) == NULL)
56220c707cSclaudio 		return "could not convert time";
57220c707cSclaudio 
58220c707cSclaudio 	strftime(buf, sizeof(buf), "%h %d %T %Y %Z", &tm);
59220c707cSclaudio 	return buf;
60220c707cSclaudio }
61220c707cSclaudio 
62714f4e3fSclaudio void
63714f4e3fSclaudio tal_print(const struct tal *p)
64714f4e3fSclaudio {
65714f4e3fSclaudio 	size_t	 i;
66714f4e3fSclaudio 
67714f4e3fSclaudio 	for (i = 0; i < p->urisz; i++)
68714f4e3fSclaudio 		printf("%5zu: URI: %s\n", i + 1, p->uri[i]);
69714f4e3fSclaudio }
70714f4e3fSclaudio 
71714f4e3fSclaudio void
72714f4e3fSclaudio cert_print(const struct cert *p)
73714f4e3fSclaudio {
74714f4e3fSclaudio 	size_t	 i;
75714f4e3fSclaudio 	char	 buf1[64], buf2[64];
76714f4e3fSclaudio 	int	 sockt;
77714f4e3fSclaudio 	char	 tbuf[21];
78714f4e3fSclaudio 
79714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
80714f4e3fSclaudio 	if (p->aki != NULL)
81714f4e3fSclaudio 		printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
82714f4e3fSclaudio 	if (p->aia != NULL)
83714f4e3fSclaudio 		printf("Authority info access: %s\n", p->aia);
84714f4e3fSclaudio 	if (p->mft != NULL)
85714f4e3fSclaudio 		printf("Manifest: %s\n", p->mft);
86714f4e3fSclaudio 	if (p->repo != NULL)
87714f4e3fSclaudio 		printf("caRepository: %s\n", p->repo);
88714f4e3fSclaudio 	if (p->notify != NULL)
89714f4e3fSclaudio 		printf("Notify URL: %s\n", p->notify);
90714f4e3fSclaudio 	if (p->pubkey != NULL)
91714f4e3fSclaudio 		printf("BGPsec P-256 ECDSA public key: %s\n", p->pubkey);
92714f4e3fSclaudio 	strftime(tbuf, sizeof(tbuf), "%FT%TZ", gmtime(&p->expires));
93714f4e3fSclaudio 	printf("Valid until: %s\n", tbuf);
94714f4e3fSclaudio 
95714f4e3fSclaudio 	printf("Subordinate Resources:\n");
96714f4e3fSclaudio 
97714f4e3fSclaudio 	for (i = 0; i < p->asz; i++)
98714f4e3fSclaudio 		switch (p->as[i].type) {
99714f4e3fSclaudio 		case CERT_AS_ID:
100714f4e3fSclaudio 			printf("%5zu: AS: %u\n", i + 1, p->as[i].id);
101714f4e3fSclaudio 			break;
102714f4e3fSclaudio 		case CERT_AS_INHERIT:
103714f4e3fSclaudio 			printf("%5zu: AS: inherit\n", i + 1);
104714f4e3fSclaudio 			break;
105714f4e3fSclaudio 		case CERT_AS_RANGE:
106714f4e3fSclaudio 			printf("%5zu: AS: %u -- %u\n", i + 1,
107714f4e3fSclaudio 				p->as[i].range.min, p->as[i].range.max);
108714f4e3fSclaudio 			break;
109714f4e3fSclaudio 		}
110714f4e3fSclaudio 
111714f4e3fSclaudio 	for (i = 0; i < p->ipsz; i++)
112714f4e3fSclaudio 		switch (p->ips[i].type) {
113714f4e3fSclaudio 		case CERT_IP_INHERIT:
114714f4e3fSclaudio 			printf("%5zu: IP: inherit\n", i + 1);
115714f4e3fSclaudio 			break;
116714f4e3fSclaudio 		case CERT_IP_ADDR:
117714f4e3fSclaudio 			ip_addr_print(&p->ips[i].ip,
118714f4e3fSclaudio 				p->ips[i].afi, buf1, sizeof(buf1));
119714f4e3fSclaudio 			printf("%5zu: IP: %s\n", i + 1, buf1);
120714f4e3fSclaudio 			break;
121714f4e3fSclaudio 		case CERT_IP_RANGE:
122714f4e3fSclaudio 			sockt = (p->ips[i].afi == AFI_IPV4) ?
123714f4e3fSclaudio 				AF_INET : AF_INET6;
124714f4e3fSclaudio 			inet_ntop(sockt, p->ips[i].min, buf1, sizeof(buf1));
125714f4e3fSclaudio 			inet_ntop(sockt, p->ips[i].max, buf2, sizeof(buf2));
126714f4e3fSclaudio 			printf("%5zu: IP: %s -- %s\n", i + 1, buf1, buf2);
127714f4e3fSclaudio 			break;
128714f4e3fSclaudio 		}
129714f4e3fSclaudio 
130714f4e3fSclaudio }
131714f4e3fSclaudio 
132714f4e3fSclaudio void
133220c707cSclaudio crl_print(const struct crl *p)
134220c707cSclaudio {
135220c707cSclaudio 	STACK_OF(X509_REVOKED)	*revlist;
136220c707cSclaudio 	X509_REVOKED *rev;
1377cdd491fSclaudio 	ASN1_INTEGER *crlnum;
138220c707cSclaudio 	int i;
1397cdd491fSclaudio 	char *serial;
140220c707cSclaudio 	time_t t;
141220c707cSclaudio 
142220c707cSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
1437cdd491fSclaudio 
1447cdd491fSclaudio 	crlnum = X509_CRL_get_ext_d2i(p->x509_crl, NID_crl_number, NULL, NULL);
1457cdd491fSclaudio 	serial = x509_convert_seqnum(__func__, crlnum);
1467cdd491fSclaudio 	if (serial != NULL)
1477cdd491fSclaudio 		printf("CRL Serial Number: %s\n", serial);
1487cdd491fSclaudio 	free(serial);
1497cdd491fSclaudio 	ASN1_INTEGER_free(crlnum);
1507cdd491fSclaudio 
151220c707cSclaudio 	printf("CRL valid since: %s\n", time2str(p->issued));
152220c707cSclaudio 	printf("CRL valid until: %s\n", time2str(p->expires));
153220c707cSclaudio 
154220c707cSclaudio 	revlist = X509_CRL_get_REVOKED(p->x509_crl);
155220c707cSclaudio 	for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) {
156220c707cSclaudio 		if (i == 0)
157220c707cSclaudio 			printf("Revoked Certificates:\n");
158220c707cSclaudio 		rev = sk_X509_REVOKED_value(revlist, i);
1597cdd491fSclaudio 
1607cdd491fSclaudio 		serial = x509_convert_seqnum(__func__,
1617cdd491fSclaudio 		    X509_REVOKED_get0_serialNumber(rev));
162220c707cSclaudio 		x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t);
1637cdd491fSclaudio 		if (serial != NULL)
1647cdd491fSclaudio 			printf("    Serial: %8s   Revocation Date: %s\n",
1657cdd491fSclaudio 			    serial, time2str(t));
1667cdd491fSclaudio 		free(serial);
167220c707cSclaudio 	}
168220c707cSclaudio 	if (i == 0)
169220c707cSclaudio 		printf("No Revoked Certificates\n");
170220c707cSclaudio }
171220c707cSclaudio 
172220c707cSclaudio void
173714f4e3fSclaudio mft_print(const struct mft *p)
174714f4e3fSclaudio {
175714f4e3fSclaudio 	size_t i;
176714f4e3fSclaudio 	char *hash;
177714f4e3fSclaudio 
178714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
179714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
180714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
181714f4e3fSclaudio 	printf("Manifest Number: %s\n", p->seqnum);
182714f4e3fSclaudio 	for (i = 0; i < p->filesz; i++) {
183714f4e3fSclaudio 		if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash),
184714f4e3fSclaudio 		    &hash) == -1)
185714f4e3fSclaudio 			errx(1, "base64_encode failure");
186714f4e3fSclaudio 		printf("%5zu: %s\n", i + 1, p->files[i].file);
187714f4e3fSclaudio 		printf("\thash %s\n", hash);
188714f4e3fSclaudio 		free(hash);
189714f4e3fSclaudio 	}
190714f4e3fSclaudio }
191714f4e3fSclaudio 
192714f4e3fSclaudio void
193714f4e3fSclaudio roa_print(const struct roa *p)
194714f4e3fSclaudio {
195714f4e3fSclaudio 	char	 buf[128];
196714f4e3fSclaudio 	size_t	 i;
197714f4e3fSclaudio 
198714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
199714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
200714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
201220c707cSclaudio 	printf("ROA valid until: %s\n", time2str(p->expires));
202714f4e3fSclaudio 
203714f4e3fSclaudio 	printf("asID: %u\n", p->asid);
204714f4e3fSclaudio 	for (i = 0; i < p->ipsz; i++) {
205714f4e3fSclaudio 		ip_addr_print(&p->ips[i].addr,
206714f4e3fSclaudio 			p->ips[i].afi, buf, sizeof(buf));
207b6884e9fSclaudio 		printf("%5zu: %s maxlen: %hhu\n", i + 1,
208714f4e3fSclaudio 			buf, p->ips[i].maxlength);
209714f4e3fSclaudio 	}
210714f4e3fSclaudio }
211714f4e3fSclaudio 
212714f4e3fSclaudio void
213714f4e3fSclaudio gbr_print(const struct gbr *p)
214714f4e3fSclaudio {
215714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
216714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
217714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
218714f4e3fSclaudio 	printf("vcard:\n%s", p->vcard);
219714f4e3fSclaudio }
220