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