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