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