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