xref: /openbsd/usr.sbin/rpki-client/main.c (revision 7e284d50)
1 /*	$OpenBSD: main.c,v 1.257 2024/04/08 14:02:13 tb 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/resource.h>
22 #include <sys/socket.h>
23 #include <sys/statvfs.h>
24 #include <sys/time.h>
25 #include <sys/tree.h>
26 #include <sys/wait.h>
27 
28 #include <assert.h>
29 #include <dirent.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <fnmatch.h>
34 #include <limits.h>
35 #include <poll.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <time.h>
44 #include <unistd.h>
45 
46 #include <imsg.h>
47 
48 #include "extern.h"
49 #include "version.h"
50 
51 const char	*tals[TALSZ_MAX];
52 const char	*taldescs[TALSZ_MAX];
53 unsigned int	 talrepocnt[TALSZ_MAX];
54 struct repotalstats talstats[TALSZ_MAX];
55 int		 talsz;
56 
57 size_t	entity_queue;
58 int	timeout = 60*60;
59 volatile sig_atomic_t killme;
60 void	suicide(int sig);
61 
62 static struct filepath_tree	fpt = RB_INITIALIZER(&fpt);
63 static struct msgbuf		procq, rsyncq, httpq, rrdpq;
64 static int			cachefd, outdirfd;
65 
66 const char	*bird_tablename = "ROAS";
67 
68 int	verbose;
69 int	noop;
70 int	excludeaspa;
71 int	filemode;
72 int	shortlistmode;
73 int	rrdpon = 1;
74 int	repo_timeout;
75 int	experimental;
76 time_t	deadline;
77 
78 /* 9999-12-31 23:59:59 UTC */
79 #define X509_TIME_MAX 253402300799LL
80 /* 0000-01-01 00:00:00 UTC */
81 #define X509_TIME_MIN -62167219200LL
82 
83 int64_t  evaluation_time = X509_TIME_MIN;
84 
85 struct stats	 stats;
86 
87 struct fqdnlistentry {
88 	LIST_ENTRY(fqdnlistentry)	 entry;
89 	char				*fqdn;
90 };
91 LIST_HEAD(fqdns, fqdnlistentry);
92 
93 struct fqdns shortlist = LIST_HEAD_INITIALIZER(fqdns);
94 struct fqdns skiplist = LIST_HEAD_INITIALIZER(fqdns);
95 
96 /*
97  * Log a message to stderr if and only if "verbose" is non-zero.
98  * This uses the err(3) functionality.
99  */
100 void
logx(const char * fmt,...)101 logx(const char *fmt, ...)
102 {
103 	va_list		 ap;
104 
105 	if (verbose && fmt != NULL) {
106 		va_start(ap, fmt);
107 		vwarnx(fmt, ap);
108 		va_end(ap);
109 	}
110 }
111 
112 time_t
getmonotime(void)113 getmonotime(void)
114 {
115 	struct timespec ts;
116 
117 	if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
118 		err(1, "clock_gettime");
119 	return (ts.tv_sec);
120 }
121 
122 /*
123  * Time - Evaluation time is used as the current time if it is
124  * larger than X509_TIME_MIN, otherwise the system time is used.
125  */
126 time_t
get_current_time(void)127 get_current_time(void)
128 {
129 	if (evaluation_time > X509_TIME_MIN)
130 		return (time_t)evaluation_time;
131 	return time(NULL);
132 }
133 
134 void
entity_free(struct entity * ent)135 entity_free(struct entity *ent)
136 {
137 	if (ent == NULL)
138 		return;
139 
140 	free(ent->path);
141 	free(ent->file);
142 	free(ent->mftaki);
143 	free(ent->data);
144 	free(ent);
145 }
146 
147 /*
148  * Read a queue entity from the descriptor.
149  * Matched by entity_write_req().
150  * The pointer must be passed entity_free().
151  */
152 void
entity_read_req(struct ibuf * b,struct entity * ent)153 entity_read_req(struct ibuf *b, struct entity *ent)
154 {
155 	io_read_buf(b, &ent->type, sizeof(ent->type));
156 	io_read_buf(b, &ent->location, sizeof(ent->location));
157 	io_read_buf(b, &ent->repoid, sizeof(ent->repoid));
158 	io_read_buf(b, &ent->talid, sizeof(ent->talid));
159 	io_read_str(b, &ent->path);
160 	io_read_str(b, &ent->file);
161 	io_read_str(b, &ent->mftaki);
162 	io_read_buf_alloc(b, (void **)&ent->data, &ent->datasz);
163 }
164 
165 /*
166  * Write the queue entity.
167  * Matched by entity_read_req().
168  */
169 static void
entity_write_req(const struct entity * ent)170 entity_write_req(const struct entity *ent)
171 {
172 	struct ibuf *b;
173 
174 	b = io_new_buffer();
175 	io_simple_buffer(b, &ent->type, sizeof(ent->type));
176 	io_simple_buffer(b, &ent->location, sizeof(ent->location));
177 	io_simple_buffer(b, &ent->repoid, sizeof(ent->repoid));
178 	io_simple_buffer(b, &ent->talid, sizeof(ent->talid));
179 	io_str_buffer(b, ent->path);
180 	io_str_buffer(b, ent->file);
181 	io_str_buffer(b, ent->mftaki);
182 	io_buf_buffer(b, ent->data, ent->datasz);
183 	io_close_buffer(&procq, b);
184 }
185 
186 static void
entity_write_repo(const struct repo * rp)187 entity_write_repo(const struct repo *rp)
188 {
189 	struct ibuf *b;
190 	enum rtype type = RTYPE_REPO;
191 	enum location loc = DIR_UNKNOWN;
192 	unsigned int repoid;
193 	char *path, *altpath;
194 	int talid = 0;
195 
196 	repoid = repo_id(rp);
197 	path = repo_basedir(rp, 0);
198 	altpath = repo_basedir(rp, 1);
199 	b = io_new_buffer();
200 	io_simple_buffer(b, &type, sizeof(type));
201 	io_simple_buffer(b, &loc, sizeof(loc));
202 	io_simple_buffer(b, &repoid, sizeof(repoid));
203 	io_simple_buffer(b, &talid, sizeof(talid));
204 	io_str_buffer(b, path);
205 	io_str_buffer(b, altpath);
206 	io_buf_buffer(b, NULL, 0); /* ent->mftaki */
207 	io_buf_buffer(b, NULL, 0); /* ent->data */
208 	io_close_buffer(&procq, b);
209 	free(path);
210 	free(altpath);
211 }
212 
213 /*
214  * Scan through all queued requests and see which ones are in the given
215  * repo, then flush those into the parser process.
216  */
217 void
entityq_flush(struct entityq * q,struct repo * rp)218 entityq_flush(struct entityq *q, struct repo *rp)
219 {
220 	struct entity	*p, *np;
221 
222 	entity_write_repo(rp);
223 
224 	TAILQ_FOREACH_SAFE(p, q, entries, np) {
225 		entity_write_req(p);
226 		TAILQ_REMOVE(q, p, entries);
227 		entity_free(p);
228 	}
229 }
230 
231 /*
232  * Add the heap-allocated file to the queue for processing.
233  */
234 static void
entityq_add(char * path,char * file,enum rtype type,enum location loc,struct repo * rp,unsigned char * data,size_t datasz,int talid,char * mftaki)235 entityq_add(char *path, char *file, enum rtype type, enum location loc,
236     struct repo *rp, unsigned char *data, size_t datasz, int talid,
237     char *mftaki)
238 {
239 	struct entity	*p;
240 
241 	if ((p = calloc(1, sizeof(struct entity))) == NULL)
242 		err(1, NULL);
243 
244 	p->type = type;
245 	p->location = loc;
246 	p->talid = talid;
247 	p->mftaki = mftaki;
248 	p->path = path;
249 	if (rp != NULL)
250 		p->repoid = repo_id(rp);
251 	p->file = file;
252 	p->data = data;
253 	p->datasz = (data != NULL) ? datasz : 0;
254 
255 	entity_queue++;
256 
257 	/*
258 	 * Write to the queue if there's no repo or the repo has already
259 	 * been loaded else enqueue it for later.
260 	 */
261 
262 	if (rp == NULL || !repo_queued(rp, p)) {
263 		entity_write_req(p);
264 		entity_free(p);
265 	}
266 }
267 
268 static void
rrdp_file_resp(unsigned int id,int ok)269 rrdp_file_resp(unsigned int id, int ok)
270 {
271 	enum rrdp_msg type = RRDP_FILE;
272 	struct ibuf *b;
273 
274 	b = io_new_buffer();
275 	io_simple_buffer(b, &type, sizeof(type));
276 	io_simple_buffer(b, &id, sizeof(id));
277 	io_simple_buffer(b, &ok, sizeof(ok));
278 	io_close_buffer(&rrdpq, b);
279 }
280 
281 void
rrdp_fetch(unsigned int id,const char * uri,const char * local,struct rrdp_session * s)282 rrdp_fetch(unsigned int id, const char *uri, const char *local,
283     struct rrdp_session *s)
284 {
285 	enum rrdp_msg type = RRDP_START;
286 	struct ibuf *b;
287 
288 	b = io_new_buffer();
289 	io_simple_buffer(b, &type, sizeof(type));
290 	io_simple_buffer(b, &id, sizeof(id));
291 	io_str_buffer(b, local);
292 	io_str_buffer(b, uri);
293 
294 	rrdp_session_buffer(b, s);
295 	io_close_buffer(&rrdpq, b);
296 }
297 
298 void
rrdp_abort(unsigned int id)299 rrdp_abort(unsigned int id)
300 {
301 	enum rrdp_msg type = RRDP_ABORT;
302 	struct ibuf *b;
303 
304 	b = io_new_buffer();
305 	io_simple_buffer(b, &type, sizeof(type));
306 	io_simple_buffer(b, &id, sizeof(id));
307 	io_close_buffer(&rrdpq, b);
308 }
309 
310 /*
311  * Request a repository sync via rsync URI to directory local.
312  */
313 void
rsync_fetch(unsigned int id,const char * uri,const char * local,const char * base)314 rsync_fetch(unsigned int id, const char *uri, const char *local,
315     const char *base)
316 {
317 	struct ibuf	*b;
318 
319 	b = io_new_buffer();
320 	io_simple_buffer(b, &id, sizeof(id));
321 	io_str_buffer(b, local);
322 	io_str_buffer(b, base);
323 	io_str_buffer(b, uri);
324 	io_close_buffer(&rsyncq, b);
325 }
326 
327 void
rsync_abort(unsigned int id)328 rsync_abort(unsigned int id)
329 {
330 	struct ibuf	*b;
331 
332 	b = io_new_buffer();
333 	io_simple_buffer(b, &id, sizeof(id));
334 	io_str_buffer(b, NULL);
335 	io_str_buffer(b, NULL);
336 	io_str_buffer(b, NULL);
337 	io_close_buffer(&rsyncq, b);
338 }
339 
340 /*
341  * Request a file from a https uri, data is written to the file descriptor fd.
342  */
343 void
http_fetch(unsigned int id,const char * uri,const char * last_mod,int fd)344 http_fetch(unsigned int id, const char *uri, const char *last_mod, int fd)
345 {
346 	struct ibuf	*b;
347 
348 	b = io_new_buffer();
349 	io_simple_buffer(b, &id, sizeof(id));
350 	io_str_buffer(b, uri);
351 	io_str_buffer(b, last_mod);
352 	/* pass file as fd */
353 	ibuf_fd_set(b, fd);
354 	io_close_buffer(&httpq, b);
355 }
356 
357 /*
358  * Request some XML file on behalf of the rrdp parser.
359  * Create a pipe and pass the pipe endpoints to the http and rrdp process.
360  */
361 static void
rrdp_http_fetch(unsigned int id,const char * uri,const char * last_mod)362 rrdp_http_fetch(unsigned int id, const char *uri, const char *last_mod)
363 {
364 	enum rrdp_msg type = RRDP_HTTP_INI;
365 	struct ibuf *b;
366 	int pi[2];
367 
368 	if (pipe2(pi, O_CLOEXEC | O_NONBLOCK) == -1)
369 		err(1, "pipe");
370 
371 	b = io_new_buffer();
372 	io_simple_buffer(b, &type, sizeof(type));
373 	io_simple_buffer(b, &id, sizeof(id));
374 	ibuf_fd_set(b, pi[0]);
375 	io_close_buffer(&rrdpq, b);
376 
377 	http_fetch(id, uri, last_mod, pi[1]);
378 }
379 
380 void
rrdp_http_done(unsigned int id,enum http_result res,const char * last_mod)381 rrdp_http_done(unsigned int id, enum http_result res, const char *last_mod)
382 {
383 	enum rrdp_msg type = RRDP_HTTP_FIN;
384 	struct ibuf *b;
385 
386 	/* RRDP request, relay response over to the rrdp process */
387 	b = io_new_buffer();
388 	io_simple_buffer(b, &type, sizeof(type));
389 	io_simple_buffer(b, &id, sizeof(id));
390 	io_simple_buffer(b, &res, sizeof(res));
391 	io_str_buffer(b, last_mod);
392 	io_close_buffer(&rrdpq, b);
393 }
394 
395 /*
396  * Add a file (CER, ROA, CRL) from an MFT file, RFC 6486.
397  * These are always relative to the directory in which "mft" sits.
398  */
399 static void
queue_add_from_mft(const struct mft * mft)400 queue_add_from_mft(const struct mft *mft)
401 {
402 	size_t			 i;
403 	struct repo		*rp;
404 	const struct mftfile	*f;
405 	char			*mftaki, *nfile, *npath = NULL;
406 
407 	rp = repo_byid(mft->repoid);
408 	for (i = 0; i < mft->filesz; i++) {
409 		f = &mft->files[i];
410 
411 		if (f->type == RTYPE_INVALID || f->type == RTYPE_CRL)
412 			continue;
413 
414 		if (mft->path != NULL)
415 			if ((npath = strdup(mft->path)) == NULL)
416 				err(1, NULL);
417 		if ((nfile = strdup(f->file)) == NULL)
418 			err(1, NULL);
419 		if ((mftaki = strdup(mft->aki)) == NULL)
420 			err(1, NULL);
421 		entityq_add(npath, nfile, f->type, f->location, rp, NULL, 0,
422 		    mft->talid, mftaki);
423 	}
424 }
425 
426 /*
427  * Add a local file to the queue of files to fetch.
428  */
429 static void
queue_add_file(const char * file,enum rtype type,int talid)430 queue_add_file(const char *file, enum rtype type, int talid)
431 {
432 	unsigned char	*buf = NULL;
433 	char		*nfile;
434 	size_t		 len = 0;
435 
436 	if (!filemode || strncmp(file, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0) {
437 		buf = load_file(file, &len);
438 		if (buf == NULL)
439 			err(1, "%s", file);
440 	}
441 
442 	if ((nfile = strdup(file)) == NULL)
443 		err(1, NULL);
444 	/* Not in a repository, so directly add to queue. */
445 	entityq_add(NULL, nfile, type, DIR_UNKNOWN, NULL, buf, len, talid,
446 	    NULL);
447 }
448 
449 /*
450  * Add URIs (CER) from a TAL file, RFC 8630.
451  */
452 static void
queue_add_from_tal(struct tal * tal)453 queue_add_from_tal(struct tal *tal)
454 {
455 	struct repo	*repo;
456 	unsigned char	*data;
457 	char		*nfile;
458 
459 	assert(tal->urisz);
460 
461 	if ((taldescs[tal->id] = strdup(tal->descr)) == NULL)
462 		err(1, NULL);
463 
464 	/* figure out the TA filename, must be done before repo lookup */
465 	nfile = strrchr(tal->uri[0], '/');
466 	assert(nfile != NULL);
467 	if ((nfile = strdup(nfile + 1)) == NULL)
468 		err(1, NULL);
469 
470 	/* Look up the repository. */
471 	repo = ta_lookup(tal->id, tal);
472 	if (repo == NULL) {
473 		free(nfile);
474 		return;
475 	}
476 
477 	/* steal the pkey from the tal structure */
478 	data = tal->pkey;
479 	tal->pkey = NULL;
480 	entityq_add(NULL, nfile, RTYPE_CER, DIR_VALID, repo, data,
481 	    tal->pkeysz, tal->id, NULL);
482 }
483 
484 /*
485  * Add a manifest (MFT) found in an X509 certificate, RFC 6487.
486  */
487 static void
queue_add_from_cert(const struct cert * cert)488 queue_add_from_cert(const struct cert *cert)
489 {
490 	struct repo		*repo;
491 	struct fqdnlistentry	*le;
492 	char			*nfile, *npath, *host;
493 	const char		*uri, *repouri, *file;
494 	size_t			 repourisz;
495 	int			 shortlisted = 0;
496 
497 	if (strncmp(cert->repo, RSYNC_PROTO, RSYNC_PROTO_LEN) != 0)
498 		errx(1, "unexpected protocol");
499 	host = cert->repo + 8;
500 
501 	LIST_FOREACH(le, &skiplist, entry) {
502 		if (strncasecmp(host, le->fqdn, strcspn(host, "/")) == 0) {
503 			warnx("skipping %s (listed in skiplist)", cert->repo);
504 			return;
505 		}
506 	}
507 
508 	LIST_FOREACH(le, &shortlist, entry) {
509 		if (strncasecmp(host, le->fqdn, strcspn(host, "/")) == 0) {
510 			shortlisted = 1;
511 			break;
512 		}
513 	}
514 	if (shortlistmode && shortlisted == 0) {
515 		if (verbose)
516 			warnx("skipping %s (not shortlisted)", cert->repo);
517 		return;
518 	}
519 
520 	repo = repo_lookup(cert->talid, cert->repo,
521 	    rrdpon ? cert->notify : NULL);
522 	if (repo == NULL)
523 		return;
524 
525 	/*
526 	 * Figure out the cert filename and path by chopping up the
527 	 * MFT URI in the cert based on the repo base URI.
528 	 */
529 	uri = cert->mft;
530 	repouri = repo_uri(repo);
531 	repourisz = strlen(repouri);
532 	if (strncmp(repouri, cert->mft, repourisz) != 0) {
533 		warnx("%s: URI %s outside of repository", repouri, uri);
534 		return;
535 	}
536 	uri += repourisz + 1;	/* skip base and '/' */
537 	file = strrchr(uri, '/');
538 	if (file == NULL) {
539 		npath = NULL;
540 		if ((nfile = strdup(uri)) == NULL)
541 			err(1, NULL);
542 	} else {
543 		if ((npath = strndup(uri, file - uri)) == NULL)
544 			err(1, NULL);
545 		if ((nfile = strdup(file + 1)) == NULL)
546 			err(1, NULL);
547 	}
548 
549 	entityq_add(npath, nfile, RTYPE_MFT, DIR_UNKNOWN, repo, NULL, 0,
550 	    cert->talid, NULL);
551 }
552 
553 /*
554  * Process parsed content.
555  * For non-ROAs, we grok for more data.
556  * For ROAs, we want to extract the valid info.
557  * In all cases, we gather statistics.
558  */
559 static void
entity_process(struct ibuf * b,struct stats * st,struct vrp_tree * tree,struct brk_tree * brktree,struct vap_tree * vaptree,struct vsp_tree * vsptree)560 entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
561     struct brk_tree *brktree, struct vap_tree *vaptree,
562     struct vsp_tree *vsptree)
563 {
564 	enum rtype	 type;
565 	struct tal	*tal;
566 	struct cert	*cert;
567 	struct mft	*mft;
568 	struct roa	*roa;
569 	struct aspa	*aspa;
570 	struct spl	*spl;
571 	struct repo	*rp;
572 	char		*file;
573 	time_t		 mtime;
574 	unsigned int	 id;
575 	int		 talid;
576 	int		 c;
577 
578 	/*
579 	 * For most of these, we first read whether there's any content
580 	 * at all---this means that the syntactic parse failed (X509
581 	 * certificate, for example).
582 	 * We follow that up with whether the resources didn't parse.
583 	 */
584 	io_read_buf(b, &type, sizeof(type));
585 	io_read_buf(b, &id, sizeof(id));
586 	io_read_buf(b, &talid, sizeof(talid));
587 	io_read_str(b, &file);
588 	io_read_buf(b, &mtime, sizeof(mtime));
589 
590 	/* in filemode messages can be ignored, only the accounting matters */
591 	if (filemode)
592 		goto done;
593 
594 	if (filepath_add(&fpt, file, mtime) == 0) {
595 		warnx("%s: File already visited", file);
596 		goto done;
597 	}
598 
599 	rp = repo_byid(id);
600 	repo_stat_inc(rp, talid, type, STYPE_OK);
601 	repostats_new_files_inc(rp, file);
602 	switch (type) {
603 	case RTYPE_TAL:
604 		st->tals++;
605 		tal = tal_read(b);
606 		queue_add_from_tal(tal);
607 		tal_free(tal);
608 		break;
609 	case RTYPE_CER:
610 		io_read_buf(b, &c, sizeof(c));
611 		if (c == 0) {
612 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
613 			break;
614 		}
615 		cert = cert_read(b);
616 		switch (cert->purpose) {
617 		case CERT_PURPOSE_CA:
618 			queue_add_from_cert(cert);
619 			break;
620 		case CERT_PURPOSE_BGPSEC_ROUTER:
621 			cert_insert_brks(brktree, cert);
622 			repo_stat_inc(rp, talid, type, STYPE_BGPSEC);
623 			break;
624 		default:
625 			errx(1, "unexpected cert purpose received");
626 			break;
627 		}
628 		cert_free(cert);
629 		break;
630 	case RTYPE_MFT:
631 		io_read_buf(b, &c, sizeof(c));
632 		if (c == 0) {
633 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
634 			break;
635 		}
636 		mft = mft_read(b);
637 		queue_add_from_mft(mft);
638 		mft_free(mft);
639 		break;
640 	case RTYPE_CRL:
641 		/* CRLs are sent together with MFT and not accounted for */
642 		entity_queue++;
643 		break;
644 	case RTYPE_ROA:
645 		io_read_buf(b, &c, sizeof(c));
646 		if (c == 0) {
647 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
648 			break;
649 		}
650 		roa = roa_read(b);
651 		if (roa->valid)
652 			roa_insert_vrps(tree, roa, rp);
653 		else
654 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
655 		roa_free(roa);
656 		break;
657 	case RTYPE_GBR:
658 		break;
659 	case RTYPE_ASPA:
660 		io_read_buf(b, &c, sizeof(c));
661 		if (c == 0) {
662 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
663 			break;
664 		}
665 		aspa = aspa_read(b);
666 		if (aspa->valid)
667 			aspa_insert_vaps(file, vaptree, aspa, rp);
668 		else
669 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
670 		aspa_free(aspa);
671 		break;
672 	case RTYPE_SPL:
673 		io_read_buf(b, &c, sizeof(c));
674 		if (c == 0) {
675 			if (experimental)
676 				repo_stat_inc(rp, talid, type, STYPE_FAIL);
677 			break;
678 		}
679 		spl = spl_read(b);
680 		if (spl->valid)
681 			spl_insert_vsps(vsptree, spl, rp);
682 		else
683 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
684 		spl_free(spl);
685 		break;
686 	case RTYPE_TAK:
687 		break;
688 	case RTYPE_FILE:
689 		break;
690 	default:
691 		warnx("%s: unknown entity type %d", file, type);
692 		break;
693 	}
694 
695 done:
696 	free(file);
697 	entity_queue--;
698 }
699 
700 static void
rrdp_process(struct ibuf * b)701 rrdp_process(struct ibuf *b)
702 {
703 	enum rrdp_msg type;
704 	enum publish_type pt;
705 	struct rrdp_session *s;
706 	char *uri, *last_mod, *data;
707 	char hash[SHA256_DIGEST_LENGTH];
708 	size_t dsz;
709 	unsigned int id;
710 	int ok;
711 
712 	io_read_buf(b, &type, sizeof(type));
713 	io_read_buf(b, &id, sizeof(id));
714 
715 	switch (type) {
716 	case RRDP_END:
717 		io_read_buf(b, &ok, sizeof(ok));
718 		rrdp_finish(id, ok);
719 		break;
720 	case RRDP_HTTP_REQ:
721 		io_read_str(b, &uri);
722 		io_read_str(b, &last_mod);
723 		rrdp_http_fetch(id, uri, last_mod);
724 		break;
725 	case RRDP_SESSION:
726 		s = rrdp_session_read(b);
727 		rrdp_session_save(id, s);
728 		rrdp_session_free(s);
729 		break;
730 	case RRDP_FILE:
731 		io_read_buf(b, &pt, sizeof(pt));
732 		if (pt != PUB_ADD)
733 			io_read_buf(b, &hash, sizeof(hash));
734 		io_read_str(b, &uri);
735 		io_read_buf_alloc(b, (void **)&data, &dsz);
736 
737 		ok = rrdp_handle_file(id, pt, uri, hash, sizeof(hash),
738 		    data, dsz);
739 		rrdp_file_resp(id, ok);
740 
741 		free(uri);
742 		free(data);
743 		break;
744 	case RRDP_CLEAR:
745 		rrdp_clear(id);
746 		break;
747 	default:
748 		errx(1, "unexpected rrdp response");
749 	}
750 }
751 
752 static void
sum_stats(const struct repo * rp,const struct repotalstats * in,void * arg)753 sum_stats(const struct repo *rp, const struct repotalstats *in, void *arg)
754 {
755 	struct repotalstats *out = arg;
756 
757 	out->mfts += in->mfts;
758 	out->mfts_fail += in->mfts_fail;
759 	out->certs += in->certs;
760 	out->certs_fail += in->certs_fail;
761 	out->roas += in->roas;
762 	out->roas_fail += in->roas_fail;
763 	out->roas_invalid += in->roas_invalid;
764 	out->aspas += in->aspas;
765 	out->aspas_fail += in->aspas_fail;
766 	out->aspas_invalid += in->aspas_invalid;
767 	out->brks += in->brks;
768 	out->crls += in->crls;
769 	out->gbrs += in->gbrs;
770 	out->taks += in->taks;
771 	out->vrps += in->vrps;
772 	out->vrps_uniqs += in->vrps_uniqs;
773 	out->vaps += in->vaps;
774 	out->vaps_uniqs += in->vaps_uniqs;
775 	out->vaps_pas += in->vaps_pas;
776 	out->vaps_overflowed += in->vaps_overflowed;
777 	out->spls += in->spls;
778 	out->spls_fail += in->spls_fail;
779 	out->spls_invalid += in->spls_invalid;
780 	out->vsps += in->vsps;
781 	out->vsps_uniqs += in->vsps_uniqs;
782 }
783 
784 static void
sum_repostats(const struct repo * rp,const struct repostats * in,void * arg)785 sum_repostats(const struct repo *rp, const struct repostats *in, void *arg)
786 {
787 	struct repostats *out = arg;
788 
789 	out->del_files += in->del_files;
790 	out->extra_files += in->extra_files;
791 	out->del_extra_files += in->del_extra_files;
792 	out->del_dirs += in->del_dirs;
793 	out->new_files += in->new_files;
794 	timespecadd(&in->sync_time, &out->sync_time, &out->sync_time);
795 }
796 
797 /*
798  * Assign filenames ending in ".tal" in "/etc/rpki" into "tals",
799  * returning the number of files found and filled-in.
800  * This may be zero.
801  * Don't exceed "max" filenames.
802  */
803 static int
tal_load_default(void)804 tal_load_default(void)
805 {
806 	static const char *confdir = "/etc/rpki";
807 	int s = 0;
808 	char *path;
809 	DIR *dirp;
810 	struct dirent *dp;
811 
812 	dirp = opendir(confdir);
813 	if (dirp == NULL)
814 		err(1, "open %s", confdir);
815 	while ((dp = readdir(dirp)) != NULL) {
816 		if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH)
817 			continue;
818 		if (s >= TALSZ_MAX)
819 			err(1, "too many tal files found in %s",
820 			    confdir);
821 		if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1)
822 			err(1, NULL);
823 		tals[s++] = path;
824 	}
825 	closedir(dirp);
826 	return s;
827 }
828 
829 /*
830  * Load the list of FQDNs from the skiplist which are to be distrusted.
831  * Return 0 on success.
832  */
833 static void
load_skiplist(const char * slf)834 load_skiplist(const char *slf)
835 {
836 	struct fqdnlistentry	*le;
837 	FILE			*fp;
838 	char			*line = NULL;
839 	size_t			 linesize = 0, linelen;
840 
841 	if ((fp = fopen(slf, "r")) == NULL) {
842 		if (errno == ENOENT && strcmp(slf, DEFAULT_SKIPLIST_FILE) == 0)
843 			return;
844 		err(1, "failed to open %s", slf);
845 	}
846 
847 	while (getline(&line, &linesize, fp) != -1) {
848 		/* just eat comment lines or empty lines*/
849 		if (line[0] == '#' || line[0] == '\n')
850 			continue;
851 
852 		if (line[0] == ' ' || line[0] == '\t')
853 			errx(1, "invalid entry in skiplist: %s", line);
854 
855 		/*
856 		 * Ignore anything after comment sign, whitespaces,
857 		 * also chop off LF or CR.
858 		 */
859 		linelen = strcspn(line, " #\r\n\t");
860 		line[linelen] = '\0';
861 
862 		if (!valid_uri(line, linelen, NULL))
863 			errx(1, "invalid entry in skiplist: %s", line);
864 
865 		if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
866 			err(1, NULL);
867 		if ((le->fqdn = strdup(line)) == NULL)
868 			err(1, NULL);
869 
870 		LIST_INSERT_HEAD(&skiplist, le, entry);
871 		stats.skiplistentries++;
872 	}
873 
874 	fclose(fp);
875 	free(line);
876 }
877 
878 /*
879  * Load shortlist entries.
880  */
881 static void
load_shortlist(const char * fqdn)882 load_shortlist(const char *fqdn)
883 {
884 	struct fqdnlistentry	*le;
885 
886 	if (!valid_uri(fqdn, strlen(fqdn), NULL))
887 		errx(1, "invalid fqdn passed to -q: %s", fqdn);
888 
889 	if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
890 		err(1, NULL);
891 
892 	if ((le->fqdn = strdup(fqdn)) == NULL)
893 		err(1, NULL);
894 
895 	LIST_INSERT_HEAD(&shortlist, le, entry);
896 }
897 
898 static void
check_fs_size(int fd,const char * cachedir)899 check_fs_size(int fd, const char *cachedir)
900 {
901 	struct statvfs		fs;
902 	unsigned long long	minsize = 500 * 1024 * 1024;
903 	unsigned long long	minnode = 300 * 1000;
904 
905 	if (fstatvfs(fd, &fs) == -1)
906 		err(1, "statfs %s", cachedir);
907 
908 	if (fs.f_bavail < minsize / fs.f_frsize ||
909 	    (fs.f_ffree > 0 && fs.f_favail < minnode)) {
910 		fprintf(stderr, "WARNING: rpki-client may need more than "
911 		    "the available disk space\n"
912 		    "on the file-system holding %s.\n", cachedir);
913 		fprintf(stderr, "available space: %llukB, "
914 		    "suggested minimum %llukB\n",
915 		    (unsigned long long)fs.f_bavail * fs.f_frsize / 1024,
916 		    minsize / 1024);
917 		fprintf(stderr, "available inodes: %llu, "
918 		    "suggested minimum: %llu\n\n",
919 		    (unsigned long long)fs.f_favail, minnode);
920 		fflush(stderr);
921 	}
922 }
923 
924 static pid_t
process_start(const char * title,int * fd)925 process_start(const char *title, int *fd)
926 {
927 	int		 fl = SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
928 	pid_t		 pid;
929 	int		 pair[2];
930 
931 	if (socketpair(AF_UNIX, fl, 0, pair) == -1)
932 		err(1, "socketpair");
933 	if ((pid = fork()) == -1)
934 		err(1, "fork");
935 
936 	if (pid == 0) {
937 		setproctitle("%s", title);
938 		/* change working directory to the cache directory */
939 		if (fchdir(cachefd) == -1)
940 			err(1, "fchdir");
941 		if (!filemode && timeout > 0)
942 			alarm(timeout);
943 		close(pair[1]);
944 		*fd = pair[0];
945 	} else {
946 		close(pair[0]);
947 		*fd = pair[1];
948 	}
949 	return pid;
950 }
951 
952 void
suicide(int sig)953 suicide(int sig __attribute__((unused)))
954 {
955 	killme = 1;
956 }
957 
958 #define NPFD	4
959 
960 int
main(int argc,char * argv[])961 main(int argc, char *argv[])
962 {
963 	int		 rc, c, i, st, proc, rsync, http, rrdp, hangup = 0;
964 	pid_t		 pid, procpid, rsyncpid, httppid, rrdppid;
965 	struct pollfd	 pfd[NPFD];
966 	struct msgbuf	*queues[NPFD];
967 	struct ibuf	*b, *httpbuf = NULL, *procbuf = NULL;
968 	struct ibuf	*rrdpbuf = NULL, *rsyncbuf = NULL;
969 	char		*rsync_prog = "openrsync";
970 	char		*bind_addr = NULL;
971 	const char	*cachedir = NULL, *outputdir = NULL;
972 	const char	*errs, *name;
973 	const char	*skiplistfile = NULL;
974 	struct vrp_tree	 vrps = RB_INITIALIZER(&vrps);
975 	struct vsp_tree	 vsps = RB_INITIALIZER(&vsps);
976 	struct brk_tree	 brks = RB_INITIALIZER(&brks);
977 	struct vap_tree	 vaps = RB_INITIALIZER(&vaps);
978 	struct rusage	 ru;
979 	struct timespec	 start_time, now_time;
980 
981 	clock_gettime(CLOCK_MONOTONIC, &start_time);
982 
983 	/* If started as root, priv-drop to _rpki-client */
984 	if (getuid() == 0) {
985 		struct passwd *pw;
986 
987 		pw = getpwnam("_rpki-client");
988 		if (!pw)
989 			errx(1, "no _rpki-client user to revoke to");
990 		if (setgroups(1, &pw->pw_gid) == -1 ||
991 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
992 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
993 			err(1, "unable to revoke privs");
994 	}
995 	cachedir = RPKI_PATH_BASE_DIR;
996 	outputdir = RPKI_PATH_OUT_DIR;
997 	repo_timeout = timeout / 4;
998 	skiplistfile = DEFAULT_SKIPLIST_FILE;
999 
1000 	if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd "
1001 	    "proc exec unveil", NULL) == -1)
1002 		err(1, "pledge");
1003 
1004 	while ((c = getopt(argc, argv, "Ab:Bcd:e:fH:jmnoP:rRs:S:t:T:vVx")) != -1)
1005 		switch (c) {
1006 		case 'A':
1007 			excludeaspa = 1;
1008 			break;
1009 		case 'b':
1010 			bind_addr = optarg;
1011 			break;
1012 		case 'B':
1013 			outformats |= FORMAT_BIRD;
1014 			break;
1015 		case 'c':
1016 			outformats |= FORMAT_CSV;
1017 			break;
1018 		case 'd':
1019 			cachedir = optarg;
1020 			break;
1021 		case 'e':
1022 			rsync_prog = optarg;
1023 			break;
1024 		case 'f':
1025 			filemode = 1;
1026 			noop = 1;
1027 			break;
1028 		case 'H':
1029 			shortlistmode = 1;
1030 			load_shortlist(optarg);
1031 			break;
1032 		case 'j':
1033 			outformats |= FORMAT_JSON;
1034 			break;
1035 		case 'm':
1036 			outformats |= FORMAT_OMETRIC;
1037 			break;
1038 		case 'n':
1039 			noop = 1;
1040 			break;
1041 		case 'o':
1042 			outformats |= FORMAT_OPENBGPD;
1043 			break;
1044 		case 'P':
1045 			evaluation_time = strtonum(optarg, X509_TIME_MIN + 1,
1046 			    X509_TIME_MAX, &errs);
1047 			if (errs)
1048 				errx(1, "-P: time in seconds %s", errs);
1049 			break;
1050 		case 'R':
1051 			rrdpon = 0;
1052 			break;
1053 		case 'r': /* Remove after OpenBSD 7.3 */
1054 			rrdpon = 1;
1055 			break;
1056 		case 's':
1057 			timeout = strtonum(optarg, 0, 24*60*60, &errs);
1058 			if (errs)
1059 				errx(1, "-s: %s", errs);
1060 			if (timeout == 0)
1061 				repo_timeout = 24*60*60;
1062 			else
1063 				repo_timeout = timeout / 4;
1064 			break;
1065 		case 'S':
1066 			skiplistfile = optarg;
1067 			break;
1068 		case 't':
1069 			if (talsz >= TALSZ_MAX)
1070 				err(1, "too many tal files specified");
1071 			tals[talsz++] = optarg;
1072 			break;
1073 		case 'T':
1074 			bird_tablename = optarg;
1075 			break;
1076 		case 'v':
1077 			verbose++;
1078 			break;
1079 		case 'V':
1080 			fprintf(stderr, "rpki-client %s\n", RPKI_VERSION);
1081 			return 0;
1082 		case 'x':
1083 			experimental = 1;
1084 			break;
1085 		default:
1086 			goto usage;
1087 		}
1088 
1089 	argv += optind;
1090 	argc -= optind;
1091 
1092 	if (!filemode) {
1093 		if (argc == 1)
1094 			outputdir = argv[0];
1095 		else if (argc > 1)
1096 			goto usage;
1097 
1098 		if (outputdir == NULL) {
1099 			warnx("output directory required");
1100 			goto usage;
1101 		}
1102 	} else {
1103 		if (argc == 0)
1104 			goto usage;
1105 		outputdir = NULL;
1106 	}
1107 
1108 	if (cachedir == NULL) {
1109 		warnx("cache directory required");
1110 		goto usage;
1111 	}
1112 
1113 	signal(SIGPIPE, SIG_IGN);
1114 
1115 	if ((cachefd = open(cachedir, O_RDONLY | O_DIRECTORY)) == -1)
1116 		err(1, "cache directory %s", cachedir);
1117 	if (outputdir != NULL) {
1118 		if ((outdirfd = open(outputdir, O_RDONLY | O_DIRECTORY)) == -1)
1119 			err(1, "output directory %s", outputdir);
1120 		if (outformats == 0)
1121 			outformats = FORMAT_OPENBGPD;
1122 	}
1123 
1124 	check_fs_size(cachefd, cachedir);
1125 
1126 	if (talsz == 0)
1127 		talsz = tal_load_default();
1128 	if (talsz == 0)
1129 		err(1, "no TAL files found in %s", "/etc/rpki");
1130 
1131 	/* Load optional constraint files sitting next to the TALs. */
1132 	constraints_load();
1133 
1134 	/*
1135 	 * Create the file reader as a jailed child process.
1136 	 * It will be responsible for reading all of the files (ROAs,
1137 	 * manifests, certificates, etc.) and returning contents.
1138 	 */
1139 
1140 	procpid = process_start("parser", &proc);
1141 	if (procpid == 0) {
1142 		if (!filemode)
1143 			proc_parser(proc);
1144 		else
1145 			proc_filemode(proc);
1146 	}
1147 
1148 	/* Constraints are only needed in the filemode and parser processes. */
1149 	constraints_unload();
1150 
1151 	/*
1152 	 * Create a process that will do the rsync'ing.
1153 	 * This process is responsible for making sure that all the
1154 	 * repositories referenced by a certificate manifest (or the
1155 	 * TAL) exists and has been downloaded.
1156 	 */
1157 
1158 	if (!noop) {
1159 		rsyncpid = process_start("rsync", &rsync);
1160 		if (rsyncpid == 0) {
1161 			close(proc);
1162 			proc_rsync(rsync_prog, bind_addr, rsync);
1163 		}
1164 	} else {
1165 		rsync = -1;
1166 		rsyncpid = -1;
1167 	}
1168 
1169 	/*
1170 	 * Create a process that will fetch data via https.
1171 	 * With every request the http process receives a file descriptor
1172 	 * where the data should be written to.
1173 	 */
1174 
1175 	if (!noop && rrdpon) {
1176 		httppid = process_start("http", &http);
1177 
1178 		if (httppid == 0) {
1179 			close(proc);
1180 			close(rsync);
1181 			proc_http(bind_addr, http);
1182 		}
1183 	} else {
1184 		http = -1;
1185 		httppid = -1;
1186 	}
1187 
1188 	/*
1189 	 * Create a process that will process RRDP.
1190 	 * The rrdp process requires the http process to fetch the various
1191 	 * XML files and does this via the main process.
1192 	 */
1193 
1194 	if (!noop && rrdpon) {
1195 		rrdppid = process_start("rrdp", &rrdp);
1196 		if (rrdppid == 0) {
1197 			close(proc);
1198 			close(rsync);
1199 			close(http);
1200 			proc_rrdp(rrdp);
1201 		}
1202 	} else {
1203 		rrdp = -1;
1204 		rrdppid = -1;
1205 	}
1206 
1207 	if (!filemode && timeout > 0) {
1208 		/*
1209 		 * Commit suicide eventually
1210 		 * cron will normally start a new one
1211 		 */
1212 		alarm(timeout);
1213 		signal(SIGALRM, suicide);
1214 
1215 		/* give up a bit before the hard timeout and try to finish up */
1216 		if (!noop)
1217 			deadline = getmonotime() + timeout - repo_timeout / 2;
1218 	}
1219 
1220 	if (pledge("stdio rpath wpath cpath fattr sendfd unveil", NULL) == -1)
1221 		err(1, "pledge");
1222 
1223 	msgbuf_init(&procq);
1224 	msgbuf_init(&rsyncq);
1225 	msgbuf_init(&httpq);
1226 	msgbuf_init(&rrdpq);
1227 	procq.fd = proc;
1228 	rsyncq.fd = rsync;
1229 	httpq.fd = http;
1230 	rrdpq.fd = rrdp;
1231 
1232 	/*
1233 	 * The main process drives the top-down scan to leaf ROAs using
1234 	 * data downloaded by the rsync process and parsed by the
1235 	 * parsing process.
1236 	 */
1237 
1238 	pfd[0].fd = proc;
1239 	queues[0] = &procq;
1240 	pfd[1].fd = rsync;
1241 	queues[1] = &rsyncq;
1242 	pfd[2].fd = http;
1243 	queues[2] = &httpq;
1244 	pfd[3].fd = rrdp;
1245 	queues[3] = &rrdpq;
1246 
1247 	load_skiplist(skiplistfile);
1248 
1249 	/*
1250 	 * Prime the process with our TAL files.
1251 	 * These will (hopefully) contain links to manifests and we
1252 	 * can get the ball rolling.
1253 	 */
1254 
1255 	for (i = 0; i < talsz; i++)
1256 		queue_add_file(tals[i], RTYPE_TAL, i);
1257 
1258 	if (filemode) {
1259 		while (*argv != NULL)
1260 			queue_add_file(*argv++, RTYPE_FILE, 0);
1261 
1262 		if (unveil(cachedir, "r") == -1)
1263 			err(1, "unveil cachedir");
1264 	} else {
1265 		if (unveil(outputdir, "rwc") == -1)
1266 			err(1, "unveil outputdir");
1267 		if (unveil(cachedir, "rwc") == -1)
1268 			err(1, "unveil cachedir");
1269 	}
1270 	if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1)
1271 		err(1, "unveil");
1272 
1273 	/* change working directory to the cache directory */
1274 	if (fchdir(cachefd) == -1)
1275 		err(1, "fchdir");
1276 
1277 	while (entity_queue > 0 && !killme) {
1278 		int polltim;
1279 
1280 		for (i = 0; i < NPFD; i++) {
1281 			pfd[i].events = POLLIN;
1282 			if (queues[i]->queued)
1283 				pfd[i].events |= POLLOUT;
1284 		}
1285 
1286 		polltim = repo_check_timeout(INFTIM);
1287 
1288 		if (poll(pfd, NPFD, polltim) == -1) {
1289 			if (errno == EINTR)
1290 				continue;
1291 			err(1, "poll");
1292 		}
1293 
1294 		for (i = 0; i < NPFD; i++) {
1295 			if (pfd[i].revents & (POLLERR|POLLNVAL)) {
1296 				warnx("poll[%d]: bad fd", i);
1297 				hangup = 1;
1298 			}
1299 			if (pfd[i].revents & POLLHUP)
1300 				hangup = 1;
1301 			if (pfd[i].revents & POLLOUT) {
1302 				switch (msgbuf_write(queues[i])) {
1303 				case 0:
1304 					warnx("write[%d]: "
1305 					    "connection closed", i);
1306 					hangup = 1;
1307 					break;
1308 				case -1:
1309 					warn("write[%d]", i);
1310 					hangup = 1;
1311 					break;
1312 				}
1313 			}
1314 		}
1315 		if (hangup)
1316 			break;
1317 
1318 		/*
1319 		 * Check the rsync and http process.
1320 		 * This means that one of our modules has completed
1321 		 * downloading and we can flush the module requests into
1322 		 * the parser process.
1323 		 */
1324 
1325 		if ((pfd[1].revents & POLLIN)) {
1326 			b = io_buf_read(rsync, &rsyncbuf);
1327 			if (b != NULL) {
1328 				unsigned int id;
1329 				int ok;
1330 
1331 				io_read_buf(b, &id, sizeof(id));
1332 				io_read_buf(b, &ok, sizeof(ok));
1333 				rsync_finish(id, ok);
1334 				ibuf_free(b);
1335 			}
1336 		}
1337 
1338 		if ((pfd[2].revents & POLLIN)) {
1339 			b = io_buf_read(http, &httpbuf);
1340 			if (b != NULL) {
1341 				unsigned int id;
1342 				enum http_result res;
1343 				char *last_mod;
1344 
1345 				io_read_buf(b, &id, sizeof(id));
1346 				io_read_buf(b, &res, sizeof(res));
1347 				io_read_str(b, &last_mod);
1348 				http_finish(id, res, last_mod);
1349 				free(last_mod);
1350 				ibuf_free(b);
1351 			}
1352 		}
1353 
1354 		/*
1355 		 * Handle RRDP requests here.
1356 		 */
1357 		if ((pfd[3].revents & POLLIN)) {
1358 			b = io_buf_read(rrdp, &rrdpbuf);
1359 			if (b != NULL) {
1360 				rrdp_process(b);
1361 				ibuf_free(b);
1362 			}
1363 		}
1364 
1365 		/*
1366 		 * The parser has finished something for us.
1367 		 * Dequeue these one by one.
1368 		 */
1369 
1370 		if ((pfd[0].revents & POLLIN)) {
1371 			b = io_buf_read(proc, &procbuf);
1372 			if (b != NULL) {
1373 				entity_process(b, &stats, &vrps, &brks, &vaps,
1374 				    &vsps);
1375 				ibuf_free(b);
1376 			}
1377 		}
1378 	}
1379 
1380 	signal(SIGALRM, SIG_DFL);
1381 	if (killme) {
1382 		syslog(LOG_CRIT|LOG_DAEMON,
1383 		    "excessive runtime (%d seconds), giving up", timeout);
1384 		errx(1, "excessive runtime (%d seconds), giving up", timeout);
1385 	}
1386 
1387 	/*
1388 	 * For clean-up, close the input for the parser and rsync
1389 	 * process.
1390 	 * This will cause them to exit, then we reap them.
1391 	 */
1392 
1393 	close(proc);
1394 	close(rsync);
1395 	close(http);
1396 	close(rrdp);
1397 
1398 	rc = 0;
1399 	for (;;) {
1400 		pid = waitpid(WAIT_ANY, &st, 0);
1401 		if (pid == -1) {
1402 			if (errno == EINTR)
1403 				continue;
1404 			if (errno == ECHILD)
1405 				break;
1406 			err(1, "wait");
1407 		}
1408 
1409 		if (pid == procpid)
1410 			name = "parser";
1411 		else if (pid == rsyncpid)
1412 			name = "rsync";
1413 		else if (pid == httppid)
1414 			name = "http";
1415 		else if (pid == rrdppid)
1416 			name = "rrdp";
1417 		else
1418 			name = "unknown";
1419 
1420 		if (WIFSIGNALED(st)) {
1421 			warnx("%s terminated signal %d", name, WTERMSIG(st));
1422 			rc = 1;
1423 		} else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
1424 			warnx("%s process exited abnormally", name);
1425 			rc = 1;
1426 		}
1427 	}
1428 
1429 	/* processing did not finish because of error */
1430 	if (entity_queue != 0)
1431 		errx(1, "not all files processed, giving up");
1432 
1433 	/* if processing in filemode the process is done, no cleanup */
1434 	if (filemode)
1435 		return rc;
1436 
1437 	logx("all files parsed: generating output");
1438 
1439 	if (!noop)
1440 		repo_cleanup(&fpt, cachefd);
1441 
1442 	clock_gettime(CLOCK_MONOTONIC, &now_time);
1443 	timespecsub(&now_time, &start_time, &stats.elapsed_time);
1444 	if (getrusage(RUSAGE_SELF, &ru) == 0) {
1445 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &stats.user_time);
1446 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &stats.system_time);
1447 	}
1448 	if (getrusage(RUSAGE_CHILDREN, &ru) == 0) {
1449 		struct timespec ts;
1450 
1451 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &ts);
1452 		timespecadd(&stats.user_time, &ts, &stats.user_time);
1453 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &ts);
1454 		timespecadd(&stats.system_time, &ts, &stats.system_time);
1455 	}
1456 
1457 	/* change working directory to the output directory */
1458 	if (fchdir(outdirfd) == -1)
1459 		err(1, "fchdir output dir");
1460 
1461 	for (i = 0; i < talsz; i++) {
1462 		repo_tal_stats_collect(sum_stats, i, &talstats[i]);
1463 		repo_tal_stats_collect(sum_stats, i, &stats.repo_tal_stats);
1464 	}
1465 	repo_stats_collect(sum_repostats, &stats.repo_stats);
1466 
1467 	if (outputfiles(&vrps, &brks, &vaps, &vsps, &stats))
1468 		rc = 1;
1469 
1470 	printf("Processing time %lld seconds "
1471 	    "(%lld seconds user, %lld seconds system)\n",
1472 	    (long long)stats.elapsed_time.tv_sec,
1473 	    (long long)stats.user_time.tv_sec,
1474 	    (long long)stats.system_time.tv_sec);
1475 	printf("Skiplist entries: %u\n", stats.skiplistentries);
1476 	printf("Route Origin Authorizations: %u (%u failed parse, %u "
1477 	    "invalid)\n", stats.repo_tal_stats.roas,
1478 	    stats.repo_tal_stats.roas_fail,
1479 	    stats.repo_tal_stats.roas_invalid);
1480 	printf("AS Provider Attestations: %u (%u failed parse, %u "
1481 	    "invalid)\n", stats.repo_tal_stats.aspas,
1482 	    stats.repo_tal_stats.aspas_fail,
1483 	    stats.repo_tal_stats.aspas_invalid);
1484 	printf("Signed Prefix Lists: %u (%u failed parse, %u invalid)\n",
1485 	    stats.repo_tal_stats.spls, stats.repo_tal_stats.spls_fail,
1486 	    stats.repo_tal_stats.spls_invalid);
1487 	printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks);
1488 	printf("Certificates: %u (%u invalid)\n",
1489 	    stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail);
1490 	printf("Trust Anchor Locators: %u (%u invalid)\n",
1491 	    stats.tals, talsz - stats.tals);
1492 	printf("Manifests: %u (%u failed parse)\n",
1493 	    stats.repo_tal_stats.mfts, stats.repo_tal_stats.mfts_fail);
1494 	printf("Certificate revocation lists: %u\n", stats.repo_tal_stats.crls);
1495 	printf("Ghostbuster records: %u\n", stats.repo_tal_stats.gbrs);
1496 	printf("Trust Anchor Keys: %u\n", stats.repo_tal_stats.taks);
1497 	printf("Repositories: %u\n", stats.repos);
1498 	printf("New files moved into validated cache: %u\n",
1499 	    stats.repo_stats.new_files);
1500 	printf("Cleanup: removed %u files, %u directories\n"
1501 	    "Repository cleanup: kept %u and removed %u superfluous files\n",
1502 	    stats.repo_stats.del_files, stats.repo_stats.del_dirs,
1503 	    stats.repo_stats.extra_files, stats.repo_stats.del_extra_files);
1504 	printf("VRP Entries: %u (%u unique)\n", stats.repo_tal_stats.vrps,
1505 	    stats.repo_tal_stats.vrps_uniqs);
1506 	printf("VAP Entries: %u (%u unique, %u overflowed)\n",
1507 	    stats.repo_tal_stats.vaps, stats.repo_tal_stats.vaps_uniqs,
1508 	    stats.repo_tal_stats.vaps_overflowed);
1509 	printf("VSP Entries: %u (%u unique)\n", stats.repo_tal_stats.vsps,
1510 	    stats.repo_tal_stats.vsps_uniqs);
1511 
1512 	/* Memory cleanup. */
1513 	repo_free();
1514 
1515 	return rc;
1516 
1517 usage:
1518 	fprintf(stderr,
1519 	    "usage: rpki-client [-ABcjmnoRrVvx] [-b sourceaddr] [-d cachedir]"
1520 	    " [-e rsync_prog]\n"
1521 	    "                   [-H fqdn] [-P epoch] [-S skiplist] [-s timeout]"
1522 	    " [-T table]\n"
1523 	    "                   [-t tal] [outputdir]\n"
1524 	    "       rpki-client [-Vv] [-d cachedir] [-j] [-t tal] -f file ..."
1525 	    "\n");
1526 	return 1;
1527 }
1528