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