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