xref: /openbsd/usr.sbin/rpki-client/main.c (revision 318f0572)
1 /*	$OpenBSD: main.c,v 1.269 2024/11/02 12:30:28 job 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		 ok = 1;
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_valid(&fpt, file, talid)) {
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, &ok, sizeof(ok));
615 		if (ok == 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, &ok, sizeof(ok));
637 		if (ok == 0) {
638 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
639 			break;
640 		}
641 		mft = mft_read(b);
642 		if (mft->seqnum_gap)
643 			repo_stat_inc(rp, talid, type, STYPE_SEQNUM_GAP);
644 		queue_add_from_mft(mft);
645 		mft_free(mft);
646 		break;
647 	case RTYPE_CRL:
648 		/* CRLs are sent together with MFT and not accounted for */
649 		entity_queue++;
650 		break;
651 	case RTYPE_ROA:
652 		io_read_buf(b, &ok, sizeof(ok));
653 		if (ok == 0) {
654 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
655 			break;
656 		}
657 		roa = roa_read(b);
658 		if (roa->valid)
659 			roa_insert_vrps(tree, roa, rp);
660 		else
661 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
662 		roa_free(roa);
663 		break;
664 	case RTYPE_GBR:
665 		break;
666 	case RTYPE_ASPA:
667 		io_read_buf(b, &ok, sizeof(ok));
668 		if (ok == 0) {
669 			repo_stat_inc(rp, talid, type, STYPE_FAIL);
670 			break;
671 		}
672 		aspa = aspa_read(b);
673 		if (aspa->valid)
674 			aspa_insert_vaps(file, vaptree, aspa, rp);
675 		else
676 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
677 		aspa_free(aspa);
678 		break;
679 	case RTYPE_SPL:
680 		io_read_buf(b, &ok, sizeof(ok));
681 		if (ok == 0) {
682 			if (experimental)
683 				repo_stat_inc(rp, talid, type, STYPE_FAIL);
684 			break;
685 		}
686 		spl = spl_read(b);
687 		if (spl->valid)
688 			spl_insert_vsps(vsptree, spl, rp);
689 		else
690 			repo_stat_inc(rp, talid, type, STYPE_INVALID);
691 		spl_free(spl);
692 		break;
693 	case RTYPE_TAK:
694 		break;
695 	case RTYPE_FILE:
696 		break;
697 	default:
698 		warnx("%s: unknown entity type %d", file, type);
699 		break;
700 	}
701 
702 	if (filepath_add(&fpt, file, talid, mtime, ok) == 0)
703 		errx(1, "%s: File already in tree", file);
704 
705 done:
706 	free(file);
707 	entity_queue--;
708 }
709 
710 static void
rrdp_process(struct ibuf * b)711 rrdp_process(struct ibuf *b)
712 {
713 	enum rrdp_msg type;
714 	enum publish_type pt;
715 	struct rrdp_session *s;
716 	char *uri, *last_mod, *data;
717 	char hash[SHA256_DIGEST_LENGTH];
718 	size_t dsz;
719 	unsigned int id;
720 	int ok;
721 
722 	io_read_buf(b, &type, sizeof(type));
723 	io_read_buf(b, &id, sizeof(id));
724 
725 	switch (type) {
726 	case RRDP_END:
727 		io_read_buf(b, &ok, sizeof(ok));
728 		rrdp_finish(id, ok);
729 		break;
730 	case RRDP_HTTP_REQ:
731 		io_read_str(b, &uri);
732 		io_read_str(b, &last_mod);
733 		rrdp_http_fetch(id, uri, last_mod);
734 		break;
735 	case RRDP_SESSION:
736 		s = rrdp_session_read(b);
737 		rrdp_session_save(id, s);
738 		rrdp_session_free(s);
739 		break;
740 	case RRDP_FILE:
741 		io_read_buf(b, &pt, sizeof(pt));
742 		if (pt != PUB_ADD)
743 			io_read_buf(b, &hash, sizeof(hash));
744 		io_read_str(b, &uri);
745 		io_read_buf_alloc(b, (void **)&data, &dsz);
746 
747 		ok = rrdp_handle_file(id, pt, uri, hash, sizeof(hash),
748 		    data, dsz);
749 		rrdp_file_resp(id, ok);
750 
751 		free(uri);
752 		free(data);
753 		break;
754 	case RRDP_CLEAR:
755 		rrdp_clear(id);
756 		break;
757 	default:
758 		errx(1, "unexpected rrdp response");
759 	}
760 }
761 
762 static void
sum_stats(const struct repo * rp,const struct repotalstats * in,void * arg)763 sum_stats(const struct repo *rp, const struct repotalstats *in, void *arg)
764 {
765 	struct repotalstats *out = arg;
766 
767 	out->mfts += in->mfts;
768 	out->mfts_fail += in->mfts_fail;
769 	out->mfts_gap += in->mfts_gap;
770 	out->certs += in->certs;
771 	out->certs_fail += in->certs_fail;
772 	out->roas += in->roas;
773 	out->roas_fail += in->roas_fail;
774 	out->roas_invalid += in->roas_invalid;
775 	out->aspas += in->aspas;
776 	out->aspas_fail += in->aspas_fail;
777 	out->aspas_invalid += in->aspas_invalid;
778 	out->brks += in->brks;
779 	out->crls += in->crls;
780 	out->gbrs += in->gbrs;
781 	out->taks += in->taks;
782 	out->vrps += in->vrps;
783 	out->vrps_uniqs += in->vrps_uniqs;
784 	out->vaps += in->vaps;
785 	out->vaps_uniqs += in->vaps_uniqs;
786 	out->vaps_pas += in->vaps_pas;
787 	out->vaps_overflowed += in->vaps_overflowed;
788 	out->spls += in->spls;
789 	out->spls_fail += in->spls_fail;
790 	out->spls_invalid += in->spls_invalid;
791 	out->vsps += in->vsps;
792 	out->vsps_uniqs += in->vsps_uniqs;
793 }
794 
795 static void
sum_repostats(const struct repo * rp,const struct repostats * in,void * arg)796 sum_repostats(const struct repo *rp, const struct repostats *in, void *arg)
797 {
798 	struct repostats *out = arg;
799 
800 	out->del_files += in->del_files;
801 	out->extra_files += in->extra_files;
802 	out->del_extra_files += in->del_extra_files;
803 	out->del_dirs += in->del_dirs;
804 	out->new_files += in->new_files;
805 	timespecadd(&in->sync_time, &out->sync_time, &out->sync_time);
806 }
807 
808 /*
809  * Assign filenames ending in ".tal" in "/etc/rpki" into "tals",
810  * returning the number of files found and filled-in.
811  * This may be zero.
812  * Don't exceed "max" filenames.
813  */
814 static int
tal_load_default(void)815 tal_load_default(void)
816 {
817 	static const char *confdir = "/etc/rpki";
818 	int s = 0;
819 	char *path;
820 	DIR *dirp;
821 	struct dirent *dp;
822 
823 	dirp = opendir(confdir);
824 	if (dirp == NULL)
825 		err(1, "open %s", confdir);
826 	while ((dp = readdir(dirp)) != NULL) {
827 		if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH)
828 			continue;
829 		if (s >= TALSZ_MAX)
830 			err(1, "too many tal files found in %s",
831 			    confdir);
832 		if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1)
833 			err(1, NULL);
834 		tals[s++] = path;
835 	}
836 	closedir(dirp);
837 	return s;
838 }
839 
840 /*
841  * Load the list of FQDNs from the skiplist which are to be distrusted.
842  * Return 0 on success.
843  */
844 static void
load_skiplist(const char * slf)845 load_skiplist(const char *slf)
846 {
847 	struct fqdnlistentry	*le;
848 	FILE			*fp;
849 	char			*line = NULL;
850 	size_t			 linesize = 0, linelen;
851 
852 	if ((fp = fopen(slf, "r")) == NULL) {
853 		if (errno == ENOENT && strcmp(slf, DEFAULT_SKIPLIST_FILE) == 0)
854 			return;
855 		err(1, "failed to open %s", slf);
856 	}
857 
858 	while (getline(&line, &linesize, fp) != -1) {
859 		/* just eat comment lines or empty lines*/
860 		if (line[0] == '#' || line[0] == '\n')
861 			continue;
862 
863 		if (line[0] == ' ' || line[0] == '\t')
864 			errx(1, "invalid entry in skiplist: %s", line);
865 
866 		/*
867 		 * Ignore anything after comment sign, whitespaces,
868 		 * also chop off LF or CR.
869 		 */
870 		linelen = strcspn(line, " #\r\n\t");
871 		line[linelen] = '\0';
872 
873 		if (!valid_uri(line, linelen, NULL))
874 			errx(1, "invalid entry in skiplist: %s", line);
875 
876 		if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
877 			err(1, NULL);
878 		if ((le->fqdn = strdup(line)) == NULL)
879 			err(1, NULL);
880 
881 		LIST_INSERT_HEAD(&skiplist, le, entry);
882 		stats.skiplistentries++;
883 	}
884 	if (ferror(fp))
885 		err(1, "error reading %s", slf);
886 
887 	fclose(fp);
888 	free(line);
889 }
890 
891 /*
892  * Load shortlist entries.
893  */
894 static void
load_shortlist(const char * fqdn)895 load_shortlist(const char *fqdn)
896 {
897 	struct fqdnlistentry	*le;
898 
899 	if (!valid_uri(fqdn, strlen(fqdn), NULL))
900 		errx(1, "invalid fqdn passed to -q: %s", fqdn);
901 
902 	if ((le = malloc(sizeof(struct fqdnlistentry))) == NULL)
903 		err(1, NULL);
904 
905 	if ((le->fqdn = strdup(fqdn)) == NULL)
906 		err(1, NULL);
907 
908 	LIST_INSERT_HEAD(&shortlist, le, entry);
909 }
910 
911 static void
check_fs_size(int fd,const char * cachedir)912 check_fs_size(int fd, const char *cachedir)
913 {
914 	struct statvfs		fs;
915 	unsigned long long	minsize = 500 * 1024 * 1024;
916 	unsigned long long	minnode = 300 * 1000;
917 
918 	if (fstatvfs(fd, &fs) == -1)
919 		err(1, "statfs %s", cachedir);
920 
921 	if (fs.f_bavail < minsize / fs.f_frsize ||
922 	    (fs.f_ffree > 0 && fs.f_favail < minnode)) {
923 		fprintf(stderr, "WARNING: rpki-client may need more than "
924 		    "the available disk space\n"
925 		    "on the file-system holding %s.\n", cachedir);
926 		fprintf(stderr, "available space: %llukB, "
927 		    "suggested minimum %llukB\n",
928 		    (unsigned long long)fs.f_bavail * fs.f_frsize / 1024,
929 		    minsize / 1024);
930 		fprintf(stderr, "available inodes: %llu, "
931 		    "suggested minimum: %llu\n\n",
932 		    (unsigned long long)fs.f_favail, minnode);
933 		fflush(stderr);
934 	}
935 }
936 
937 static pid_t
process_start(const char * title,int * fd)938 process_start(const char *title, int *fd)
939 {
940 	int		 fl = SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK;
941 	pid_t		 pid;
942 	int		 pair[2];
943 
944 	if (socketpair(AF_UNIX, fl, 0, pair) == -1)
945 		err(1, "socketpair");
946 	if ((pid = fork()) == -1)
947 		err(1, "fork");
948 
949 	if (pid == 0) {
950 		setproctitle("%s", title);
951 		/* change working directory to the cache directory */
952 		if (fchdir(cachefd) == -1)
953 			err(1, "fchdir");
954 		if (!filemode && timeout > 0)
955 			alarm(timeout);
956 		close(pair[1]);
957 		*fd = pair[0];
958 	} else {
959 		close(pair[0]);
960 		*fd = pair[1];
961 	}
962 	return pid;
963 }
964 
965 void
suicide(int sig)966 suicide(int sig __attribute__((unused)))
967 {
968 	killme = 1;
969 }
970 
971 #define NPFD	4
972 
973 int
main(int argc,char * argv[])974 main(int argc, char *argv[])
975 {
976 	int		 rc, c, i, st, hangup = 0;
977 	int		 procfd, rsyncfd, httpfd, rrdpfd;
978 	pid_t		 pid, procpid, rsyncpid, httppid, rrdppid;
979 	struct pollfd	 pfd[NPFD];
980 	struct msgbuf	*queues[NPFD];
981 	struct ibuf	*b, *httpbuf = NULL, *procbuf = NULL;
982 	struct ibuf	*rrdpbuf = NULL, *rsyncbuf = NULL;
983 	char		*rsync_prog = "openrsync";
984 	char		*bind_addr = NULL;
985 	const char	*cachedir = NULL, *outputdir = NULL;
986 	const char	*errs, *name;
987 	const char	*skiplistfile = NULL;
988 	struct vrp_tree	 vrps = RB_INITIALIZER(&vrps);
989 	struct vsp_tree	 vsps = RB_INITIALIZER(&vsps);
990 	struct brk_tree	 brks = RB_INITIALIZER(&brks);
991 	struct vap_tree	 vaps = RB_INITIALIZER(&vaps);
992 	struct rusage	 ru;
993 	struct timespec	 start_time, now_time;
994 
995 	clock_gettime(CLOCK_MONOTONIC, &start_time);
996 
997 	/* If started as root, priv-drop to _rpki-client */
998 	if (getuid() == 0) {
999 		struct passwd *pw;
1000 
1001 		pw = getpwnam("_rpki-client");
1002 		if (!pw)
1003 			errx(1, "no _rpki-client user to revoke to");
1004 		if (setgroups(1, &pw->pw_gid) == -1 ||
1005 		    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 ||
1006 		    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
1007 			err(1, "unable to revoke privs");
1008 	}
1009 	cachedir = RPKI_PATH_BASE_DIR;
1010 	outputdir = RPKI_PATH_OUT_DIR;
1011 	repo_timeout = timeout / 4;
1012 	skiplistfile = DEFAULT_SKIPLIST_FILE;
1013 
1014 	if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd "
1015 	    "proc exec unveil", NULL) == -1)
1016 		err(1, "pledge");
1017 
1018 	while ((c = getopt(argc, argv, "Ab:Bcd:e:fH:jmnoP:Rs:S:t:T:vVx")) != -1)
1019 		switch (c) {
1020 		case 'A':
1021 			excludeaspa = 1;
1022 			break;
1023 		case 'b':
1024 			bind_addr = optarg;
1025 			break;
1026 		case 'B':
1027 			outformats |= FORMAT_BIRD;
1028 			break;
1029 		case 'c':
1030 			outformats |= FORMAT_CSV;
1031 			break;
1032 		case 'd':
1033 			cachedir = optarg;
1034 			break;
1035 		case 'e':
1036 			rsync_prog = optarg;
1037 			break;
1038 		case 'f':
1039 			filemode = 1;
1040 			noop = 1;
1041 			break;
1042 		case 'H':
1043 			shortlistmode = 1;
1044 			load_shortlist(optarg);
1045 			break;
1046 		case 'j':
1047 			outformats |= FORMAT_JSON;
1048 			break;
1049 		case 'm':
1050 			outformats |= FORMAT_OMETRIC;
1051 			break;
1052 		case 'n':
1053 			noop = 1;
1054 			break;
1055 		case 'o':
1056 			outformats |= FORMAT_OPENBGPD;
1057 			break;
1058 		case 'P':
1059 			evaluation_time = strtonum(optarg, X509_TIME_MIN + 1,
1060 			    X509_TIME_MAX, &errs);
1061 			if (errs)
1062 				errx(1, "-P: time in seconds %s", errs);
1063 			break;
1064 		case 'R':
1065 			rrdpon = 0;
1066 			break;
1067 		case 's':
1068 			timeout = strtonum(optarg, 0, 24*60*60, &errs);
1069 			if (errs)
1070 				errx(1, "-s: %s", errs);
1071 			if (timeout == 0)
1072 				repo_timeout = 24*60*60;
1073 			else
1074 				repo_timeout = timeout / 4;
1075 			break;
1076 		case 'S':
1077 			skiplistfile = optarg;
1078 			break;
1079 		case 't':
1080 			if (talsz >= TALSZ_MAX)
1081 				err(1, "too many tal files specified");
1082 			tals[talsz++] = optarg;
1083 			break;
1084 		case 'T':
1085 			bird_tablename = optarg;
1086 			break;
1087 		case 'v':
1088 			verbose++;
1089 			break;
1090 		case 'V':
1091 			fprintf(stderr, "rpki-client %s\n", RPKI_VERSION);
1092 			return 0;
1093 		case 'x':
1094 			experimental = 1;
1095 			break;
1096 		default:
1097 			goto usage;
1098 		}
1099 
1100 	argv += optind;
1101 	argc -= optind;
1102 
1103 	if (!filemode) {
1104 		if (argc == 1)
1105 			outputdir = argv[0];
1106 		else if (argc > 1)
1107 			goto usage;
1108 
1109 		if (outputdir == NULL) {
1110 			warnx("output directory required");
1111 			goto usage;
1112 		}
1113 	} else {
1114 		if (argc == 0)
1115 			goto usage;
1116 		outputdir = NULL;
1117 	}
1118 
1119 	if (cachedir == NULL) {
1120 		warnx("cache directory required");
1121 		goto usage;
1122 	}
1123 
1124 	signal(SIGPIPE, SIG_IGN);
1125 
1126 	if ((cachefd = open(cachedir, O_RDONLY | O_DIRECTORY)) == -1)
1127 		err(1, "cache directory %s", cachedir);
1128 	if (outputdir != NULL) {
1129 		if ((outdirfd = open(outputdir, O_RDONLY | O_DIRECTORY)) == -1)
1130 			err(1, "output directory %s", outputdir);
1131 		if (outformats == 0)
1132 			outformats = FORMAT_OPENBGPD;
1133 	}
1134 
1135 	check_fs_size(cachefd, cachedir);
1136 
1137 	if (talsz == 0)
1138 		talsz = tal_load_default();
1139 	if (talsz == 0)
1140 		err(1, "no TAL files found in %s", "/etc/rpki");
1141 
1142 	/* Load optional constraint files sitting next to the TALs. */
1143 	constraints_load();
1144 
1145 	/*
1146 	 * Create the file reader as a jailed child process.
1147 	 * It will be responsible for reading all of the files (ROAs,
1148 	 * manifests, certificates, etc.) and returning contents.
1149 	 */
1150 
1151 	procpid = process_start("parser", &procfd);
1152 	if (procpid == 0) {
1153 		if (!filemode)
1154 			proc_parser(procfd);
1155 		else
1156 			proc_filemode(procfd);
1157 	}
1158 
1159 	/* Constraints are only needed in the filemode and parser processes. */
1160 	constraints_unload();
1161 
1162 	/*
1163 	 * Create a process that will do the rsync'ing.
1164 	 * This process is responsible for making sure that all the
1165 	 * repositories referenced by a certificate manifest (or the
1166 	 * TAL) exists and has been downloaded.
1167 	 */
1168 
1169 	if (!noop) {
1170 		rsyncpid = process_start("rsync", &rsyncfd);
1171 		if (rsyncpid == 0) {
1172 			close(procfd);
1173 			proc_rsync(rsync_prog, bind_addr, rsyncfd);
1174 		}
1175 	} else {
1176 		rsyncfd = -1;
1177 		rsyncpid = -1;
1178 	}
1179 
1180 	/*
1181 	 * Create a process that will fetch data via https.
1182 	 * With every request the http process receives a file descriptor
1183 	 * where the data should be written to.
1184 	 */
1185 
1186 	if (!noop && rrdpon) {
1187 		httppid = process_start("http", &httpfd);
1188 
1189 		if (httppid == 0) {
1190 			close(procfd);
1191 			close(rsyncfd);
1192 			proc_http(bind_addr, httpfd);
1193 		}
1194 	} else {
1195 		httpfd = -1;
1196 		httppid = -1;
1197 	}
1198 
1199 	/*
1200 	 * Create a process that will process RRDP.
1201 	 * The rrdp process requires the http process to fetch the various
1202 	 * XML files and does this via the main process.
1203 	 */
1204 
1205 	if (!noop && rrdpon) {
1206 		rrdppid = process_start("rrdp", &rrdpfd);
1207 		if (rrdppid == 0) {
1208 			close(procfd);
1209 			close(rsyncfd);
1210 			close(httpfd);
1211 			proc_rrdp(rrdpfd);
1212 		}
1213 	} else {
1214 		rrdpfd = -1;
1215 		rrdppid = -1;
1216 	}
1217 
1218 	if (!filemode && timeout > 0) {
1219 		/*
1220 		 * Commit suicide eventually
1221 		 * cron will normally start a new one
1222 		 */
1223 		alarm(timeout);
1224 		signal(SIGALRM, suicide);
1225 
1226 		/* give up a bit before the hard timeout and try to finish up */
1227 		if (!noop)
1228 			deadline = getmonotime() + timeout - repo_timeout / 2;
1229 	}
1230 
1231 	if (pledge("stdio rpath wpath cpath fattr sendfd unveil", NULL) == -1)
1232 		err(1, "pledge");
1233 
1234 	msgbuf_init(&procq);
1235 	msgbuf_init(&rsyncq);
1236 	msgbuf_init(&httpq);
1237 	msgbuf_init(&rrdpq);
1238 	procq.fd = procfd;
1239 	rsyncq.fd = rsyncfd;
1240 	httpq.fd = httpfd;
1241 	rrdpq.fd = rrdpfd;
1242 
1243 	/*
1244 	 * The main process drives the top-down scan to leaf ROAs using
1245 	 * data downloaded by the rsync process and parsed by the
1246 	 * parsing process.
1247 	 */
1248 
1249 	pfd[0].fd = procfd;
1250 	queues[0] = &procq;
1251 	pfd[1].fd = rsyncfd;
1252 	queues[1] = &rsyncq;
1253 	pfd[2].fd = httpfd;
1254 	queues[2] = &httpq;
1255 	pfd[3].fd = rrdpfd;
1256 	queues[3] = &rrdpq;
1257 
1258 	load_skiplist(skiplistfile);
1259 
1260 	/*
1261 	 * Prime the process with our TAL files.
1262 	 * These will (hopefully) contain links to manifests and we
1263 	 * can get the ball rolling.
1264 	 */
1265 
1266 	for (i = 0; i < talsz; i++)
1267 		queue_add_file(tals[i], RTYPE_TAL, i);
1268 
1269 	if (filemode) {
1270 		while (*argv != NULL)
1271 			queue_add_file(*argv++, RTYPE_FILE, 0);
1272 
1273 		if (unveil(cachedir, "r") == -1)
1274 			err(1, "unveil cachedir");
1275 	} else {
1276 		if (unveil(outputdir, "rwc") == -1)
1277 			err(1, "unveil outputdir");
1278 		if (unveil(cachedir, "rwc") == -1)
1279 			err(1, "unveil cachedir");
1280 	}
1281 	if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1)
1282 		err(1, "unveil");
1283 
1284 	/* change working directory to the cache directory */
1285 	if (fchdir(cachefd) == -1)
1286 		err(1, "fchdir");
1287 
1288 	while (entity_queue > 0 && !killme) {
1289 		int polltim;
1290 
1291 		polltim = repo_check_timeout(INFTIM);
1292 
1293 		for (i = 0; i < NPFD; i++) {
1294 			pfd[i].events = POLLIN;
1295 			if (msgbuf_queuelen(queues[i]) > 0)
1296 				pfd[i].events |= POLLOUT;
1297 		}
1298 
1299 		if (poll(pfd, NPFD, polltim) == -1) {
1300 			if (errno == EINTR)
1301 				continue;
1302 			err(1, "poll");
1303 		}
1304 
1305 		for (i = 0; i < NPFD; i++) {
1306 			if (pfd[i].revents & (POLLERR|POLLNVAL)) {
1307 				warnx("poll[%d]: bad fd", i);
1308 				hangup = 1;
1309 			}
1310 			if (pfd[i].revents & POLLHUP)
1311 				hangup = 1;
1312 			if (pfd[i].revents & POLLOUT) {
1313 				switch (msgbuf_write(queues[i])) {
1314 				case 0:
1315 					warnx("write[%d]: "
1316 					    "connection closed", i);
1317 					hangup = 1;
1318 					break;
1319 				case -1:
1320 					warn("write[%d]", i);
1321 					hangup = 1;
1322 					break;
1323 				}
1324 			}
1325 		}
1326 		if (hangup)
1327 			break;
1328 
1329 		/*
1330 		 * Check the rsync and http process.
1331 		 * This means that one of our modules has completed
1332 		 * downloading and we can flush the module requests into
1333 		 * the parser process.
1334 		 */
1335 
1336 		if ((pfd[1].revents & POLLIN)) {
1337 			b = io_buf_read(rsyncfd, &rsyncbuf);
1338 			if (b != NULL) {
1339 				unsigned int id;
1340 				int ok;
1341 
1342 				io_read_buf(b, &id, sizeof(id));
1343 				io_read_buf(b, &ok, sizeof(ok));
1344 				rsync_finish(id, ok);
1345 				ibuf_free(b);
1346 			}
1347 		}
1348 
1349 		if ((pfd[2].revents & POLLIN)) {
1350 			b = io_buf_read(httpfd, &httpbuf);
1351 			if (b != NULL) {
1352 				unsigned int id;
1353 				enum http_result res;
1354 				char *last_mod;
1355 
1356 				io_read_buf(b, &id, sizeof(id));
1357 				io_read_buf(b, &res, sizeof(res));
1358 				io_read_str(b, &last_mod);
1359 				http_finish(id, res, last_mod);
1360 				free(last_mod);
1361 				ibuf_free(b);
1362 			}
1363 		}
1364 
1365 		/*
1366 		 * Handle RRDP requests here.
1367 		 */
1368 		if ((pfd[3].revents & POLLIN)) {
1369 			b = io_buf_read(rrdpfd, &rrdpbuf);
1370 			if (b != NULL) {
1371 				rrdp_process(b);
1372 				ibuf_free(b);
1373 			}
1374 		}
1375 
1376 		/*
1377 		 * The parser has finished something for us.
1378 		 * Dequeue these one by one.
1379 		 */
1380 
1381 		if ((pfd[0].revents & POLLIN)) {
1382 			b = io_buf_read(procfd, &procbuf);
1383 			if (b != NULL) {
1384 				entity_process(b, &stats, &vrps, &brks, &vaps,
1385 				    &vsps);
1386 				ibuf_free(b);
1387 			}
1388 		}
1389 	}
1390 
1391 	signal(SIGALRM, SIG_DFL);
1392 	if (killme) {
1393 		syslog(LOG_CRIT|LOG_DAEMON,
1394 		    "excessive runtime (%d seconds), giving up", timeout);
1395 		errx(1, "excessive runtime (%d seconds), giving up", timeout);
1396 	}
1397 
1398 	/*
1399 	 * For clean-up, close the input for the parser and rsync
1400 	 * process.
1401 	 * This will cause them to exit, then we reap them.
1402 	 */
1403 
1404 	close(procfd);
1405 	close(rsyncfd);
1406 	close(httpfd);
1407 	close(rrdpfd);
1408 
1409 	rc = 0;
1410 	for (;;) {
1411 		pid = waitpid(WAIT_ANY, &st, 0);
1412 		if (pid == -1) {
1413 			if (errno == EINTR)
1414 				continue;
1415 			if (errno == ECHILD)
1416 				break;
1417 			err(1, "wait");
1418 		}
1419 
1420 		if (pid == procpid)
1421 			name = "parser";
1422 		else if (pid == rsyncpid)
1423 			name = "rsync";
1424 		else if (pid == httppid)
1425 			name = "http";
1426 		else if (pid == rrdppid)
1427 			name = "rrdp";
1428 		else
1429 			name = "unknown";
1430 
1431 		if (WIFSIGNALED(st)) {
1432 			warnx("%s terminated signal %d", name, WTERMSIG(st));
1433 			rc = 1;
1434 		} else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) {
1435 			warnx("%s process exited abnormally", name);
1436 			rc = 1;
1437 		}
1438 	}
1439 
1440 	/* processing did not finish because of error */
1441 	if (entity_queue != 0)
1442 		errx(1, "not all files processed, giving up");
1443 
1444 	/* if processing in filemode the process is done, no cleanup */
1445 	if (filemode)
1446 		return rc;
1447 
1448 	logx("all files parsed: generating output");
1449 
1450 	if (!noop)
1451 		repo_cleanup(&fpt, cachefd);
1452 
1453 	clock_gettime(CLOCK_MONOTONIC, &now_time);
1454 	timespecsub(&now_time, &start_time, &stats.elapsed_time);
1455 	if (getrusage(RUSAGE_SELF, &ru) == 0) {
1456 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &stats.user_time);
1457 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &stats.system_time);
1458 	}
1459 	if (getrusage(RUSAGE_CHILDREN, &ru) == 0) {
1460 		struct timespec ts;
1461 
1462 		TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &ts);
1463 		timespecadd(&stats.user_time, &ts, &stats.user_time);
1464 		TIMEVAL_TO_TIMESPEC(&ru.ru_stime, &ts);
1465 		timespecadd(&stats.system_time, &ts, &stats.system_time);
1466 	}
1467 
1468 	/* change working directory to the output directory */
1469 	if (fchdir(outdirfd) == -1)
1470 		err(1, "fchdir output dir");
1471 
1472 	for (i = 0; i < talsz; i++) {
1473 		repo_tal_stats_collect(sum_stats, i, &talstats[i]);
1474 		repo_tal_stats_collect(sum_stats, i, &stats.repo_tal_stats);
1475 	}
1476 	repo_stats_collect(sum_repostats, &stats.repo_stats);
1477 
1478 	if (outputfiles(&vrps, &brks, &vaps, &vsps, &stats))
1479 		rc = 1;
1480 
1481 	printf("Processing time %lld seconds "
1482 	    "(%lld seconds user, %lld seconds system)\n",
1483 	    (long long)stats.elapsed_time.tv_sec,
1484 	    (long long)stats.user_time.tv_sec,
1485 	    (long long)stats.system_time.tv_sec);
1486 	printf("Skiplist entries: %u\n", stats.skiplistentries);
1487 	printf("Route Origin Authorizations: %u (%u failed parse, %u "
1488 	    "invalid)\n", stats.repo_tal_stats.roas,
1489 	    stats.repo_tal_stats.roas_fail,
1490 	    stats.repo_tal_stats.roas_invalid);
1491 	printf("AS Provider Attestations: %u (%u failed parse, %u "
1492 	    "invalid)\n", stats.repo_tal_stats.aspas,
1493 	    stats.repo_tal_stats.aspas_fail,
1494 	    stats.repo_tal_stats.aspas_invalid);
1495 	if (experimental) {
1496 		printf("Signed Prefix Lists: %u "
1497 		    "(%u failed parse, %u invalid)\n",
1498 		    stats.repo_tal_stats.spls, stats.repo_tal_stats.spls_fail,
1499 		    stats.repo_tal_stats.spls_invalid);
1500 	}
1501 	printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks);
1502 	printf("Certificates: %u (%u invalid)\n",
1503 	    stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail);
1504 	printf("Trust Anchor Locators: %u (%u invalid)\n",
1505 	    stats.tals, talsz - stats.tals);
1506 	printf("Manifests: %u (%u failed parse, %u seqnum gaps)\n",
1507 	    stats.repo_tal_stats.mfts, stats.repo_tal_stats.mfts_fail,
1508 	    stats.repo_tal_stats.mfts_gap);
1509 	printf("Certificate revocation lists: %u\n", stats.repo_tal_stats.crls);
1510 	printf("Ghostbuster records: %u\n", stats.repo_tal_stats.gbrs);
1511 	printf("Trust Anchor Keys: %u\n", stats.repo_tal_stats.taks);
1512 	printf("Repositories: %u\n", stats.repos);
1513 	printf("New files moved into validated cache: %u\n",
1514 	    stats.repo_stats.new_files);
1515 	printf("Cleanup: removed %u files, %u directories\n"
1516 	    "Repository cleanup: kept %u and removed %u superfluous files\n",
1517 	    stats.repo_stats.del_files, stats.repo_stats.del_dirs,
1518 	    stats.repo_stats.extra_files, stats.repo_stats.del_extra_files);
1519 	printf("VRP Entries: %u (%u unique)\n", stats.repo_tal_stats.vrps,
1520 	    stats.repo_tal_stats.vrps_uniqs);
1521 	printf("VAP Entries: %u (%u unique, %u overflowed)\n",
1522 	    stats.repo_tal_stats.vaps, stats.repo_tal_stats.vaps_uniqs,
1523 	    stats.repo_tal_stats.vaps_overflowed);
1524 	printf("VSP Entries: %u (%u unique)\n", stats.repo_tal_stats.vsps,
1525 	    stats.repo_tal_stats.vsps_uniqs);
1526 
1527 	/* Memory cleanup. */
1528 	repo_free();
1529 
1530 	return rc;
1531 
1532 usage:
1533 	fprintf(stderr,
1534 	    "usage: rpki-client [-ABcjmnoRVvx] [-b sourceaddr] [-d cachedir]"
1535 	    " [-e rsync_prog]\n"
1536 	    "                   [-H fqdn] [-P epoch] [-S skiplist] [-s timeout]"
1537 	    " [-T table]\n"
1538 	    "                   [-t tal] [outputdir]\n"
1539 	    "       rpki-client [-Vv] [-d cachedir] [-j] [-t tal] -f file ..."
1540 	    "\n");
1541 	return 1;
1542 }
1543