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