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