xref: /openbsd/usr.sbin/rpki-client/print.c (revision 220c707c)
1*220c707cSclaudio /*	$OpenBSD: print.c,v 1.4 2022/02/10 15:33:47 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 
47*220c707cSclaudio char *
48*220c707cSclaudio time2str(time_t t)
49*220c707cSclaudio {
50*220c707cSclaudio 	static char buf[64];
51*220c707cSclaudio 	struct tm tm;
52*220c707cSclaudio 
53*220c707cSclaudio 	if (gmtime_r(&t, &tm) == NULL)
54*220c707cSclaudio 		return "could not convert time";
55*220c707cSclaudio 
56*220c707cSclaudio 	strftime(buf, sizeof(buf), "%h %d %T %Y %Z", &tm);
57*220c707cSclaudio 	return buf;
58*220c707cSclaudio }
59*220c707cSclaudio 
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
131*220c707cSclaudio crl_print(const struct crl *p)
132*220c707cSclaudio {
133*220c707cSclaudio 	STACK_OF(X509_REVOKED)	*revlist;
134*220c707cSclaudio 	X509_REVOKED *rev;
135*220c707cSclaudio 	int i;
136*220c707cSclaudio 	long serial;
137*220c707cSclaudio 	time_t t;
138*220c707cSclaudio 
139*220c707cSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
140*220c707cSclaudio 	printf("CRL valid since: %s\n", time2str(p->issued));
141*220c707cSclaudio 	printf("CRL valid until: %s\n", time2str(p->expires));
142*220c707cSclaudio 
143*220c707cSclaudio 	revlist = X509_CRL_get_REVOKED(p->x509_crl);
144*220c707cSclaudio 	for (i = 0; i < sk_X509_REVOKED_num(revlist); i++) {
145*220c707cSclaudio 		if (i == 0)
146*220c707cSclaudio 			printf("Revoked Certificates:\n");
147*220c707cSclaudio 		rev = sk_X509_REVOKED_value(revlist, i);
148*220c707cSclaudio 		serial = ASN1_INTEGER_get(X509_REVOKED_get0_serialNumber(rev));
149*220c707cSclaudio 		x509_get_time(X509_REVOKED_get0_revocationDate(rev), &t);
150*220c707cSclaudio 		printf("    Serial: %8lx\tRevocation Date: %s\n", serial,
151*220c707cSclaudio 		    time2str(t));
152*220c707cSclaudio 	}
153*220c707cSclaudio 	if (i == 0)
154*220c707cSclaudio 		printf("No Revoked Certificates\n");
155*220c707cSclaudio }
156*220c707cSclaudio 
157*220c707cSclaudio void
158714f4e3fSclaudio mft_print(const struct mft *p)
159714f4e3fSclaudio {
160714f4e3fSclaudio 	size_t i;
161714f4e3fSclaudio 	char *hash;
162714f4e3fSclaudio 
163714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
164714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
165714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
166714f4e3fSclaudio 	printf("Manifest Number: %s\n", p->seqnum);
167714f4e3fSclaudio 	for (i = 0; i < p->filesz; i++) {
168714f4e3fSclaudio 		if (base64_encode(p->files[i].hash, sizeof(p->files[i].hash),
169714f4e3fSclaudio 		    &hash) == -1)
170714f4e3fSclaudio 			errx(1, "base64_encode failure");
171714f4e3fSclaudio 		printf("%5zu: %s\n", i + 1, p->files[i].file);
172714f4e3fSclaudio 		printf("\thash %s\n", hash);
173714f4e3fSclaudio 		free(hash);
174714f4e3fSclaudio 	}
175714f4e3fSclaudio }
176714f4e3fSclaudio 
177714f4e3fSclaudio void
178714f4e3fSclaudio roa_print(const struct roa *p)
179714f4e3fSclaudio {
180714f4e3fSclaudio 	char	 buf[128];
181714f4e3fSclaudio 	size_t	 i;
182714f4e3fSclaudio 
183714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
184714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
185714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
186*220c707cSclaudio 	printf("ROA valid until: %s\n", time2str(p->expires));
187714f4e3fSclaudio 
188714f4e3fSclaudio 	printf("asID: %u\n", p->asid);
189714f4e3fSclaudio 	for (i = 0; i < p->ipsz; i++) {
190714f4e3fSclaudio 		ip_addr_print(&p->ips[i].addr,
191714f4e3fSclaudio 			p->ips[i].afi, buf, sizeof(buf));
192b6884e9fSclaudio 		printf("%5zu: %s maxlen: %hhu\n", i + 1,
193714f4e3fSclaudio 			buf, p->ips[i].maxlength);
194714f4e3fSclaudio 	}
195714f4e3fSclaudio }
196714f4e3fSclaudio 
197714f4e3fSclaudio void
198714f4e3fSclaudio gbr_print(const struct gbr *p)
199714f4e3fSclaudio {
200714f4e3fSclaudio 	printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
201714f4e3fSclaudio 	printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
202714f4e3fSclaudio 	printf("Authority info access: %s\n", p->aia);
203714f4e3fSclaudio 	printf("vcard:\n%s", p->vcard);
204714f4e3fSclaudio }
205