1 /* $OpenBSD: parser.c,v 1.143 2024/08/29 13:46:28 tb 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 <err.h> 24 #include <fcntl.h> 25 #include <poll.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <limits.h> 30 #include <unistd.h> 31 #include <imsg.h> 32 33 #include <openssl/asn1.h> 34 #include <openssl/err.h> 35 #include <openssl/evp.h> 36 #include <openssl/x509.h> 37 #include <openssl/x509v3.h> 38 39 #include "extern.h" 40 41 extern int certid; 42 43 static X509_STORE_CTX *ctx; 44 static struct auth_tree auths = RB_INITIALIZER(&auths); 45 static struct crl_tree crlt = RB_INITIALIZER(&crlt); 46 47 struct parse_repo { 48 RB_ENTRY(parse_repo) entry; 49 char *path; 50 char *validpath; 51 unsigned int id; 52 }; 53 54 static RB_HEAD(repo_tree, parse_repo) repos = RB_INITIALIZER(&repos); 55 56 static inline int 57 repocmp(struct parse_repo *a, struct parse_repo *b) 58 { 59 return a->id - b->id; 60 } 61 62 RB_GENERATE_STATIC(repo_tree, parse_repo, entry, repocmp); 63 64 static struct parse_repo * 65 repo_get(unsigned int id) 66 { 67 struct parse_repo needle = { .id = id }; 68 69 return RB_FIND(repo_tree, &repos, &needle); 70 } 71 72 static void 73 repo_add(unsigned int id, char *path, char *validpath) 74 { 75 struct parse_repo *rp; 76 77 if ((rp = calloc(1, sizeof(*rp))) == NULL) 78 err(1, NULL); 79 rp->id = id; 80 if (path != NULL) 81 if ((rp->path = strdup(path)) == NULL) 82 err(1, NULL); 83 if (validpath != NULL) 84 if ((rp->validpath = strdup(validpath)) == NULL) 85 err(1, NULL); 86 87 if (RB_INSERT(repo_tree, &repos, rp) != NULL) 88 errx(1, "repository already added: id %d, %s", id, path); 89 } 90 91 /* 92 * Return the issuer by its certificate id, or NULL on failure. 93 * Make sure the AKI is the same as the AKI listed on the Manifest, 94 * and that the SKI of the cert matches with the AKI. 95 */ 96 static struct auth * 97 find_issuer(const char *fn, int id, const char *aki, const char *mftaki) 98 { 99 struct auth *a; 100 101 a = auth_find(&auths, id); 102 if (a == NULL) { 103 if (certid <= CERTID_MAX) 104 warnx("%s: RFC 6487: unknown cert with SKI %s", fn, 105 aki); 106 return NULL; 107 } 108 109 if (mftaki != NULL) { 110 if (strcmp(aki, mftaki) != 0) { 111 warnx("%s: AKI %s doesn't match Manifest AKI %s", fn, 112 aki, mftaki); 113 return NULL; 114 } 115 } 116 117 if (strcmp(aki, a->cert->ski) != 0) { 118 warnx("%s: AKI %s doesn't match issuer SKI %s", fn, 119 aki, a->cert->ski); 120 return NULL; 121 } 122 123 return a; 124 } 125 126 /* 127 * Build access path to file based on repoid, path, location and file values. 128 */ 129 static char * 130 parse_filepath(unsigned int repoid, const char *path, const char *file, 131 enum location loc) 132 { 133 struct parse_repo *rp; 134 char *fn, *repopath; 135 136 /* build file path based on repoid, entity path and filename */ 137 rp = repo_get(repoid); 138 if (rp == NULL) 139 errx(1, "build file path: repository %u missing", repoid); 140 141 if (loc == DIR_VALID) 142 repopath = rp->validpath; 143 else 144 repopath = rp->path; 145 146 if (repopath == NULL) 147 return NULL; 148 149 if (path == NULL) { 150 if (asprintf(&fn, "%s/%s", repopath, file) == -1) 151 err(1, NULL); 152 } else { 153 if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1) 154 err(1, NULL); 155 } 156 return fn; 157 } 158 159 /* 160 * Parse and validate a ROA. 161 * This is standard stuff. 162 * Returns the roa on success, NULL on failure. 163 */ 164 static struct roa * 165 proc_parser_roa(char *file, const unsigned char *der, size_t len, 166 const struct entity *entp) 167 { 168 struct roa *roa; 169 X509 *x509 = NULL; 170 struct auth *a; 171 struct crl *crl; 172 const char *errstr; 173 174 if ((roa = roa_parse(&x509, file, entp->talid, der, len)) == NULL) 175 goto out; 176 177 a = find_issuer(file, entp->certid, roa->aki, entp->mftaki); 178 if (a == NULL) 179 goto out; 180 crl = crl_get(&crlt, a); 181 182 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 183 warnx("%s: %s", file, errstr); 184 goto out; 185 } 186 X509_free(x509); 187 x509 = NULL; 188 189 roa->talid = a->cert->talid; 190 191 roa->expires = x509_find_expires(roa->notafter, a, &crlt); 192 193 return roa; 194 195 out: 196 roa_free(roa); 197 X509_free(x509); 198 199 return NULL; 200 } 201 202 /* 203 * Parse and validate a draft-ietf-sidrops-rpki-prefixlist SPL. 204 * Returns the spl on success, NULL on failure. 205 */ 206 static struct spl * 207 proc_parser_spl(char *file, const unsigned char *der, size_t len, 208 const struct entity *entp) 209 { 210 struct spl *spl; 211 X509 *x509 = NULL; 212 struct auth *a; 213 struct crl *crl; 214 const char *errstr; 215 216 if ((spl = spl_parse(&x509, file, entp->talid, der, len)) == NULL) 217 goto out; 218 219 a = find_issuer(file, entp->certid, spl->aki, entp->mftaki); 220 if (a == NULL) 221 goto out; 222 crl = crl_get(&crlt, a); 223 224 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 225 warnx("%s: %s", file, errstr); 226 goto out; 227 } 228 X509_free(x509); 229 x509 = NULL; 230 231 spl->talid = a->cert->talid; 232 233 spl->expires = x509_find_expires(spl->notafter, a, &crlt); 234 235 return spl; 236 237 out: 238 spl_free(spl); 239 X509_free(x509); 240 241 return NULL; 242 } 243 244 /* 245 * Check all files and their hashes in a MFT structure. 246 * Return zero on failure, non-zero on success. 247 */ 248 static int 249 proc_parser_mft_check(const char *fn, struct mft *p) 250 { 251 const enum location loc[2] = { DIR_TEMP, DIR_VALID }; 252 size_t i; 253 int rc = 1; 254 char *path; 255 256 if (p == NULL) 257 return 0; 258 259 for (i = 0; i < p->filesz; i++) { 260 struct mftfile *m = &p->files[i]; 261 int try, fd = -1, noent = 0, valid = 0; 262 for (try = 0; try < 2 && !valid; try++) { 263 if ((path = parse_filepath(p->repoid, p->path, m->file, 264 loc[try])) == NULL) 265 continue; 266 fd = open(path, O_RDONLY); 267 if (fd == -1 && errno == ENOENT) 268 noent++; 269 free(path); 270 271 /* remember which path was checked */ 272 m->location = loc[try]; 273 valid = valid_filehash(fd, m->hash, sizeof(m->hash)); 274 } 275 276 if (!valid) { 277 /* silently skip not-existing unknown files */ 278 if (m->type == RTYPE_INVALID && noent == 2) 279 continue; 280 warnx("%s#%s: bad message digest for %s", fn, 281 p->seqnum, m->file); 282 rc = 0; 283 continue; 284 } 285 } 286 287 return rc; 288 } 289 290 /* 291 * Load the CRL from loc using the info from the MFT. 292 */ 293 static struct crl * 294 parse_load_crl_from_mft(struct entity *entp, struct mft *mft, enum location loc, 295 char **crlfile) 296 { 297 struct crl *crl = NULL; 298 unsigned char *f = NULL; 299 char *fn = NULL; 300 size_t flen; 301 302 *crlfile = NULL; 303 304 fn = parse_filepath(entp->repoid, entp->path, mft->crl, loc); 305 if (fn == NULL) 306 goto out; 307 308 f = load_file(fn, &flen); 309 if (f == NULL) { 310 if (errno != ENOENT) 311 warn("parse file %s", fn); 312 goto out; 313 } 314 315 if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash))) 316 goto out; 317 318 crl = crl_parse(fn, f, flen); 319 if (crl == NULL) 320 goto out; 321 322 if (strcmp(crl->aki, mft->aki) != 0) { 323 warnx("%s: AKI doesn't match Manifest AKI", fn); 324 goto out; 325 } 326 327 if ((crl->mftpath = strdup(mft->sia)) == NULL) 328 err(1, NULL); 329 330 *crlfile = fn; 331 free(f); 332 333 return crl; 334 335 out: 336 crl_free(crl); 337 free(f); 338 free(fn); 339 340 return NULL; 341 } 342 343 /* 344 * Parse and validate a manifest file. 345 * Don't check the fileandhash, this is done later on. 346 * Return the mft on success, or NULL on failure. 347 */ 348 static struct mft * 349 proc_parser_mft_pre(struct entity *entp, char *file, struct crl **crl, 350 char **crlfile, struct mft *cached_mft, const char **errstr) 351 { 352 struct mft *mft; 353 X509 *x509; 354 struct auth *a; 355 unsigned char *der; 356 size_t len; 357 time_t now; 358 int issued_cmp, seqnum_cmp; 359 360 *crl = NULL; 361 *crlfile = NULL; 362 *errstr = NULL; 363 364 if (file == NULL) 365 return NULL; 366 367 der = load_file(file, &len); 368 if (der == NULL && errno != ENOENT) 369 warn("parse file %s", file); 370 371 if ((mft = mft_parse(&x509, file, entp->talid, der, len)) == NULL) { 372 free(der); 373 return NULL; 374 } 375 376 if (entp->path != NULL) { 377 if ((mft->path = strdup(entp->path)) == NULL) 378 err(1, NULL); 379 } 380 381 if (!EVP_Digest(der, len, mft->mfthash, NULL, EVP_sha256(), NULL)) 382 errx(1, "EVP_Digest failed"); 383 384 free(der); 385 386 *crl = parse_load_crl_from_mft(entp, mft, DIR_TEMP, crlfile); 387 if (*crl == NULL) 388 *crl = parse_load_crl_from_mft(entp, mft, DIR_VALID, crlfile); 389 390 a = find_issuer(file, entp->certid, mft->aki, NULL); 391 if (a == NULL) 392 goto err; 393 if (!valid_x509(file, ctx, x509, a, *crl, errstr)) 394 goto err; 395 X509_free(x509); 396 x509 = NULL; 397 398 mft->repoid = entp->repoid; 399 mft->talid = a->cert->talid; 400 mft->certid = entp->certid; 401 402 now = get_current_time(); 403 /* check that now is not before from */ 404 if (now < mft->thisupdate) { 405 warnx("%s: manifest not yet valid %s", file, 406 time2str(mft->thisupdate)); 407 goto err; 408 } 409 /* check that now is not after until */ 410 if (now > mft->nextupdate) { 411 warnx("%s: manifest expired on %s", file, 412 time2str(mft->nextupdate)); 413 goto err; 414 } 415 416 /* if there is nothing to compare to, return now */ 417 if (cached_mft == NULL) 418 return mft; 419 420 /* 421 * Check that the cached manifest is older in the sense that it was 422 * issued earlier and that it has a smaller sequence number. 423 */ 424 425 if ((issued_cmp = mft_compare_issued(mft, cached_mft)) < 0) { 426 warnx("%s: unexpected manifest issuance date (want >= %lld, " 427 "got %lld)", file, (long long)cached_mft->thisupdate, 428 (long long)mft->thisupdate); 429 goto err; 430 } 431 if ((seqnum_cmp = mft_compare_seqnum(mft, cached_mft)) < 0) { 432 warnx("%s: unexpected manifest number (want >= #%s, got #%s)", 433 file, cached_mft->seqnum, mft->seqnum); 434 goto err; 435 } 436 if (issued_cmp > 0 && seqnum_cmp == 0) { 437 warnx("%s: manifest issued at %lld and %lld with same " 438 "manifest number #%s", file, (long long)mft->thisupdate, 439 (long long)cached_mft->thisupdate, cached_mft->seqnum); 440 goto err; 441 } 442 if (issued_cmp == 0 && seqnum_cmp > 0) { 443 warnx("%s: #%s and #%s were issued at same issuance date %lld", 444 file, mft->seqnum, cached_mft->seqnum, 445 (long long)mft->thisupdate); 446 goto err; 447 } 448 if (issued_cmp == 0 && seqnum_cmp == 0 && memcmp(mft->mfthash, 449 cached_mft->mfthash, SHA256_DIGEST_LENGTH) != 0) { 450 warnx("%s: misissuance, issuance date %lld and manifest number " 451 "#%s were recycled", file, (long long)mft->thisupdate, 452 mft->seqnum); 453 goto err; 454 } 455 456 return mft; 457 458 err: 459 X509_free(x509); 460 mft_free(mft); 461 crl_free(*crl); 462 *crl = NULL; 463 free(*crlfile); 464 *crlfile = NULL; 465 return NULL; 466 } 467 468 /* 469 * Load the most recent MFT by opening both options and comparing the two. 470 */ 471 static char * 472 proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile, 473 time_t *crlmtime) 474 { 475 struct mft *mft1 = NULL, *mft2 = NULL; 476 struct crl *crl, *crl1 = NULL, *crl2 = NULL; 477 char *file, *file1 = NULL, *file2 = NULL; 478 char *crl1file = NULL, *crl2file = NULL; 479 const char *err1 = NULL, *err2 = NULL; 480 481 *mp = NULL; 482 *crlmtime = 0; 483 484 file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID); 485 mft2 = proc_parser_mft_pre(entp, file2, &crl2, &crl2file, NULL, &err2); 486 487 if (!noop) { 488 file1 = parse_filepath(entp->repoid, entp->path, entp->file, 489 DIR_TEMP); 490 mft1 = proc_parser_mft_pre(entp, file1, &crl1, &crl1file, mft2, 491 &err1); 492 } 493 494 if (proc_parser_mft_check(file1, mft1)) { 495 mft_free(mft2); 496 crl_free(crl2); 497 free(crl2file); 498 free(file2); 499 500 *mp = mft1; 501 crl = crl1; 502 file = file1; 503 *crlfile = crl1file; 504 } else { 505 if (mft1 != NULL && mft2 != NULL) 506 warnx("%s: failed fetch, continuing with #%s " 507 "from cache", file2, mft2->seqnum); 508 509 if (!proc_parser_mft_check(file2, mft2)) { 510 mft_free(mft2); 511 mft2 = NULL; 512 513 if (err2 == NULL) 514 err2 = err1; 515 if (err2 == NULL) 516 err2 = "no valid manifest available"; 517 if (certid <= CERTID_MAX) 518 warnx("%s: %s", file2, err2); 519 } 520 521 mft_free(mft1); 522 crl_free(crl1); 523 free(crl1file); 524 free(file1); 525 526 *mp = mft2; 527 crl = crl2; 528 file = file2; 529 *crlfile = crl2file; 530 } 531 532 if (*mp != NULL) { 533 *crlmtime = crl->thisupdate; 534 if (crl_insert(&crlt, crl)) 535 crl = NULL; 536 } 537 crl_free(crl); 538 539 return file; 540 } 541 542 /* 543 * Certificates are from manifests (has a digest and is signed with 544 * another certificate) Parse the certificate, make sure its 545 * signatures are valid (with CRLs), then validate the RPKI content. 546 * This returns a certificate (which must not be freed) or NULL on 547 * parse failure. 548 */ 549 static struct cert * 550 proc_parser_cert(char *file, const unsigned char *der, size_t len, 551 const struct entity *entp) 552 { 553 struct cert *cert; 554 struct crl *crl; 555 struct auth *a; 556 const char *errstr = NULL; 557 558 /* Extract certificate data. */ 559 560 cert = cert_parse_pre(file, der, len); 561 cert = cert_parse(file, cert); 562 if (cert == NULL) 563 goto out; 564 565 a = find_issuer(file, entp->certid, cert->aki, entp->mftaki); 566 if (a == NULL) 567 goto out; 568 crl = crl_get(&crlt, a); 569 570 if (!valid_x509(file, ctx, cert->x509, a, crl, &errstr) || 571 !valid_cert(file, a, cert)) { 572 if (errstr != NULL) 573 warnx("%s: %s", file, errstr); 574 goto out; 575 } 576 577 cert->talid = a->cert->talid; 578 579 if (cert->purpose == CERT_PURPOSE_BGPSEC_ROUTER) { 580 if (!constraints_validate(file, cert)) 581 goto out; 582 } 583 584 /* 585 * Add validated CA certs to the RPKI auth tree. 586 */ 587 if (cert->purpose == CERT_PURPOSE_CA) 588 auth_insert(file, &auths, cert, a); 589 590 return cert; 591 592 out: 593 cert_free(cert); 594 595 return NULL; 596 } 597 598 static int 599 proc_parser_ta_cmp(const struct cert *cert1, const struct cert *cert2) 600 { 601 if (cert1 == NULL) 602 return -1; 603 if (cert2 == NULL) 604 return 1; 605 606 /* 607 * The standards don't specify tiebreakers. While RFC 6487 and other 608 * sources advise against backdating, it's explicitly allowed and some 609 * TAs do. Some TAs have also re-issued with new dates and old 610 * serialNumber. 611 * Our tiebreaker logic: a more recent notBefore is taken to mean a 612 * more recent issuance, and thus preferable. Given equal notBefore 613 * values, prefer the TA cert with the narrower validity window. This 614 * hopefully encourages TA operators to reduce egregiously long TA 615 * validity periods. 616 */ 617 618 if (cert1->notbefore < cert2->notbefore) 619 return -1; 620 if (cert1->notbefore > cert2->notbefore) 621 return 1; 622 623 if (cert1->notafter > cert2->notafter) 624 return -1; 625 if (cert1->notafter < cert2->notafter) 626 return 1; 627 628 /* 629 * Both certs are valid from our perspective. If anything changed, 630 * prefer the freshly-fetched one. We rely on cert_parse_pre() having 631 * cached the extensions and thus libcrypto has already computed the 632 * certs' hashes (SHA-1 for OpenSSL, SHA-512 for LibreSSL). The below 633 * compares them. 634 */ 635 636 return X509_cmp(cert1->x509, cert2->x509) != 0; 637 } 638 639 /* 640 * Root certificates come from TALs. Inspect and validate both options and 641 * compare the two. The cert in out_cert must not be freed. Returns the file 642 * name of the chosen TA. 643 */ 644 static char * 645 proc_parser_root_cert(struct entity *entp, struct cert **out_cert) 646 { 647 struct cert *cert1 = NULL, *cert2 = NULL; 648 char *file1 = NULL, *file2 = NULL; 649 unsigned char *der = NULL, *pkey = entp->data; 650 size_t der_len = 0, pkeysz = entp->datasz; 651 int cmp; 652 653 *out_cert = NULL; 654 655 file2 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID); 656 der = load_file(file2, &der_len); 657 cert2 = cert_parse_pre(file2, der, der_len); 658 free(der); 659 cert2 = ta_parse(file2, cert2, pkey, pkeysz); 660 661 if (!noop) { 662 file1 = parse_filepath(entp->repoid, entp->path, entp->file, 663 DIR_TEMP); 664 der = load_file(file1, &der_len); 665 cert1 = cert_parse_pre(file1, der, der_len); 666 free(der); 667 cert1 = ta_parse(file1, cert1, pkey, pkeysz); 668 } 669 670 if ((cmp = proc_parser_ta_cmp(cert1, cert2)) > 0) { 671 cert_free(cert2); 672 free(file2); 673 674 cert1->talid = entp->talid; 675 auth_insert(file1, &auths, cert1, NULL); 676 677 *out_cert = cert1; 678 return file1; 679 } else { 680 if (cmp < 0 && cert1 != NULL && cert2 != NULL) 681 warnx("%s: cached TA is newer", entp->file); 682 cert_free(cert1); 683 free(file1); 684 685 if (cert2 != 0) { 686 cert2->talid = entp->talid; 687 auth_insert(file2, &auths, cert2, NULL); 688 } 689 690 *out_cert = cert2; 691 return file2; 692 } 693 } 694 695 /* 696 * Parse a ghostbuster record 697 */ 698 static struct gbr * 699 proc_parser_gbr(char *file, const unsigned char *der, size_t len, 700 const struct entity *entp) 701 { 702 struct gbr *gbr; 703 X509 *x509 = NULL; 704 struct crl *crl; 705 struct auth *a; 706 const char *errstr; 707 708 if ((gbr = gbr_parse(&x509, file, entp->talid, der, len)) == NULL) 709 goto out; 710 711 a = find_issuer(file, entp->certid, gbr->aki, entp->mftaki); 712 if (a == NULL) 713 goto out; 714 crl = crl_get(&crlt, a); 715 716 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 717 warnx("%s: %s", file, errstr); 718 goto out; 719 } 720 X509_free(x509); 721 x509 = NULL; 722 723 gbr->talid = a->cert->talid; 724 725 return gbr; 726 727 out: 728 gbr_free(gbr); 729 X509_free(x509); 730 731 return NULL; 732 } 733 734 /* 735 * Parse an ASPA object 736 */ 737 static struct aspa * 738 proc_parser_aspa(char *file, const unsigned char *der, size_t len, 739 const struct entity *entp) 740 { 741 struct aspa *aspa; 742 X509 *x509 = NULL; 743 struct auth *a; 744 struct crl *crl; 745 const char *errstr; 746 747 if ((aspa = aspa_parse(&x509, file, entp->talid, der, len)) == NULL) 748 goto out; 749 750 a = find_issuer(file, entp->certid, aspa->aki, entp->mftaki); 751 if (a == NULL) 752 goto out; 753 crl = crl_get(&crlt, a); 754 755 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 756 warnx("%s: %s", file, errstr); 757 goto out; 758 } 759 X509_free(x509); 760 x509 = NULL; 761 762 aspa->talid = a->cert->talid; 763 764 aspa->expires = x509_find_expires(aspa->notafter, a, &crlt); 765 766 return aspa; 767 768 out: 769 aspa_free(aspa); 770 X509_free(x509); 771 772 return NULL; 773 } 774 775 /* 776 * Parse a TAK object. 777 */ 778 static struct tak * 779 proc_parser_tak(char *file, const unsigned char *der, size_t len, 780 const struct entity *entp) 781 { 782 struct tak *tak; 783 X509 *x509 = NULL; 784 struct crl *crl; 785 struct auth *a; 786 const char *errstr; 787 788 if ((tak = tak_parse(&x509, file, entp->talid, der, len)) == NULL) 789 goto out; 790 791 a = find_issuer(file, entp->certid, tak->aki, entp->mftaki); 792 if (a == NULL) 793 goto out; 794 crl = crl_get(&crlt, a); 795 796 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 797 warnx("%s: %s", file, errstr); 798 goto out; 799 } 800 X509_free(x509); 801 x509 = NULL; 802 803 /* TAK EE must be signed by self-signed CA */ 804 if (a->issuer != NULL) 805 goto out; 806 807 tak->talid = a->cert->talid; 808 809 return tak; 810 811 out: 812 tak_free(tak); 813 X509_free(x509); 814 815 return NULL; 816 } 817 818 /* 819 * Load the file specified by the entity information. 820 */ 821 static char * 822 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen) 823 { 824 char *file; 825 826 file = parse_filepath(entp->repoid, entp->path, entp->file, 827 entp->location); 828 if (file == NULL) 829 errx(1, "no path to file"); 830 831 *f = load_file(file, flen); 832 if (*f == NULL) 833 warn("parse file %s", file); 834 835 return file; 836 } 837 838 /* 839 * Process an entity and respond to parent process. 840 */ 841 static void 842 parse_entity(struct entityq *q, struct msgbuf *msgq) 843 { 844 struct entity *entp; 845 struct tal *tal; 846 struct cert *cert; 847 struct mft *mft; 848 struct roa *roa; 849 struct aspa *aspa; 850 struct gbr *gbr; 851 struct tak *tak; 852 struct spl *spl; 853 struct ibuf *b; 854 unsigned char *f; 855 time_t mtime, crlmtime; 856 size_t flen; 857 char *file, *crlfile; 858 int c; 859 860 while ((entp = TAILQ_FIRST(q)) != NULL) { 861 TAILQ_REMOVE(q, entp, entries); 862 863 /* handle RTYPE_REPO first */ 864 if (entp->type == RTYPE_REPO) { 865 repo_add(entp->repoid, entp->path, entp->file); 866 entity_free(entp); 867 continue; 868 } 869 870 /* pass back at least type, repoid and filename */ 871 b = io_new_buffer(); 872 io_simple_buffer(b, &entp->type, sizeof(entp->type)); 873 io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid)); 874 io_simple_buffer(b, &entp->talid, sizeof(entp->talid)); 875 876 file = NULL; 877 f = NULL; 878 mtime = 0; 879 crlmtime = 0; 880 881 switch (entp->type) { 882 case RTYPE_TAL: 883 io_str_buffer(b, entp->file); 884 io_simple_buffer(b, &mtime, sizeof(mtime)); 885 if ((tal = tal_parse(entp->file, entp->data, 886 entp->datasz)) == NULL) 887 errx(1, "%s: could not parse tal file", 888 entp->file); 889 tal->id = entp->talid; 890 tal_buffer(b, tal); 891 tal_free(tal); 892 break; 893 case RTYPE_CER: 894 if (entp->data != NULL) { 895 file = proc_parser_root_cert(entp, &cert); 896 } else { 897 file = parse_load_file(entp, &f, &flen); 898 cert = proc_parser_cert(file, f, flen, entp); 899 } 900 io_str_buffer(b, file); 901 if (cert != NULL) 902 mtime = cert->notbefore; 903 io_simple_buffer(b, &mtime, sizeof(mtime)); 904 c = (cert != NULL); 905 io_simple_buffer(b, &c, sizeof(int)); 906 if (cert != NULL) { 907 cert->repoid = entp->repoid; 908 cert_buffer(b, cert); 909 } 910 /* 911 * The parsed certificate data "cert" is now 912 * managed in the "auths" table, so don't free 913 * it here. 914 */ 915 break; 916 case RTYPE_MFT: 917 file = proc_parser_mft(entp, &mft, &crlfile, &crlmtime); 918 io_str_buffer(b, file); 919 if (mft != NULL) 920 mtime = mft->signtime; 921 io_simple_buffer(b, &mtime, sizeof(mtime)); 922 c = (mft != NULL); 923 io_simple_buffer(b, &c, sizeof(int)); 924 if (mft != NULL) 925 mft_buffer(b, mft); 926 927 /* Push valid CRL together with the MFT. */ 928 if (crlfile != NULL) { 929 enum rtype type; 930 struct ibuf *b2; 931 932 b2 = io_new_buffer(); 933 type = RTYPE_CRL; 934 io_simple_buffer(b2, &type, sizeof(type)); 935 io_simple_buffer(b2, &entp->repoid, 936 sizeof(entp->repoid)); 937 io_simple_buffer(b2, &entp->talid, 938 sizeof(entp->talid)); 939 io_str_buffer(b2, crlfile); 940 io_simple_buffer(b2, &crlmtime, 941 sizeof(crlmtime)); 942 free(crlfile); 943 944 io_close_buffer(msgq, b2); 945 } 946 mft_free(mft); 947 break; 948 case RTYPE_ROA: 949 file = parse_load_file(entp, &f, &flen); 950 io_str_buffer(b, file); 951 roa = proc_parser_roa(file, f, flen, entp); 952 if (roa != NULL) 953 mtime = roa->signtime; 954 io_simple_buffer(b, &mtime, sizeof(mtime)); 955 c = (roa != NULL); 956 io_simple_buffer(b, &c, sizeof(int)); 957 if (roa != NULL) 958 roa_buffer(b, roa); 959 roa_free(roa); 960 break; 961 case RTYPE_GBR: 962 file = parse_load_file(entp, &f, &flen); 963 io_str_buffer(b, file); 964 gbr = proc_parser_gbr(file, f, flen, entp); 965 if (gbr != NULL) 966 mtime = gbr->signtime; 967 io_simple_buffer(b, &mtime, sizeof(mtime)); 968 gbr_free(gbr); 969 break; 970 case RTYPE_ASPA: 971 file = parse_load_file(entp, &f, &flen); 972 io_str_buffer(b, file); 973 aspa = proc_parser_aspa(file, f, flen, entp); 974 if (aspa != NULL) 975 mtime = aspa->signtime; 976 io_simple_buffer(b, &mtime, sizeof(mtime)); 977 c = (aspa != NULL); 978 io_simple_buffer(b, &c, sizeof(int)); 979 if (aspa != NULL) 980 aspa_buffer(b, aspa); 981 aspa_free(aspa); 982 break; 983 case RTYPE_TAK: 984 file = parse_load_file(entp, &f, &flen); 985 io_str_buffer(b, file); 986 tak = proc_parser_tak(file, f, flen, entp); 987 if (tak != NULL) 988 mtime = tak->signtime; 989 io_simple_buffer(b, &mtime, sizeof(mtime)); 990 tak_free(tak); 991 break; 992 case RTYPE_SPL: 993 file = parse_load_file(entp, &f, &flen); 994 io_str_buffer(b, file); 995 if (experimental) { 996 spl = proc_parser_spl(file, f, flen, entp); 997 if (spl != NULL) 998 mtime = spl->signtime; 999 } else { 1000 if (verbose > 0) 1001 warnx("%s: skipped", file); 1002 spl = NULL; 1003 } 1004 io_simple_buffer(b, &mtime, sizeof(mtime)); 1005 c = (spl != NULL); 1006 io_simple_buffer(b, &c, sizeof(int)); 1007 if (spl != NULL) 1008 spl_buffer(b, spl); 1009 spl_free(spl); 1010 break; 1011 case RTYPE_CRL: 1012 default: 1013 file = parse_filepath(entp->repoid, entp->path, 1014 entp->file, entp->location); 1015 io_str_buffer(b, file); 1016 io_simple_buffer(b, &mtime, sizeof(mtime)); 1017 warnx("%s: unhandled type %d", file, entp->type); 1018 break; 1019 } 1020 1021 free(f); 1022 free(file); 1023 io_close_buffer(msgq, b); 1024 entity_free(entp); 1025 } 1026 } 1027 1028 /* 1029 * Process responsible for parsing and validating content. 1030 * All this process does is wait to be told about a file to parse, then 1031 * it parses it and makes sure that the data being returned is fully 1032 * validated and verified. 1033 * The process will exit cleanly only when fd is closed. 1034 */ 1035 void 1036 proc_parser(int fd) 1037 { 1038 struct entityq q; 1039 struct msgbuf msgq; 1040 struct pollfd pfd; 1041 struct entity *entp; 1042 struct ibuf *b, *inbuf = NULL; 1043 1044 /* Only allow access to the cache directory. */ 1045 if (unveil(".", "r") == -1) 1046 err(1, "unveil cachedir"); 1047 if (pledge("stdio rpath", NULL) == -1) 1048 err(1, "pledge"); 1049 1050 ERR_load_crypto_strings(); 1051 OpenSSL_add_all_ciphers(); 1052 OpenSSL_add_all_digests(); 1053 x509_init_oid(); 1054 constraints_parse(); 1055 1056 if ((ctx = X509_STORE_CTX_new()) == NULL) 1057 err(1, "X509_STORE_CTX_new"); 1058 1059 TAILQ_INIT(&q); 1060 1061 msgbuf_init(&msgq); 1062 msgq.fd = fd; 1063 1064 pfd.fd = fd; 1065 1066 for (;;) { 1067 pfd.events = POLLIN; 1068 if (msgbuf_queuelen(&msgq) > 0) 1069 pfd.events |= POLLOUT; 1070 1071 if (poll(&pfd, 1, INFTIM) == -1) { 1072 if (errno == EINTR) 1073 continue; 1074 err(1, "poll"); 1075 } 1076 if ((pfd.revents & (POLLERR|POLLNVAL))) 1077 errx(1, "poll: bad descriptor"); 1078 1079 /* If the parent closes, return immediately. */ 1080 1081 if ((pfd.revents & POLLHUP)) 1082 break; 1083 1084 if ((pfd.revents & POLLIN)) { 1085 b = io_buf_read(fd, &inbuf); 1086 if (b != NULL) { 1087 entp = calloc(1, sizeof(struct entity)); 1088 if (entp == NULL) 1089 err(1, NULL); 1090 entity_read_req(b, entp); 1091 TAILQ_INSERT_TAIL(&q, entp, entries); 1092 ibuf_free(b); 1093 } 1094 } 1095 1096 if (pfd.revents & POLLOUT) { 1097 switch (msgbuf_write(&msgq)) { 1098 case 0: 1099 errx(1, "write: connection closed"); 1100 case -1: 1101 err(1, "write"); 1102 } 1103 } 1104 1105 parse_entity(&q, &msgq); 1106 } 1107 1108 while ((entp = TAILQ_FIRST(&q)) != NULL) { 1109 TAILQ_REMOVE(&q, entp, entries); 1110 entity_free(entp); 1111 } 1112 1113 auth_tree_free(&auths); 1114 crl_tree_free(&crlt); 1115 1116 X509_STORE_CTX_free(ctx); 1117 msgbuf_clear(&msgq); 1118 1119 ibuf_free(inbuf); 1120 1121 if (certid > CERTID_MAX) 1122 errx(1, "processing incomplete: too many certificates"); 1123 1124 exit(0); 1125 } 1126