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