1 /* $OpenBSD: parser.c,v 1.73 2022/04/21 12:59:03 claudio Exp $ */ 2 /* 3 * Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org> 4 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/queue.h> 20 #include <sys/tree.h> 21 #include <sys/types.h> 22 23 #include <assert.h> 24 #include <err.h> 25 #include <fcntl.h> 26 #include <poll.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <limits.h> 31 #include <unistd.h> 32 #include <imsg.h> 33 34 #include <openssl/asn1.h> 35 #include <openssl/err.h> 36 #include <openssl/evp.h> 37 #include <openssl/x509.h> 38 #include <openssl/x509v3.h> 39 40 #include "extern.h" 41 42 static X509_STORE_CTX *ctx; 43 static struct auth_tree auths = RB_INITIALIZER(&auths); 44 static struct crl_tree crlt = RB_INITIALIZER(&crlt); 45 46 struct parse_repo { 47 RB_ENTRY(parse_repo) entry; 48 char *path; 49 char *validpath; 50 unsigned int id; 51 }; 52 53 static RB_HEAD(repo_tree, parse_repo) repos = RB_INITIALIZER(&repos); 54 55 static inline int 56 repocmp(struct parse_repo *a, struct parse_repo *b) 57 { 58 return a->id - b->id; 59 } 60 61 RB_GENERATE_STATIC(repo_tree, parse_repo, entry, repocmp); 62 63 static struct parse_repo * 64 repo_get(unsigned int id) 65 { 66 struct parse_repo needle = { .id = id }; 67 68 return RB_FIND(repo_tree, &repos, &needle); 69 } 70 71 static void 72 repo_add(unsigned int id, char *path, char *validpath) 73 { 74 struct parse_repo *rp; 75 76 if ((rp = calloc(1, sizeof(*rp))) == NULL) 77 err(1, NULL); 78 rp->id = id; 79 if (path != NULL) 80 if ((rp->path = strdup(path)) == NULL) 81 err(1, NULL); 82 if (validpath != NULL) 83 if ((rp->validpath = strdup(validpath)) == NULL) 84 err(1, NULL); 85 86 if (RB_INSERT(repo_tree, &repos, rp) != NULL) 87 errx(1, "repository already added: id %d, %s", id, path); 88 } 89 90 /* 91 * Build access path to file based on repoid, path, location and file values. 92 */ 93 static char * 94 parse_filepath(unsigned int repoid, const char *path, const char *file, 95 enum location loc) 96 { 97 struct parse_repo *rp; 98 char *fn, *repopath; 99 100 /* build file path based on repoid, entity path and filename */ 101 rp = repo_get(repoid); 102 if (rp == NULL) 103 errx(1, "build file path: repository %u missing", repoid); 104 105 if (loc == DIR_VALID) 106 repopath = rp->validpath; 107 else 108 repopath = rp->path; 109 110 if (repopath == NULL) 111 return NULL; 112 113 if (path == NULL) { 114 if (asprintf(&fn, "%s/%s", repopath, file) == -1) 115 err(1, NULL); 116 } else { 117 if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1) 118 err(1, NULL); 119 } 120 return fn; 121 } 122 123 /* 124 * Parse and validate a ROA. 125 * This is standard stuff. 126 * Returns the roa on success, NULL on failure. 127 */ 128 static struct roa * 129 proc_parser_roa(char *file, const unsigned char *der, size_t len) 130 { 131 struct roa *roa; 132 struct auth *a; 133 struct crl *crl; 134 X509 *x509; 135 136 if ((roa = roa_parse(&x509, file, der, len)) == NULL) 137 return NULL; 138 139 a = valid_ski_aki(file, &auths, roa->ski, roa->aki); 140 crl = crl_get(&crlt, a); 141 142 if (!valid_x509(file, ctx, x509, a, crl, 0)) { 143 X509_free(x509); 144 roa_free(roa); 145 return NULL; 146 } 147 X509_free(x509); 148 149 roa->talid = a->cert->talid; 150 151 /* 152 * If the ROA isn't valid, we accept it anyway and depend upon 153 * the code around roa_read() to check the "valid" field itself. 154 */ 155 156 if (valid_roa(file, a, roa)) 157 roa->valid = 1; 158 159 /* 160 * Check CRL to figure out the soonest transitive expiry moment 161 */ 162 if (crl != NULL && roa->expires > crl->expires) 163 roa->expires = crl->expires; 164 165 /* 166 * Scan the cert tree to figure out the soonest transitive 167 * expiry moment 168 */ 169 for (; a != NULL; a = a->parent) { 170 if (roa->expires > a->cert->expires) 171 roa->expires = a->cert->expires; 172 } 173 174 return roa; 175 } 176 177 /* 178 * Check all files and their hashes in a MFT structure. 179 * Return zero on failure, non-zero on success. 180 */ 181 static int 182 proc_parser_mft_check(const char *fn, struct mft *p) 183 { 184 const enum location loc[2] = { DIR_TEMP, DIR_VALID }; 185 size_t i; 186 int rc = 1; 187 char *path; 188 189 for (i = 0; i < p->filesz; i++) { 190 struct mftfile *m = &p->files[i]; 191 int try, fd = -1, noent = 0, valid = 0; 192 for (try = 0; try < 2 && !valid; try++) { 193 if ((path = parse_filepath(p->repoid, p->path, m->file, 194 loc[try])) == NULL) 195 continue; 196 fd = open(path, O_RDONLY); 197 if (fd == -1 && errno == ENOENT) 198 noent++; 199 free(path); 200 201 /* remember which path was checked */ 202 m->location = loc[try]; 203 valid = valid_filehash(fd, m->hash, sizeof(m->hash)); 204 } 205 206 if (!valid) { 207 /* silently skip not-existing unknown files */ 208 if (m->type == RTYPE_INVALID && noent == 2) 209 continue; 210 warnx("%s: bad message digest for %s", fn, m->file); 211 rc = 0; 212 continue; 213 } 214 } 215 216 return rc; 217 } 218 219 /* 220 * Load the correct CRL using the info from the MFT. 221 */ 222 static struct crl * 223 parse_load_crl_from_mft(struct entity *entp, struct mft *mft, enum location loc) 224 { 225 struct crl *crl = NULL; 226 unsigned char *f = NULL; 227 char *fn = NULL; 228 size_t flen; 229 230 while (1) { 231 fn = parse_filepath(entp->repoid, entp->path, mft->crl, loc); 232 if (fn == NULL) 233 goto next; 234 235 f = load_file(fn, &flen); 236 if (f == NULL && errno != ENOENT) 237 warn("parse file %s", fn); 238 if (f == NULL) 239 goto next; 240 if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash))) 241 goto next; 242 crl = crl_parse(fn, f, flen); 243 next: 244 free(f); 245 free(fn); 246 f = NULL; 247 fn = NULL; 248 249 if (crl != NULL) 250 return crl; 251 if (loc == DIR_TEMP) 252 loc = DIR_VALID; 253 else 254 return NULL; 255 } 256 } 257 258 /* 259 * Parse and validate a manifest file. Skip checking the fileandhash 260 * this is done in the post check. After this step we know the mft is 261 * valid and can be compared. 262 * Return the mft on success or NULL on failure. 263 */ 264 static struct mft * 265 proc_parser_mft_pre(char *file, const unsigned char *der, size_t len, 266 struct entity *entp, enum location loc, struct crl **crl) 267 { 268 struct mft *mft; 269 X509 *x509; 270 struct auth *a; 271 272 *crl = NULL; 273 if ((mft = mft_parse(&x509, file, der, len)) == NULL) 274 return NULL; 275 *crl = parse_load_crl_from_mft(entp, mft, loc); 276 277 a = valid_ski_aki(file, &auths, mft->ski, mft->aki); 278 if (!valid_x509(file, ctx, x509, a, *crl, 1)) { 279 X509_free(x509); 280 mft_free(mft); 281 crl_free(*crl); 282 *crl = NULL; 283 return NULL; 284 } 285 X509_free(x509); 286 287 mft->repoid = entp->repoid; 288 return mft; 289 } 290 291 /* 292 * Do the end of manifest validation. 293 * Return the mft on success or NULL on failure. 294 */ 295 static struct mft * 296 proc_parser_mft_post(char *file, struct mft *mft, const char *path) 297 { 298 /* check that now is not before from */ 299 time_t now = time(NULL); 300 301 if (mft == NULL) { 302 warnx("%s: no valid mft available", file); 303 return NULL; 304 } 305 306 /* check that now is not before from */ 307 if (now < mft->valid_since) { 308 warnx("%s: mft not yet valid %s", file, 309 time2str(mft->valid_since)); 310 mft->stale = 1; 311 } 312 /* check that now is not after until */ 313 if (now > mft->valid_until) { 314 warnx("%s: mft expired on %s", file, 315 time2str(mft->valid_until)); 316 mft->stale = 1; 317 } 318 319 if (path != NULL) 320 if ((mft->path = strdup(path)) == NULL) 321 err(1, NULL); 322 323 if (!mft->stale) 324 if (!proc_parser_mft_check(file, mft)) { 325 mft_free(mft); 326 return NULL; 327 } 328 329 return mft; 330 } 331 332 /* 333 * Load the most recent MFT by opening both options and comparing the two. 334 */ 335 static char * 336 proc_parser_mft(struct entity *entp, struct mft **mp) 337 { 338 struct mft *mft1 = NULL, *mft2 = NULL; 339 struct crl *crl, *crl1 = NULL, *crl2 = NULL; 340 char *f, *file, *file1, *file2; 341 size_t flen; 342 343 *mp = NULL; 344 file1 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID); 345 file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_TEMP); 346 347 if (file1 != NULL) { 348 f = load_file(file1, &flen); 349 if (f == NULL && errno != ENOENT) 350 warn("parse file %s", file1); 351 mft1 = proc_parser_mft_pre(file1, f, flen, entp, DIR_VALID, 352 &crl1); 353 free(f); 354 } 355 if (file2 != NULL) { 356 f = load_file(file2, &flen); 357 if (f == NULL && errno != ENOENT) 358 warn("parse file %s", file2); 359 mft2 = proc_parser_mft_pre(file2, f, flen, entp, DIR_TEMP, 360 &crl2); 361 free(f); 362 } 363 364 if (mft_compare(mft1, mft2) == 1) { 365 mft_free(mft2); 366 crl_free(crl2); 367 free(file2); 368 *mp = proc_parser_mft_post(file1, mft1, entp->path); 369 crl = crl1; 370 file = file1; 371 } else { 372 mft_free(mft1); 373 crl_free(crl1); 374 free(file1); 375 *mp = proc_parser_mft_post(file2, mft2, entp->path); 376 crl = crl2; 377 file = file2; 378 } 379 380 if (*mp != NULL) { 381 if (!crl_insert(&crlt, crl)) { 382 warnx("%s: duplicate AKI %s", file, crl->aki); 383 crl_free(crl); 384 } 385 } else { 386 crl_free(crl); 387 } 388 return file; 389 } 390 391 /* 392 * Certificates are from manifests (has a digest and is signed with 393 * another certificate) Parse the certificate, make sure its 394 * signatures are valid (with CRLs), then validate the RPKI content. 395 * This returns a certificate (which must not be freed) or NULL on 396 * parse failure. 397 */ 398 static struct cert * 399 proc_parser_cert(char *file, const unsigned char *der, size_t len) 400 { 401 struct cert *cert; 402 struct crl *crl; 403 struct auth *a; 404 405 /* Extract certificate data. */ 406 407 cert = cert_parse_pre(file, der, len); 408 cert = cert_parse(file, cert); 409 if (cert == NULL) 410 return NULL; 411 412 a = valid_ski_aki(file, &auths, cert->ski, cert->aki); 413 crl = crl_get(&crlt, a); 414 415 if (!valid_x509(file, ctx, cert->x509, a, crl, 0) || 416 !valid_cert(file, a, cert)) { 417 cert_free(cert); 418 return NULL; 419 } 420 421 cert->talid = a->cert->talid; 422 423 /* 424 * Add validated CA certs to the RPKI auth tree. 425 */ 426 if (cert->purpose == CERT_PURPOSE_CA) 427 auth_insert(&auths, cert, a); 428 429 return cert; 430 } 431 432 /* 433 * Root certificates come from TALs (has a pkey and is self-signed). 434 * Parse the certificate, ensure that its public key matches the 435 * known public key from the TAL, and then validate the RPKI 436 * content. 437 * 438 * This returns a certificate (which must not be freed) or NULL on 439 * parse failure. 440 */ 441 static struct cert * 442 proc_parser_root_cert(char *file, const unsigned char *der, size_t len, 443 unsigned char *pkey, size_t pkeysz, int talid) 444 { 445 struct cert *cert; 446 447 /* Extract certificate data. */ 448 449 cert = cert_parse_pre(file, der, len); 450 cert = ta_parse(file, cert, pkey, pkeysz); 451 if (cert == NULL) 452 return NULL; 453 454 if (!valid_ta(file, &auths, cert)) { 455 warnx("%s: certificate not a valid ta", file); 456 cert_free(cert); 457 return NULL; 458 } 459 460 cert->talid = talid; 461 462 /* 463 * Add valid roots to the RPKI auth tree. 464 */ 465 auth_insert(&auths, cert, NULL); 466 467 return cert; 468 } 469 470 /* 471 * Parse a ghostbuster record 472 */ 473 static void 474 proc_parser_gbr(char *file, const unsigned char *der, size_t len) 475 { 476 struct gbr *gbr; 477 X509 *x509; 478 struct crl *crl; 479 struct auth *a; 480 481 if ((gbr = gbr_parse(&x509, file, der, len)) == NULL) 482 return; 483 484 a = valid_ski_aki(file, &auths, gbr->ski, gbr->aki); 485 crl = crl_get(&crlt, a); 486 487 /* return value can be ignored since nothing happens here */ 488 valid_x509(file, ctx, x509, a, crl, 0); 489 490 X509_free(x509); 491 gbr_free(gbr); 492 } 493 494 /* 495 * Load the file specified by the entity information. 496 */ 497 static char * 498 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen) 499 { 500 char *file; 501 502 file = parse_filepath(entp->repoid, entp->path, entp->file, 503 entp->location); 504 if (file == NULL) 505 errx(1, "no path to file"); 506 507 *f = load_file(file, flen); 508 if (*f == NULL) 509 warn("parse file %s", file); 510 511 return file; 512 } 513 514 /* 515 * Process an entity and responing to parent process. 516 */ 517 static void 518 parse_entity(struct entityq *q, struct msgbuf *msgq) 519 { 520 struct entity *entp; 521 struct tal *tal; 522 struct cert *cert; 523 struct mft *mft; 524 struct roa *roa; 525 struct ibuf *b; 526 unsigned char *f; 527 size_t flen; 528 char *file; 529 int c; 530 531 while ((entp = TAILQ_FIRST(q)) != NULL) { 532 TAILQ_REMOVE(q, entp, entries); 533 534 /* handle RTYPE_REPO first */ 535 if (entp->type == RTYPE_REPO) { 536 repo_add(entp->repoid, entp->path, entp->file); 537 entity_free(entp); 538 continue; 539 } 540 541 /* pass back at least type, repoid and filename */ 542 b = io_new_buffer(); 543 io_simple_buffer(b, &entp->type, sizeof(entp->type)); 544 545 file = NULL; 546 f = NULL; 547 switch (entp->type) { 548 case RTYPE_TAL: 549 io_str_buffer(b, entp->file); 550 if ((tal = tal_parse(entp->file, entp->data, 551 entp->datasz)) == NULL) 552 errx(1, "%s: could not parse tal file", 553 entp->file); 554 tal->id = entp->talid; 555 tal_buffer(b, tal); 556 tal_free(tal); 557 break; 558 case RTYPE_CER: 559 file = parse_load_file(entp, &f, &flen); 560 io_str_buffer(b, file); 561 if (entp->data != NULL) 562 cert = proc_parser_root_cert(file, 563 f, flen, entp->data, entp->datasz, 564 entp->talid); 565 else 566 cert = proc_parser_cert(file, f, flen); 567 c = (cert != NULL); 568 io_simple_buffer(b, &c, sizeof(int)); 569 if (cert != NULL) 570 cert_buffer(b, cert); 571 /* 572 * The parsed certificate data "cert" is now 573 * managed in the "auths" table, so don't free 574 * it here. 575 */ 576 break; 577 case RTYPE_CRL: 578 /* 579 * CRLs are already loaded with the MFT so nothing 580 * really needs to be done here. 581 */ 582 file = parse_filepath(entp->repoid, entp->path, 583 entp->file, entp->location); 584 io_str_buffer(b, file); 585 break; 586 case RTYPE_MFT: 587 file = proc_parser_mft(entp, &mft); 588 io_str_buffer(b, file); 589 c = (mft != NULL); 590 io_simple_buffer(b, &c, sizeof(int)); 591 if (mft != NULL) 592 mft_buffer(b, mft); 593 mft_free(mft); 594 break; 595 case RTYPE_ROA: 596 file = parse_load_file(entp, &f, &flen); 597 io_str_buffer(b, file); 598 roa = proc_parser_roa(file, f, flen); 599 c = (roa != NULL); 600 io_simple_buffer(b, &c, sizeof(int)); 601 if (roa != NULL) 602 roa_buffer(b, roa); 603 roa_free(roa); 604 break; 605 case RTYPE_GBR: 606 file = parse_load_file(entp, &f, &flen); 607 io_str_buffer(b, file); 608 proc_parser_gbr(file, f, flen); 609 break; 610 default: 611 errx(1, "unhandled entity type %d", entp->type); 612 } 613 614 free(f); 615 free(file); 616 io_close_buffer(msgq, b); 617 entity_free(entp); 618 } 619 } 620 621 /* 622 * Process responsible for parsing and validating content. 623 * All this process does is wait to be told about a file to parse, then 624 * it parses it and makes sure that the data being returned is fully 625 * validated and verified. 626 * The process will exit cleanly only when fd is closed. 627 */ 628 void 629 proc_parser(int fd) 630 { 631 struct entityq q; 632 struct msgbuf msgq; 633 struct pollfd pfd; 634 struct entity *entp; 635 struct ibuf *b, *inbuf = NULL; 636 637 /* Only allow access to the cache directory. */ 638 if (unveil(".", "r") == -1) 639 err(1, "unveil cachedir"); 640 if (pledge("stdio rpath", NULL) == -1) 641 err(1, "pledge"); 642 643 ERR_load_crypto_strings(); 644 OpenSSL_add_all_ciphers(); 645 OpenSSL_add_all_digests(); 646 x509_init_oid(); 647 648 if ((ctx = X509_STORE_CTX_new()) == NULL) 649 cryptoerrx("X509_STORE_CTX_new"); 650 651 TAILQ_INIT(&q); 652 653 msgbuf_init(&msgq); 654 msgq.fd = fd; 655 656 pfd.fd = fd; 657 658 for (;;) { 659 pfd.events = POLLIN; 660 if (msgq.queued) 661 pfd.events |= POLLOUT; 662 663 if (poll(&pfd, 1, INFTIM) == -1) { 664 if (errno == EINTR) 665 continue; 666 err(1, "poll"); 667 } 668 if ((pfd.revents & (POLLERR|POLLNVAL))) 669 errx(1, "poll: bad descriptor"); 670 671 /* If the parent closes, return immediately. */ 672 673 if ((pfd.revents & POLLHUP)) 674 break; 675 676 if ((pfd.revents & POLLIN)) { 677 b = io_buf_read(fd, &inbuf); 678 if (b != NULL) { 679 entp = calloc(1, sizeof(struct entity)); 680 if (entp == NULL) 681 err(1, NULL); 682 entity_read_req(b, entp); 683 TAILQ_INSERT_TAIL(&q, entp, entries); 684 ibuf_free(b); 685 } 686 } 687 688 if (pfd.revents & POLLOUT) { 689 switch (msgbuf_write(&msgq)) { 690 case 0: 691 errx(1, "write: connection closed"); 692 case -1: 693 err(1, "write"); 694 } 695 } 696 697 parse_entity(&q, &msgq); 698 } 699 700 while ((entp = TAILQ_FIRST(&q)) != NULL) { 701 TAILQ_REMOVE(&q, entp, entries); 702 entity_free(entp); 703 } 704 705 /* XXX free auths and crl tree */ 706 707 X509_STORE_CTX_free(ctx); 708 msgbuf_clear(&msgq); 709 710 exit(0); 711 } 712