main.c revision 1.21
1/* $OpenBSD: main.c,v 1.21 2019/10/31 08:36:43 claudio Exp $ */ 2/* 3 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#include <sys/queue.h> 19#include <sys/socket.h> 20#include <sys/stat.h> 21#include <sys/types.h> 22#include <sys/wait.h> 23 24#include <assert.h> 25#include <ctype.h> 26#include <err.h> 27#include <dirent.h> 28#include <fcntl.h> 29#include <fnmatch.h> 30#include <fts.h> 31#include <inttypes.h> 32#include <poll.h> 33#include <signal.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <unistd.h> 38 39#include <openssl/err.h> 40#include <openssl/evp.h> 41#include <openssl/x509v3.h> 42 43#include "extern.h" 44 45/* 46 * Base directory for where we'll look for all media. 47 */ 48#define BASE_DIR "/var/cache/rpki-client" 49 50/* 51 * Statistics collected during run-time. 52 */ 53struct stats { 54 size_t tals; /* total number of locators */ 55 size_t mfts; /* total number of manifests */ 56 size_t mfts_fail; /* failing syntactic parse */ 57 size_t mfts_stale; /* stale manifests */ 58 size_t certs; /* certificates */ 59 size_t certs_fail; /* failing syntactic parse */ 60 size_t certs_invalid; /* invalid resources */ 61 size_t roas; /* route origin authorizations */ 62 size_t roas_fail; /* failing syntactic parse */ 63 size_t roas_invalid; /* invalid resources */ 64 size_t repos; /* repositories */ 65 size_t crls; /* revocation lists */ 66 size_t vrps; /* total number of vrps */ 67 size_t uniqs; /* number of unique vrps */ 68}; 69 70/* 71 * An rsync repository. 72 */ 73struct repo { 74 char *host; /* hostname */ 75 char *module; /* module name */ 76 int loaded; /* whether loaded or not */ 77 size_t id; /* identifier (array index) */ 78}; 79 80/* 81 * A running rsync process. 82 * We can have multiple of these simultaneously and need to keep track 83 * of which process maps to which request. 84 */ 85struct rsyncproc { 86 char *uri; /* uri of this rsync proc */ 87 size_t id; /* identity of request */ 88 pid_t pid; /* pid of process or 0 if unassociated */ 89}; 90 91/* 92 * Table of all known repositories. 93 */ 94struct repotab { 95 struct repo *repos; /* repositories */ 96 size_t reposz; /* number of repos */ 97}; 98 99/* 100 * An entity (MFT, ROA, certificate, etc.) that needs to be downloaded 101 * and parsed. 102 */ 103struct entity { 104 size_t id; /* unique identifier */ 105 enum rtype type; /* type of entity (not RTYPE_EOF) */ 106 char *uri; /* file or rsync:// URI */ 107 int has_dgst; /* whether dgst is specified */ 108 unsigned char dgst[SHA256_DIGEST_LENGTH]; /* optional */ 109 ssize_t repo; /* repo index or <0 if w/o repo */ 110 int has_pkey; /* whether pkey/sz is specified */ 111 unsigned char *pkey; /* public key (optional) */ 112 size_t pkeysz; /* public key length (optional) */ 113 int has_descr; /* whether descr is specified */ 114 char *descr; /* tal description */ 115 TAILQ_ENTRY(entity) entries; 116}; 117 118TAILQ_HEAD(entityq, entity); 119 120/* 121 * Mark that our subprocesses will never return. 122 */ 123static void proc_parser(int, int, int) 124 __attribute__((noreturn)); 125static void proc_rsync(const char *, const char *, int, int) 126 __attribute__((noreturn)); 127static void logx(const char *fmt, ...) 128 __attribute__((format(printf, 1, 2))); 129 130enum output_fmt { 131 BGPD, 132 BIRD, 133 CSV, 134 JSON 135}; 136 137int verbose; 138 139/* 140 * Log a message to stderr if and only if "verbose" is non-zero. 141 * This uses the err(3) functionality. 142 */ 143static void 144logx(const char *fmt, ...) 145{ 146 va_list ap; 147 148 if (verbose && fmt != NULL) { 149 va_start(ap, fmt); 150 vwarnx(fmt, ap); 151 va_end(ap); 152 } 153} 154 155/* 156 * Resolve the media type of a resource by looking at its suffice. 157 * Returns the type of RTYPE_EOF if not found. 158 */ 159static enum rtype 160rtype_resolve(const char *uri) 161{ 162 enum rtype rp; 163 164 rsync_uri_parse(NULL, NULL, NULL, NULL, NULL, NULL, &rp, uri); 165 return rp; 166} 167 168static void 169entity_free(struct entity *ent) 170{ 171 172 if (ent == NULL) 173 return; 174 175 free(ent->pkey); 176 free(ent->uri); 177 free(ent->descr); 178 free(ent); 179} 180 181/* 182 * Read a queue entity from the descriptor. 183 * Matched by entity_buffer_req(). 184 * The pointer must be passed entity_free(). 185 */ 186static void 187entity_read_req(int fd, struct entity *ent) 188{ 189 190 io_simple_read(fd, &ent->id, sizeof(size_t)); 191 io_simple_read(fd, &ent->type, sizeof(enum rtype)); 192 io_str_read(fd, &ent->uri); 193 io_simple_read(fd, &ent->has_dgst, sizeof(int)); 194 if (ent->has_dgst) 195 io_simple_read(fd, ent->dgst, sizeof(ent->dgst)); 196 io_simple_read(fd, &ent->has_pkey, sizeof(int)); 197 if (ent->has_pkey) 198 io_buf_read_alloc(fd, (void **)&ent->pkey, &ent->pkeysz); 199 io_simple_read(fd, &ent->has_descr, sizeof(int)); 200 if (ent->has_descr) 201 io_str_read(fd, &ent->descr); 202} 203 204/* 205 * Look up a repository, queueing it for discovery if not found. 206 */ 207static const struct repo * 208repo_lookup(int fd, struct repotab *rt, const char *uri) 209{ 210 const char *host, *mod; 211 size_t hostsz, modsz, i; 212 struct repo *rp; 213 214 if (!rsync_uri_parse(&host, &hostsz, 215 &mod, &modsz, NULL, NULL, NULL, uri)) 216 errx(EXIT_FAILURE, "%s: malformed", uri); 217 218 /* Look up in repository table. */ 219 220 for (i = 0; i < rt->reposz; i++) { 221 if (strlen(rt->repos[i].host) != hostsz) 222 continue; 223 if (strlen(rt->repos[i].module) != modsz) 224 continue; 225 if (strncasecmp(rt->repos[i].host, host, hostsz)) 226 continue; 227 if (strncasecmp(rt->repos[i].module, mod, modsz)) 228 continue; 229 return &rt->repos[i]; 230 } 231 232 rt->repos = reallocarray(rt->repos, 233 rt->reposz + 1, sizeof(struct repo)); 234 if (rt->repos == NULL) 235 err(EXIT_FAILURE, "reallocarray"); 236 237 rp = &rt->repos[rt->reposz++]; 238 memset(rp, 0, sizeof(struct repo)); 239 rp->id = rt->reposz - 1; 240 241 if ((rp->host = strndup(host, hostsz)) == NULL || 242 (rp->module = strndup(mod, modsz)) == NULL) 243 err(EXIT_FAILURE, "strndup"); 244 245 i = rt->reposz - 1; 246 247 logx("%s/%s: loading", rp->host, rp->module); 248 io_simple_write(fd, &i, sizeof(size_t)); 249 io_str_write(fd, rp->host); 250 io_str_write(fd, rp->module); 251 return rp; 252} 253 254/* 255 * Read the next entity from the parser process, removing it from the 256 * queue of pending requests in the process. 257 * This always returns a valid entity. 258 */ 259static struct entity * 260entityq_next(int fd, struct entityq *q) 261{ 262 size_t id; 263 struct entity *entp; 264 265 io_simple_read(fd, &id, sizeof(size_t)); 266 267 TAILQ_FOREACH(entp, q, entries) 268 if (entp->id == id) 269 break; 270 271 assert(entp != NULL); 272 TAILQ_REMOVE(q, entp, entries); 273 return entp; 274} 275 276static void 277entity_buffer_resp(char **b, size_t *bsz, size_t *bmax, 278 const struct entity *ent) 279{ 280 281 io_simple_buffer(b, bsz, bmax, &ent->id, sizeof(size_t)); 282} 283 284/* 285 * Like entity_write_req() but into a buffer. 286 * Matched by entity_read_req(). 287 */ 288static void 289entity_buffer_req(char **b, size_t *bsz, size_t *bmax, 290 const struct entity *ent) 291{ 292 293 io_simple_buffer(b, bsz, bmax, &ent->id, sizeof(size_t)); 294 io_simple_buffer(b, bsz, bmax, &ent->type, sizeof(enum rtype)); 295 io_str_buffer(b, bsz, bmax, ent->uri); 296 io_simple_buffer(b, bsz, bmax, &ent->has_dgst, sizeof(int)); 297 if (ent->has_dgst) 298 io_simple_buffer(b, bsz, bmax, ent->dgst, sizeof(ent->dgst)); 299 io_simple_buffer(b, bsz, bmax, &ent->has_pkey, sizeof(int)); 300 if (ent->has_pkey) 301 io_buf_buffer(b, bsz, bmax, ent->pkey, ent->pkeysz); 302 io_simple_buffer(b, bsz, bmax, &ent->has_descr, sizeof(int)); 303 if (ent->has_descr) 304 io_str_buffer(b, bsz, bmax, ent->descr); 305} 306 307/* 308 * Write the queue entity. 309 * Simply a wrapper around entity_buffer_req(). 310 */ 311static void 312entity_write_req(int fd, const struct entity *ent) 313{ 314 char *b = NULL; 315 size_t bsz = 0, bmax = 0; 316 317 entity_buffer_req(&b, &bsz, &bmax, ent); 318 io_simple_write(fd, b, bsz); 319 free(b); 320} 321 322/* 323 * Scan through all queued requests and see which ones are in the given 324 * repo, then flush those into the parser process. 325 */ 326static void 327entityq_flush(int fd, struct entityq *q, const struct repo *repo) 328{ 329 struct entity *p; 330 331 TAILQ_FOREACH(p, q, entries) { 332 if (p->repo < 0 || repo->id != (size_t)p->repo) 333 continue; 334 entity_write_req(fd, p); 335 } 336} 337 338/* 339 * Add the heap-allocated file to the queue for processing. 340 */ 341static void 342entityq_add(int fd, struct entityq *q, char *file, enum rtype type, 343 const struct repo *rp, const unsigned char *dgst, 344 const unsigned char *pkey, size_t pkeysz, char *descr, size_t *eid) 345{ 346 struct entity *p; 347 348 if ((p = calloc(1, sizeof(struct entity))) == NULL) 349 err(EXIT_FAILURE, "calloc"); 350 351 p->id = (*eid)++; 352 p->type = type; 353 p->uri = file; 354 p->repo = (rp != NULL) ? (ssize_t)rp->id : -1; 355 p->has_dgst = dgst != NULL; 356 p->has_pkey = pkey != NULL; 357 p->has_descr = descr != NULL; 358 if (p->has_dgst) 359 memcpy(p->dgst, dgst, sizeof(p->dgst)); 360 if (p->has_pkey) { 361 p->pkeysz = pkeysz; 362 if ((p->pkey = malloc(pkeysz)) == NULL) 363 err(EXIT_FAILURE, "malloc"); 364 memcpy(p->pkey, pkey, pkeysz); 365 } 366 if (p->has_descr) 367 if ((p->descr = strdup(descr)) == NULL) 368 err(EXIT_FAILURE, "strdup"); 369 370 TAILQ_INSERT_TAIL(q, p, entries); 371 372 /* 373 * Write to the queue if there's no repo or the repo has already 374 * been loaded. 375 */ 376 377 if (rp == NULL || rp->loaded) 378 entity_write_req(fd, p); 379} 380 381/* 382 * Add a file (CER, ROA, CRL) from an MFT file, RFC 6486. 383 * These are always relative to the directory in which "mft" sits. 384 */ 385static void 386queue_add_from_mft(int fd, struct entityq *q, const char *mft, 387 const struct mftfile *file, enum rtype type, size_t *eid) 388{ 389 size_t sz; 390 char *cp, *nfile; 391 392 assert(strncmp(mft, BASE_DIR, strlen(BASE_DIR)) == 0); 393 394 /* Construct local path from filename. */ 395 396 sz = strlen(file->file) + strlen(mft); 397 if ((nfile = calloc(sz + 1, 1)) == NULL) 398 err(EXIT_FAILURE, "calloc"); 399 400 /* We know this is BASE_DIR/host/module/... */ 401 402 strlcpy(nfile, mft, sz + 1); 403 cp = strrchr(nfile, '/'); 404 assert(cp != NULL); 405 cp++; 406 *cp = '\0'; 407 strlcat(nfile, file->file, sz + 1); 408 409 /* 410 * Since we're from the same directory as the MFT file, we know 411 * that the repository has already been loaded. 412 */ 413 414 entityq_add(fd, q, nfile, type, NULL, file->hash, NULL, 0, NULL, eid); 415} 416 417/* 418 * Loops over queue_add_from_mft() for all files. 419 * The order here is important: we want to parse the revocation 420 * list *before* we parse anything else. 421 * FIXME: set the type of file in the mftfile so that we don't need to 422 * keep doing the check (this should be done in the parser, where we 423 * check the suffix anyway). 424 */ 425static void 426queue_add_from_mft_set(int fd, struct entityq *q, const struct mft *mft, 427 size_t *eid) 428{ 429 size_t i, sz; 430 const struct mftfile *f; 431 432 for (i = 0; i < mft->filesz; i++) { 433 f = &mft->files[i]; 434 sz = strlen(f->file); 435 assert(sz > 4); 436 if (strcasecmp(f->file + sz - 4, ".crl")) 437 continue; 438 queue_add_from_mft(fd, q, mft->file, f, RTYPE_CRL, eid); 439 } 440 441 for (i = 0; i < mft->filesz; i++) { 442 f = &mft->files[i]; 443 sz = strlen(f->file); 444 assert(sz > 4); 445 if (strcasecmp(f->file + sz - 4, ".cer")) 446 continue; 447 queue_add_from_mft(fd, q, mft->file, f, RTYPE_CER, eid); 448 } 449 450 for (i = 0; i < mft->filesz; i++) { 451 f = &mft->files[i]; 452 sz = strlen(f->file); 453 assert(sz > 4); 454 if (strcasecmp(f->file + sz - 4, ".roa")) 455 continue; 456 queue_add_from_mft(fd, q, mft->file, f, RTYPE_ROA, eid); 457 } 458} 459 460/* 461 * Add a local TAL file (RFC 7730) to the queue of files to fetch. 462 */ 463static void 464queue_add_tal(int fd, struct entityq *q, const char *file, size_t *eid) 465{ 466 char *nfile, *nbuf, *line = NULL, *buf = NULL; 467 FILE *in; 468 ssize_t n, i; 469 size_t sz = 0, bsz = 0; 470 int optcomment = 1; 471 472 if ((in = fopen(file, "r")) == NULL) 473 err(EXIT_FAILURE, "fopen: %s", file); 474 475 while ((n = getline(&line, &sz, in)) != -1) { 476 /* replace CRLF with just LF */ 477 if (n > 1 && line[n - 1] == '\n' && line[n - 2] == '\r') { 478 line[n - 2] = '\n'; 479 line[n - 1] = '\0'; 480 n--; 481 } 482 if (optcomment) { 483 /* if this is comment, just eat the line */ 484 if (line[0] == '#') 485 continue; 486 optcomment = 0; 487 /* 488 * Empty line is end of section and needs 489 * to be eaten as well. 490 */ 491 if (line[0] == '\n') 492 continue; 493 } 494 495 /* make sure every line is valid ascii */ 496 for (i = 0; i < n; i++) 497 if (!isprint(line[i]) && !isspace(line[i])) 498 errx(EXIT_FAILURE, "getline: %s: " 499 "invalid content", file); 500 501 /* concat line to buf */ 502 if ((nbuf = realloc(buf, bsz + n + 1)) == NULL) 503 err(EXIT_FAILURE, NULL); 504 buf = nbuf; 505 bsz += n + 1; 506 strlcat(buf, line, bsz); 507 /* limit the buffer size */ 508 if (bsz > 4096) 509 errx(EXIT_FAILURE, "%s: file too big", file); 510 } 511 512 free(line); 513 if (ferror(in)) 514 err(EXIT_FAILURE, "getline: %s", file); 515 fclose(in); 516 517 if ((nfile = strdup(file)) == NULL) 518 err(EXIT_FAILURE, "strdup"); 519 520 /* Not in a repository, so directly add to queue. */ 521 entityq_add(fd, q, nfile, RTYPE_TAL, NULL, NULL, NULL, 0, buf, eid); 522 /* entityq_add makes a copy of buf */ 523 free(buf); 524} 525 526/* 527 * Add rsync URIs (CER) from a TAL file, RFC 7730. 528 * Only use the first URI of the set. 529 */ 530static void 531queue_add_from_tal(int proc, int rsync, struct entityq *q, 532 const struct tal *tal, struct repotab *rt, size_t *eid) 533{ 534 char *nfile; 535 const struct repo *repo; 536 const char *uri; 537 538 assert(tal->urisz); 539 uri = tal->uri[0]; 540 541 /* Look up the repository. */ 542 543 assert(rtype_resolve(uri) == RTYPE_CER); 544 repo = repo_lookup(rsync, rt, uri); 545 uri += 8 + strlen(repo->host) + 1 + strlen(repo->module) + 1; 546 547 if (asprintf(&nfile, "%s/%s/%s/%s", 548 BASE_DIR, repo->host, repo->module, uri) == -1) 549 err(EXIT_FAILURE, "asprintf"); 550 551 entityq_add(proc, q, nfile, RTYPE_CER, repo, NULL, tal->pkey, 552 tal->pkeysz, tal->descr, eid); 553} 554 555/* 556 * Add a manifest (MFT) or CRL found in an X509 certificate, RFC 6487. 557 */ 558static void 559queue_add_from_cert(int proc, int rsync, struct entityq *q, 560 const char *uri, struct repotab *rt, size_t *eid) 561{ 562 char *nfile; 563 enum rtype type; 564 const struct repo *repo; 565 566 if ((type = rtype_resolve(uri)) == RTYPE_EOF) 567 errx(EXIT_FAILURE, "%s: unknown file type", uri); 568 if (type != RTYPE_MFT && type != RTYPE_CRL) 569 errx(EXIT_FAILURE, "%s: invalid file type", uri); 570 571 /* Look up the repository. */ 572 573 repo = repo_lookup(rsync, rt, uri); 574 uri += 8 + strlen(repo->host) + 1 + strlen(repo->module) + 1; 575 576 if (asprintf(&nfile, "%s/%s/%s/%s", 577 BASE_DIR, repo->host, repo->module, uri) == -1) 578 err(EXIT_FAILURE, "asprintf"); 579 580 entityq_add(proc, q, nfile, type, repo, NULL, NULL, 0, NULL, eid); 581} 582 583static void 584proc_child(int signal) 585{ 586 587 /* Nothing: just discard. */ 588} 589 590/* 591 * Process used for synchronising repositories. 592 * This simply waits to be told which repository to synchronise, then 593 * does so. 594 * It then responds with the identifier of the repo that it updated. 595 * It only exits cleanly when fd is closed. 596 * FIXME: this should use buffered output to prevent deadlocks, but it's 597 * very unlikely that we're going to fill our buffer, so whatever. 598 * FIXME: limit the number of simultaneous process. 599 * Currently, an attacker can trivially specify thousands of different 600 * repositories and saturate our system. 601 */ 602static void 603proc_rsync(const char *prog, const char *bind_addr, int fd, int noop) 604{ 605 size_t id, i, idsz = 0; 606 ssize_t ssz; 607 char *host = NULL, *mod = NULL, *uri = NULL, 608 *dst = NULL, *path, *save, *cmd; 609 const char *pp; 610 pid_t pid; 611 char *args[32]; 612 int st, rc = 0; 613 struct stat stt; 614 struct pollfd pfd; 615 sigset_t mask, oldmask; 616 struct rsyncproc *ids = NULL; 617 618 pfd.fd = fd; 619 pfd.events = POLLIN; 620 621 /* 622 * Unveil the command we want to run. 623 * If this has a pathname component in it, interpret as a file 624 * and unveil the file directly. 625 * Otherwise, look up the command in our PATH. 626 */ 627 628 if (!noop) { 629 if (strchr(prog, '/') == NULL) { 630 if (getenv("PATH") == NULL) 631 errx(EXIT_FAILURE, "PATH is unset"); 632 if ((path = strdup(getenv("PATH"))) == NULL) 633 err(EXIT_FAILURE, "strdup"); 634 save = path; 635 while ((pp = strsep(&path, ":")) != NULL) { 636 if (*pp == '\0') 637 continue; 638 if (asprintf(&cmd, "%s/%s", pp, prog) == -1) 639 err(EXIT_FAILURE, "asprintf"); 640 if (lstat(cmd, &stt) == -1) { 641 free(cmd); 642 continue; 643 } else if (unveil(cmd, "x") == -1) 644 err(EXIT_FAILURE, "%s: unveil", cmd); 645 free(cmd); 646 break; 647 } 648 free(save); 649 } else if (unveil(prog, "x") == -1) 650 err(EXIT_FAILURE, "%s: unveil", prog); 651 652 /* Unveil the repository directory and terminate unveiling. */ 653 654 if (unveil(BASE_DIR, "c") == -1) 655 err(EXIT_FAILURE, "%s: unveil", BASE_DIR); 656 if (unveil(NULL, NULL) == -1) 657 err(EXIT_FAILURE, "unveil"); 658 } 659 660 /* Initialise retriever for children exiting. */ 661 662 if (sigemptyset(&mask) == -1) 663 err(EXIT_FAILURE, NULL); 664 if (signal(SIGCHLD, proc_child) == SIG_ERR) 665 err(EXIT_FAILURE, NULL); 666 if (sigaddset(&mask, SIGCHLD) == -1) 667 err(EXIT_FAILURE, NULL); 668 if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) 669 err(EXIT_FAILURE, NULL); 670 671 for (;;) { 672 if (ppoll(&pfd, 1, NULL, &oldmask) == -1) { 673 if (errno != EINTR) 674 err(EXIT_FAILURE, "ppoll"); 675 676 /* 677 * If we've received an EINTR, it means that one 678 * of our children has exited and we can reap it 679 * and look up its identifier. 680 * Then we respond to the parent. 681 */ 682 683 if ((pid = waitpid(WAIT_ANY, &st, 0)) == -1) 684 err(EXIT_FAILURE, "waitpid"); 685 686 for (i = 0; i < idsz; i++) 687 if (ids[i].pid == pid) 688 break; 689 assert(i < idsz); 690 691 if (!WIFEXITED(st)) { 692 warnx("rsync %s did not exit", ids[i].uri); 693 goto out; 694 } else if (WEXITSTATUS(st) != EXIT_SUCCESS) { 695 warnx("rsync %s failed", ids[i].uri); 696 goto out; 697 } 698 699 io_simple_write(fd, &ids[i].id, sizeof(size_t)); 700 free(ids[i].uri); 701 ids[i].uri = NULL; 702 ids[i].pid = 0; 703 ids[i].id = 0; 704 continue; 705 } 706 707 /* 708 * Read til the parent exits. 709 * That will mean that we can safely exit. 710 */ 711 712 if ((ssz = read(fd, &id, sizeof(size_t))) == -1) 713 err(EXIT_FAILURE, "read"); 714 if (ssz == 0) 715 break; 716 717 /* Read host and module. */ 718 719 io_str_read(fd, &host); 720 io_str_read(fd, &mod); 721 722 if (noop) { 723 io_simple_write(fd, &id, sizeof(size_t)); 724 free(host); 725 free(mod); 726 continue; 727 } 728 729 /* 730 * Create source and destination locations. 731 * Build up the tree to this point because GPL rsync(1) 732 * will not build the destination for us. 733 */ 734 735 if (asprintf(&dst, "%s/%s", BASE_DIR, host) == -1) 736 err(EXIT_FAILURE, NULL); 737 if (mkdir(dst, 0700) == -1 && EEXIST != errno) 738 err(EXIT_FAILURE, "%s", dst); 739 free(dst); 740 741 if (asprintf(&dst, "%s/%s/%s", BASE_DIR, host, mod) == -1) 742 err(EXIT_FAILURE, NULL); 743 if (mkdir(dst, 0700) == -1 && EEXIST != errno) 744 err(EXIT_FAILURE, "%s", dst); 745 746 if (asprintf(&uri, "rsync://%s/%s", host, mod) == -1) 747 err(EXIT_FAILURE, NULL); 748 749 /* Run process itself, wait for exit, check error. */ 750 751 if ((pid = fork()) == -1) 752 err(EXIT_FAILURE, "fork"); 753 754 if (pid == 0) { 755 if (pledge("stdio exec", NULL) == -1) 756 err(EXIT_FAILURE, "pledge"); 757 i = 0; 758 args[i++] = (char *)prog; 759 args[i++] = "-rlt"; 760 args[i++] = "--delete"; 761 if (bind_addr != NULL) { 762 args[i++] = "--address"; 763 args[i++] = (char *)bind_addr; 764 } 765 args[i++] = uri; 766 args[i++] = dst; 767 args[i] = NULL; 768 execvp(args[0], args); 769 err(EXIT_FAILURE, "%s: execvp", prog); 770 } 771 772 /* Augment the list of running processes. */ 773 774 for (i = 0; i < idsz; i++) 775 if (ids[i].pid == 0) 776 break; 777 if (i == idsz) { 778 ids = reallocarray(ids, idsz + 1, sizeof(*ids)); 779 if (ids == NULL) 780 err(EXIT_FAILURE, NULL); 781 idsz++; 782 } 783 784 ids[i].id = id; 785 ids[i].pid = pid; 786 ids[i].uri = uri; 787 788 /* Clean up temporary values. */ 789 790 free(mod); 791 free(dst); 792 free(host); 793 } 794 rc = 1; 795out: 796 797 /* No need for these to be hanging around. */ 798 799 for (i = 0; i < idsz; i++) 800 if (ids[i].pid > 0) { 801 kill(ids[i].pid, SIGTERM); 802 free(ids[i].uri); 803 } 804 805 free(ids); 806 exit(rc ? EXIT_SUCCESS : EXIT_FAILURE); 807 /* NOTREACHED */ 808} 809 810/* 811 * Parse and validate a ROA, not parsing the CRL bits of "norev" has 812 * been set. 813 * This is standard stuff. 814 * Returns the roa on success, NULL on failure. 815 */ 816static struct roa * 817proc_parser_roa(struct entity *entp, int norev, 818 X509_STORE *store, X509_STORE_CTX *ctx, 819 const struct auth *auths, size_t authsz) 820{ 821 struct roa *roa; 822 X509 *x509; 823 int c; 824 X509_VERIFY_PARAM *param; 825 unsigned int fl, nfl; 826 ssize_t aidx; 827 828 assert(entp->has_dgst); 829 if ((roa = roa_parse(&x509, entp->uri, entp->dgst)) == NULL) 830 return NULL; 831 832 assert(x509 != NULL); 833 if (!X509_STORE_CTX_init(ctx, store, x509, NULL)) 834 cryptoerrx("X509_STORE_CTX_init"); 835 836 if ((param = X509_STORE_CTX_get0_param(ctx)) == NULL) 837 cryptoerrx("X509_STORE_CTX_get0_param"); 838 fl = X509_VERIFY_PARAM_get_flags(param); 839 nfl = X509_V_FLAG_IGNORE_CRITICAL; 840 if (!norev) 841 nfl |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; 842 if (!X509_VERIFY_PARAM_set_flags(param, fl | nfl)) 843 cryptoerrx("X509_VERIFY_PARAM_set_flags"); 844 845 if (X509_verify_cert(ctx) <= 0) { 846 c = X509_STORE_CTX_get_error(ctx); 847 X509_STORE_CTX_cleanup(ctx); 848 if (verbose > 0 || c != X509_V_ERR_UNABLE_TO_GET_CRL) 849 warnx("%s: %s", entp->uri, 850 X509_verify_cert_error_string(c)); 851 X509_free(x509); 852 roa_free(roa); 853 return NULL; 854 } 855 X509_STORE_CTX_cleanup(ctx); 856 X509_free(x509); 857 858 /* 859 * If the ROA isn't valid, we accept it anyway and depend upon 860 * the code around roa_read() to check the "valid" field itself. 861 */ 862 863 aidx = valid_roa(entp->uri, auths, authsz, roa); 864 if (aidx != -1) { 865 roa->valid = 1; 866 if ((roa->tal = strdup(auths[aidx].tal)) == NULL) 867 err(EXIT_FAILURE, NULL); 868 } 869 return roa; 870} 871 872/* 873 * Parse and validate a manifest file. 874 * Here we *don't* validate against the list of CRLs, because the 875 * certificate used to sign the manifest may specify a CRL that the root 876 * certificate didn't, and we haven't scanned for it yet. 877 * This chicken-and-egg isn't important, however, because we'll catch 878 * the revocation list by the time we scan for any contained resources 879 * (ROA, CER) and will see it then. 880 * Return the mft on success or NULL on failure. 881 */ 882static struct mft * 883proc_parser_mft(struct entity *entp, int force, X509_STORE *store, 884 X509_STORE_CTX *ctx, const struct auth *auths, size_t authsz) 885{ 886 struct mft *mft; 887 X509 *x509; 888 int c; 889 unsigned int fl, nfl; 890 X509_VERIFY_PARAM *param; 891 892 assert(!entp->has_dgst); 893 if ((mft = mft_parse(&x509, entp->uri, force)) == NULL) 894 return NULL; 895 896 if (!X509_STORE_CTX_init(ctx, store, x509, NULL)) 897 cryptoerrx("X509_STORE_CTX_init"); 898 899 if ((param = X509_STORE_CTX_get0_param(ctx)) == NULL) 900 cryptoerrx("X509_STORE_CTX_get0_param"); 901 fl = X509_VERIFY_PARAM_get_flags(param); 902 nfl = X509_V_FLAG_IGNORE_CRITICAL; 903 if (!X509_VERIFY_PARAM_set_flags(param, fl | nfl)) 904 cryptoerrx("X509_VERIFY_PARAM_set_flags"); 905 906 if (X509_verify_cert(ctx) <= 0) { 907 c = X509_STORE_CTX_get_error(ctx); 908 X509_STORE_CTX_cleanup(ctx); 909 warnx("%s: %s", entp->uri, X509_verify_cert_error_string(c)); 910 mft_free(mft); 911 X509_free(x509); 912 return NULL; 913 } 914 915 X509_STORE_CTX_cleanup(ctx); 916 X509_free(x509); 917 return mft; 918} 919 920/* 921 * Certificates are from manifests (has a digest and is signed with 922 * another certificate) or TALs (has a pkey and is self-signed). 923 * Parse the certificate, make sure its signatures are valid (with CRLs 924 * unless "norev" has been specified), then validate the RPKI content. 925 * This returns a certificate (which must not be freed) or NULL on parse 926 * failure. 927 */ 928static struct cert * 929proc_parser_cert(const struct entity *entp, int norev, 930 X509_STORE *store, X509_STORE_CTX *ctx, 931 struct auth **auths, size_t *authsz) 932{ 933 struct cert *cert; 934 X509 *x509; 935 int c; 936 X509_VERIFY_PARAM *param; 937 unsigned int fl, nfl; 938 ssize_t id; 939 char *tal; 940 941 assert(!entp->has_dgst != !entp->has_pkey); 942 943 /* Extract certificate data and X509. */ 944 945 cert = entp->has_dgst ? cert_parse(&x509, entp->uri, entp->dgst) : 946 ta_parse(&x509, entp->uri, entp->pkey, entp->pkeysz); 947 if (cert == NULL) 948 return NULL; 949 950 /* 951 * Validate certificate chain w/CRLs. 952 * Only check the CRLs if specifically asked. 953 */ 954 955 assert(x509 != NULL); 956 if (!X509_STORE_CTX_init(ctx, store, x509, NULL)) 957 cryptoerrx("X509_STORE_CTX_init"); 958 if ((param = X509_STORE_CTX_get0_param(ctx)) == NULL) 959 cryptoerrx("X509_STORE_CTX_get0_param"); 960 fl = X509_VERIFY_PARAM_get_flags(param); 961 nfl = X509_V_FLAG_IGNORE_CRITICAL; 962 if (!norev) 963 nfl |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; 964 if (!X509_VERIFY_PARAM_set_flags(param, fl | nfl)) 965 cryptoerrx("X509_VERIFY_PARAM_set_flags"); 966 967 /* 968 * FIXME: can we pass any options to the verification that make 969 * the depth-zero self-signed bits verify properly? 970 */ 971 972 if (X509_verify_cert(ctx) <= 0) { 973 c = X509_STORE_CTX_get_error(ctx); 974 if (c != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || 975 !entp->has_pkey) { 976 warnx("%s: %s", entp->uri, 977 X509_verify_cert_error_string(c)); 978 X509_STORE_CTX_cleanup(ctx); 979 X509_free(x509); 980 cert_free(cert); 981 return NULL; 982 } 983 } 984 X509_STORE_CTX_cleanup(ctx); 985 986 /* Semantic validation of RPKI content. */ 987 988 id = entp->has_pkey ? 989 valid_ta(entp->uri, *auths, *authsz, cert) : 990 valid_cert(entp->uri, *auths, *authsz, cert); 991 992 if (id < 0) { 993 X509_free(x509); 994 return cert; 995 } 996 997 /* 998 * Only on success of all do we add the certificate to the store 999 * of trusted certificates, both X509 and RPKI semantic. 1000 */ 1001 1002 cert->valid = 1; 1003 *auths = reallocarray(*auths, *authsz + 1, sizeof(struct auth)); 1004 if (*auths == NULL) 1005 err(EXIT_FAILURE, NULL); 1006 if (entp->has_pkey) { 1007 if ((tal = strdup(entp->descr)) == NULL) 1008 err(EXIT_FAILURE, NULL); 1009 } else 1010 tal = (*auths)[id].tal; 1011 1012 (*auths)[*authsz].id = *authsz; 1013 (*auths)[*authsz].parent = id; 1014 (*auths)[*authsz].cert = cert; 1015 (*auths)[*authsz].tal = tal; 1016 (*auths)[*authsz].fn = strdup(entp->uri); 1017 if ((*auths)[*authsz].fn == NULL) 1018 err(EXIT_FAILURE, NULL); 1019 (*authsz)++; 1020 1021 X509_STORE_add_cert(store, x509); 1022 X509_free(x509); 1023 return cert; 1024} 1025 1026/* 1027 * Parse a certificate revocation list (unless "norev", in which case 1028 * this is a noop that returns success). 1029 * This simply parses the CRL content itself, optionally validating it 1030 * within the digest if it comes from a manifest, then adds it to the 1031 * store of CRLs. 1032 */ 1033static void 1034proc_parser_crl(struct entity *entp, int norev, X509_STORE *store, 1035 X509_STORE_CTX *ctx, const struct auth *auths, size_t authsz) 1036{ 1037 X509_CRL *x509; 1038 const unsigned char *dgst; 1039 1040 if (norev) 1041 return; 1042 1043 dgst = entp->has_dgst ? entp->dgst : NULL; 1044 if ((x509 = crl_parse(entp->uri, dgst)) != NULL) { 1045 X509_STORE_add_crl(store, x509); 1046 X509_CRL_free(x509); 1047 } 1048} 1049 1050/* 1051 * Process responsible for parsing and validating content. 1052 * All this process does is wait to be told about a file to parse, then 1053 * it parses it and makes sure that the data being returned is fully 1054 * validated and verified. 1055 * The process will exit cleanly only when fd is closed. 1056 */ 1057static void 1058proc_parser(int fd, int force, int norev) 1059{ 1060 struct tal *tal; 1061 struct cert *cert; 1062 struct mft *mft; 1063 struct roa *roa; 1064 struct entity *entp; 1065 struct entityq q; 1066 int c, rc = 0; 1067 struct pollfd pfd; 1068 char *b = NULL; 1069 size_t i, bsz = 0, bmax = 0, bpos = 0, authsz = 0; 1070 ssize_t ssz; 1071 X509_STORE *store; 1072 X509_STORE_CTX *ctx; 1073 struct auth *auths = NULL; 1074 1075 ERR_load_crypto_strings(); 1076 OpenSSL_add_all_ciphers(); 1077 OpenSSL_add_all_digests(); 1078 1079 if ((store = X509_STORE_new()) == NULL) 1080 cryptoerrx("X509_STORE_new"); 1081 if ((ctx = X509_STORE_CTX_new()) == NULL) 1082 cryptoerrx("X509_STORE_CTX_new"); 1083 1084 TAILQ_INIT(&q); 1085 1086 pfd.fd = fd; 1087 pfd.events = POLLIN; 1088 1089 io_socket_nonblocking(pfd.fd); 1090 1091 for (;;) { 1092 if (poll(&pfd, 1, INFTIM) == -1) 1093 err(EXIT_FAILURE, "poll"); 1094 if ((pfd.revents & (POLLERR|POLLNVAL))) 1095 errx(EXIT_FAILURE, "poll: bad descriptor"); 1096 1097 /* If the parent closes, return immediately. */ 1098 1099 if ((pfd.revents & POLLHUP)) 1100 break; 1101 1102 /* 1103 * Start with read events. 1104 * This means that the parent process is sending us 1105 * something we need to parse. 1106 * We don't actually parse it til we have space in our 1107 * outgoing buffer for responding, though. 1108 */ 1109 1110 if ((pfd.revents & POLLIN)) { 1111 io_socket_blocking(fd); 1112 entp = calloc(1, sizeof(struct entity)); 1113 if (entp == NULL) 1114 err(EXIT_FAILURE, NULL); 1115 entity_read_req(fd, entp); 1116 TAILQ_INSERT_TAIL(&q, entp, entries); 1117 pfd.events |= POLLOUT; 1118 io_socket_nonblocking(fd); 1119 } 1120 1121 if (!(pfd.revents & POLLOUT)) 1122 continue; 1123 1124 /* 1125 * If we have a write buffer, then continue trying to 1126 * push it all out. 1127 * When it's all pushed out, reset it and get ready to 1128 * continue sucking down more data. 1129 */ 1130 1131 if (bsz) { 1132 assert(bpos < bmax); 1133 if ((ssz = write(fd, b + bpos, bsz)) == -1) 1134 err(EXIT_FAILURE, "write"); 1135 bpos += ssz; 1136 bsz -= ssz; 1137 if (bsz) 1138 continue; 1139 bpos = bsz = 0; 1140 } 1141 1142 /* 1143 * If there's nothing to parse, then stop waiting for 1144 * the write signal. 1145 */ 1146 1147 if (TAILQ_EMPTY(&q)) { 1148 pfd.events &= ~POLLOUT; 1149 continue; 1150 } 1151 1152 entp = TAILQ_FIRST(&q); 1153 assert(entp != NULL); 1154 1155 entity_buffer_resp(&b, &bsz, &bmax, entp); 1156 1157 switch (entp->type) { 1158 case RTYPE_TAL: 1159 assert(!entp->has_dgst); 1160 if ((tal = tal_parse(entp->uri, entp->descr)) == NULL) 1161 goto out; 1162 tal_buffer(&b, &bsz, &bmax, tal); 1163 tal_free(tal); 1164 break; 1165 case RTYPE_CER: 1166 cert = proc_parser_cert(entp, norev, 1167 store, ctx, &auths, &authsz); 1168 c = (cert != NULL); 1169 io_simple_buffer(&b, &bsz, &bmax, &c, sizeof(int)); 1170 if (cert != NULL) 1171 cert_buffer(&b, &bsz, &bmax, cert); 1172 /* 1173 * The parsed certificate data "cert" is now 1174 * managed in the "auths" table, so don't free 1175 * it here (see the loop after "out"). 1176 */ 1177 break; 1178 case RTYPE_MFT: 1179 mft = proc_parser_mft(entp, force, 1180 store, ctx, auths, authsz); 1181 c = (mft != NULL); 1182 io_simple_buffer(&b, &bsz, &bmax, &c, sizeof(int)); 1183 if (mft != NULL) 1184 mft_buffer(&b, &bsz, &bmax, mft); 1185 mft_free(mft); 1186 break; 1187 case RTYPE_CRL: 1188 proc_parser_crl(entp, norev, 1189 store, ctx, auths, authsz); 1190 break; 1191 case RTYPE_ROA: 1192 assert(entp->has_dgst); 1193 roa = proc_parser_roa(entp, norev, 1194 store, ctx, auths, authsz); 1195 c = (roa != NULL); 1196 io_simple_buffer(&b, &bsz, &bmax, &c, sizeof(int)); 1197 if (roa != NULL) 1198 roa_buffer(&b, &bsz, &bmax, roa); 1199 roa_free(roa); 1200 break; 1201 default: 1202 abort(); 1203 } 1204 1205 TAILQ_REMOVE(&q, entp, entries); 1206 entity_free(entp); 1207 } 1208 1209 rc = 1; 1210out: 1211 while ((entp = TAILQ_FIRST(&q)) != NULL) { 1212 TAILQ_REMOVE(&q, entp, entries); 1213 entity_free(entp); 1214 } 1215 1216 for (i = 0; i < authsz; i++) { 1217 free(auths[i].fn); 1218 if (i == auths[i].parent) 1219 free(auths[i].tal); 1220 cert_free(auths[i].cert); 1221 } 1222 1223 X509_STORE_CTX_free(ctx); 1224 X509_STORE_free(store); 1225 free(auths); 1226 1227 free(b); 1228 1229 EVP_cleanup(); 1230 CRYPTO_cleanup_all_ex_data(); 1231 ERR_remove_state(0); 1232 ERR_free_strings(); 1233 1234 exit(rc ? EXIT_SUCCESS : EXIT_FAILURE); 1235} 1236 1237/* 1238 * Process parsed content. 1239 * For non-ROAs, we grok for more data. 1240 * For ROAs, we want to extract the valid info. 1241 * In all cases, we gather statistics. 1242 */ 1243static void 1244entity_process(int proc, int rsync, struct stats *st, 1245 struct entityq *q, const struct entity *ent, struct repotab *rt, 1246 size_t *eid, struct vrp_tree *tree) 1247{ 1248 struct tal *tal; 1249 struct cert *cert; 1250 struct mft *mft; 1251 struct roa *roa; 1252 int c; 1253 1254 /* 1255 * For most of these, we first read whether there's any content 1256 * at all---this means that the syntactic parse failed (X509 1257 * certificate, for example). 1258 * We follow that up with whether the resources didn't parse. 1259 */ 1260 1261 switch (ent->type) { 1262 case RTYPE_TAL: 1263 st->tals++; 1264 tal = tal_read(proc); 1265 queue_add_from_tal(proc, rsync, q, tal, rt, eid); 1266 tal_free(tal); 1267 break; 1268 case RTYPE_CER: 1269 st->certs++; 1270 io_simple_read(proc, &c, sizeof(int)); 1271 if (c == 0) { 1272 st->certs_fail++; 1273 break; 1274 } 1275 cert = cert_read(proc); 1276 if (cert->valid) { 1277 /* 1278 * Process the revocation list from the 1279 * certificate *first*, since it might mark that 1280 * we're revoked and then we don't want to 1281 * process the MFT. 1282 */ 1283 if (cert->crl != NULL) 1284 queue_add_from_cert(proc, rsync, 1285 q, cert->crl, rt, eid); 1286 if (cert->mft != NULL) 1287 queue_add_from_cert(proc, rsync, 1288 q, cert->mft, rt, eid); 1289 } else 1290 st->certs_invalid++; 1291 cert_free(cert); 1292 break; 1293 case RTYPE_MFT: 1294 st->mfts++; 1295 io_simple_read(proc, &c, sizeof(int)); 1296 if (c == 0) { 1297 st->mfts_fail++; 1298 break; 1299 } 1300 mft = mft_read(proc); 1301 if (mft->stale) 1302 st->mfts_stale++; 1303 queue_add_from_mft_set(proc, q, mft, eid); 1304 mft_free(mft); 1305 break; 1306 case RTYPE_CRL: 1307 st->crls++; 1308 break; 1309 case RTYPE_ROA: 1310 st->roas++; 1311 io_simple_read(proc, &c, sizeof(int)); 1312 if (c == 0) { 1313 st->roas_fail++; 1314 break; 1315 } 1316 roa = roa_read(proc); 1317 if (roa->valid) 1318 roa_insert_vrps(tree, roa, &st->vrps, &st->uniqs); 1319 else 1320 st->roas_invalid++; 1321 roa_free(roa); 1322 break; 1323 default: 1324 abort(); 1325 } 1326} 1327 1328#define TALSZ_MAX 8 1329 1330size_t 1331tal_load_default(const char *tals[], size_t max) 1332{ 1333 static const char *basedir = "/etc/rpki"; 1334 size_t s = 0; 1335 char *path; 1336 DIR *dirp; 1337 struct dirent *dp; 1338 1339 dirp = opendir(basedir); 1340 if (dirp == NULL) 1341 err(EXIT_FAILURE, "open %s", basedir); 1342 while ((dp = readdir(dirp)) != NULL) { 1343 if (fnmatch("*.tal", dp->d_name, FNM_PERIOD) == FNM_NOMATCH) 1344 continue; 1345 if (s >= max) 1346 err(EXIT_FAILURE, "too many tal files found in %s", 1347 basedir); 1348 if (asprintf(&path, "%s/%s", basedir, dp->d_name) == -1) 1349 err(EXIT_FAILURE, "asprintf"); 1350 tals[s++] = path; 1351 } 1352 closedir (dirp); 1353 return (s); 1354} 1355 1356int 1357main(int argc, char *argv[]) 1358{ 1359 int rc = 0, c, proc, st, rsync, 1360 fl = SOCK_STREAM | SOCK_CLOEXEC, noop = 0, 1361 force = 0, norev = 0; 1362 size_t i, j, eid = 1, outsz = 0, talsz = 0; 1363 pid_t procpid, rsyncpid; 1364 int fd[2]; 1365 struct entityq q; 1366 struct entity *ent; 1367 struct pollfd pfd[2]; 1368 struct repotab rt; 1369 struct stats stats; 1370 struct roa **out = NULL; 1371 const char *rsync_prog = "openrsync"; 1372 const char *bind_addr = NULL; 1373 const char *tals[TALSZ_MAX]; 1374 const char *tablename = "roa"; 1375 FILE *output = NULL; 1376 struct vrp_tree v = RB_INITIALIZER(&v); 1377 enum output_fmt outfmt = BGPD; 1378 1379 if (pledge("stdio rpath wpath cpath proc exec unveil", NULL) == -1) 1380 err(EXIT_FAILURE, "pledge"); 1381 1382 while ((c = getopt(argc, argv, "b:Bce:fjnrt:T:v")) != -1) 1383 switch (c) { 1384 case 'b': 1385 bind_addr = optarg; 1386 break; 1387 case 'B': 1388 outfmt = BIRD; 1389 break; 1390 case 'c': 1391 outfmt = CSV; 1392 break; 1393 case 'e': 1394 rsync_prog = optarg; 1395 break; 1396 case 'f': 1397 force = 1; 1398 break; 1399 case 'j': 1400 outfmt = JSON; 1401 break; 1402 case 'n': 1403 noop = 1; 1404 break; 1405 case 'r': 1406 norev = 1; 1407 break; 1408 case 't': 1409 if (talsz >= TALSZ_MAX) 1410 err(EXIT_FAILURE, 1411 "too many tal files specified"); 1412 tals[talsz++] = optarg; 1413 break; 1414 case 'T': 1415 tablename = optarg; 1416 break; 1417 case 'v': 1418 verbose++; 1419 break; 1420 default: 1421 goto usage; 1422 } 1423 1424 argv += optind; 1425 argc -= optind; 1426 if (argc != 1) 1427 goto usage; 1428 output = fopen(argv[0], "we"); 1429 if (output == NULL) 1430 err(EXIT_FAILURE, "failed to open %s", argv[0]); 1431 1432 if (talsz == 0) 1433 talsz = tal_load_default(tals, TALSZ_MAX); 1434 if (talsz == 0) 1435 err(EXIT_FAILURE, "no TAL files found in %s", "/etc/rpki"); 1436 1437 memset(&rt, 0, sizeof(struct repotab)); 1438 memset(&stats, 0, sizeof(struct stats)); 1439 TAILQ_INIT(&q); 1440 1441 /* 1442 * Create the file reader as a jailed child process. 1443 * It will be responsible for reading all of the files (ROAs, 1444 * manifests, certificates, etc.) and returning contents. 1445 */ 1446 1447 if (socketpair(AF_UNIX, fl, 0, fd) == -1) 1448 err(EXIT_FAILURE, "socketpair"); 1449 if ((procpid = fork()) == -1) 1450 err(EXIT_FAILURE, "fork"); 1451 1452 if (procpid == 0) { 1453 close(fd[1]); 1454 /* Only allow access to BASE_DIR. */ 1455 if (unveil(BASE_DIR, "r") == -1) 1456 err(EXIT_FAILURE, "%s: unveil", BASE_DIR); 1457 if (unveil(NULL, NULL) == -1) 1458 err(EXIT_FAILURE, "unveil"); 1459 if (pledge("stdio rpath", NULL) == -1) 1460 err(EXIT_FAILURE, "pledge"); 1461 proc_parser(fd[0], force, norev); 1462 /* NOTREACHED */ 1463 } 1464 1465 close(fd[0]); 1466 proc = fd[1]; 1467 1468 /* 1469 * Create a process that will do the rsync'ing. 1470 * This process is responsible for making sure that all the 1471 * repositories referenced by a certificate manifest (or the 1472 * TAL) exists and has been downloaded. 1473 */ 1474 1475 if (socketpair(AF_UNIX, fl, 0, fd) == -1) 1476 err(EXIT_FAILURE, "socketpair"); 1477 if ((rsyncpid = fork()) == -1) 1478 err(EXIT_FAILURE, "fork"); 1479 1480 if (rsyncpid == 0) { 1481 close(proc); 1482 close(fd[1]); 1483 if (pledge("stdio rpath cpath proc exec unveil", NULL) == -1) 1484 err(EXIT_FAILURE, "pledge"); 1485 1486 /* If -n, we don't exec or mkdir. */ 1487 1488 if (noop && pledge("stdio", NULL) == -1) 1489 err(EXIT_FAILURE, "pledge"); 1490 proc_rsync(rsync_prog, bind_addr, fd[0], noop); 1491 /* NOTREACHED */ 1492 } 1493 1494 close(fd[0]); 1495 rsync = fd[1]; 1496 1497 assert(rsync != proc); 1498 1499 if (pledge("stdio rpath", NULL) == -1) 1500 err(EXIT_FAILURE, "pledge"); 1501 1502 /* 1503 * Prime the process with our TAL file. 1504 * This will contain (hopefully) links to our manifest and we 1505 * can get the ball rolling. 1506 */ 1507 1508 for (i = 0; i < talsz; i++) 1509 queue_add_tal(proc, &q, tals[i], &eid); 1510 1511 /* 1512 * The main process drives the top-down scan to leaf ROAs using 1513 * data downloaded by the rsync process and parsed by the 1514 * parsing process. 1515 */ 1516 1517 if (pledge("stdio", NULL) == -1) 1518 err(EXIT_FAILURE, "pledge"); 1519 1520 pfd[0].fd = rsync; 1521 pfd[1].fd = proc; 1522 pfd[0].events = pfd[1].events = POLLIN; 1523 1524 while (!TAILQ_EMPTY(&q)) { 1525 if ((c = poll(pfd, 2, verbose ? 10000 : INFTIM)) == -1) 1526 err(EXIT_FAILURE, "poll"); 1527 1528 /* Debugging: print some statistics if we stall. */ 1529 1530 if (c == 0) { 1531 for (i = j = 0; i < rt.reposz; i++) 1532 if (!rt.repos[i].loaded) 1533 j++; 1534 logx("period stats: %zu pending repos", j); 1535 j = 0; 1536 TAILQ_FOREACH(ent, &q, entries) 1537 j++; 1538 logx("period stats: %zu pending entries", j); 1539 continue; 1540 } 1541 1542 if ((pfd[0].revents & (POLLERR|POLLNVAL)) || 1543 (pfd[1].revents & (POLLERR|POLLNVAL))) 1544 errx(EXIT_FAILURE, "poll: bad fd"); 1545 if ((pfd[0].revents & POLLHUP) || 1546 (pfd[1].revents & POLLHUP)) 1547 errx(EXIT_FAILURE, "poll: hangup"); 1548 1549 /* 1550 * Check the rsync process. 1551 * This means that one of our modules has completed 1552 * downloading and we can flush the module requests into 1553 * the parser process. 1554 */ 1555 1556 if ((pfd[0].revents & POLLIN)) { 1557 io_simple_read(rsync, &i, sizeof(size_t)); 1558 assert(i < rt.reposz); 1559 assert(!rt.repos[i].loaded); 1560 rt.repos[i].loaded = 1; 1561 logx("%s/%s/%s: loaded", BASE_DIR, 1562 rt.repos[i].host, rt.repos[i].module); 1563 stats.repos++; 1564 entityq_flush(proc, &q, &rt.repos[i]); 1565 } 1566 1567 /* 1568 * The parser has finished something for us. 1569 * Dequeue these one by one. 1570 */ 1571 1572 if ((pfd[1].revents & POLLIN)) { 1573 ent = entityq_next(proc, &q); 1574 entity_process(proc, rsync, &stats, 1575 &q, ent, &rt, &eid, &v); 1576 if (verbose > 1) 1577 fprintf(stderr, "%s\n", ent->uri); 1578 entity_free(ent); 1579 } 1580 } 1581 1582 assert(TAILQ_EMPTY(&q)); 1583 logx("all files parsed: exiting"); 1584 rc = 1; 1585 1586 /* 1587 * For clean-up, close the input for the parser and rsync 1588 * process. 1589 * This will cause them to exit, then we reap them. 1590 */ 1591 1592 close(proc); 1593 close(rsync); 1594 1595 if (waitpid(procpid, &st, 0) == -1) 1596 err(EXIT_FAILURE, "waitpid"); 1597 if (!WIFEXITED(st) || WEXITSTATUS(st) != EXIT_SUCCESS) { 1598 warnx("parser process exited abnormally"); 1599 rc = 0; 1600 } 1601 if (waitpid(rsyncpid, &st, 0) == -1) 1602 err(EXIT_FAILURE, "waitpid"); 1603 if (!WIFEXITED(st) || WEXITSTATUS(st) != EXIT_SUCCESS) { 1604 warnx("rsync process exited abnormally"); 1605 rc = 0; 1606 } 1607 1608 switch (outfmt) { 1609 case BGPD: 1610 output_bgpd(output, &v); 1611 break; 1612 case BIRD: 1613 output_bird(output, &v, tablename); 1614 break; 1615 case CSV: 1616 output_csv(output, &v); 1617 break; 1618 case JSON: 1619 output_json(output, &v); 1620 break; 1621 } 1622 1623 logx("Route Origin Authorizations: %zu (%zu failed parse, %zu invalid)", 1624 stats.roas, stats.roas_fail, stats.roas_invalid); 1625 logx("Certificates: %zu (%zu failed parse, %zu invalid)", 1626 stats.certs, stats.certs_fail, stats.certs_invalid); 1627 logx("Trust Anchor Locators: %zu", stats.tals); 1628 logx("Manifests: %zu (%zu failed parse, %zu stale)", 1629 stats.mfts, stats.mfts_fail, stats.mfts_stale); 1630 logx("Certificate revocation lists: %zu", stats.crls); 1631 logx("Repositories: %zu", stats.repos); 1632 logx("VRP Entries: %zu (%zu unique)", stats.vrps, stats.uniqs); 1633 1634 /* Memory cleanup. */ 1635 1636 for (i = 0; i < rt.reposz; i++) { 1637 free(rt.repos[i].host); 1638 free(rt.repos[i].module); 1639 } 1640 free(rt.repos); 1641 1642 for (i = 0; i < outsz; i++) 1643 roa_free(out[i]); 1644 free(out); 1645 1646 return rc ? EXIT_SUCCESS : EXIT_FAILURE; 1647 1648usage: 1649 fprintf(stderr, 1650 "usage: rpki-client [-Bcfjnrv] [-b bind_addr] [-e rsync_prog] " 1651 "[-T table] [-t tal] output\n"); 1652 return EXIT_FAILURE; 1653} 1654