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