xref: /openbsd-src/usr.sbin/rpki-client/parser.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
1 /*	$OpenBSD: parser.c,v 1.94 2023/05/11 20:13:30 job 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 <err.h>
24 #include <fcntl.h>
25 #include <poll.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <unistd.h>
31 #include <imsg.h>
32 
33 #include <openssl/asn1.h>
34 #include <openssl/err.h>
35 #include <openssl/evp.h>
36 #include <openssl/x509.h>
37 #include <openssl/x509v3.h>
38 
39 #include "extern.h"
40 
41 static X509_STORE_CTX	*ctx;
42 static struct auth_tree	 auths = RB_INITIALIZER(&auths);
43 static struct crl_tree	 crlt = RB_INITIALIZER(&crlt);
44 
45 struct parse_repo {
46 	RB_ENTRY(parse_repo)	 entry;
47 	char			*path;
48 	char			*validpath;
49 	unsigned int		 id;
50 };
51 
52 static RB_HEAD(repo_tree, parse_repo)	repos = RB_INITIALIZER(&repos);
53 
54 static inline int
55 repocmp(struct parse_repo *a, struct parse_repo *b)
56 {
57 	return a->id - b->id;
58 }
59 
60 RB_GENERATE_STATIC(repo_tree, parse_repo, entry, repocmp);
61 
62 static struct parse_repo *
63 repo_get(unsigned int id)
64 {
65 	struct parse_repo needle = { .id = id };
66 
67 	return RB_FIND(repo_tree, &repos, &needle);
68 }
69 
70 static void
71 repo_add(unsigned int id, char *path, char *validpath)
72 {
73 	struct parse_repo *rp;
74 
75 	if ((rp = calloc(1, sizeof(*rp))) == NULL)
76 		err(1, NULL);
77 	rp->id = id;
78 	if (path != NULL)
79 		if ((rp->path = strdup(path)) == NULL)
80 			err(1, NULL);
81 	if (validpath != NULL)
82 		if ((rp->validpath = strdup(validpath)) == NULL)
83 			err(1, NULL);
84 
85 	if (RB_INSERT(repo_tree, &repos, rp) != NULL)
86 		errx(1, "repository already added: id %d, %s", id, path);
87 }
88 
89 /*
90  * Build access path to file based on repoid, path, location and file values.
91  */
92 static char *
93 parse_filepath(unsigned int repoid, const char *path, const char *file,
94     enum location loc)
95 {
96 	struct parse_repo	*rp;
97 	char			*fn, *repopath;
98 
99 	/* build file path based on repoid, entity path and filename */
100 	rp = repo_get(repoid);
101 	if (rp == NULL)
102 		errx(1, "build file path: repository %u missing", repoid);
103 
104 	if (loc == DIR_VALID)
105 		repopath = rp->validpath;
106 	else
107 		repopath = rp->path;
108 
109 	if (repopath == NULL)
110 		return NULL;
111 
112 	if (path == NULL) {
113 		if (asprintf(&fn, "%s/%s", repopath, file) == -1)
114 			err(1, NULL);
115 	} else {
116 		if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1)
117 			err(1, NULL);
118 	}
119 	return fn;
120 }
121 
122 /*
123  * Parse and validate a ROA.
124  * This is standard stuff.
125  * Returns the roa on success, NULL on failure.
126  */
127 static struct roa *
128 proc_parser_roa(char *file, const unsigned char *der, size_t len,
129     const char *mftaki)
130 {
131 	struct roa		*roa;
132 	struct auth		*a;
133 	struct crl		*crl;
134 	X509			*x509;
135 	const char		*errstr;
136 
137 	if ((roa = roa_parse(&x509, file, der, len)) == NULL)
138 		return NULL;
139 
140 	a = valid_ski_aki(file, &auths, roa->ski, roa->aki, mftaki);
141 	crl = crl_get(&crlt, a);
142 
143 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
144 		warnx("%s: %s", file, errstr);
145 		X509_free(x509);
146 		roa_free(roa);
147 		return NULL;
148 	}
149 	X509_free(x509);
150 
151 	roa->talid = a->cert->talid;
152 
153 	roa->expires = x509_find_expires(roa->notafter, a, &crlt);
154 
155 	return roa;
156 }
157 
158 /*
159  * Check all files and their hashes in a MFT structure.
160  * Return zero on failure, non-zero on success.
161  */
162 static int
163 proc_parser_mft_check(const char *fn, struct mft *p)
164 {
165 	const enum location loc[2] = { DIR_TEMP, DIR_VALID };
166 	size_t	 i;
167 	int	 rc = 1;
168 	char	*path;
169 
170 	for (i = 0; i < p->filesz; i++) {
171 		struct mftfile *m = &p->files[i];
172 		int try, fd = -1, noent = 0, valid = 0;
173 		for (try = 0; try < 2 && !valid; try++) {
174 			if ((path = parse_filepath(p->repoid, p->path, m->file,
175 			    loc[try])) == NULL)
176 				continue;
177 			fd = open(path, O_RDONLY);
178 			if (fd == -1 && errno == ENOENT)
179 				noent++;
180 			free(path);
181 
182 			/* remember which path was checked */
183 			m->location = loc[try];
184 			valid = valid_filehash(fd, m->hash, sizeof(m->hash));
185 		}
186 
187 		if (!valid) {
188 			/* silently skip not-existing unknown files */
189 			if (m->type == RTYPE_INVALID && noent == 2)
190 				continue;
191 			warnx("%s#%s: bad message digest for %s", fn,
192 			    p->seqnum, m->file);
193 			rc = 0;
194 			continue;
195 		}
196 	}
197 
198 	return rc;
199 }
200 
201 /*
202  * Load the CRL from loc using the info from the MFT.
203  */
204 static struct crl *
205 parse_load_crl_from_mft(struct entity *entp, struct mft *mft, enum location loc,
206     char **crlfile)
207 {
208 	struct crl	*crl = NULL;
209 	unsigned char	*f = NULL;
210 	char		*fn = NULL;
211 	size_t		 flen;
212 
213 	*crlfile = NULL;
214 
215 	fn = parse_filepath(entp->repoid, entp->path, mft->crl, loc);
216 	if (fn == NULL)
217 		goto out;
218 
219 	f = load_file(fn, &flen);
220 	if (f == NULL) {
221 		if (errno != ENOENT)
222 			warn("parse file %s", fn);
223 		goto out;
224 	}
225 
226 	if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash)))
227 		goto out;
228 
229 	crl = crl_parse(fn, f, flen);
230 	if (crl == NULL)
231 		goto out;
232 
233 	if (strcmp(crl->aki, mft->aki) != 0) {
234 		warnx("%s: AKI doesn't match Manifest AKI", fn);
235 		goto out;
236 	}
237 
238 	*crlfile = fn;
239 	free(f);
240 
241 	return crl;
242 
243  out:
244 	crl_free(crl);
245 	free(f);
246 	free(fn);
247 
248 	return NULL;
249 }
250 
251 /*
252  * Parse and validate a manifest file. Skip checking the fileandhash
253  * this is done in the post check. After this step we know the mft is
254  * valid and can be compared.
255  * Return the mft on success or NULL on failure.
256  */
257 static struct mft *
258 proc_parser_mft_pre(struct entity *entp, enum location loc, char **file,
259     struct crl **crl, char **crlfile, const char **errstr)
260 {
261 	struct mft	*mft;
262 	X509		*x509;
263 	struct auth	*a;
264 	unsigned char	*der;
265 	size_t		 len;
266 
267 	*crl = NULL;
268 	*crlfile = NULL;
269 	*errstr = NULL;
270 
271 	*file = parse_filepath(entp->repoid, entp->path, entp->file, loc);
272 	if (*file == NULL)
273 		return NULL;
274 
275 	der = load_file(*file, &len);
276 	if (der == NULL && errno != ENOENT)
277 		warn("parse file %s", *file);
278 
279 	if ((mft = mft_parse(&x509, *file, der, len)) == NULL) {
280 		free(der);
281 		return NULL;
282 	}
283 	free(der);
284 
285 	*crl = parse_load_crl_from_mft(entp, mft, DIR_TEMP, crlfile);
286 	if (*crl == NULL)
287 		*crl = parse_load_crl_from_mft(entp, mft, DIR_VALID, crlfile);
288 
289 	a = valid_ski_aki(*file, &auths, mft->ski, mft->aki, NULL);
290 	if (!valid_x509(*file, ctx, x509, a, *crl, errstr)) {
291 		X509_free(x509);
292 		mft_free(mft);
293 		crl_free(*crl);
294 		*crl = NULL;
295 		free(*crlfile);
296 		*crlfile = NULL;
297 		return NULL;
298 	}
299 	X509_free(x509);
300 
301 	mft->repoid = entp->repoid;
302 	mft->talid = a->cert->talid;
303 
304 	return mft;
305 }
306 
307 /*
308  * Do the end of manifest validation.
309  * Return the mft on success or NULL on failure.
310  */
311 static struct mft *
312 proc_parser_mft_post(char *file, struct mft *mft, const char *path,
313     const char *errstr)
314 {
315 	if (mft == NULL) {
316 		if (errstr == NULL)
317 			errstr = "no valid mft available";
318 		warnx("%s: %s", file, errstr);
319 		return NULL;
320 	}
321 
322 	/* check that evaluation_time is not before from */
323 	if (evaluation_time < mft->thisupdate) {
324 		warnx("%s: mft not yet valid %s", file,
325 		    time2str(mft->thisupdate));
326 		mft->stale = 1;
327 	}
328 	/* check that evaluation_time is not after until */
329 	if (evaluation_time > mft->nextupdate) {
330 		warnx("%s: mft expired on %s", file,
331 		    time2str(mft->nextupdate));
332 		mft->stale = 1;
333 	}
334 
335 	if (path != NULL)
336 		if ((mft->path = strdup(path)) == NULL)
337 			err(1, NULL);
338 
339 	if (!mft->stale)
340 		if (!proc_parser_mft_check(file, mft)) {
341 			mft_free(mft);
342 			return NULL;
343 		}
344 
345 	return mft;
346 }
347 
348 /*
349  * Load the most recent MFT by opening both options and comparing the two.
350  */
351 static char *
352 proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile)
353 {
354 	struct mft	*mft1 = NULL, *mft2 = NULL;
355 	struct crl	*crl, *crl1, *crl2;
356 	char		*file, *file1, *file2, *crl1file, *crl2file;
357 	const char	*err1, *err2;
358 
359 	*mp = NULL;
360 
361 	mft1 = proc_parser_mft_pre(entp, DIR_VALID, &file1, &crl1, &crl1file,
362 	    &err1);
363 	mft2 = proc_parser_mft_pre(entp, DIR_TEMP, &file2, &crl2, &crl2file,
364 	    &err2);
365 
366 	/* overload error from temp file if it is set */
367 	if (mft1 == NULL && mft2 == NULL)
368 		if (err2 != NULL)
369 			err1 = err2;
370 
371 	if (mft_compare(mft1, mft2) == 1) {
372 		mft_free(mft2);
373 		crl_free(crl2);
374 		free(crl2file);
375 		free(file2);
376 		*mp = proc_parser_mft_post(file1, mft1, entp->path, err1);
377 		crl = crl1;
378 		file = file1;
379 		*crlfile = crl1file;
380 	} else {
381 		mft_free(mft1);
382 		crl_free(crl1);
383 		free(crl1file);
384 		free(file1);
385 		*mp = proc_parser_mft_post(file2, mft2, entp->path, err2);
386 		crl = crl2;
387 		file = file2;
388 		*crlfile = crl2file;
389 	}
390 
391 	if (*mp != NULL) {
392 		if (!crl_insert(&crlt, crl)) {
393 			warnx("%s: duplicate AKI %s", file, crl->aki);
394 			crl_free(crl);
395 		}
396 	} else {
397 		crl_free(crl);
398 	}
399 	return file;
400 }
401 
402 /*
403  * Certificates are from manifests (has a digest and is signed with
404  * another certificate) Parse the certificate, make sure its
405  * signatures are valid (with CRLs), then validate the RPKI content.
406  * This returns a certificate (which must not be freed) or NULL on
407  * parse failure.
408  */
409 static struct cert *
410 proc_parser_cert(char *file, const unsigned char *der, size_t len,
411     const char *mftaki)
412 {
413 	struct cert	*cert;
414 	struct crl	*crl;
415 	struct auth	*a;
416 	const char	*errstr = NULL;
417 
418 	/* Extract certificate data. */
419 
420 	cert = cert_parse_pre(file, der, len);
421 	cert = cert_parse(file, cert);
422 	if (cert == NULL)
423 		return NULL;
424 
425 	a = valid_ski_aki(file, &auths, cert->ski, cert->aki, mftaki);
426 	crl = crl_get(&crlt, a);
427 
428 	if (!valid_x509(file, ctx, cert->x509, a, crl, &errstr) ||
429 	    !valid_cert(file, a, cert)) {
430 		if (errstr != NULL)
431 			warnx("%s: %s", file, errstr);
432 		cert_free(cert);
433 		return NULL;
434 	}
435 
436 	cert->talid = a->cert->talid;
437 
438 	/*
439 	 * Add validated CA certs to the RPKI auth tree.
440 	 */
441 	if (cert->purpose == CERT_PURPOSE_CA)
442 		auth_insert(&auths, cert, a);
443 
444 	return cert;
445 }
446 
447 /*
448  * Root certificates come from TALs (has a pkey and is self-signed).
449  * Parse the certificate, ensure that its public key matches the
450  * known public key from the TAL, and then validate the RPKI
451  * content.
452  *
453  * This returns a certificate (which must not be freed) or NULL on
454  * parse failure.
455  */
456 static struct cert *
457 proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
458     unsigned char *pkey, size_t pkeysz, int talid)
459 {
460 	struct cert		*cert;
461 
462 	/* Extract certificate data. */
463 
464 	cert = cert_parse_pre(file, der, len);
465 	cert = ta_parse(file, cert, pkey, pkeysz);
466 	if (cert == NULL)
467 		return NULL;
468 
469 	if (!valid_ta(file, &auths, cert)) {
470 		warnx("%s: certificate not a valid ta", file);
471 		cert_free(cert);
472 		return NULL;
473 	}
474 
475 	cert->talid = talid;
476 
477 	/*
478 	 * Add valid roots to the RPKI auth tree.
479 	 */
480 	auth_insert(&auths, cert, NULL);
481 
482 	return cert;
483 }
484 
485 /*
486  * Parse a ghostbuster record
487  */
488 static void
489 proc_parser_gbr(char *file, const unsigned char *der, size_t len,
490     const char *mftaki)
491 {
492 	struct gbr	*gbr;
493 	X509		*x509;
494 	struct crl	*crl;
495 	struct auth	*a;
496 	const char	*errstr;
497 
498 	if ((gbr = gbr_parse(&x509, file, der, len)) == NULL)
499 		return;
500 
501 	a = valid_ski_aki(file, &auths, gbr->ski, gbr->aki, mftaki);
502 	crl = crl_get(&crlt, a);
503 
504 	/* return value can be ignored since nothing happens here */
505 	if (!valid_x509(file, ctx, x509, a, crl, &errstr))
506 		warnx("%s: %s", file, errstr);
507 
508 	X509_free(x509);
509 	gbr_free(gbr);
510 }
511 
512 /*
513  * Parse an ASPA object
514  */
515 static struct aspa *
516 proc_parser_aspa(char *file, const unsigned char *der, size_t len,
517     const char *mftaki)
518 {
519 	struct aspa	*aspa;
520 	struct auth	*a;
521 	struct crl	*crl;
522 	X509		*x509;
523 	const char	*errstr;
524 
525 	if ((aspa = aspa_parse(&x509, file, der, len)) == NULL)
526 		return NULL;
527 
528 	a = valid_ski_aki(file, &auths, aspa->ski, aspa->aki, mftaki);
529 	crl = crl_get(&crlt, a);
530 
531 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
532 		warnx("%s: %s", file, errstr);
533 		X509_free(x509);
534 		aspa_free(aspa);
535 		return NULL;
536 	}
537 	X509_free(x509);
538 
539 	aspa->talid = a->cert->talid;
540 
541 	aspa->expires = x509_find_expires(aspa->notafter, a, &crlt);
542 
543 	return aspa;
544 }
545 
546 /*
547  * Parse a TAK object.
548  */
549 static struct tak *
550 proc_parser_tak(char *file, const unsigned char *der, size_t len,
551     const char *mftaki)
552 {
553 	struct tak	*tak;
554 	X509		*x509;
555 	struct crl	*crl;
556 	struct auth	*a;
557 	const char	*errstr;
558 	int		 rc = 0;
559 
560 	if ((tak = tak_parse(&x509, file, der, len)) == NULL)
561 		return NULL;
562 
563 	a = valid_ski_aki(file, &auths, tak->ski, tak->aki, mftaki);
564 	crl = crl_get(&crlt, a);
565 
566 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
567 		warnx("%s: %s", file, errstr);
568 		goto out;
569 	}
570 
571 	/* TAK EE must be signed by self-signed CA */
572 	if (a->parent != NULL)
573 		goto out;
574 
575 	tak->talid = a->cert->talid;
576 	rc = 1;
577  out:
578 	if (rc == 0) {
579 		tak_free(tak);
580 		tak = NULL;
581 	}
582 	X509_free(x509);
583 	return tak;
584 }
585 
586 /*
587  * Load the file specified by the entity information.
588  */
589 static char *
590 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen)
591 {
592 	char *file;
593 
594 	file = parse_filepath(entp->repoid, entp->path, entp->file,
595 	    entp->location);
596 	if (file == NULL)
597 		errx(1, "no path to file");
598 
599 	*f = load_file(file, flen);
600 	if (*f == NULL)
601 		warn("parse file %s", file);
602 
603 	return file;
604 }
605 
606 /*
607  * Process an entity and responing to parent process.
608  */
609 static void
610 parse_entity(struct entityq *q, struct msgbuf *msgq)
611 {
612 	struct entity	*entp;
613 	struct tal	*tal;
614 	struct cert	*cert;
615 	struct mft	*mft;
616 	struct roa	*roa;
617 	struct aspa	*aspa;
618 	struct ibuf	*b;
619 	unsigned char	*f;
620 	size_t		 flen;
621 	char		*file, *crlfile;
622 	int		 c;
623 
624 	while ((entp = TAILQ_FIRST(q)) != NULL) {
625 		TAILQ_REMOVE(q, entp, entries);
626 
627 		/* handle RTYPE_REPO first */
628 		if (entp->type == RTYPE_REPO) {
629 			repo_add(entp->repoid, entp->path, entp->file);
630 			entity_free(entp);
631 			continue;
632 		}
633 
634 		/* pass back at least type, repoid and filename */
635 		b = io_new_buffer();
636 		io_simple_buffer(b, &entp->type, sizeof(entp->type));
637 		io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid));
638 		io_simple_buffer(b, &entp->talid, sizeof(entp->talid));
639 
640 		file = NULL;
641 		f = NULL;
642 		switch (entp->type) {
643 		case RTYPE_TAL:
644 			io_str_buffer(b, entp->file);
645 			if ((tal = tal_parse(entp->file, entp->data,
646 			    entp->datasz)) == NULL)
647 				errx(1, "%s: could not parse tal file",
648 				    entp->file);
649 			tal->id = entp->talid;
650 			tal_buffer(b, tal);
651 			tal_free(tal);
652 			break;
653 		case RTYPE_CER:
654 			file = parse_load_file(entp, &f, &flen);
655 			io_str_buffer(b, file);
656 			if (entp->data != NULL)
657 				cert = proc_parser_root_cert(file,
658 				    f, flen, entp->data, entp->datasz,
659 				    entp->talid);
660 			else
661 				cert = proc_parser_cert(file, f, flen,
662 				    entp->mftaki);
663 			c = (cert != NULL);
664 			io_simple_buffer(b, &c, sizeof(int));
665 			if (cert != NULL) {
666 				cert->repoid = entp->repoid;
667 				cert_buffer(b, cert);
668 			}
669 			/*
670 			 * The parsed certificate data "cert" is now
671 			 * managed in the "auths" table, so don't free
672 			 * it here.
673 			 */
674 			break;
675 		case RTYPE_MFT:
676 			file = proc_parser_mft(entp, &mft, &crlfile);
677 			io_str_buffer(b, file);
678 			c = (mft != NULL);
679 			io_simple_buffer(b, &c, sizeof(int));
680 			if (mft != NULL)
681 				mft_buffer(b, mft);
682 
683 			/* Push valid CRL together with the MFT. */
684 			if (crlfile != NULL) {
685 				enum rtype type;
686 				struct ibuf *b2;
687 
688 				b2 = io_new_buffer();
689 				type = RTYPE_CRL;
690 				io_simple_buffer(b2, &type, sizeof(type));
691 				io_simple_buffer(b2, &entp->repoid,
692 				    sizeof(entp->repoid));
693 				io_simple_buffer(b2, &entp->talid,
694 				    sizeof(entp->talid));
695 				io_str_buffer(b2, crlfile);
696 				free(crlfile);
697 
698 				io_close_buffer(msgq, b2);
699 			}
700 			mft_free(mft);
701 			break;
702 		case RTYPE_ROA:
703 			file = parse_load_file(entp, &f, &flen);
704 			io_str_buffer(b, file);
705 			roa = proc_parser_roa(file, f, flen, entp->mftaki);
706 			c = (roa != NULL);
707 			io_simple_buffer(b, &c, sizeof(int));
708 			if (roa != NULL)
709 				roa_buffer(b, roa);
710 			roa_free(roa);
711 			break;
712 		case RTYPE_GBR:
713 			file = parse_load_file(entp, &f, &flen);
714 			io_str_buffer(b, file);
715 			proc_parser_gbr(file, f, flen, entp->mftaki);
716 			break;
717 		case RTYPE_ASPA:
718 			file = parse_load_file(entp, &f, &flen);
719 			io_str_buffer(b, file);
720 			aspa = proc_parser_aspa(file, f, flen, entp->mftaki);
721 			c = (aspa != NULL);
722 			io_simple_buffer(b, &c, sizeof(int));
723 			if (aspa != NULL)
724 				aspa_buffer(b, aspa);
725 			aspa_free(aspa);
726 			break;
727 		case RTYPE_TAK:
728 			file = parse_load_file(entp, &f, &flen);
729 			io_str_buffer(b, file);
730 			proc_parser_tak(file, f, flen, entp->mftaki);
731 			break;
732 		case RTYPE_CRL:
733 		default:
734 			file = parse_filepath(entp->repoid, entp->path,
735 			    entp->file, entp->location);
736 			io_str_buffer(b, file);
737 			warnx("%s: unhandled type %d", file, entp->type);
738 			break;
739 		}
740 
741 		free(f);
742 		free(file);
743 		io_close_buffer(msgq, b);
744 		entity_free(entp);
745 	}
746 }
747 
748 /*
749  * Process responsible for parsing and validating content.
750  * All this process does is wait to be told about a file to parse, then
751  * it parses it and makes sure that the data being returned is fully
752  * validated and verified.
753  * The process will exit cleanly only when fd is closed.
754  */
755 void
756 proc_parser(int fd)
757 {
758 	struct entityq	 q;
759 	struct msgbuf	 msgq;
760 	struct pollfd	 pfd;
761 	struct entity	*entp;
762 	struct ibuf	*b, *inbuf = NULL;
763 
764 	/* Only allow access to the cache directory. */
765 	if (unveil(".", "r") == -1)
766 		err(1, "unveil cachedir");
767 	if (pledge("stdio rpath", NULL) == -1)
768 		err(1, "pledge");
769 
770 	ERR_load_crypto_strings();
771 	OpenSSL_add_all_ciphers();
772 	OpenSSL_add_all_digests();
773 	x509_init_oid();
774 
775 	if ((ctx = X509_STORE_CTX_new()) == NULL)
776 		cryptoerrx("X509_STORE_CTX_new");
777 
778 	TAILQ_INIT(&q);
779 
780 	msgbuf_init(&msgq);
781 	msgq.fd = fd;
782 
783 	pfd.fd = fd;
784 
785 	for (;;) {
786 		pfd.events = POLLIN;
787 		if (msgq.queued)
788 			pfd.events |= POLLOUT;
789 
790 		if (poll(&pfd, 1, INFTIM) == -1) {
791 			if (errno == EINTR)
792 				continue;
793 			err(1, "poll");
794 		}
795 		if ((pfd.revents & (POLLERR|POLLNVAL)))
796 			errx(1, "poll: bad descriptor");
797 
798 		/* If the parent closes, return immediately. */
799 
800 		if ((pfd.revents & POLLHUP))
801 			break;
802 
803 		if ((pfd.revents & POLLIN)) {
804 			b = io_buf_read(fd, &inbuf);
805 			if (b != NULL) {
806 				entp = calloc(1, sizeof(struct entity));
807 				if (entp == NULL)
808 					err(1, NULL);
809 				entity_read_req(b, entp);
810 				TAILQ_INSERT_TAIL(&q, entp, entries);
811 				ibuf_free(b);
812 			}
813 		}
814 
815 		if (pfd.revents & POLLOUT) {
816 			switch (msgbuf_write(&msgq)) {
817 			case 0:
818 				errx(1, "write: connection closed");
819 			case -1:
820 				err(1, "write");
821 			}
822 		}
823 
824 		parse_entity(&q, &msgq);
825 	}
826 
827 	while ((entp = TAILQ_FIRST(&q)) != NULL) {
828 		TAILQ_REMOVE(&q, entp, entries);
829 		entity_free(entp);
830 	}
831 
832 	auth_tree_free(&auths);
833 	crl_tree_free(&crlt);
834 
835 	X509_STORE_CTX_free(ctx);
836 	msgbuf_clear(&msgq);
837 
838 	ibuf_free(inbuf);
839 
840 	exit(0);
841 }
842