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