1 /* $OpenBSD: main.c,v 1.199 2022/04/21 09:53:07 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 const char *tals[TALSZ_MAX]; 48 const char *taldescs[TALSZ_MAX]; 49 unsigned int talrepocnt[TALSZ_MAX]; 50 int talsz; 51 52 size_t entity_queue; 53 int timeout = 60*60; 54 volatile sig_atomic_t killme; 55 void suicide(int sig); 56 57 static struct filepath_tree fpt = RB_INITIALIZER(&fpt); 58 static struct msgbuf procq, rsyncq, httpq, rrdpq; 59 static int cachefd, outdirfd; 60 61 const char *bird_tablename = "ROAS"; 62 63 int verbose; 64 int noop; 65 int filemode; 66 int rrdpon = 1; 67 int repo_timeout; 68 69 struct 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 */ 75 void 76 logx(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 87 time_t 88 getmonotime(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 97 void 98 entity_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 */ 114 void 115 entity_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 */ 130 static void 131 entity_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 146 static void 147 entity_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 */ 176 void 177 entityq_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 */ 193 static void 194 entityq_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 225 static void 226 rrdp_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 238 void 239 rrdp_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 */ 259 void 260 rsync_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 */ 276 void 277 http_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 */ 294 static void 295 rrdp_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 313 void 314 rrdp_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 */ 332 static void 333 queue_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 */ 354 static void 355 queue_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 */ 376 static void 377 queue_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 */ 411 static void 412 queue_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 */ 457 static void 458 entity_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 if (cert->purpose == CERT_PURPOSE_CA) { 503 /* 504 * Process the revocation list from the 505 * certificate *first*, since it might mark that 506 * we're revoked and then we don't want to 507 * process the MFT. 508 */ 509 queue_add_from_cert(cert); 510 } else if (cert->purpose == CERT_PURPOSE_BGPSEC_ROUTER) { 511 cert_insert_brks(brktree, cert); 512 st->brks++; 513 } else 514 st->certs_fail++; 515 cert_free(cert); 516 break; 517 case RTYPE_MFT: 518 st->mfts++; 519 io_read_buf(b, &c, sizeof(c)); 520 if (c == 0) { 521 st->mfts_fail++; 522 break; 523 } 524 mft = mft_read(b); 525 if (!mft->stale) 526 queue_add_from_mft(mft, repo_byid(mft->repoid)); 527 else 528 st->mfts_stale++; 529 mft_free(mft); 530 break; 531 case RTYPE_CRL: 532 st->crls++; 533 break; 534 case RTYPE_ROA: 535 st->roas++; 536 io_read_buf(b, &c, sizeof(c)); 537 if (c == 0) { 538 st->roas_fail++; 539 break; 540 } 541 roa = roa_read(b); 542 if (roa->valid) 543 roa_insert_vrps(tree, roa, &st->vrps, &st->uniqs); 544 else 545 st->roas_invalid++; 546 roa_free(roa); 547 break; 548 case RTYPE_GBR: 549 st->gbrs++; 550 break; 551 case RTYPE_FILE: 552 break; 553 default: 554 errx(1, "unknown entity type %d", type); 555 } 556 557 done: 558 free(file); 559 entity_queue--; 560 } 561 562 static void 563 rrdp_process(struct ibuf *b) 564 { 565 enum rrdp_msg type; 566 enum publish_type pt; 567 struct rrdp_session s; 568 char *uri, *last_mod, *data; 569 char hash[SHA256_DIGEST_LENGTH]; 570 size_t dsz; 571 unsigned int id; 572 int ok; 573 574 io_read_buf(b, &type, sizeof(type)); 575 io_read_buf(b, &id, sizeof(id)); 576 577 switch (type) { 578 case RRDP_END: 579 io_read_buf(b, &ok, sizeof(ok)); 580 rrdp_finish(id, ok); 581 break; 582 case RRDP_HTTP_REQ: 583 io_read_str(b, &uri); 584 io_read_str(b, &last_mod); 585 rrdp_http_fetch(id, uri, last_mod); 586 break; 587 case RRDP_SESSION: 588 io_read_str(b, &s.session_id); 589 io_read_buf(b, &s.serial, sizeof(s.serial)); 590 io_read_str(b, &s.last_mod); 591 rrdp_save_state(id, &s); 592 free(s.session_id); 593 free(s.last_mod); 594 break; 595 case RRDP_FILE: 596 io_read_buf(b, &pt, sizeof(pt)); 597 if (pt != PUB_ADD) 598 io_read_buf(b, &hash, sizeof(hash)); 599 io_read_str(b, &uri); 600 io_read_buf_alloc(b, (void **)&data, &dsz); 601 602 ok = rrdp_handle_file(id, pt, uri, hash, sizeof(hash), 603 data, dsz); 604 rrdp_file_resp(id, ok); 605 606 free(uri); 607 free(data); 608 break; 609 case RRDP_CLEAR: 610 rrdp_clear(id); 611 break; 612 default: 613 errx(1, "unexpected rrdp response"); 614 } 615 } 616 617 /* 618 * Assign filenames ending in ".tal" in "/etc/rpki" into "tals", 619 * returning the number of files found and filled-in. 620 * This may be zero. 621 * Don't exceded "max" filenames. 622 */ 623 static int 624 tal_load_default(void) 625 { 626 static const char *confdir = "/etc/rpki"; 627 int s = 0; 628 char *path; 629 DIR *dirp; 630 struct dirent *dp; 631 632 dirp = opendir(confdir); 633 if (dirp == NULL) 634 err(1, "open %s", confdir); 635 while ((dp = readdir(dirp)) != NULL) { 636 if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH) 637 continue; 638 if (s >= TALSZ_MAX) 639 err(1, "too many tal files found in %s", 640 confdir); 641 if (asprintf(&path, "%s/%s", confdir, dp->d_name) == -1) 642 err(1, NULL); 643 tals[s++] = path; 644 } 645 closedir(dirp); 646 return s; 647 } 648 649 static void 650 check_fs_size(int fd, const char *cachedir) 651 { 652 struct statvfs fs; 653 const long long minsize = 500 * 1024 * 1024; 654 const long long minnode = 300 * 1000; 655 656 if (fstatvfs(fd, &fs) == -1) 657 err(1, "statfs %s", cachedir); 658 659 if (fs.f_bavail < minsize / fs.f_frsize || 660 (fs.f_ffree > 0 && fs.f_favail < minnode)) { 661 fprintf(stderr, "WARNING: rpki-client may need more than " 662 "the available disk space\n" 663 "on the file-system holding %s.\n", cachedir); 664 fprintf(stderr, "available space: %lldkB, " 665 "suggested minimum %lldkB\n", 666 (long long)fs.f_bavail * fs.f_frsize / 1024, 667 minsize / 1024); 668 fprintf(stderr, "available inodes %lld, " 669 "suggested minimum %lld\n\n", 670 (long long)fs.f_favail, minnode); 671 fflush(stderr); 672 } 673 } 674 675 static pid_t 676 process_start(const char *title, int *fd) 677 { 678 int fl = SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK; 679 pid_t pid; 680 int pair[2]; 681 682 if (socketpair(AF_UNIX, fl, 0, pair) == -1) 683 err(1, "socketpair"); 684 if ((pid = fork()) == -1) 685 err(1, "fork"); 686 687 if (pid == 0) { 688 setproctitle("%s", title); 689 /* change working directory to the cache directory */ 690 if (fchdir(cachefd) == -1) 691 err(1, "fchdir"); 692 if (timeout) 693 alarm(timeout); 694 close(pair[1]); 695 *fd = pair[0]; 696 } else { 697 close(pair[0]); 698 *fd = pair[1]; 699 } 700 return pid; 701 } 702 703 void 704 suicide(int sig __attribute__((unused))) 705 { 706 killme = 1; 707 } 708 709 #define NPFD 4 710 711 int 712 main(int argc, char *argv[]) 713 { 714 int rc, c, i, st, proc, rsync, http, rrdp, hangup = 0; 715 pid_t pid, procpid, rsyncpid, httppid, rrdppid; 716 struct pollfd pfd[NPFD]; 717 struct msgbuf *queues[NPFD]; 718 struct ibuf *b, *httpbuf = NULL, *procbuf = NULL; 719 struct ibuf *rrdpbuf = NULL, *rsyncbuf = NULL; 720 char *rsync_prog = "openrsync"; 721 char *bind_addr = NULL; 722 const char *cachedir = NULL, *outputdir = NULL; 723 const char *errs, *name; 724 struct vrp_tree vrps = RB_INITIALIZER(&vrps); 725 struct brk_tree brks = RB_INITIALIZER(&brks); 726 struct rusage ru; 727 struct timeval start_time, now_time; 728 729 gettimeofday(&start_time, NULL); 730 731 /* If started as root, priv-drop to _rpki-client */ 732 if (getuid() == 0) { 733 struct passwd *pw; 734 735 pw = getpwnam("_rpki-client"); 736 if (!pw) 737 errx(1, "no _rpki-client user to revoke to"); 738 if (setgroups(1, &pw->pw_gid) == -1 || 739 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1 || 740 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) 741 err(1, "unable to revoke privs"); 742 } 743 cachedir = RPKI_PATH_BASE_DIR; 744 outputdir = RPKI_PATH_OUT_DIR; 745 repo_timeout = timeout / 4; 746 747 if (pledge("stdio rpath wpath cpath inet fattr dns sendfd recvfd " 748 "proc exec unveil", NULL) == -1) 749 err(1, "pledge"); 750 751 while ((c = getopt(argc, argv, "b:Bcd:e:fjnorRs:t:T:vV")) != -1) 752 switch (c) { 753 case 'b': 754 bind_addr = optarg; 755 break; 756 case 'B': 757 outformats |= FORMAT_BIRD; 758 break; 759 case 'c': 760 outformats |= FORMAT_CSV; 761 break; 762 case 'd': 763 cachedir = optarg; 764 break; 765 case 'e': 766 rsync_prog = optarg; 767 break; 768 case 'f': 769 filemode = 1; 770 noop = 1; 771 break; 772 case 'j': 773 outformats |= FORMAT_JSON; 774 break; 775 case 'n': 776 noop = 1; 777 break; 778 case 'o': 779 outformats |= FORMAT_OPENBGPD; 780 break; 781 case 'R': 782 rrdpon = 0; 783 break; 784 case 'r': 785 rrdpon = 1; 786 break; 787 case 's': 788 timeout = strtonum(optarg, 0, 24*60*60, &errs); 789 if (errs) 790 errx(1, "-s: %s", errs); 791 if (timeout == 0) 792 repo_timeout = 24*60*60; 793 else 794 repo_timeout = timeout / 4; 795 break; 796 case 't': 797 if (talsz >= TALSZ_MAX) 798 err(1, "too many tal files specified"); 799 tals[talsz++] = optarg; 800 break; 801 case 'T': 802 bird_tablename = optarg; 803 break; 804 case 'v': 805 verbose++; 806 break; 807 case 'V': 808 fprintf(stderr, "rpki-client %s\n", RPKI_VERSION); 809 return 0; 810 default: 811 goto usage; 812 } 813 814 argv += optind; 815 argc -= optind; 816 817 if (!filemode) { 818 if (argc == 1) 819 outputdir = argv[0]; 820 else if (argc > 1) 821 goto usage; 822 823 if (outputdir == NULL) { 824 warnx("output directory required"); 825 goto usage; 826 } 827 } else { 828 if (argc == 0) 829 goto usage; 830 outputdir = NULL; 831 } 832 833 if (cachedir == NULL) { 834 warnx("cache directory required"); 835 goto usage; 836 } 837 838 signal(SIGPIPE, SIG_IGN); 839 840 if ((cachefd = open(cachedir, O_RDONLY | O_DIRECTORY)) == -1) 841 err(1, "cache directory %s", cachedir); 842 if (outputdir != NULL) { 843 if ((outdirfd = open(outputdir, O_RDONLY | O_DIRECTORY)) == -1) 844 err(1, "output directory %s", outputdir); 845 if (outformats == 0) 846 outformats = FORMAT_OPENBGPD; 847 } 848 849 check_fs_size(cachefd, cachedir); 850 851 if (talsz == 0) 852 talsz = tal_load_default(); 853 if (talsz == 0) 854 err(1, "no TAL files found in %s", "/etc/rpki"); 855 856 /* 857 * Create the file reader as a jailed child process. 858 * It will be responsible for reading all of the files (ROAs, 859 * manifests, certificates, etc.) and returning contents. 860 */ 861 862 procpid = process_start("parser", &proc); 863 if (procpid == 0) { 864 if (!filemode) 865 proc_parser(proc); 866 else 867 proc_filemode(proc); 868 } 869 870 /* 871 * Create a process that will do the rsync'ing. 872 * This process is responsible for making sure that all the 873 * repositories referenced by a certificate manifest (or the 874 * TAL) exists and has been downloaded. 875 */ 876 877 if (!noop) { 878 rsyncpid = process_start("rsync", &rsync); 879 if (rsyncpid == 0) { 880 close(proc); 881 proc_rsync(rsync_prog, bind_addr, rsync); 882 } 883 } else { 884 rsync = -1; 885 rsyncpid = -1; 886 } 887 888 /* 889 * Create a process that will fetch data via https. 890 * With every request the http process receives a file descriptor 891 * where the data should be written to. 892 */ 893 894 if (!noop && rrdpon) { 895 httppid = process_start("http", &http); 896 897 if (httppid == 0) { 898 close(proc); 899 close(rsync); 900 proc_http(bind_addr, http); 901 } 902 } else { 903 http = -1; 904 httppid = -1; 905 } 906 907 /* 908 * Create a process that will process RRDP. 909 * The rrdp process requires the http process to fetch the various 910 * XML files and does this via the main process. 911 */ 912 913 if (!noop && rrdpon) { 914 rrdppid = process_start("rrdp", &rrdp); 915 if (rrdppid == 0) { 916 close(proc); 917 close(rsync); 918 close(http); 919 proc_rrdp(rrdp); 920 } 921 } else { 922 rrdp = -1; 923 rrdppid = -1; 924 } 925 926 if (timeout) { 927 /* 928 * Commit suicide eventually 929 * cron will normally start a new one 930 */ 931 alarm(timeout); 932 signal(SIGALRM, suicide); 933 } 934 935 /* TODO unveil cachedir and outputdir, no other access allowed */ 936 if (pledge("stdio rpath wpath cpath fattr sendfd", NULL) == -1) 937 err(1, "pledge"); 938 939 msgbuf_init(&procq); 940 msgbuf_init(&rsyncq); 941 msgbuf_init(&httpq); 942 msgbuf_init(&rrdpq); 943 procq.fd = proc; 944 rsyncq.fd = rsync; 945 httpq.fd = http; 946 rrdpq.fd = rrdp; 947 948 /* 949 * The main process drives the top-down scan to leaf ROAs using 950 * data downloaded by the rsync process and parsed by the 951 * parsing process. 952 */ 953 954 pfd[0].fd = proc; 955 queues[0] = &procq; 956 pfd[1].fd = rsync; 957 queues[1] = &rsyncq; 958 pfd[2].fd = http; 959 queues[2] = &httpq; 960 pfd[3].fd = rrdp; 961 queues[3] = &rrdpq; 962 963 /* 964 * Prime the process with our TAL file. 965 * This will contain (hopefully) links to our manifest and we 966 * can get the ball rolling. 967 */ 968 969 for (i = 0; i < talsz; i++) 970 queue_add_file(tals[i], RTYPE_TAL, i); 971 972 if (filemode) { 973 while (*argv != NULL) 974 queue_add_file(*argv++, RTYPE_FILE, 0); 975 } 976 977 /* change working directory to the cache directory */ 978 if (fchdir(cachefd) == -1) 979 err(1, "fchdir"); 980 981 while (entity_queue > 0 && !killme) { 982 int polltim; 983 984 for (i = 0; i < NPFD; i++) { 985 pfd[i].events = POLLIN; 986 if (queues[i]->queued) 987 pfd[i].events |= POLLOUT; 988 } 989 990 polltim = repo_check_timeout(INFTIM); 991 992 if ((c = poll(pfd, NPFD, polltim)) == -1) { 993 if (errno == EINTR) 994 continue; 995 err(1, "poll"); 996 } 997 998 for (i = 0; i < NPFD; i++) { 999 if (pfd[i].revents & (POLLERR|POLLNVAL)) { 1000 warnx("poll[%d]: bad fd", i); 1001 hangup = 1; 1002 } 1003 if (pfd[i].revents & POLLHUP) 1004 hangup = 1; 1005 if (pfd[i].revents & POLLOUT) { 1006 switch (msgbuf_write(queues[i])) { 1007 case 0: 1008 warnx("write[%d]: " 1009 "connection closed", i); 1010 hangup = 1; 1011 break; 1012 case -1: 1013 warn("write[%d]", i); 1014 hangup = 1; 1015 break; 1016 } 1017 } 1018 } 1019 if (hangup) 1020 break; 1021 1022 /* 1023 * Check the rsync and http process. 1024 * This means that one of our modules has completed 1025 * downloading and we can flush the module requests into 1026 * the parser process. 1027 */ 1028 1029 if ((pfd[1].revents & POLLIN)) { 1030 b = io_buf_read(rsync, &rsyncbuf); 1031 if (b != NULL) { 1032 unsigned int id; 1033 int ok; 1034 1035 io_read_buf(b, &id, sizeof(id)); 1036 io_read_buf(b, &ok, sizeof(ok)); 1037 rsync_finish(id, ok); 1038 ibuf_free(b); 1039 } 1040 } 1041 1042 if ((pfd[2].revents & POLLIN)) { 1043 b = io_buf_read(http, &httpbuf); 1044 if (b != NULL) { 1045 unsigned int id; 1046 enum http_result res; 1047 char *last_mod; 1048 1049 io_read_buf(b, &id, sizeof(id)); 1050 io_read_buf(b, &res, sizeof(res)); 1051 io_read_str(b, &last_mod); 1052 http_finish(id, res, last_mod); 1053 free(last_mod); 1054 ibuf_free(b); 1055 } 1056 } 1057 1058 /* 1059 * Handle RRDP requests here. 1060 */ 1061 if ((pfd[3].revents & POLLIN)) { 1062 b = io_buf_read(rrdp, &rrdpbuf); 1063 if (b != NULL) { 1064 rrdp_process(b); 1065 ibuf_free(b); 1066 } 1067 } 1068 1069 /* 1070 * The parser has finished something for us. 1071 * Dequeue these one by one. 1072 */ 1073 1074 if ((pfd[0].revents & POLLIN)) { 1075 b = io_buf_read(proc, &procbuf); 1076 if (b != NULL) { 1077 entity_process(b, &stats, &vrps, &brks); 1078 ibuf_free(b); 1079 } 1080 } 1081 } 1082 1083 signal(SIGALRM, SIG_DFL); 1084 if (killme) { 1085 syslog(LOG_CRIT|LOG_DAEMON, 1086 "excessive runtime (%d seconds), giving up", timeout); 1087 errx(1, "excessive runtime (%d seconds), giving up", timeout); 1088 } 1089 1090 /* 1091 * For clean-up, close the input for the parser and rsync 1092 * process. 1093 * This will cause them to exit, then we reap them. 1094 */ 1095 1096 close(proc); 1097 close(rsync); 1098 close(http); 1099 close(rrdp); 1100 1101 rc = 0; 1102 for (;;) { 1103 pid = waitpid(WAIT_ANY, &st, 0); 1104 if (pid == -1) { 1105 if (errno == EINTR) 1106 continue; 1107 if (errno == ECHILD) 1108 break; 1109 err(1, "wait"); 1110 } 1111 1112 if (pid == procpid) 1113 name = "parser"; 1114 else if (pid == rsyncpid) 1115 name = "rsync"; 1116 else if (pid == httppid) 1117 name = "http"; 1118 else if (pid == rrdppid) 1119 name = "rrdp"; 1120 else 1121 name = "unknown"; 1122 1123 if (WIFSIGNALED(st)) { 1124 warnx("%s terminated signal %d", name, WTERMSIG(st)); 1125 rc = 1; 1126 } else if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) { 1127 warnx("%s process exited abnormally", name); 1128 rc = 1; 1129 } 1130 } 1131 1132 /* processing did not finish because of error */ 1133 if (entity_queue != 0) 1134 errx(1, "not all files processed, giving up"); 1135 1136 /* if processing in filemode the process is done, no cleanup */ 1137 if (filemode) 1138 return rc; 1139 1140 logx("all files parsed: generating output"); 1141 1142 if (!noop) 1143 repo_cleanup(&fpt, cachefd); 1144 1145 gettimeofday(&now_time, NULL); 1146 timersub(&now_time, &start_time, &stats.elapsed_time); 1147 if (getrusage(RUSAGE_SELF, &ru) == 0) { 1148 stats.user_time = ru.ru_utime; 1149 stats.system_time = ru.ru_stime; 1150 } 1151 if (getrusage(RUSAGE_CHILDREN, &ru) == 0) { 1152 timeradd(&stats.user_time, &ru.ru_utime, &stats.user_time); 1153 timeradd(&stats.system_time, &ru.ru_stime, &stats.system_time); 1154 } 1155 1156 /* change working directory to the output directory */ 1157 if (fchdir(outdirfd) == -1) 1158 err(1, "fchdir output dir"); 1159 1160 if (outputfiles(&vrps, &brks, &stats)) 1161 rc = 1; 1162 1163 logx("Processing time %lld seconds " 1164 "(%lld seconds user, %lld seconds system)", 1165 (long long)stats.elapsed_time.tv_sec, 1166 (long long)stats.user_time.tv_sec, 1167 (long long)stats.system_time.tv_sec); 1168 logx("Route Origin Authorizations: %zu (%zu failed parse, %zu invalid)", 1169 stats.roas, stats.roas_fail, stats.roas_invalid); 1170 logx("BGPsec Router Certificates: %zu", stats.brks); 1171 logx("Certificates: %zu (%zu invalid)", 1172 stats.certs, stats.certs_fail); 1173 logx("Trust Anchor Locators: %zu (%zu invalid)", 1174 stats.tals, talsz - stats.tals); 1175 logx("Manifests: %zu (%zu failed parse, %zu stale)", 1176 stats.mfts, stats.mfts_fail, stats.mfts_stale); 1177 logx("Certificate revocation lists: %zu", stats.crls); 1178 logx("Ghostbuster records: %zu", stats.gbrs); 1179 logx("Repositories: %zu", stats.repos); 1180 logx("Cleanup: removed %zu files, %zu directories, %zu superfluous", 1181 stats.del_files, stats.del_dirs, stats.extra_files); 1182 logx("VRP Entries: %zu (%zu unique)", stats.vrps, stats.uniqs); 1183 1184 /* Memory cleanup. */ 1185 repo_free(); 1186 1187 return rc; 1188 1189 usage: 1190 fprintf(stderr, 1191 "usage: rpki-client [-BcjnoRrVv] [-b sourceaddr] [-d cachedir]" 1192 " [-e rsync_prog]\n" 1193 " [-s timeout] [-T table] [-t tal]" 1194 " [outputdir]\n" 1195 " rpki-client [-Vv] [-d cachedir] [-t tal] -f file ...\n"); 1196 return 1; 1197 } 1198