xref: /openbsd/usr.sbin/rpki-client/print.c (revision 7cdd491f)
1*7cdd491fSclaudio /*	$OpenBSD: print.c,v 1.5 2022/02/10 17:33:28 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 *
31714f4e3fSclaudio pretty_key_id(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++) {
37714f4e3fSclaudio 		if  (i % 3 == 2 && *hex != '\0')
38714f4e3fSclaudio 			buf[i] = ':';
39714f4e3fSclaudio 		else
40714f4e3fSclaudio 			buf[i] = *hex++;
41714f4e3fSclaudio 	}
42714f4e3fSclaudio 	if (i == sizeof(buf))
43714f4e3fSclaudio 		memcpy(buf + sizeof(buf) - 4, "...", 4);
44714f4e3fSclaudio 	return buf;
45714f4e3fSclaudio }
46714f4e3fSclaudio 
47220c707cSclaudio char *
48220c707cSclaudio time2str(time_t t)
49220c707cSclaudio {
50220c707cSclaudio 	static char buf[64];
51220c707cSclaudio 	struct tm tm;
52220c707cSclaudio 
53220c707cSclaudio 	if (gmtime_r(&t, &tm) == NULL)
54220c707cSclaudio 		return "could not convert time";
55220c707cSclaudio 
56220c707cSclaudio 	strftime(buf, sizeof(buf), "%h %d %T %Y %Z", &tm);
57220c707cSclaudio 	return buf;
58220c707cSclaudio }
59220c707cSclaudio 
60714f4e3fSclaudio void
61714f4e3fSclaudio tal_print(const struct tal *p)
62714f4e3fSclaudio {
63714f4e3fSclaudio 	size_t	 i;
64714f4e3fSclaudio 
65714f4e3fSclaudio 	for (i = 0; i < p->urisz; i++)
66714f4e3fSclaudio 		printf("%5zu: URI: %s\n", i + 1, p->uri[i]);
67714f4e3fSclaudio }
68714f4e3fSclaudio 
69714f4e3fSclaudio void
70714f4e3fSclaudio cert_print(const struct cert *p)
71714f4e3fSclaudio {
72714f4e3fSclaudio 	size_t	 i;
73714f4e3fSclaudio 	char	 buf1[64], buf2[64];
74714f4e3fSclaudio 	int	 sockt;
75714f4e3fSclaudio 	char	 tbuf[21];
76714f4e3fSclaudio 
77714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
78714f4e3fSclaudio 	if (p->aki != NULL)
79714f4e3fSclaudio 		printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
80714f4e3fSclaudio 	if (p->aia != NULL)
81714f4e3fSclaudio 		printf("Authority info access: %s\n", p->aia);
82714f4e3fSclaudio 	if (p->mft != NULL)
83714f4e3fSclaudio 		printf("Manifest: %s\n", p->mft);
84714f4e3fSclaudio 	if (p->repo != NULL)
85714f4e3fSclaudio 		printf("caRepository: %s\n", p->repo);
86714f4e3fSclaudio 	if (p->notify != NULL)
87714f4e3fSclaudio 		printf("Notify URL: %s\n", p->notify);
88714f4e3fSclaudio 	if (p->pubkey != NULL)
89714f4e3fSclaudio 		printf("BGPsec P-256 ECDSA public key: %s\n", p->pubkey);
90714f4e3fSclaudio 	strftime(tbuf, sizeof(tbuf), "%FT%TZ", gmtime(&p->expires));
91714f4e3fSclaudio 	printf("Valid until: %s\n", tbuf);
92714f4e3fSclaudio 
93714f4e3fSclaudio 	printf("Subordinate Resources:\n");
94714f4e3fSclaudio 
95714f4e3fSclaudio 	for (i = 0; i < p->asz; i++)
96714f4e3fSclaudio 		switch (p->as[i].type) {
97714f4e3fSclaudio 		case CERT_AS_ID:
98714f4e3fSclaudio 			printf("%5zu: AS: %u\n", i + 1, p->as[i].id);
99714f4e3fSclaudio 			break;
100714f4e3fSclaudio 		case CERT_AS_INHERIT:
101714f4e3fSclaudio 			printf("%5zu: AS: inherit\n", i + 1);
102714f4e3fSclaudio 			break;
103714f4e3fSclaudio 		case CERT_AS_RANGE:
104714f4e3fSclaudio 			printf("%5zu: AS: %u -- %u\n", i + 1,
105714f4e3fSclaudio 				p->as[i].range.min, p->as[i].range.max);
106714f4e3fSclaudio 			break;
107714f4e3fSclaudio 		}
108714f4e3fSclaudio 
109714f4e3fSclaudio 	for (i = 0; i < p->ipsz; i++)
110714f4e3fSclaudio 		switch (p->ips[i].type) {
111714f4e3fSclaudio 		case CERT_IP_INHERIT:
112714f4e3fSclaudio 			printf("%5zu: IP: inherit\n", i + 1);
113714f4e3fSclaudio 			break;
114714f4e3fSclaudio 		case CERT_IP_ADDR:
115714f4e3fSclaudio 			ip_addr_print(&p->ips[i].ip,
116714f4e3fSclaudio 				p->ips[i].afi, buf1, sizeof(buf1));
117714f4e3fSclaudio 			printf("%5zu: IP: %s\n", i + 1, buf1);
118714f4e3fSclaudio 			break;
119714f4e3fSclaudio 		case CERT_IP_RANGE:
120714f4e3fSclaudio 			sockt = (p->ips[i].afi == AFI_IPV4) ?
121714f4e3fSclaudio 				AF_INET : AF_INET6;
122714f4e3fSclaudio 			inet_ntop(sockt, p->ips[i].min, buf1, sizeof(buf1));
123714f4e3fSclaudio 			inet_ntop(sockt, p->ips[i].max, buf2, sizeof(buf2));
124714f4e3fSclaudio 			printf("%5zu: IP: %s -- %s\n", i + 1, buf1, buf2);
125714f4e3fSclaudio 			break;
126714f4e3fSclaudio 		}
127714f4e3fSclaudio 
128714f4e3fSclaudio }
129714f4e3fSclaudio 
130714f4e3fSclaudio void
131220c707cSclaudio crl_print(const struct crl *p)
132220c707cSclaudio {
133220c707cSclaudio 	STACK_OF(X509_REVOKED)	*revlist;
134220c707cSclaudio 	X509_REVOKED *rev;
135*7cdd491fSclaudio 	ASN1_INTEGER *crlnum;
136220c707cSclaudio 	int i;
137*7cdd491fSclaudio 	char *serial;
138220c707cSclaudio 	time_t t;
139220c707cSclaudio 
140220c707cSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
141*7cdd491fSclaudio 
142*7cdd491fSclaudio 	crlnum = X509_CRL_get_ext_d2i(p->x509_crl, NID_crl_number, NULL, NULL);
143*7cdd491fSclaudio 	serial = x509_convert_seqnum(__func__, crlnum);
144*7cdd491fSclaudio 	if (serial != NULL)
145*7cdd491fSclaudio 		printf("CRL Serial Number: %s\n", serial);
146*7cdd491fSclaudio 	free(serial);
147*7cdd491fSclaudio 	ASN1_INTEGER_free(crlnum);
148*7cdd491fSclaudio 
149220c707cSclaudio 	printf("CRL valid since: %s\n", time2str(p->issued));
150220c707cSclaudio 	printf("CRL valid until: %s\n", time2str(p->expires));
151220c707cSclaudio 
152220c707cSclaudio 	revlist = X509_CRL_get_REVOKED(p->x509_crl);
153220c707cSclaudio 	for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) {
154220c707cSclaudio 		if (i == 0)
155220c707cSclaudio 			printf("Revoked Certificates:\n");
156220c707cSclaudio 		rev = sk_X509_REVOKED_value(revlist, i);
157*7cdd491fSclaudio 
158*7cdd491fSclaudio 		serial = x509_convert_seqnum(__func__,
159*7cdd491fSclaudio 		    X509_REVOKED_get0_serialNumber(rev));
160220c707cSclaudio 		x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t);
161*7cdd491fSclaudio 		if (serial != NULL)
162*7cdd491fSclaudio 			printf("    Serial: %8s   Revocation Date: %s\n",
163*7cdd491fSclaudio 			    serial, time2str(t));
164*7cdd491fSclaudio 		free(serial);
165220c707cSclaudio 	}
166220c707cSclaudio 	if (i == 0)
167220c707cSclaudio 		printf("No Revoked Certificates\n");
168220c707cSclaudio }
169220c707cSclaudio 
170220c707cSclaudio void
171714f4e3fSclaudio mft_print(const struct mft *p)
172714f4e3fSclaudio {
173714f4e3fSclaudio 	size_t i;
174714f4e3fSclaudio 	char *hash;
175714f4e3fSclaudio 
176714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
177714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
178714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
179714f4e3fSclaudio 	printf("Manifest Number: %s\n", p->seqnum);
180714f4e3fSclaudio 	for (i = 0; i < p->filesz; i++) {
181714f4e3fSclaudio 		if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash),
182714f4e3fSclaudio 		    &hash) == -1)
183714f4e3fSclaudio 			errx(1, "base64_encode failure");
184714f4e3fSclaudio 		printf("%5zu: %s\n", i + 1, p->files[i].file);
185714f4e3fSclaudio 		printf("\thash %s\n", hash);
186714f4e3fSclaudio 		free(hash);
187714f4e3fSclaudio 	}
188714f4e3fSclaudio }
189714f4e3fSclaudio 
190714f4e3fSclaudio void
191714f4e3fSclaudio roa_print(const struct roa *p)
192714f4e3fSclaudio {
193714f4e3fSclaudio 	char	 buf[128];
194714f4e3fSclaudio 	size_t	 i;
195714f4e3fSclaudio 
196714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
197714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
198714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
199220c707cSclaudio 	printf("ROA valid until: %s\n", time2str(p->expires));
200714f4e3fSclaudio 
201714f4e3fSclaudio 	printf("asID: %u\n", p->asid);
202714f4e3fSclaudio 	for (i = 0; i < p->ipsz; i++) {
203714f4e3fSclaudio 		ip_addr_print(&p->ips[i].addr,
204714f4e3fSclaudio 			p->ips[i].afi, buf, sizeof(buf));
205b6884e9fSclaudio 		printf("%5zu: %s maxlen: %hhu\n", i + 1,
206714f4e3fSclaudio 			buf, p->ips[i].maxlength);
207714f4e3fSclaudio 	}
208714f4e3fSclaudio }
209714f4e3fSclaudio 
210714f4e3fSclaudio void
211714f4e3fSclaudio gbr_print(const struct gbr *p)
212714f4e3fSclaudio {
213714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
214714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
215714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
216714f4e3fSclaudio 	printf("vcard:\n%s", p->vcard);
217714f4e3fSclaudio }
218