xref: /openbsd-src/usr.sbin/rpki-client/main.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /*	$OpenBSD: main.c,v 1.141 2021/05/11 11:48:02 claudio Exp $ */
2 /*
3  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/queue.h>
19 #include <sys/socket.h>
20 #include <sys/resource.h>
21 #include <sys/tree.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 
25 #include <assert.h>
26 #include <err.h>
27 #include <errno.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30 #include <fnmatch.h>
31 #include <poll.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <signal.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <syslog.h>
39 #include <unistd.h>
40 #include <imsg.h>
41 
42 #include "extern.h"
43 #include "version.h"
44 
45 /*
46  * Maximum number of TAL files we'll load.
47  */
48 #define	TALSZ_MAX	8
49 
50 size_t	entity_queue;
51 int	timeout = 60*60;
52 volatile sig_atomic_t killme;
53 void	suicide(int sig);
54 
55 static struct filepath_tree	fpt = RB_INITIALIZER(&fpt);
56 static struct msgbuf		procq, rsyncq, httpq, rrdpq;
57 static int			cachefd, outdirfd;
58 
59 const char	*bird_tablename = "ROAS";
60 
61 int	verbose;
62 int	noop;
63 int	rrdpon;
64 
65 struct stats	 stats;
66 
67 /*
68  * Log a message to stderr if and only if "verbose" is non-zero.
69  * This uses the err(3) functionality.
70  */
71 void
72 logx(const char *fmt, ...)
73 {
74 	va_list		 ap;
75 
76 	if (verbose && fmt != NULL) {
77 		va_start(ap, fmt);
78 		vwarnx(fmt, ap);
79 		va_end(ap);
80 	}
81 }
82 
83 void
84 entity_free(struct entity *ent)
85 {
86 
87 	if (ent == NULL)
88 		return;
89 
90 	free(ent->pkey);
91 	free(ent->file);
92 	free(ent->descr);
93 	free(ent);
94 }
95 
96 /*
97  * Read a queue entity from the descriptor.
98  * Matched by entity_buffer_req().
99  * The pointer must be passed entity_free().
100  */
101 void
102 entity_read_req(int fd, struct entity *ent)
103 {
104 
105 	io_simple_read(fd, &ent->type, sizeof(enum rtype));
106 	io_str_read(fd, &ent->file);
107 	io_simple_read(fd, &ent->has_pkey, sizeof(int));
108 	if (ent->has_pkey)
109 		io_buf_read_alloc(fd, (void **)&ent->pkey, &ent->pkeysz);
110 	io_str_read(fd, &ent->descr);
111 }
112 
113 /*
114  * Write the queue entity.
115  * Matched by entity_read_req().
116  */
117 static void
118 entity_write_req(const struct entity *ent)
119 {
120 	struct ibuf *b;
121 
122 	if (filepath_add(&fpt, ent->file) == 0) {
123 		warnx("%s: File already visited", ent->file);
124 		return;
125 	}
126 
127 	if ((b = ibuf_dynamic(sizeof(*ent), UINT_MAX)) == NULL)
128 		err(1, NULL);
129 	io_simple_buffer(b, &ent->type, sizeof(ent->type));
130 	io_str_buffer(b, ent->file);
131 	io_simple_buffer(b, &ent->has_pkey, sizeof(int));
132 	if (ent->has_pkey)
133 		io_buf_buffer(b, ent->pkey, ent->pkeysz);
134 	io_str_buffer(b, ent->descr);
135 	ibuf_close(&procq, b);
136 }
137 
138 /*
139  * Scan through all queued requests and see which ones are in the given
140  * repo, then flush those into the parser process.
141  */
142 void
143 entityq_flush(struct entityq *q, struct repo *rp)
144 {
145 	struct entity	*p, *np;
146 
147 	TAILQ_FOREACH_SAFE(p, q, entries, np) {
148 		char *file = p->file;
149 
150 		/*
151 		 * XXX fixup path here since the repo may change
152 		 * during load because of fallback. In that case
153 		 * the file path changes as well since RRDP and RSYNC
154 		 * can not share a common repo.
155 		 */
156 		p->file = repo_filename(rp, file);
157 		if (p->file == NULL)
158 			err(1, "can't construct repo filename");
159 		free(file);
160 
161 		entity_write_req(p);
162 		TAILQ_REMOVE(q, p, entries);
163 		entity_free(p);
164 	}
165 }
166 
167 /*
168  * Add the heap-allocated file to the queue for processing.
169  */
170 static void
171 entityq_add(char *file, enum rtype type, struct repo *rp,
172     const unsigned char *pkey, size_t pkeysz, char *descr)
173 {
174 	struct entity	*p;
175 
176 	if ((p = calloc(1, sizeof(struct entity))) == NULL)
177 		err(1, NULL);
178 
179 	p->type = type;
180 	p->file = file;
181 	p->has_pkey = pkey != NULL;
182 	if (p->has_pkey) {
183 		p->pkeysz = pkeysz;
184 		if ((p->pkey = malloc(pkeysz)) == NULL)
185 			err(1, NULL);
186 		memcpy(p->pkey, pkey, pkeysz);
187 	}
188 	if (descr != NULL)
189 		if ((p->descr = strdup(descr)) == NULL)
190 			err(1, NULL);
191 
192 	entity_queue++;
193 
194 	/*
195 	 * Write to the queue if there's no repo or the repo has already
196 	 * been loaded else enqueue it for later.
197 	 */
198 
199 	if (rp == NULL || !repo_queued(rp, p)) {
200 		/*
201 		 * XXX fixup path here since for repo path the
202 		 * file path has not yet been fixed here.
203 		 * This is a quick way to make this work but in
204 		 * the long run repos need to be passed to the parser.
205 		 */
206 		if (rp != NULL) {
207 			file = p->file;
208 			p->file = repo_filename(rp, file);
209 			if (p->file == NULL)
210 				err(1, "can't construct repo filename from %s",
211 				    file);
212 			free(file);
213 		}
214 		entity_write_req(p);
215 		entity_free(p);
216 	}
217 }
218 
219 static void
220 rrdp_file_resp(size_t id, int ok)
221 {
222 	enum rrdp_msg type = RRDP_FILE;
223 	struct ibuf *b;
224 
225 	if ((b = ibuf_open(sizeof(type) + sizeof(id) + sizeof(ok))) == NULL)
226 		err(1, NULL);
227 	io_simple_buffer(b, &type, sizeof(type));
228 	io_simple_buffer(b, &id, sizeof(id));
229 	io_simple_buffer(b, &ok, sizeof(ok));
230 	ibuf_close(&rrdpq, b);
231 }
232 
233 void
234 rrdp_fetch(size_t id, const char *uri, const char *local,
235     struct rrdp_session *s)
236 {
237 	enum rrdp_msg type = RRDP_START;
238 	struct ibuf *b;
239 
240 	if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL)
241 		err(1, NULL);
242 	io_simple_buffer(b, &type, sizeof(type));
243 	io_simple_buffer(b, &id, sizeof(id));
244 	io_str_buffer(b, local);
245 	io_str_buffer(b, uri);
246 	io_str_buffer(b, s->session_id);
247 	io_simple_buffer(b, &s->serial, sizeof(s->serial));
248 	io_str_buffer(b, s->last_mod);
249 	ibuf_close(&rrdpq, b);
250 }
251 
252 /*
253  * Request a repository sync via rsync URI to directory local.
254  */
255 void
256 rsync_fetch(size_t id, const char *uri, const char *local)
257 {
258 	struct ibuf	*b;
259 
260 	if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL)
261 		err(1, NULL);
262 	io_simple_buffer(b, &id, sizeof(id));
263 	io_str_buffer(b, local);
264 	io_str_buffer(b, uri);
265 	ibuf_close(&rsyncq, b);
266 }
267 
268 /*
269  * Request a file from a https uri, data is written to the file descriptor fd.
270  */
271 void
272 http_fetch(size_t id, const char *uri, const char *last_mod, int fd)
273 {
274 	struct ibuf	*b;
275 
276 	if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL)
277 		err(1, NULL);
278 	io_simple_buffer(b, &id, sizeof(id));
279 	io_str_buffer(b, uri);
280 	io_str_buffer(b, last_mod);
281 	/* pass file as fd */
282 	b->fd = fd;
283 	ibuf_close(&httpq, b);
284 }
285 
286 /*
287  * Request some XML file on behalf of the rrdp parser.
288  * Create a pipe and pass the pipe endpoints to the http and rrdp process.
289  */
290 static void
291 rrdp_http_fetch(size_t id, const char *uri, const char *last_mod)
292 {
293 	enum rrdp_msg type = RRDP_HTTP_INI;
294 	struct ibuf *b;
295 	int pi[2];
296 
297 	if (pipe2(pi, O_CLOEXEC | O_NONBLOCK) == -1)
298 		err(1, "pipe");
299 
300 	if ((b = ibuf_open(sizeof(type) + sizeof(id))) == NULL)
301 		err(1, NULL);
302 	io_simple_buffer(b, &type, sizeof(type));
303 	io_simple_buffer(b, &id, sizeof(id));
304 	b->fd = pi[0];
305 	ibuf_close(&rrdpq, b);
306 
307 	http_fetch(id, uri, last_mod, pi[1]);
308 }
309 
310 void
311 rrdp_http_done(size_t id, enum http_result res, const char *last_mod)
312 {
313 	enum rrdp_msg type = RRDP_HTTP_FIN;
314 	struct ibuf *b;
315 
316 	/* RRDP request, relay response over to the rrdp process */
317 	if ((b = ibuf_dynamic(256, UINT_MAX)) == NULL)
318 		err(1, NULL);
319 	io_simple_buffer(b, &type, sizeof(type));
320 	io_simple_buffer(b, &id, sizeof(id));
321 	io_simple_buffer(b, &res, sizeof(res));
322 	io_str_buffer(b, last_mod);
323 	ibuf_close(&rrdpq, b);
324 }
325 
326 /*
327  * Add a file (CER, ROA, CRL) from an MFT file, RFC 6486.
328  * These are always relative to the directory in which "mft" sits.
329  */
330 static void
331 queue_add_from_mft(const char *mft, const struct mftfile *file, enum rtype type)
332 {
333 	char		*cp, *nfile;
334 
335 	/* Construct local path from filename. */
336 	cp = strrchr(mft, '/');
337 	assert(cp != NULL);
338 	assert(cp - mft < INT_MAX);
339 	if (asprintf(&nfile, "%.*s/%s", (int)(cp - mft), mft, file->file) == -1)
340 		err(1, NULL);
341 
342 	/*
343 	 * Since we're from the same directory as the MFT file, we know
344 	 * that the repository has already been loaded.
345 	 */
346 
347 	entityq_add(nfile, type, NULL, NULL, 0, NULL);
348 }
349 
350 /*
351  * Loops over queue_add_from_mft() for all files.
352  * The order here is important: we want to parse the revocation
353  * list *before* we parse anything else.
354  * FIXME: set the type of file in the mftfile so that we don't need to
355  * keep doing the check (this should be done in the parser, where we
356  * check the suffix anyway).
357  */
358 static void
359 queue_add_from_mft_set(const struct mft *mft)
360 {
361 	size_t			 i, sz;
362 	const struct mftfile	*f;
363 
364 	for (i = 0; i < mft->filesz; i++) {
365 		f = &mft->files[i];
366 		sz = strlen(f->file);
367 		assert(sz > 4);
368 		if (strcasecmp(f->file + sz - 4, ".crl") != 0)
369 			continue;
370 		queue_add_from_mft(mft->file, f, RTYPE_CRL);
371 	}
372 
373 	for (i = 0; i < mft->filesz; i++) {
374 		f = &mft->files[i];
375 		sz = strlen(f->file);
376 		assert(sz > 4);
377 		if (strcasecmp(f->file + sz - 4, ".crl") == 0)
378 			continue;
379 		else if (strcasecmp(f->file + sz - 4, ".cer") == 0)
380 			queue_add_from_mft(mft->file, f, RTYPE_CER);
381 		else if (strcasecmp(f->file + sz - 4, ".roa") == 0)
382 			queue_add_from_mft(mft->file, f, RTYPE_ROA);
383 		else if (strcasecmp(f->file + sz - 4, ".gbr") == 0)
384 			queue_add_from_mft(mft->file, f, RTYPE_GBR);
385 		else
386 			logx("%s: unsupported file type: %s", mft->file,
387 			    f->file);
388 	}
389 }
390 
391 /*
392  * Add a local TAL file (RFC 7730) to the queue of files to fetch.
393  */
394 static void
395 queue_add_tal(const char *file)
396 {
397 	char	*nfile, *buf;
398 
399 	if ((nfile = strdup(file)) == NULL)
400 		err(1, NULL);
401 	buf = tal_read_file(file);
402 
403 	/* Record tal for later reporting */
404 	if (stats.talnames == NULL) {
405 		if ((stats.talnames = strdup(file)) == NULL)
406 			err(1, NULL);
407 	} else {
408 		char *tmp;
409 
410 		if (asprintf(&tmp, "%s %s", stats.talnames, file) == -1)
411 			err(1, NULL);
412 		free(stats.talnames);
413 		stats.talnames = tmp;
414 	}
415 
416 	/* Not in a repository, so directly add to queue. */
417 	entityq_add(nfile, RTYPE_TAL, NULL, NULL, 0, buf);
418 	/* entityq_add makes a copy of buf */
419 	free(buf);
420 }
421 
422 /*
423  * Add URIs (CER) from a TAL file, RFC 8630.
424  */
425 static void
426 queue_add_from_tal(struct tal *tal)
427 {
428 	struct repo	*repo;
429 
430 	assert(tal->urisz);
431 
432 	/* Look up the repository. */
433 	repo = ta_lookup(tal);
434 
435 	entityq_add(NULL, RTYPE_CER, repo, tal->pkey,
436 	    tal->pkeysz, tal->descr);
437 }
438 
439 /*
440  * Add a manifest (MFT) found in an X509 certificate, RFC 6487.
441  */
442 static void
443 queue_add_from_cert(const struct cert *cert)
444 {
445 	struct repo	*repo;
446 	char		*nfile;
447 
448 	repo = repo_lookup(cert->repo, rrdpon ? cert->notify : NULL);
449 	if (repo == NULL) {
450 		warnx("%s: repository lookup failed", cert->repo);
451 		return;
452 	}
453 
454 	if ((nfile = strdup(cert->mft)) == NULL)
455 		err(1, NULL);
456 	entityq_add(nfile, RTYPE_MFT, repo, NULL, 0, NULL);
457 }
458 
459 /*
460  * Process parsed content.
461  * For non-ROAs, we grok for more data.
462  * For ROAs, we want to extract the valid info.
463  * In all cases, we gather statistics.
464  */
465 static void
466 entity_process(int proc, struct stats *st, struct vrp_tree *tree)
467 {
468 	enum rtype	type;
469 	struct tal	*tal;
470 	struct cert	*cert;
471 	struct mft	*mft;
472 	struct roa	*roa;
473 	int		 c;
474 
475 	/*
476 	 * For most of these, we first read whether there's any content
477 	 * at all---this means that the syntactic parse failed (X509
478 	 * certificate, for example).
479 	 * We follow that up with whether the resources didn't parse.
480 	 */
481 	io_simple_read(proc, &type, sizeof(type));
482 
483 	switch (type) {
484 	case RTYPE_TAL:
485 		st->tals++;
486 		tal = tal_read(proc);
487 		queue_add_from_tal(tal);
488 		tal_free(tal);
489 		break;
490 	case RTYPE_CER:
491 		st->certs++;
492 		io_simple_read(proc, &c, sizeof(int));
493 		if (c == 0) {
494 			st->certs_fail++;
495 			break;
496 		}
497 		cert = cert_read(proc);
498 		if (cert->valid) {
499 			/*
500 			 * Process the revocation list from the
501 			 * certificate *first*, since it might mark that
502 			 * we're revoked and then we don't want to
503 			 * process the MFT.
504 			 */
505 			queue_add_from_cert(cert);
506 		} else
507 			st->certs_invalid++;
508 		cert_free(cert);
509 		break;
510 	case RTYPE_MFT:
511 		st->mfts++;
512 		io_simple_read(proc, &c, sizeof(int));
513 		if (c == 0) {
514 			st->mfts_fail++;
515 			break;
516 		}
517 		mft = mft_read(proc);
518 		if (mft->stale)
519 			st->mfts_stale++;
520 		queue_add_from_mft_set(mft);
521 		mft_free(mft);
522 		break;
523 	case RTYPE_CRL:
524 		st->crls++;
525 		break;
526 	case RTYPE_ROA:
527 		st->roas++;
528 		io_simple_read(proc, &c, sizeof(int));
529 		if (c == 0) {
530 			st->roas_fail++;
531 			break;
532 		}
533 		roa = roa_read(proc);
534 		if (roa->valid)
535 			roa_insert_vrps(tree, roa, &st->vrps, &st->uniqs);
536 		else
537 			st->roas_invalid++;
538 		roa_free(roa);
539 		break;
540 	case RTYPE_GBR:
541 		st->gbrs++;
542 		break;
543 	default:
544 		errx(1, "unknown entity type");
545 	}
546 
547 	entity_queue--;
548 }
549 
550 /*
551  * Assign filenames ending in ".tal" in "/etc/rpki" into "tals",
552  * returning the number of files found and filled-in.
553  * This may be zero.
554  * Don't exceded "max" filenames.
555  */
556 static size_t
557 tal_load_default(const char *tals[], size_t max)
558 {
559 	static const char *confdir = "/etc/rpki";
560 	size_t s = 0;
561 	char *path;
562 	DIR *dirp;
563 	struct dirent *dp;
564 
565 	dirp = opendir(confdir);
566 	if (dirp == NULL)
567 		err(1, "open %s", confdir);
568 	while ((dp = readdir(dirp)) != NULL) {
569 		if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH)
570 			continue;
571 		if (s >= max)
572 			err(1, "too many tal files found in %s",
573 			    confdir);
574 		if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1)
575 			err(1, NULL);
576 		tals[s++] = path;
577 	}
578 	closedir(dirp);
579 	return s;
580 }
581 
582 void
583 suicide(int sig __attribute__((unused)))
584 {
585 	killme = 1;
586 }
587 
588 #define NPFD	4
589 
590 int
591 main(int argc, char *argv[])
592 {
593 	int		 rc, c, st, proc, rsync, http, rrdp, ok,
594 			 hangup = 0, fl = SOCK_STREAM | SOCK_CLOEXEC;
595 	size_t		 i, id, outsz = 0, talsz = 0;
596 	pid_t		 pid, procpid, rsyncpid, httppid, rrdppid;
597 	int		 fd[2];
598 	struct pollfd	 pfd[NPFD];
599 	struct msgbuf	*queues[NPFD];
600 	struct roa	**out = NULL;
601 	char		*rsync_prog = "openrsync";
602 	char		*bind_addr = NULL;
603 	const char	*cachedir = NULL, *outputdir = NULL;
604 	const char	*tals[TALSZ_MAX], *errs, *name;
605 	struct vrp_tree	 v = RB_INITIALIZER(&v);
606 	struct rusage	ru;
607 	struct timeval	start_time, now_time;
608 
609 	gettimeofday(&start_time, NULL);
610 
611 	/* If started as root, priv-drop to _rpki-client */
612 	if (getuid() == 0) {
613 		struct passwd *pw;
614 
615 		pw = getpwnam("_rpki-client");
616 		if (!pw)
617 			errx(1, "no _rpki-client user to revoke to");
618 		if (setgroups(1, &pw->pw_gid) == -1 ||
619 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
620 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
621 			err(1, "unable to revoke privs");
622 	}
623 	cachedir = RPKI_PATH_BASE_DIR;
624 	outputdir = RPKI_PATH_OUT_DIR;
625 
626 	if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd "
627 	    "proc exec unveil", NULL) == -1)
628 		err(1, "pledge");
629 
630 	while ((c = getopt(argc, argv, "b:Bcd:e:jnorRs:t:T:vV")) != -1)
631 		switch (c) {
632 		case 'b':
633 			bind_addr = optarg;
634 			break;
635 		case 'B':
636 			outformats |= FORMAT_BIRD;
637 			break;
638 		case 'c':
639 			outformats |= FORMAT_CSV;
640 			break;
641 		case 'd':
642 			cachedir = optarg;
643 			break;
644 		case 'e':
645 			rsync_prog = optarg;
646 			break;
647 		case 'j':
648 			outformats |= FORMAT_JSON;
649 			break;
650 		case 'n':
651 			noop = 1;
652 			break;
653 		case 'o':
654 			outformats |= FORMAT_OPENBGPD;
655 			break;
656 		case 'R':
657 			rrdpon = 0;
658 			break;
659 		case 'r':
660 			rrdpon = 1;
661 			break;
662 		case 's':
663 			timeout = strtonum(optarg, 0, 24*60*60, &errs);
664 			if (errs)
665 				errx(1, "-s: %s", errs);
666 			break;
667 		case 't':
668 			if (talsz >= TALSZ_MAX)
669 				err(1,
670 				    "too many tal files specified");
671 			tals[talsz++] = optarg;
672 			break;
673 		case 'T':
674 			bird_tablename = optarg;
675 			break;
676 		case 'v':
677 			verbose++;
678 			break;
679 		case 'V':
680 			fprintf(stderr, "rpki-client %s\n", RPKI_VERSION);
681 			return 0;
682 		default:
683 			goto usage;
684 		}
685 
686 	argv += optind;
687 	argc -= optind;
688 	if (argc == 1)
689 		outputdir = argv[0];
690 	else if (argc > 1)
691 		goto usage;
692 
693 	signal(SIGPIPE, SIG_IGN);
694 
695 	if (cachedir == NULL) {
696 		warnx("cache directory required");
697 		goto usage;
698 	}
699 	if (outputdir == NULL) {
700 		warnx("output directory required");
701 		goto usage;
702 	}
703 
704 	if ((cachefd = open(cachedir, O_RDONLY, 0)) == -1)
705 		err(1, "cache directory %s", cachedir);
706 	if ((outdirfd = open(outputdir, O_RDONLY, 0)) == -1)
707 		err(1, "output directory %s", outputdir);
708 
709 	if (outformats == 0)
710 		outformats = FORMAT_OPENBGPD;
711 
712 	if (talsz == 0)
713 		talsz = tal_load_default(tals, TALSZ_MAX);
714 	if (talsz == 0)
715 		err(1, "no TAL files found in %s", "/etc/rpki");
716 
717 	/*
718 	 * Create the file reader as a jailed child process.
719 	 * It will be responsible for reading all of the files (ROAs,
720 	 * manifests, certificates, etc.) and returning contents.
721 	 */
722 
723 	if (socketpair(AF_UNIX, fl, 0, fd) == -1)
724 		err(1, "socketpair");
725 	if ((procpid = fork()) == -1)
726 		err(1, "fork");
727 
728 	if (procpid == 0) {
729 		close(fd[1]);
730 
731 		setproctitle("parser");
732 		/* change working directory to the cache directory */
733 		if (fchdir(cachefd) == -1)
734 			err(1, "fchdir");
735 
736 		if (timeout)
737 			alarm(timeout);
738 
739 		/* Only allow access to the cache directory. */
740 		if (unveil(".", "r") == -1)
741 			err(1, "%s: unveil", cachedir);
742 		if (pledge("stdio rpath", NULL) == -1)
743 			err(1, "pledge");
744 		proc_parser(fd[0]);
745 		errx(1, "parser process returned");
746 	}
747 
748 	close(fd[0]);
749 	proc = fd[1];
750 
751 	/*
752 	 * Create a process that will do the rsync'ing.
753 	 * This process is responsible for making sure that all the
754 	 * repositories referenced by a certificate manifest (or the
755 	 * TAL) exists and has been downloaded.
756 	 */
757 
758 	if (!noop) {
759 		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
760 			err(1, "socketpair");
761 		if ((rsyncpid = fork()) == -1)
762 			err(1, "fork");
763 
764 		if (rsyncpid == 0) {
765 			close(proc);
766 			close(fd[1]);
767 
768 			setproctitle("rsync");
769 			/* change working directory to the cache directory */
770 			if (fchdir(cachefd) == -1)
771 				err(1, "fchdir");
772 
773 			if (timeout)
774 				alarm(timeout);
775 
776 			if (pledge("stdio rpath proc exec unveil", NULL) == -1)
777 				err(1, "pledge");
778 
779 			proc_rsync(rsync_prog, bind_addr, fd[0]);
780 			errx(1, "rsync process returned");
781 		}
782 
783 		close(fd[0]);
784 		rsync = fd[1];
785 	} else {
786 		rsync = -1;
787 		rsyncpid = -1;
788 	}
789 
790 	/*
791 	 * Create a process that will fetch data via https.
792 	 * With every request the http process receives a file descriptor
793 	 * where the data should be written to.
794 	 */
795 
796 	if (!noop) {
797 		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
798 			err(1, "socketpair");
799 		if ((httppid = fork()) == -1)
800 			err(1, "fork");
801 
802 		if (httppid == 0) {
803 			close(proc);
804 			close(rsync);
805 			close(fd[1]);
806 
807 			setproctitle("http");
808 			/* change working directory to the cache directory */
809 			if (fchdir(cachefd) == -1)
810 				err(1, "fchdir");
811 
812 			if (timeout)
813 				alarm(timeout);
814 
815 			if (pledge("stdio rpath inet dns recvfd", NULL) == -1)
816 				err(1, "pledge");
817 
818 			proc_http(bind_addr, fd[0]);
819 			errx(1, "http process returned");
820 		}
821 
822 		close(fd[0]);
823 		http = fd[1];
824 	} else {
825 		http = -1;
826 		httppid = -1;
827 	}
828 
829 	/*
830 	 * Create a process that will process RRDP.
831 	 * The rrdp process requires the http process to fetch the various
832 	 * XML files and does this via the main process.
833 	 */
834 
835 	if (!noop && rrdpon) {
836 		if (socketpair(AF_UNIX, fl, 0, fd) == -1)
837 			err(1, "socketpair");
838 		if ((rrdppid = fork()) == -1)
839 			err(1, "fork");
840 
841 		if (rrdppid == 0) {
842 			close(proc);
843 			close(rsync);
844 			close(http);
845 			close(fd[1]);
846 
847 			setproctitle("rrdp");
848 			/* change working directory to the cache directory */
849 			if (fchdir(cachefd) == -1)
850 				err(1, "fchdir");
851 
852 			if (timeout)
853 				alarm(timeout);
854 
855 			if (pledge("stdio recvfd", NULL) == -1)
856 				err(1, "pledge");
857 
858 			proc_rrdp(fd[0]);
859 			/* NOTREACHED */
860 		}
861 
862 		close(fd[0]);
863 		rrdp = fd[1];
864 	} else {
865 		rrdp = -1;
866 		rrdppid = -1;
867 	}
868 
869 	if (timeout) {
870 		/*
871 		 * Commit suicide eventually
872 		 * cron will normally start a new one
873 		 */
874 		alarm(timeout);
875 		signal(SIGALRM, suicide);
876 	}
877 
878 	/* TODO unveil cachedir and outputdir, no other access allowed */
879 	if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1)
880 		err(1, "pledge");
881 
882 	msgbuf_init(&procq);
883 	msgbuf_init(&rsyncq);
884 	msgbuf_init(&httpq);
885 	msgbuf_init(&rrdpq);
886 	procq.fd = proc;
887 	rsyncq.fd = rsync;
888 	httpq.fd = http;
889 	rrdpq.fd = rrdp;
890 
891 	/*
892 	 * The main process drives the top-down scan to leaf ROAs using
893 	 * data downloaded by the rsync process and parsed by the
894 	 * parsing process.
895 	 */
896 
897 	pfd[0].fd = proc;
898 	queues[0] = &procq;
899 	pfd[1].fd = rsync;
900 	queues[1] = &rsyncq;
901 	pfd[2].fd = http;
902 	queues[2] = &httpq;
903 	pfd[3].fd = rrdp;
904 	queues[3] = &rrdpq;
905 
906 	/*
907 	 * Prime the process with our TAL file.
908 	 * This will contain (hopefully) links to our manifest and we
909 	 * can get the ball rolling.
910 	 */
911 
912 	for (i = 0; i < talsz; i++)
913 		queue_add_tal(tals[i]);
914 
915 	/* change working directory to the cache directory */
916 	if (fchdir(cachefd) == -1)
917 		err(1, "fchdir");
918 
919 	while (entity_queue > 0 && !killme) {
920 		for (i = 0; i < NPFD; i++) {
921 			pfd[i].events = POLLIN;
922 			if (queues[i]->queued)
923 				pfd[i].events |= POLLOUT;
924 		}
925 
926 		if ((c = poll(pfd, NPFD, INFTIM)) == -1) {
927 			if (errno == EINTR)
928 				continue;
929 			err(1, "poll");
930 		}
931 
932 		for (i = 0; i < NPFD; i++) {
933 			if (pfd[i].revents & (POLLERR|POLLNVAL))
934 				errx(1, "poll[%zu]: bad fd", i);
935 			if (pfd[i].revents & POLLHUP) {
936 				warnx("poll[%zu]: hangup", i);
937 				hangup = 1;
938 			}
939 			if (pfd[i].revents & POLLOUT) {
940 				/*
941 				 * XXX work around deadlocks because of
942 				 * blocking read vs non-blocking writes.
943 				 */
944 				if (i > 1)
945 					io_socket_nonblocking(pfd[i].fd);
946 				switch (msgbuf_write(queues[i])) {
947 				case 0:
948 					errx(1, "write[%zu]: "
949 					    "connection closed", i);
950 				case -1:
951 					err(1, "write[%zu]", i);
952 				}
953 				if (i > 1)
954 					io_socket_blocking(pfd[i].fd);
955 			}
956 		}
957 		if (hangup)
958 			break;
959 
960 		/*
961 		 * Check the rsync and http process.
962 		 * This means that one of our modules has completed
963 		 * downloading and we can flush the module requests into
964 		 * the parser process.
965 		 */
966 
967 		if ((pfd[1].revents & POLLIN)) {
968 			io_simple_read(rsync, &id, sizeof(id));
969 			io_simple_read(rsync, &ok, sizeof(ok));
970 			rsync_finish(id, ok);
971 		}
972 
973 		if ((pfd[2].revents & POLLIN)) {
974 			enum http_result res;
975 			char *last_mod;
976 
977 			io_simple_read(http, &id, sizeof(id));
978 			io_simple_read(http, &res, sizeof(res));
979 			io_str_read(http, &last_mod);
980 			http_finish(id, res, last_mod);
981 			free(last_mod);
982 		}
983 
984 		/*
985 		 * Handle RRDP requests here.
986 		 */
987 		if ((pfd[3].revents & POLLIN)) {
988 			enum rrdp_msg type;
989 			enum publish_type pt;
990 			struct rrdp_session s;
991 			char *uri, *last_mod, *data;
992 			char hash[SHA256_DIGEST_LENGTH];
993 			size_t dsz;
994 
995 			io_simple_read(rrdp, &type, sizeof(type));
996 			io_simple_read(rrdp, &id, sizeof(id));
997 
998 			switch (type) {
999 			case RRDP_END:
1000 				io_simple_read(rrdp, &ok, sizeof(ok));
1001 				rrdp_finish(id, ok);
1002 				break;
1003 			case RRDP_HTTP_REQ:
1004 				io_str_read(rrdp, &uri);
1005 				io_str_read(rrdp, &last_mod);
1006 				rrdp_http_fetch(id, uri, last_mod);
1007 				break;
1008 			case RRDP_SESSION:
1009 				io_str_read(rrdp, &s.session_id);
1010 				io_simple_read(rrdp, &s.serial,
1011 				    sizeof(s.serial));
1012 				io_str_read(rrdp, &s.last_mod);
1013 				rrdp_save_state(id, &s);
1014 				free(s.session_id);
1015 				free(s.last_mod);
1016 				break;
1017 			case RRDP_FILE:
1018 				io_simple_read(rrdp, &pt, sizeof(pt));
1019 				if (pt != PUB_ADD)
1020 					io_simple_read(rrdp, &hash,
1021 					    sizeof(hash));
1022 				io_str_read(rrdp, &uri);
1023 				io_buf_read_alloc(rrdp, (void **)&data, &dsz);
1024 
1025 				ok = rrdp_handle_file(id, pt, uri,
1026 				    hash, sizeof(hash), data, dsz);
1027 				rrdp_file_resp(id, ok);
1028 
1029 				free(uri);
1030 				free(data);
1031 				break;
1032 			default:
1033 				errx(1, "unexpected rrdp response");
1034 			}
1035 		}
1036 
1037 		/*
1038 		 * The parser has finished something for us.
1039 		 * Dequeue these one by one.
1040 		 */
1041 
1042 		if ((pfd[0].revents & POLLIN)) {
1043 			entity_process(proc, &stats, &v);
1044 		}
1045 	}
1046 
1047 	signal(SIGALRM, SIG_DFL);
1048 	if (killme) {
1049 		syslog(LOG_CRIT|LOG_DAEMON,
1050 		    "excessive runtime (%d seconds), giving up", timeout);
1051 		errx(1, "excessive runtime (%d seconds), giving up", timeout);
1052 	}
1053 
1054 	/*
1055 	 * For clean-up, close the input for the parser and rsync
1056 	 * process.
1057 	 * This will cause them to exit, then we reap them.
1058 	 */
1059 
1060 	close(proc);
1061 	close(rsync);
1062 	close(http);
1063 	close(rrdp);
1064 
1065 	rc = 0;
1066 	for (;;) {
1067 		pid = waitpid(WAIT_ANY, &st, 0);
1068 		if (pid == -1) {
1069 			if (errno == EINTR)
1070 				continue;
1071 			if (errno == ECHILD)
1072 				break;
1073 			err(1, "wait");
1074 		}
1075 
1076 		if (pid == procpid)
1077 			name = "parser";
1078 		else if (pid == rsyncpid)
1079 			name = "rsync";
1080 		else if (pid == httppid)
1081 			name = "http";
1082 		else if (pid == rrdppid)
1083 			name = "rrdp";
1084 		else
1085 			name = "unknown";
1086 
1087 		if (WIFSIGNALED(st)) {
1088 			warnx("%s terminated signal %d", name, WTERMSIG(st));
1089 			rc = 1;
1090 		} else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
1091 			warnx("%s process exited abnormally", name);
1092 			rc = 1;
1093 		}
1094 	}
1095 
1096 	/* processing did not finish because of error */
1097 	if (entity_queue != 0)
1098 		return 1;
1099 
1100 	logx("all files parsed: generating output");
1101 
1102 	repo_cleanup(&fpt);
1103 
1104 	gettimeofday(&now_time, NULL);
1105 	timersub(&now_time, &start_time, &stats.elapsed_time);
1106 	if (getrusage(RUSAGE_SELF, &ru) == 0) {
1107 		stats.user_time = ru.ru_utime;
1108 		stats.system_time = ru.ru_stime;
1109 	}
1110 	if (getrusage(RUSAGE_CHILDREN, &ru) == 0) {
1111 		timeradd(&stats.user_time, &ru.ru_utime, &stats.user_time);
1112 		timeradd(&stats.system_time, &ru.ru_stime, &stats.system_time);
1113 	}
1114 
1115 	/* change working directory to the output directory */
1116 	if (fchdir(outdirfd) == -1)
1117 		err(1, "fchdir output dir");
1118 
1119 	if (outputfiles(&v, &stats))
1120 		rc = 1;
1121 
1122 
1123 	logx("Route Origin Authorizations: %zu (%zu failed parse, %zu invalid)",
1124 	    stats.roas, stats.roas_fail, stats.roas_invalid);
1125 	logx("Certificates: %zu (%zu failed parse, %zu invalid)",
1126 	    stats.certs, stats.certs_fail, stats.certs_invalid);
1127 	logx("Trust Anchor Locators: %zu", stats.tals);
1128 	logx("Manifests: %zu (%zu failed parse, %zu stale)",
1129 	    stats.mfts, stats.mfts_fail, stats.mfts_stale);
1130 	logx("Certificate revocation lists: %zu", stats.crls);
1131 	logx("Ghostbuster records: %zu", stats.gbrs);
1132 	logx("Repositories: %zu", stats.repos);
1133 	logx("Cleanup: removed %zu files, %zu directories",
1134 	    stats.del_files, stats.del_dirs);
1135 	logx("VRP Entries: %zu (%zu unique)", stats.vrps, stats.uniqs);
1136 
1137 	/* Memory cleanup. */
1138 	repo_free();
1139 
1140 	for (i = 0; i < outsz; i++)
1141 		roa_free(out[i]);
1142 	free(out);
1143 
1144 	return rc;
1145 
1146 usage:
1147 	fprintf(stderr,
1148 	    "usage: rpki-client [-BcjnoRrVv] [-b sourceaddr] [-d cachedir]"
1149 	    " [-e rsync_prog]\n"
1150 	    "                   [-s timeout] [-T table] [-t tal]"
1151 	    " [outputdir]\n");
1152 	return 1;
1153 }
1154