xref: /openbsd/usr.sbin/rpki-client/filemode.c (revision 9e6efb0a)
1 /*	$OpenBSD: filemode.c,v 1.42 2024/05/20 15:51:43 claudio Exp $ */
2 /*
3  * Copyright (c) 2019 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/queue.h>
20 #include <sys/tree.h>
21 #include <sys/types.h>
22 
23 #include <assert.h>
24 #include <err.h>
25 #include <fcntl.h>
26 #include <poll.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <unistd.h>
32 #include <imsg.h>
33 
34 #include <openssl/asn1.h>
35 #include <openssl/err.h>
36 #include <openssl/evp.h>
37 #include <openssl/pem.h>
38 #include <openssl/x509.h>
39 #include <openssl/x509v3.h>
40 
41 #include "extern.h"
42 #include "json.h"
43 
44 static X509_STORE_CTX	*ctx;
45 static struct auth_tree	 auths = RB_INITIALIZER(&auths);
46 static struct crl_tree	 crlt = RB_INITIALIZER(&crlt);
47 
48 struct tal		*talobj[TALSZ_MAX];
49 
50 struct uripath {
51 	RB_ENTRY(uripath)	 entry;
52 	const char		*uri;
53 	struct cert		*cert;
54 };
55 
56 static RB_HEAD(uripath_tree, uripath) uritree;
57 
58 static inline int
59 uripathcmp(const struct uripath *a, const struct uripath *b)
60 {
61 	return strcmp(a->uri, b->uri);
62 }
63 
64 RB_PROTOTYPE(uripath_tree, uripath, entry, uripathcmp);
65 
66 static void
67 uripath_add(const char *uri, struct cert *cert)
68 {
69 	struct uripath *up;
70 
71 	if ((up = calloc(1, sizeof(*up))) == NULL)
72 		err(1, NULL);
73 	if ((up->uri = strdup(uri)) == NULL)
74 		err(1, NULL);
75 	up->cert = cert;
76 	if (RB_INSERT(uripath_tree, &uritree, up) != NULL)
77 		errx(1, "corrupt AIA lookup tree");
78 }
79 
80 static struct cert *
81 uripath_lookup(const char *uri)
82 {
83 	struct uripath needle = { .uri = uri };
84 	struct uripath *up;
85 
86 	up = RB_FIND(uripath_tree, &uritree, &needle);
87 	if (up == NULL)
88 		return NULL;
89 	return up->cert;
90 }
91 
92 RB_GENERATE(uripath_tree, uripath, entry, uripathcmp);
93 
94 /*
95  * Use the X509 CRL Distribution Points to locate the CRL needed for
96  * verification.
97  */
98 static void
99 parse_load_crl(char *uri)
100 {
101 	struct crl *crl;
102 	char *f;
103 	size_t flen;
104 
105 	if (uri == NULL)
106 		return;
107 	if (strncmp(uri, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0) {
108 		warnx("bad CRL distribution point URI %s", uri);
109 		return;
110 	}
111 	uri += RSYNC_PROTO_LEN;
112 
113 	f = load_file(uri, &flen);
114 	if (f == NULL) {
115 		warn("parse file %s", uri);
116 		return;
117 	}
118 
119 	crl = crl_parse(uri, f, flen);
120 	if (crl != NULL && !crl_insert(&crlt, crl))
121 		crl_free(crl);
122 
123 	free(f);
124 }
125 
126 /*
127  * Parse the cert pointed at by the AIA URI while doing that also load
128  * the CRL of this cert. While the CRL is validated the returned cert
129  * is not. The caller needs to make sure it is validated once all
130  * necessary certs were loaded. Returns NULL on failure.
131  */
132 static struct cert *
133 parse_load_cert(char *uri)
134 {
135 	struct cert *cert = NULL;
136 	char *f;
137 	size_t flen;
138 
139 	if (uri == NULL)
140 		return NULL;
141 
142 	if (strncmp(uri, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0) {
143 		warnx("bad authority information access URI %s", uri);
144 		return NULL;
145 	}
146 	uri += RSYNC_PROTO_LEN;
147 
148 	f = load_file(uri, &flen);
149 	if (f == NULL) {
150 		warn("parse file %s", uri);
151 		goto done;
152 	}
153 
154 	cert = cert_parse_pre(uri, f, flen);
155 	free(f);
156 
157 	if (cert == NULL)
158 		goto done;
159 	if (cert->purpose != CERT_PURPOSE_CA) {
160 		warnx("AIA reference to bgpsec cert %s", uri);
161 		goto done;
162 	}
163 	/* try to load the CRL of this cert */
164 	parse_load_crl(cert->crl);
165 
166 	return cert;
167 
168  done:
169 	cert_free(cert);
170 	return NULL;
171 }
172 
173 /*
174  * Build the certificate chain by using the Authority Information Access.
175  * This requires that the TA are already validated and added to the auths
176  * tree. Once the TA is located in the chain the chain is validated in
177  * reverse order.
178  */
179 static struct auth *
180 parse_load_certchain(char *uri)
181 {
182 	struct cert *stack[MAX_CERT_DEPTH] = { 0 };
183 	char *filestack[MAX_CERT_DEPTH];
184 	struct cert *cert;
185 	struct crl *crl;
186 	struct auth *a;
187 	const char *errstr;
188 	int i;
189 
190 	for (i = 0; i < MAX_CERT_DEPTH; i++) {
191 		if ((cert = uripath_lookup(uri)) != NULL) {
192 			a = auth_find(&auths, cert->certid);
193 			break;
194 		}
195 		filestack[i] = uri;
196 		stack[i] = cert = parse_load_cert(uri);
197 		if (cert == NULL || cert->purpose != CERT_PURPOSE_CA) {
198 			warnx("failed to build authority chain: %s", uri);
199 			goto fail;
200 		}
201 		uri = cert->aia;
202 	}
203 
204 	if (i >= MAX_CERT_DEPTH) {
205 		warnx("authority chain exceeds max depth of %d",
206 		    MAX_CERT_DEPTH);
207 		goto fail;
208 	}
209 
210 	/* TA found play back the stack and add all certs */
211 	for (; i > 0; i--) {
212 		cert = stack[i - 1];
213 		uri = filestack[i - 1];
214 
215 		crl = crl_get(&crlt, a);
216 		if (!valid_x509(uri, ctx, cert->x509, a, crl, &errstr) ||
217 		    !valid_cert(uri, a, cert)) {
218 			if (errstr != NULL)
219 				warnx("%s: %s", uri, errstr);
220 			goto fail;
221 		}
222 		cert->talid = a->cert->talid;
223 		a = auth_insert(uri, &auths, cert, a);
224 		uripath_add(uri, cert);
225 		stack[i] = NULL;
226 	}
227 
228 	return a;
229 fail:
230 	for (i = 0; i < MAX_CERT_DEPTH; i++)
231 		cert_free(stack[i]);
232 	return NULL;
233 }
234 
235 static void
236 parse_load_ta(struct tal *tal)
237 {
238 	const char *filename;
239 	struct cert *cert;
240 	unsigned char *f = NULL;
241 	char *file;
242 	size_t flen, i;
243 
244 	/* does not matter which URI, all end with same filename */
245 	filename = strrchr(tal->uri[0], '/');
246 	assert(filename);
247 
248 	if (asprintf(&file, "ta/%s%s", tal->descr, filename) == -1)
249 		err(1, NULL);
250 
251 	f = load_file(file, &flen);
252 	if (f == NULL) {
253 		warn("parse file %s", file);
254 		goto out;
255 	}
256 
257 	/* Extract certificate data. */
258 	cert = cert_parse_pre(file, f, flen);
259 	cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
260 	if (cert == NULL)
261 		goto out;
262 
263 	cert->talid = tal->id;
264 	auth_insert(file, &auths, cert, NULL);
265 	for (i = 0; i < tal->urisz; i++) {
266 		if (strncasecmp(tal->uri[i], RSYNC_PROTO, RSYNC_PROTO_LEN) != 0)
267 			continue;
268 		/* Add all rsync uri since any of them could be used as AIA. */
269 		uripath_add(tal->uri[i], cert);
270 	}
271 
272 out:
273 	free(file);
274 	free(f);
275 }
276 
277 static struct tal *
278 find_tal(struct cert *cert)
279 {
280 	EVP_PKEY	*pk, *opk;
281 	struct tal	*tal;
282 	int		 i;
283 
284 	if ((opk = X509_get0_pubkey(cert->x509)) == NULL)
285 		return NULL;
286 
287 	for (i = 0; i < TALSZ_MAX; i++) {
288 		const unsigned char *pkey;
289 
290 		if (talobj[i] == NULL)
291 			break;
292 		tal = talobj[i];
293 		pkey = tal->pkey;
294 		pk = d2i_PUBKEY(NULL, &pkey, tal->pkeysz);
295 		if (pk == NULL)
296 			continue;
297 		if (EVP_PKEY_cmp(pk, opk) == 1) {
298 			EVP_PKEY_free(pk);
299 			return tal;
300 		}
301 		EVP_PKEY_free(pk);
302 	}
303 	return NULL;
304 }
305 
306 static void
307 print_signature_path(const char *crl, const char *aia, const struct auth *a)
308 {
309 	if (crl != NULL)
310 		printf("Signature path:           %s\n", crl);
311 	if (a->cert->mft != NULL)
312 		printf("                          %s\n", a->cert->mft);
313 	if (aia != NULL)
314 		printf("                          %s\n", aia);
315 
316 	for (; a != NULL; a = a->issuer) {
317 		if (a->cert->crl != NULL)
318 			printf("                          %s\n", a->cert->crl);
319 		if (a->issuer != NULL && a->issuer->cert != NULL &&
320 		    a->issuer->cert->mft != NULL)
321 			printf("                          %s\n",
322 			    a->issuer->cert->mft);
323 		if (a->cert->aia != NULL)
324 			printf("                          %s\n", a->cert->aia);
325 	}
326 }
327 
328 /*
329  * Parse file passed with -f option.
330  */
331 static void
332 proc_parser_file(char *file, unsigned char *buf, size_t len)
333 {
334 	static int num;
335 	X509 *x509 = NULL;
336 	struct aspa *aspa = NULL;
337 	struct cert *cert = NULL;
338 	struct crl *crl = NULL;
339 	struct gbr *gbr = NULL;
340 	struct geofeed *geofeed = NULL;
341 	struct mft *mft = NULL;
342 	struct roa *roa = NULL;
343 	struct rsc *rsc = NULL;
344 	struct spl *spl = NULL;
345 	struct tak *tak = NULL;
346 	struct tal *tal = NULL;
347 	char *aia = NULL;
348 	char *crl_uri = NULL;
349 	time_t *expires = NULL, *notafter = NULL;
350 	struct auth *a;
351 	struct crl *c;
352 	const char *errstr = NULL, *valid;
353 	int status = 0;
354 	char filehash[SHA256_DIGEST_LENGTH];
355 	char *hash;
356 	enum rtype type;
357 	int is_ta = 0;
358 
359 	if (outformats & FORMAT_JSON) {
360 		json_do_start(stdout);
361 	} else {
362 		if (num++ > 0)
363 			printf("--\n");
364 	}
365 
366 	if (strncmp(file, RSYNC_PROTO, RSYNC_PROTO_LEN) == 0) {
367 		file += RSYNC_PROTO_LEN;
368 		buf = load_file(file, &len);
369 		if (buf == NULL) {
370 			warn("parse file %s", file);
371 			return;
372 		}
373 	}
374 
375 	if (!EVP_Digest(buf, len, filehash, NULL, EVP_sha256(), NULL))
376 		errx(1, "EVP_Digest failed in %s", __func__);
377 
378 	if (base64_encode(filehash, sizeof(filehash), &hash) == -1)
379 		errx(1, "base64_encode failed in %s", __func__);
380 
381 	if (outformats & FORMAT_JSON) {
382 		json_do_string("file", file);
383 		json_do_string("hash_id", hash);
384 	} else {
385 		printf("File:                     %s\n", file);
386 		printf("Hash identifier:          %s\n", hash);
387 	}
388 
389 	free(hash);
390 
391 	type = rtype_from_file_extension(file);
392 
393 	switch (type) {
394 	case RTYPE_ASPA:
395 		aspa = aspa_parse(&x509, file, -1, buf, len);
396 		if (aspa == NULL)
397 			break;
398 		aia = aspa->aia;
399 		expires = &aspa->expires;
400 		notafter = &aspa->notafter;
401 		break;
402 	case RTYPE_CER:
403 		cert = cert_parse_pre(file, buf, len);
404 		if (cert == NULL)
405 			break;
406 		is_ta = X509_get_extension_flags(cert->x509) & EXFLAG_SS;
407 		if (!is_ta)
408 			cert = cert_parse(file, cert);
409 		if (cert == NULL)
410 			break;
411 		aia = cert->aia;
412 		x509 = cert->x509;
413 		if (X509_up_ref(x509) == 0)
414 			errx(1, "%s: X509_up_ref failed", __func__);
415 		expires = &cert->expires;
416 		notafter = &cert->notafter;
417 		break;
418 	case RTYPE_CRL:
419 		crl = crl_parse(file, buf, len);
420 		if (crl == NULL)
421 			break;
422 		crl_print(crl);
423 		break;
424 	case RTYPE_MFT:
425 		mft = mft_parse(&x509, file, -1, buf, len);
426 		if (mft == NULL)
427 			break;
428 		aia = mft->aia;
429 		expires = &mft->expires;
430 		notafter = &mft->nextupdate;
431 		break;
432 	case RTYPE_GBR:
433 		gbr = gbr_parse(&x509, file, -1, buf, len);
434 		if (gbr == NULL)
435 			break;
436 		aia = gbr->aia;
437 		expires = &gbr->expires;
438 		notafter = &gbr->notafter;
439 		break;
440 	case RTYPE_GEOFEED:
441 		geofeed = geofeed_parse(&x509, file, -1, buf, len);
442 		if (geofeed == NULL)
443 			break;
444 		aia = geofeed->aia;
445 		expires = &geofeed->expires;
446 		notafter = &geofeed->notafter;
447 		break;
448 	case RTYPE_ROA:
449 		roa = roa_parse(&x509, file, -1, buf, len);
450 		if (roa == NULL)
451 			break;
452 		aia = roa->aia;
453 		expires = &roa->expires;
454 		notafter = &roa->notafter;
455 		break;
456 	case RTYPE_RSC:
457 		rsc = rsc_parse(&x509, file, -1, buf, len);
458 		if (rsc == NULL)
459 			break;
460 		aia = rsc->aia;
461 		expires = &rsc->expires;
462 		notafter = &rsc->notafter;
463 		break;
464 	case RTYPE_SPL:
465 		spl = spl_parse(&x509, file, -1, buf, len);
466 		if (spl == NULL)
467 			break;
468 		aia = spl->aia;
469 		expires = &spl->expires;
470 		notafter = &spl->notafter;
471 		break;
472 	case RTYPE_TAK:
473 		tak = tak_parse(&x509, file, -1, buf, len);
474 		if (tak == NULL)
475 			break;
476 		aia = tak->aia;
477 		expires = &tak->expires;
478 		notafter = &tak->notafter;
479 		break;
480 	case RTYPE_TAL:
481 		tal = tal_parse(file, buf, len);
482 		if (tal == NULL)
483 			break;
484 		tal_print(tal);
485 		break;
486 	default:
487 		printf("%s: unsupported file type\n", file);
488 		break;
489 	}
490 
491 	if (aia != NULL) {
492 		x509_get_crl(x509, file, &crl_uri);
493 		parse_load_crl(crl_uri);
494 		a = parse_load_certchain(aia);
495 		c = crl_get(&crlt, a);
496 
497 		if ((status = valid_x509(file, ctx, x509, a, c, &errstr))) {
498 			switch (type) {
499 			case RTYPE_ASPA:
500 				status = aspa->valid;
501 				break;
502 			case RTYPE_GEOFEED:
503 				status = geofeed->valid;
504 				break;
505 			case RTYPE_ROA:
506 				status = roa->valid;
507 				break;
508 			case RTYPE_RSC:
509 				status = rsc->valid;
510 				break;
511 			case RTYPE_SPL:
512 				status = spl->valid;
513 			default:
514 				break;
515 			}
516 		}
517 		if (status && cert == NULL) {
518 			struct cert *eecert;
519 
520 			eecert = cert_parse_ee_cert(file, a->cert->talid, x509);
521 			if (eecert == NULL)
522 				status = 0;
523 			cert_free(eecert);
524 		} else if (status) {
525 			cert->talid = a->cert->talid;
526 			constraints_validate(file, cert);
527 		}
528 	} else if (is_ta) {
529 		if ((tal = find_tal(cert)) != NULL) {
530 			cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
531 			status = (cert != NULL);
532 			if (outformats & FORMAT_JSON)
533 				json_do_string("tal", tal->descr);
534 			else
535 				printf("TAL:                      %s\n",
536 				    tal->descr);
537 			tal = NULL;
538 		} else {
539 			cert_free(cert);
540 			cert = NULL;
541 			expires = NULL;
542 			status = 0;
543 		}
544 	}
545 
546 	if (expires != NULL) {
547 		if (status && aia != NULL)
548 			*expires = x509_find_expires(*notafter, a, &crlt);
549 
550 		switch (type) {
551 		case RTYPE_ASPA:
552 			aspa_print(x509, aspa);
553 			break;
554 		case RTYPE_CER:
555 			cert_print(cert);
556 			break;
557 		case RTYPE_GBR:
558 			gbr_print(x509, gbr);
559 			break;
560 		case RTYPE_GEOFEED:
561 			geofeed_print(x509, geofeed);
562 			break;
563 		case RTYPE_MFT:
564 			mft_print(x509, mft);
565 			break;
566 		case RTYPE_ROA:
567 			roa_print(x509, roa);
568 			break;
569 		case RTYPE_RSC:
570 			rsc_print(x509, rsc);
571 			break;
572 		case RTYPE_SPL:
573 			spl_print(x509, spl);
574 			break;
575 		case RTYPE_TAK:
576 			tak_print(x509, tak);
577 			break;
578 		default:
579 			break;
580 		}
581 	}
582 
583 	if (status)
584 		valid = "OK";
585 	else if (aia == NULL)
586 		valid = "N/A";
587 	else
588 		valid = "Failed";
589 
590 	if (outformats & FORMAT_JSON) {
591 		json_do_string("validation", valid);
592 		if (errstr != NULL)
593 			json_do_string("error", errstr);
594 	} else {
595 		printf("Validation:               %s", valid);
596 		if (errstr != NULL)
597 			printf(", %s", errstr);
598 	}
599 
600 	if (outformats & FORMAT_JSON)
601 		json_do_finish();
602 	else {
603 		printf("\n");
604 
605 		if (status && aia != NULL) {
606 			print_signature_path(crl_uri, aia, a);
607 			if (expires != NULL)
608 				printf("Signature path expires:   %s\n",
609 				    time2str(*expires));
610 		}
611 
612 		if (x509 == NULL)
613 			goto out;
614 		if (type == RTYPE_TAL || type == RTYPE_CRL)
615 			goto out;
616 
617 		if (verbose) {
618 			if (!X509_print_fp(stdout, x509))
619 				errx(1, "X509_print_fp");
620 		}
621 
622 		if (verbose > 1) {
623 			if (!PEM_write_X509(stdout, x509))
624 				errx(1, "PEM_write_X509");
625 		}
626 	}
627 
628  out:
629 	free(crl_uri);
630 	X509_free(x509);
631 	aspa_free(aspa);
632 	cert_free(cert);
633 	crl_free(crl);
634 	gbr_free(gbr);
635 	geofeed_free(geofeed);
636 	mft_free(mft);
637 	roa_free(roa);
638 	rsc_free(rsc);
639 	tak_free(tak);
640 	tal_free(tal);
641 }
642 
643 /*
644  * Process a file request, in general don't send anything back.
645  */
646 static void
647 parse_file(struct entityq *q, struct msgbuf *msgq)
648 {
649 	struct entity	*entp;
650 	struct ibuf	*b;
651 	struct tal	*tal;
652 	time_t		 dummy = 0;
653 
654 	while ((entp = TAILQ_FIRST(q)) != NULL) {
655 		TAILQ_REMOVE(q, entp, entries);
656 
657 		switch (entp->type) {
658 		case RTYPE_FILE:
659 			proc_parser_file(entp->file, entp->data, entp->datasz);
660 			break;
661 		case RTYPE_TAL:
662 			if ((tal = tal_parse(entp->file, entp->data,
663 			    entp->datasz)) == NULL)
664 				errx(1, "%s: could not parse tal file",
665 				    entp->file);
666 			tal->id = entp->talid;
667 			talobj[tal->id] = tal;
668 			parse_load_ta(tal);
669 			break;
670 		default:
671 			errx(1, "unhandled entity type %d", entp->type);
672 		}
673 
674 		b = io_new_buffer();
675 		io_simple_buffer(b, &entp->type, sizeof(entp->type));
676 		io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid));
677 		io_simple_buffer(b, &entp->talid, sizeof(entp->talid));
678 		io_str_buffer(b, entp->file);
679 		io_simple_buffer(b, &dummy, sizeof(dummy));
680 		io_close_buffer(msgq, b);
681 		entity_free(entp);
682 	}
683 }
684 
685 /*
686  * Process responsible for parsing and validating content.
687  * All this process does is wait to be told about a file to parse, then
688  * it parses it and makes sure that the data being returned is fully
689  * validated and verified.
690  * The process will exit cleanly only when fd is closed.
691  */
692 void
693 proc_filemode(int fd)
694 {
695 	struct entityq	 q;
696 	struct msgbuf	 msgq;
697 	struct pollfd	 pfd;
698 	struct entity	*entp;
699 	struct ibuf	*b, *inbuf = NULL;
700 
701 	/* Only allow access to the cache directory. */
702 	if (unveil(".", "r") == -1)
703 		err(1, "unveil cachedir");
704 	if (pledge("stdio rpath", NULL) == -1)
705 		err(1, "pledge");
706 
707 	ERR_load_crypto_strings();
708 	OpenSSL_add_all_ciphers();
709 	OpenSSL_add_all_digests();
710 	x509_init_oid();
711 	constraints_parse();
712 
713 	if ((ctx = X509_STORE_CTX_new()) == NULL)
714 		err(1, "X509_STORE_CTX_new");
715 	TAILQ_INIT(&q);
716 
717 	msgbuf_init(&msgq);
718 	msgq.fd = fd;
719 
720 	pfd.fd = fd;
721 
722 	for (;;) {
723 		pfd.events = POLLIN;
724 		if (msgq.queued)
725 			pfd.events |= POLLOUT;
726 
727 		if (poll(&pfd, 1, INFTIM) == -1) {
728 			if (errno == EINTR)
729 				continue;
730 			err(1, "poll");
731 		}
732 		if ((pfd.revents & (POLLERR|POLLNVAL)))
733 			errx(1, "poll: bad descriptor");
734 
735 		/* If the parent closes, return immediately. */
736 
737 		if ((pfd.revents & POLLHUP))
738 			break;
739 
740 		if ((pfd.revents & POLLIN)) {
741 			b = io_buf_read(fd, &inbuf);
742 			if (b != NULL) {
743 				entp = calloc(1, sizeof(struct entity));
744 				if (entp == NULL)
745 					err(1, NULL);
746 				entity_read_req(b, entp);
747 				TAILQ_INSERT_TAIL(&q, entp, entries);
748 				ibuf_free(b);
749 			}
750 		}
751 
752 		if (pfd.revents & POLLOUT) {
753 			switch (msgbuf_write(&msgq)) {
754 			case 0:
755 				errx(1, "write: connection closed");
756 			case -1:
757 				err(1, "write");
758 			}
759 		}
760 
761 		parse_file(&q, &msgq);
762 	}
763 
764 	msgbuf_clear(&msgq);
765 	while ((entp = TAILQ_FIRST(&q)) != NULL) {
766 		TAILQ_REMOVE(&q, entp, entries);
767 		entity_free(entp);
768 	}
769 
770 	auth_tree_free(&auths);
771 	crl_tree_free(&crlt);
772 
773 	X509_STORE_CTX_free(ctx);
774 	ibuf_free(inbuf);
775 
776 	exit(0);
777 }
778