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