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