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