xref: /openbsd-src/usr.sbin/rpki-client/parser.c (revision 7c0ec4b8992567abb1e1536622dc789a9a39d9f1)
1 /*	$OpenBSD: parser.c,v 1.143 2024/08/29 13:46:28 tb 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 certid;
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  * Return the issuer by its certificate id, or NULL on failure.
93  * Make sure the AKI is the same as the AKI listed on the Manifest,
94  * and that the SKI of the cert matches with the AKI.
95  */
96 static struct auth *
97 find_issuer(const char *fn, int id, const char *aki, const char *mftaki)
98 {
99 	struct auth *a;
100 
101 	a = auth_find(&auths, id);
102 	if (a == NULL) {
103 		if (certid <= CERTID_MAX)
104 			warnx("%s: RFC 6487: unknown cert with SKI %s", fn,
105 			    aki);
106 		return NULL;
107 	}
108 
109 	if (mftaki != NULL) {
110 		if (strcmp(aki, mftaki) != 0) {
111 			warnx("%s: AKI %s doesn't match Manifest AKI %s", fn,
112 			    aki, mftaki);
113 			return NULL;
114 		}
115 	}
116 
117 	if (strcmp(aki, a->cert->ski) != 0) {
118 		warnx("%s: AKI %s doesn't match issuer SKI %s", fn,
119 		    aki, a->cert->ski);
120 		return NULL;
121 	}
122 
123 	return a;
124 }
125 
126 /*
127  * Build access path to file based on repoid, path, location and file values.
128  */
129 static char *
130 parse_filepath(unsigned int repoid, const char *path, const char *file,
131     enum location loc)
132 {
133 	struct parse_repo	*rp;
134 	char			*fn, *repopath;
135 
136 	/* build file path based on repoid, entity path and filename */
137 	rp = repo_get(repoid);
138 	if (rp == NULL)
139 		errx(1, "build file path: repository %u missing", repoid);
140 
141 	if (loc == DIR_VALID)
142 		repopath = rp->validpath;
143 	else
144 		repopath = rp->path;
145 
146 	if (repopath == NULL)
147 		return NULL;
148 
149 	if (path == NULL) {
150 		if (asprintf(&fn, "%s/%s", repopath, file) == -1)
151 			err(1, NULL);
152 	} else {
153 		if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1)
154 			err(1, NULL);
155 	}
156 	return fn;
157 }
158 
159 /*
160  * Parse and validate a ROA.
161  * This is standard stuff.
162  * Returns the roa on success, NULL on failure.
163  */
164 static struct roa *
165 proc_parser_roa(char *file, const unsigned char *der, size_t len,
166     const struct entity *entp)
167 {
168 	struct roa		*roa;
169 	X509			*x509 = NULL;
170 	struct auth		*a;
171 	struct crl		*crl;
172 	const char		*errstr;
173 
174 	if ((roa = roa_parse(&x509, file, entp->talid, der, len)) == NULL)
175 		goto out;
176 
177 	a = find_issuer(file, entp->certid, roa->aki, entp->mftaki);
178 	if (a == NULL)
179 		goto out;
180 	crl = crl_get(&crlt, a);
181 
182 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
183 		warnx("%s: %s", file, errstr);
184 		goto out;
185 	}
186 	X509_free(x509);
187 	x509 = NULL;
188 
189 	roa->talid = a->cert->talid;
190 
191 	roa->expires = x509_find_expires(roa->notafter, a, &crlt);
192 
193 	return roa;
194 
195  out:
196 	roa_free(roa);
197 	X509_free(x509);
198 
199 	return NULL;
200 }
201 
202 /*
203  * Parse and validate a draft-ietf-sidrops-rpki-prefixlist SPL.
204  * Returns the spl on success, NULL on failure.
205  */
206 static struct spl *
207 proc_parser_spl(char *file, const unsigned char *der, size_t len,
208     const struct entity *entp)
209 {
210 	struct spl		*spl;
211 	X509			*x509 = NULL;
212 	struct auth		*a;
213 	struct crl		*crl;
214 	const char		*errstr;
215 
216 	if ((spl = spl_parse(&x509, file, entp->talid, der, len)) == NULL)
217 		goto out;
218 
219 	a = find_issuer(file, entp->certid, spl->aki, entp->mftaki);
220 	if (a == NULL)
221 		goto out;
222 	crl = crl_get(&crlt, a);
223 
224 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
225 		warnx("%s: %s", file, errstr);
226 		goto out;
227 	}
228 	X509_free(x509);
229 	x509 = NULL;
230 
231 	spl->talid = a->cert->talid;
232 
233 	spl->expires = x509_find_expires(spl->notafter, a, &crlt);
234 
235 	return spl;
236 
237  out:
238 	spl_free(spl);
239 	X509_free(x509);
240 
241 	return NULL;
242 }
243 
244 /*
245  * Check all files and their hashes in a MFT structure.
246  * Return zero on failure, non-zero on success.
247  */
248 static int
249 proc_parser_mft_check(const char *fn, struct mft *p)
250 {
251 	const enum location loc[2] = { DIR_TEMP, DIR_VALID };
252 	size_t	 i;
253 	int	 rc = 1;
254 	char	*path;
255 
256 	if (p == NULL)
257 		return 0;
258 
259 	for (i = 0; i < p->filesz; i++) {
260 		struct mftfile *m = &p->files[i];
261 		int try, fd = -1, noent = 0, valid = 0;
262 		for (try = 0; try < 2 && !valid; try++) {
263 			if ((path = parse_filepath(p->repoid, p->path, m->file,
264 			    loc[try])) == NULL)
265 				continue;
266 			fd = open(path, O_RDONLY);
267 			if (fd == -1 && errno == ENOENT)
268 				noent++;
269 			free(path);
270 
271 			/* remember which path was checked */
272 			m->location = loc[try];
273 			valid = valid_filehash(fd, m->hash, sizeof(m->hash));
274 		}
275 
276 		if (!valid) {
277 			/* silently skip not-existing unknown files */
278 			if (m->type == RTYPE_INVALID && noent == 2)
279 				continue;
280 			warnx("%s#%s: bad message digest for %s", fn,
281 			    p->seqnum, m->file);
282 			rc = 0;
283 			continue;
284 		}
285 	}
286 
287 	return rc;
288 }
289 
290 /*
291  * Load the CRL from loc using the info from the MFT.
292  */
293 static struct crl *
294 parse_load_crl_from_mft(struct entity *entp, struct mft *mft, enum location loc,
295     char **crlfile)
296 {
297 	struct crl	*crl = NULL;
298 	unsigned char	*f = NULL;
299 	char		*fn = NULL;
300 	size_t		 flen;
301 
302 	*crlfile = NULL;
303 
304 	fn = parse_filepath(entp->repoid, entp->path, mft->crl, loc);
305 	if (fn == NULL)
306 		goto out;
307 
308 	f = load_file(fn, &flen);
309 	if (f == NULL) {
310 		if (errno != ENOENT)
311 			warn("parse file %s", fn);
312 		goto out;
313 	}
314 
315 	if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash)))
316 		goto out;
317 
318 	crl = crl_parse(fn, f, flen);
319 	if (crl == NULL)
320 		goto out;
321 
322 	if (strcmp(crl->aki, mft->aki) != 0) {
323 		warnx("%s: AKI doesn't match Manifest AKI", fn);
324 		goto out;
325 	}
326 
327 	if ((crl->mftpath = strdup(mft->sia)) == NULL)
328 		err(1, NULL);
329 
330 	*crlfile = fn;
331 	free(f);
332 
333 	return crl;
334 
335  out:
336 	crl_free(crl);
337 	free(f);
338 	free(fn);
339 
340 	return NULL;
341 }
342 
343 /*
344  * Parse and validate a manifest file.
345  * Don't check the fileandhash, this is done later on.
346  * Return the mft on success, or NULL on failure.
347  */
348 static struct mft *
349 proc_parser_mft_pre(struct entity *entp, char *file, struct crl **crl,
350     char **crlfile, struct mft *cached_mft, const char **errstr)
351 {
352 	struct mft	*mft;
353 	X509		*x509;
354 	struct auth	*a;
355 	unsigned char	*der;
356 	size_t		 len;
357 	time_t		 now;
358 	int		 issued_cmp, seqnum_cmp;
359 
360 	*crl = NULL;
361 	*crlfile = NULL;
362 	*errstr = NULL;
363 
364 	if (file == NULL)
365 		return NULL;
366 
367 	der = load_file(file, &len);
368 	if (der == NULL && errno != ENOENT)
369 		warn("parse file %s", file);
370 
371 	if ((mft = mft_parse(&x509, file, entp->talid, der, len)) == NULL) {
372 		free(der);
373 		return NULL;
374 	}
375 
376 	if (entp->path != NULL) {
377 		if ((mft->path = strdup(entp->path)) == NULL)
378 			err(1, NULL);
379 	}
380 
381 	if (!EVP_Digest(der, len, mft->mfthash, NULL, EVP_sha256(), NULL))
382 		errx(1, "EVP_Digest failed");
383 
384 	free(der);
385 
386 	*crl = parse_load_crl_from_mft(entp, mft, DIR_TEMP, crlfile);
387 	if (*crl == NULL)
388 		*crl = parse_load_crl_from_mft(entp, mft, DIR_VALID, crlfile);
389 
390 	a = find_issuer(file, entp->certid, mft->aki, NULL);
391 	if (a == NULL)
392 		goto err;
393 	if (!valid_x509(file, ctx, x509, a, *crl, errstr))
394 		goto err;
395 	X509_free(x509);
396 	x509 = NULL;
397 
398 	mft->repoid = entp->repoid;
399 	mft->talid = a->cert->talid;
400 	mft->certid = entp->certid;
401 
402 	now = get_current_time();
403 	/* check that now is not before from */
404 	if (now < mft->thisupdate) {
405 		warnx("%s: manifest not yet valid %s", file,
406 		    time2str(mft->thisupdate));
407 		goto err;
408 	}
409 	/* check that now is not after until */
410 	if (now > mft->nextupdate) {
411 		warnx("%s: manifest expired on %s", file,
412 		    time2str(mft->nextupdate));
413 		goto err;
414 	}
415 
416 	/* if there is nothing to compare to, return now */
417 	if (cached_mft == NULL)
418 		return mft;
419 
420 	/*
421 	 * Check that the cached manifest is older in the sense that it was
422 	 * issued earlier and that it has a smaller sequence number.
423 	 */
424 
425 	if ((issued_cmp = mft_compare_issued(mft, cached_mft)) < 0) {
426 		warnx("%s: unexpected manifest issuance date (want >= %lld, "
427 		    "got %lld)", file, (long long)cached_mft->thisupdate,
428 		    (long long)mft->thisupdate);
429 		goto err;
430 	}
431 	if ((seqnum_cmp = mft_compare_seqnum(mft, cached_mft)) < 0) {
432 		warnx("%s: unexpected manifest number (want >= #%s, got #%s)",
433 		    file, cached_mft->seqnum, mft->seqnum);
434 		goto err;
435 	}
436 	if (issued_cmp > 0 && seqnum_cmp == 0) {
437 		warnx("%s: manifest issued at %lld and %lld with same "
438 		    "manifest number #%s", file, (long long)mft->thisupdate,
439 		    (long long)cached_mft->thisupdate, cached_mft->seqnum);
440 		goto err;
441 	}
442 	if (issued_cmp == 0 && seqnum_cmp > 0) {
443 		warnx("%s: #%s and #%s were issued at same issuance date %lld",
444 		    file, mft->seqnum, cached_mft->seqnum,
445 		    (long long)mft->thisupdate);
446 		goto err;
447 	}
448 	if (issued_cmp == 0 && seqnum_cmp == 0 && memcmp(mft->mfthash,
449 	    cached_mft->mfthash, SHA256_DIGEST_LENGTH) != 0) {
450 		warnx("%s: misissuance, issuance date %lld and manifest number "
451 		    "#%s were recycled", file, (long long)mft->thisupdate,
452 		    mft->seqnum);
453 		goto err;
454 	}
455 
456 	return mft;
457 
458  err:
459 	X509_free(x509);
460 	mft_free(mft);
461 	crl_free(*crl);
462 	*crl = NULL;
463 	free(*crlfile);
464 	*crlfile = NULL;
465 	return NULL;
466 }
467 
468 /*
469  * Load the most recent MFT by opening both options and comparing the two.
470  */
471 static char *
472 proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile,
473     time_t *crlmtime)
474 {
475 	struct mft	*mft1 = NULL, *mft2 = NULL;
476 	struct crl	*crl, *crl1 = NULL, *crl2 = NULL;
477 	char		*file, *file1 = NULL, *file2 = NULL;
478 	char		*crl1file = NULL, *crl2file = NULL;
479 	const char	*err1 = NULL, *err2 = NULL;
480 
481 	*mp = NULL;
482 	*crlmtime = 0;
483 
484 	file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
485 	mft2 = proc_parser_mft_pre(entp, file2, &crl2, &crl2file, NULL, &err2);
486 
487 	if (!noop) {
488 		file1 = parse_filepath(entp->repoid, entp->path, entp->file,
489 		    DIR_TEMP);
490 		mft1 = proc_parser_mft_pre(entp, file1, &crl1, &crl1file, mft2,
491 		    &err1);
492 	}
493 
494 	if (proc_parser_mft_check(file1, mft1)) {
495 		mft_free(mft2);
496 		crl_free(crl2);
497 		free(crl2file);
498 		free(file2);
499 
500 		*mp = mft1;
501 		crl = crl1;
502 		file = file1;
503 		*crlfile = crl1file;
504 	} else {
505 		if (mft1 != NULL && mft2 != NULL)
506 			warnx("%s: failed fetch, continuing with #%s "
507 			    "from cache", file2, mft2->seqnum);
508 
509 		if (!proc_parser_mft_check(file2, mft2)) {
510 			mft_free(mft2);
511 			mft2 = NULL;
512 
513 			if (err2 == NULL)
514 				err2 = err1;
515 			if (err2 == NULL)
516 				err2 = "no valid manifest available";
517 			if (certid <= CERTID_MAX)
518 				warnx("%s: %s", file2, err2);
519 		}
520 
521 		mft_free(mft1);
522 		crl_free(crl1);
523 		free(crl1file);
524 		free(file1);
525 
526 		*mp = mft2;
527 		crl = crl2;
528 		file = file2;
529 		*crlfile = crl2file;
530 	}
531 
532 	if (*mp != NULL) {
533 		*crlmtime = crl->thisupdate;
534 		if (crl_insert(&crlt, crl))
535 			crl = NULL;
536 	}
537 	crl_free(crl);
538 
539 	return file;
540 }
541 
542 /*
543  * Certificates are from manifests (has a digest and is signed with
544  * another certificate) Parse the certificate, make sure its
545  * signatures are valid (with CRLs), then validate the RPKI content.
546  * This returns a certificate (which must not be freed) or NULL on
547  * parse failure.
548  */
549 static struct cert *
550 proc_parser_cert(char *file, const unsigned char *der, size_t len,
551     const struct entity *entp)
552 {
553 	struct cert	*cert;
554 	struct crl	*crl;
555 	struct auth	*a;
556 	const char	*errstr = NULL;
557 
558 	/* Extract certificate data. */
559 
560 	cert = cert_parse_pre(file, der, len);
561 	cert = cert_parse(file, cert);
562 	if (cert == NULL)
563 		goto out;
564 
565 	a = find_issuer(file, entp->certid, cert->aki, entp->mftaki);
566 	if (a == NULL)
567 		goto out;
568 	crl = crl_get(&crlt, a);
569 
570 	if (!valid_x509(file, ctx, cert->x509, a, crl, &errstr) ||
571 	    !valid_cert(file, a, cert)) {
572 		if (errstr != NULL)
573 			warnx("%s: %s", file, errstr);
574 		goto out;
575 	}
576 
577 	cert->talid = a->cert->talid;
578 
579 	if (cert->purpose == CERT_PURPOSE_BGPSEC_ROUTER) {
580 		if (!constraints_validate(file, cert))
581 			goto out;
582 	}
583 
584 	/*
585 	 * Add validated CA certs to the RPKI auth tree.
586 	 */
587 	if (cert->purpose == CERT_PURPOSE_CA)
588 		auth_insert(file, &auths, cert, a);
589 
590 	return cert;
591 
592  out:
593 	cert_free(cert);
594 
595 	return NULL;
596 }
597 
598 static int
599 proc_parser_ta_cmp(const struct cert *cert1, const struct cert *cert2)
600 {
601 	if (cert1 == NULL)
602 		return -1;
603 	if (cert2 == NULL)
604 		return 1;
605 
606 	/*
607 	 * The standards don't specify tiebreakers. While RFC 6487 and other
608 	 * sources advise against backdating, it's explicitly allowed and some
609 	 * TAs do. Some TAs have also re-issued with new dates and old
610 	 * serialNumber.
611 	 * Our tiebreaker logic: a more recent notBefore is taken to mean a
612 	 * more recent issuance, and thus preferable. Given equal notBefore
613 	 * values, prefer the TA cert with the narrower validity window. This
614 	 * hopefully encourages TA operators to reduce egregiously long TA
615 	 * validity periods.
616 	 */
617 
618 	if (cert1->notbefore < cert2->notbefore)
619 		return -1;
620 	if (cert1->notbefore > cert2->notbefore)
621 		return 1;
622 
623 	if (cert1->notafter > cert2->notafter)
624 		return -1;
625 	if (cert1->notafter < cert2->notafter)
626 		return 1;
627 
628 	/*
629 	 * Both certs are valid from our perspective. If anything changed,
630 	 * prefer the freshly-fetched one. We rely on cert_parse_pre() having
631 	 * cached the extensions and thus libcrypto has already computed the
632 	 * certs' hashes (SHA-1 for OpenSSL, SHA-512 for LibreSSL). The below
633 	 * compares them.
634 	 */
635 
636 	return X509_cmp(cert1->x509, cert2->x509) != 0;
637 }
638 
639 /*
640  * Root certificates come from TALs. Inspect and validate both options and
641  * compare the two. The cert in out_cert must not be freed. Returns the file
642  * name of the chosen TA.
643  */
644 static char *
645 proc_parser_root_cert(struct entity *entp, struct cert **out_cert)
646 {
647 	struct cert		*cert1 = NULL, *cert2 = NULL;
648 	char			*file1 = NULL, *file2 = NULL;
649 	unsigned char		*der = NULL, *pkey = entp->data;
650 	size_t			 der_len = 0, pkeysz = entp->datasz;
651 	int			 cmp;
652 
653 	*out_cert = NULL;
654 
655 	file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
656 	der = load_file(file2, &der_len);
657 	cert2 = cert_parse_pre(file2, der, der_len);
658 	free(der);
659 	cert2 = ta_parse(file2, cert2, pkey, pkeysz);
660 
661 	if (!noop) {
662 		file1 = parse_filepath(entp->repoid, entp->path, entp->file,
663 		    DIR_TEMP);
664 		der = load_file(file1, &der_len);
665 		cert1 = cert_parse_pre(file1, der, der_len);
666 		free(der);
667 		cert1 = ta_parse(file1, cert1, pkey, pkeysz);
668 	}
669 
670 	if ((cmp = proc_parser_ta_cmp(cert1, cert2)) > 0) {
671 		cert_free(cert2);
672 		free(file2);
673 
674 		cert1->talid = entp->talid;
675 		auth_insert(file1, &auths, cert1, NULL);
676 
677 		*out_cert = cert1;
678 		return file1;
679 	} else {
680 		if (cmp < 0 && cert1 != NULL && cert2 != NULL)
681 			warnx("%s: cached TA is newer", entp->file);
682 		cert_free(cert1);
683 		free(file1);
684 
685 		if (cert2 != 0) {
686 			cert2->talid = entp->talid;
687 			auth_insert(file2, &auths, cert2, NULL);
688 		}
689 
690 		*out_cert = cert2;
691 		return file2;
692 	}
693 }
694 
695 /*
696  * Parse a ghostbuster record
697  */
698 static struct gbr *
699 proc_parser_gbr(char *file, const unsigned char *der, size_t len,
700     const struct entity *entp)
701 {
702 	struct gbr	*gbr;
703 	X509		*x509 = NULL;
704 	struct crl	*crl;
705 	struct auth	*a;
706 	const char	*errstr;
707 
708 	if ((gbr = gbr_parse(&x509, file, entp->talid, der, len)) == NULL)
709 		goto out;
710 
711 	a = find_issuer(file, entp->certid, gbr->aki, entp->mftaki);
712 	if (a == NULL)
713 		goto out;
714 	crl = crl_get(&crlt, a);
715 
716 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
717 		warnx("%s: %s", file, errstr);
718 		goto out;
719 	}
720 	X509_free(x509);
721 	x509 = NULL;
722 
723 	gbr->talid = a->cert->talid;
724 
725 	return gbr;
726 
727  out:
728 	gbr_free(gbr);
729 	X509_free(x509);
730 
731 	return NULL;
732 }
733 
734 /*
735  * Parse an ASPA object
736  */
737 static struct aspa *
738 proc_parser_aspa(char *file, const unsigned char *der, size_t len,
739     const struct entity *entp)
740 {
741 	struct aspa	*aspa;
742 	X509		*x509 = NULL;
743 	struct auth	*a;
744 	struct crl	*crl;
745 	const char	*errstr;
746 
747 	if ((aspa = aspa_parse(&x509, file, entp->talid, der, len)) == NULL)
748 		goto out;
749 
750 	a = find_issuer(file, entp->certid, aspa->aki, entp->mftaki);
751 	if (a == NULL)
752 		goto out;
753 	crl = crl_get(&crlt, a);
754 
755 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
756 		warnx("%s: %s", file, errstr);
757 		goto out;
758 	}
759 	X509_free(x509);
760 	x509 = NULL;
761 
762 	aspa->talid = a->cert->talid;
763 
764 	aspa->expires = x509_find_expires(aspa->notafter, a, &crlt);
765 
766 	return aspa;
767 
768  out:
769 	aspa_free(aspa);
770 	X509_free(x509);
771 
772 	return NULL;
773 }
774 
775 /*
776  * Parse a TAK object.
777  */
778 static struct tak *
779 proc_parser_tak(char *file, const unsigned char *der, size_t len,
780     const struct entity *entp)
781 {
782 	struct tak	*tak;
783 	X509		*x509 = NULL;
784 	struct crl	*crl;
785 	struct auth	*a;
786 	const char	*errstr;
787 
788 	if ((tak = tak_parse(&x509, file, entp->talid, der, len)) == NULL)
789 		goto out;
790 
791 	a = find_issuer(file, entp->certid, tak->aki, entp->mftaki);
792 	if (a == NULL)
793 		goto out;
794 	crl = crl_get(&crlt, a);
795 
796 	if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
797 		warnx("%s: %s", file, errstr);
798 		goto out;
799 	}
800 	X509_free(x509);
801 	x509 = NULL;
802 
803 	/* TAK EE must be signed by self-signed CA */
804 	if (a->issuer != NULL)
805 		goto out;
806 
807 	tak->talid = a->cert->talid;
808 
809 	return tak;
810 
811  out:
812 	tak_free(tak);
813 	X509_free(x509);
814 
815 	return NULL;
816 }
817 
818 /*
819  * Load the file specified by the entity information.
820  */
821 static char *
822 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen)
823 {
824 	char *file;
825 
826 	file = parse_filepath(entp->repoid, entp->path, entp->file,
827 	    entp->location);
828 	if (file == NULL)
829 		errx(1, "no path to file");
830 
831 	*f = load_file(file, flen);
832 	if (*f == NULL)
833 		warn("parse file %s", file);
834 
835 	return file;
836 }
837 
838 /*
839  * Process an entity and respond to parent process.
840  */
841 static void
842 parse_entity(struct entityq *q, struct msgbuf *msgq)
843 {
844 	struct entity	*entp;
845 	struct tal	*tal;
846 	struct cert	*cert;
847 	struct mft	*mft;
848 	struct roa	*roa;
849 	struct aspa	*aspa;
850 	struct gbr	*gbr;
851 	struct tak	*tak;
852 	struct spl	*spl;
853 	struct ibuf	*b;
854 	unsigned char	*f;
855 	time_t		 mtime, crlmtime;
856 	size_t		 flen;
857 	char		*file, *crlfile;
858 	int		 c;
859 
860 	while ((entp = TAILQ_FIRST(q)) != NULL) {
861 		TAILQ_REMOVE(q, entp, entries);
862 
863 		/* handle RTYPE_REPO first */
864 		if (entp->type == RTYPE_REPO) {
865 			repo_add(entp->repoid, entp->path, entp->file);
866 			entity_free(entp);
867 			continue;
868 		}
869 
870 		/* pass back at least type, repoid and filename */
871 		b = io_new_buffer();
872 		io_simple_buffer(b, &entp->type, sizeof(entp->type));
873 		io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid));
874 		io_simple_buffer(b, &entp->talid, sizeof(entp->talid));
875 
876 		file = NULL;
877 		f = NULL;
878 		mtime = 0;
879 		crlmtime = 0;
880 
881 		switch (entp->type) {
882 		case RTYPE_TAL:
883 			io_str_buffer(b, entp->file);
884 			io_simple_buffer(b, &mtime, sizeof(mtime));
885 			if ((tal = tal_parse(entp->file, entp->data,
886 			    entp->datasz)) == NULL)
887 				errx(1, "%s: could not parse tal file",
888 				    entp->file);
889 			tal->id = entp->talid;
890 			tal_buffer(b, tal);
891 			tal_free(tal);
892 			break;
893 		case RTYPE_CER:
894 			if (entp->data != NULL) {
895 				file = proc_parser_root_cert(entp, &cert);
896 			} else {
897 				file = parse_load_file(entp, &f, &flen);
898 				cert = proc_parser_cert(file, f, flen, entp);
899 			}
900 			io_str_buffer(b, file);
901 			if (cert != NULL)
902 				mtime = cert->notbefore;
903 			io_simple_buffer(b, &mtime, sizeof(mtime));
904 			c = (cert != NULL);
905 			io_simple_buffer(b, &c, sizeof(int));
906 			if (cert != NULL) {
907 				cert->repoid = entp->repoid;
908 				cert_buffer(b, cert);
909 			}
910 			/*
911 			 * The parsed certificate data "cert" is now
912 			 * managed in the "auths" table, so don't free
913 			 * it here.
914 			 */
915 			break;
916 		case RTYPE_MFT:
917 			file = proc_parser_mft(entp, &mft, &crlfile, &crlmtime);
918 			io_str_buffer(b, file);
919 			if (mft != NULL)
920 				mtime = mft->signtime;
921 			io_simple_buffer(b, &mtime, sizeof(mtime));
922 			c = (mft != NULL);
923 			io_simple_buffer(b, &c, sizeof(int));
924 			if (mft != NULL)
925 				mft_buffer(b, mft);
926 
927 			/* Push valid CRL together with the MFT. */
928 			if (crlfile != NULL) {
929 				enum rtype type;
930 				struct ibuf *b2;
931 
932 				b2 = io_new_buffer();
933 				type = RTYPE_CRL;
934 				io_simple_buffer(b2, &type, sizeof(type));
935 				io_simple_buffer(b2, &entp->repoid,
936 				    sizeof(entp->repoid));
937 				io_simple_buffer(b2, &entp->talid,
938 				    sizeof(entp->talid));
939 				io_str_buffer(b2, crlfile);
940 				io_simple_buffer(b2, &crlmtime,
941 				    sizeof(crlmtime));
942 				free(crlfile);
943 
944 				io_close_buffer(msgq, b2);
945 			}
946 			mft_free(mft);
947 			break;
948 		case RTYPE_ROA:
949 			file = parse_load_file(entp, &f, &flen);
950 			io_str_buffer(b, file);
951 			roa = proc_parser_roa(file, f, flen, entp);
952 			if (roa != NULL)
953 				mtime = roa->signtime;
954 			io_simple_buffer(b, &mtime, sizeof(mtime));
955 			c = (roa != NULL);
956 			io_simple_buffer(b, &c, sizeof(int));
957 			if (roa != NULL)
958 				roa_buffer(b, roa);
959 			roa_free(roa);
960 			break;
961 		case RTYPE_GBR:
962 			file = parse_load_file(entp, &f, &flen);
963 			io_str_buffer(b, file);
964 			gbr = proc_parser_gbr(file, f, flen, entp);
965 			if (gbr != NULL)
966 				mtime = gbr->signtime;
967 			io_simple_buffer(b, &mtime, sizeof(mtime));
968 			gbr_free(gbr);
969 			break;
970 		case RTYPE_ASPA:
971 			file = parse_load_file(entp, &f, &flen);
972 			io_str_buffer(b, file);
973 			aspa = proc_parser_aspa(file, f, flen, entp);
974 			if (aspa != NULL)
975 				mtime = aspa->signtime;
976 			io_simple_buffer(b, &mtime, sizeof(mtime));
977 			c = (aspa != NULL);
978 			io_simple_buffer(b, &c, sizeof(int));
979 			if (aspa != NULL)
980 				aspa_buffer(b, aspa);
981 			aspa_free(aspa);
982 			break;
983 		case RTYPE_TAK:
984 			file = parse_load_file(entp, &f, &flen);
985 			io_str_buffer(b, file);
986 			tak = proc_parser_tak(file, f, flen, entp);
987 			if (tak != NULL)
988 				mtime = tak->signtime;
989 			io_simple_buffer(b, &mtime, sizeof(mtime));
990 			tak_free(tak);
991 			break;
992 		case RTYPE_SPL:
993 			file = parse_load_file(entp, &f, &flen);
994 			io_str_buffer(b, file);
995 			if (experimental) {
996 				spl = proc_parser_spl(file, f, flen, entp);
997 				if (spl != NULL)
998 					mtime = spl->signtime;
999 			} else {
1000 				if (verbose > 0)
1001 					warnx("%s: skipped", file);
1002 				spl = NULL;
1003 			}
1004 			io_simple_buffer(b, &mtime, sizeof(mtime));
1005 			c = (spl != NULL);
1006 			io_simple_buffer(b, &c, sizeof(int));
1007 			if (spl != NULL)
1008 				spl_buffer(b, spl);
1009 			spl_free(spl);
1010 			break;
1011 		case RTYPE_CRL:
1012 		default:
1013 			file = parse_filepath(entp->repoid, entp->path,
1014 			    entp->file, entp->location);
1015 			io_str_buffer(b, file);
1016 			io_simple_buffer(b, &mtime, sizeof(mtime));
1017 			warnx("%s: unhandled type %d", file, entp->type);
1018 			break;
1019 		}
1020 
1021 		free(f);
1022 		free(file);
1023 		io_close_buffer(msgq, b);
1024 		entity_free(entp);
1025 	}
1026 }
1027 
1028 /*
1029  * Process responsible for parsing and validating content.
1030  * All this process does is wait to be told about a file to parse, then
1031  * it parses it and makes sure that the data being returned is fully
1032  * validated and verified.
1033  * The process will exit cleanly only when fd is closed.
1034  */
1035 void
1036 proc_parser(int fd)
1037 {
1038 	struct entityq	 q;
1039 	struct msgbuf	 msgq;
1040 	struct pollfd	 pfd;
1041 	struct entity	*entp;
1042 	struct ibuf	*b, *inbuf = NULL;
1043 
1044 	/* Only allow access to the cache directory. */
1045 	if (unveil(".", "r") == -1)
1046 		err(1, "unveil cachedir");
1047 	if (pledge("stdio rpath", NULL) == -1)
1048 		err(1, "pledge");
1049 
1050 	ERR_load_crypto_strings();
1051 	OpenSSL_add_all_ciphers();
1052 	OpenSSL_add_all_digests();
1053 	x509_init_oid();
1054 	constraints_parse();
1055 
1056 	if ((ctx = X509_STORE_CTX_new()) == NULL)
1057 		err(1, "X509_STORE_CTX_new");
1058 
1059 	TAILQ_INIT(&q);
1060 
1061 	msgbuf_init(&msgq);
1062 	msgq.fd = fd;
1063 
1064 	pfd.fd = fd;
1065 
1066 	for (;;) {
1067 		pfd.events = POLLIN;
1068 		if (msgbuf_queuelen(&msgq) > 0)
1069 			pfd.events |= POLLOUT;
1070 
1071 		if (poll(&pfd, 1, INFTIM) == -1) {
1072 			if (errno == EINTR)
1073 				continue;
1074 			err(1, "poll");
1075 		}
1076 		if ((pfd.revents & (POLLERR|POLLNVAL)))
1077 			errx(1, "poll: bad descriptor");
1078 
1079 		/* If the parent closes, return immediately. */
1080 
1081 		if ((pfd.revents & POLLHUP))
1082 			break;
1083 
1084 		if ((pfd.revents & POLLIN)) {
1085 			b = io_buf_read(fd, &inbuf);
1086 			if (b != NULL) {
1087 				entp = calloc(1, sizeof(struct entity));
1088 				if (entp == NULL)
1089 					err(1, NULL);
1090 				entity_read_req(b, entp);
1091 				TAILQ_INSERT_TAIL(&q, entp, entries);
1092 				ibuf_free(b);
1093 			}
1094 		}
1095 
1096 		if (pfd.revents & POLLOUT) {
1097 			switch (msgbuf_write(&msgq)) {
1098 			case 0:
1099 				errx(1, "write: connection closed");
1100 			case -1:
1101 				err(1, "write");
1102 			}
1103 		}
1104 
1105 		parse_entity(&q, &msgq);
1106 	}
1107 
1108 	while ((entp = TAILQ_FIRST(&q)) != NULL) {
1109 		TAILQ_REMOVE(&q, entp, entries);
1110 		entity_free(entp);
1111 	}
1112 
1113 	auth_tree_free(&auths);
1114 	crl_tree_free(&crlt);
1115 
1116 	X509_STORE_CTX_free(ctx);
1117 	msgbuf_clear(&msgq);
1118 
1119 	ibuf_free(inbuf);
1120 
1121 	if (certid > CERTID_MAX)
1122 		errx(1, "processing incomplete: too many certificates");
1123 
1124 	exit(0);
1125 }
1126