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