1 /* $OpenBSD: parser.c,v 1.96 2023/05/30 16:02:28 job 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 static X509_STORE_CTX *ctx; 42 static struct auth_tree auths = RB_INITIALIZER(&auths); 43 static struct crl_tree crlt = RB_INITIALIZER(&crlt); 44 45 struct parse_repo { 46 RB_ENTRY(parse_repo) entry; 47 char *path; 48 char *validpath; 49 unsigned int id; 50 }; 51 52 static RB_HEAD(repo_tree, parse_repo) repos = RB_INITIALIZER(&repos); 53 54 static inline int 55 repocmp(struct parse_repo *a, struct parse_repo *b) 56 { 57 return a->id - b->id; 58 } 59 60 RB_GENERATE_STATIC(repo_tree, parse_repo, entry, repocmp); 61 62 static struct parse_repo * 63 repo_get(unsigned int id) 64 { 65 struct parse_repo needle = { .id = id }; 66 67 return RB_FIND(repo_tree, &repos, &needle); 68 } 69 70 static void 71 repo_add(unsigned int id, char *path, char *validpath) 72 { 73 struct parse_repo *rp; 74 75 if ((rp = calloc(1, sizeof(*rp))) == NULL) 76 err(1, NULL); 77 rp->id = id; 78 if (path != NULL) 79 if ((rp->path = strdup(path)) == NULL) 80 err(1, NULL); 81 if (validpath != NULL) 82 if ((rp->validpath = strdup(validpath)) == NULL) 83 err(1, NULL); 84 85 if (RB_INSERT(repo_tree, &repos, rp) != NULL) 86 errx(1, "repository already added: id %d, %s", id, path); 87 } 88 89 /* 90 * Build access path to file based on repoid, path, location and file values. 91 */ 92 static char * 93 parse_filepath(unsigned int repoid, const char *path, const char *file, 94 enum location loc) 95 { 96 struct parse_repo *rp; 97 char *fn, *repopath; 98 99 /* build file path based on repoid, entity path and filename */ 100 rp = repo_get(repoid); 101 if (rp == NULL) 102 errx(1, "build file path: repository %u missing", repoid); 103 104 if (loc == DIR_VALID) 105 repopath = rp->validpath; 106 else 107 repopath = rp->path; 108 109 if (repopath == NULL) 110 return NULL; 111 112 if (path == NULL) { 113 if (asprintf(&fn, "%s/%s", repopath, file) == -1) 114 err(1, NULL); 115 } else { 116 if (asprintf(&fn, "%s/%s/%s", repopath, path, file) == -1) 117 err(1, NULL); 118 } 119 return fn; 120 } 121 122 /* 123 * Parse and validate a ROA. 124 * This is standard stuff. 125 * Returns the roa on success, NULL on failure. 126 */ 127 static struct roa * 128 proc_parser_roa(char *file, const unsigned char *der, size_t len, 129 const char *mftaki) 130 { 131 struct roa *roa; 132 struct auth *a; 133 struct crl *crl; 134 X509 *x509; 135 const char *errstr; 136 137 if ((roa = roa_parse(&x509, file, der, len)) == NULL) 138 return NULL; 139 140 a = valid_ski_aki(file, &auths, roa->ski, roa->aki, mftaki); 141 crl = crl_get(&crlt, a); 142 143 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 144 warnx("%s: %s", file, errstr); 145 X509_free(x509); 146 roa_free(roa); 147 return NULL; 148 } 149 X509_free(x509); 150 151 roa->talid = a->cert->talid; 152 153 roa->expires = x509_find_expires(roa->notafter, a, &crlt); 154 155 return roa; 156 } 157 158 /* 159 * Check all files and their hashes in a MFT structure. 160 * Return zero on failure, non-zero on success. 161 */ 162 static int 163 proc_parser_mft_check(const char *fn, struct mft *p) 164 { 165 const enum location loc[2] = { DIR_TEMP, DIR_VALID }; 166 size_t i; 167 int rc = 1; 168 char *path; 169 170 for (i = 0; i < p->filesz; i++) { 171 struct mftfile *m = &p->files[i]; 172 int try, fd = -1, noent = 0, valid = 0; 173 for (try = 0; try < 2 && !valid; try++) { 174 if ((path = parse_filepath(p->repoid, p->path, m->file, 175 loc[try])) == NULL) 176 continue; 177 fd = open(path, O_RDONLY); 178 if (fd == -1 && errno == ENOENT) 179 noent++; 180 free(path); 181 182 /* remember which path was checked */ 183 m->location = loc[try]; 184 valid = valid_filehash(fd, m->hash, sizeof(m->hash)); 185 } 186 187 if (!valid) { 188 /* silently skip not-existing unknown files */ 189 if (m->type == RTYPE_INVALID && noent == 2) 190 continue; 191 warnx("%s#%s: bad message digest for %s", fn, 192 p->seqnum, m->file); 193 rc = 0; 194 continue; 195 } 196 } 197 198 return rc; 199 } 200 201 /* 202 * Load the CRL from loc using the info from the MFT. 203 */ 204 static struct crl * 205 parse_load_crl_from_mft(struct entity *entp, struct mft *mft, enum location loc, 206 char **crlfile) 207 { 208 struct crl *crl = NULL; 209 unsigned char *f = NULL; 210 char *fn = NULL; 211 size_t flen; 212 213 *crlfile = NULL; 214 215 fn = parse_filepath(entp->repoid, entp->path, mft->crl, loc); 216 if (fn == NULL) 217 goto out; 218 219 f = load_file(fn, &flen); 220 if (f == NULL) { 221 if (errno != ENOENT) 222 warn("parse file %s", fn); 223 goto out; 224 } 225 226 if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash))) 227 goto out; 228 229 crl = crl_parse(fn, f, flen); 230 if (crl == NULL) 231 goto out; 232 233 if (strcmp(crl->aki, mft->aki) != 0) { 234 warnx("%s: AKI doesn't match Manifest AKI", fn); 235 goto out; 236 } 237 238 *crlfile = fn; 239 free(f); 240 241 return crl; 242 243 out: 244 crl_free(crl); 245 free(f); 246 free(fn); 247 248 return NULL; 249 } 250 251 /* 252 * Parse and validate a manifest file. Skip checking the fileandhash 253 * this is done in the post check. After this step we know the mft is 254 * valid and can be compared. 255 * Return the mft on success or NULL on failure. 256 */ 257 static struct mft * 258 proc_parser_mft_pre(struct entity *entp, enum location loc, char **file, 259 struct crl **crl, char **crlfile, const char **errstr) 260 { 261 struct mft *mft; 262 X509 *x509; 263 struct auth *a; 264 unsigned char *der; 265 size_t len; 266 267 *crl = NULL; 268 *crlfile = NULL; 269 *errstr = NULL; 270 271 *file = parse_filepath(entp->repoid, entp->path, entp->file, loc); 272 if (*file == NULL) 273 return NULL; 274 275 der = load_file(*file, &len); 276 if (der == NULL && errno != ENOENT) 277 warn("parse file %s", *file); 278 279 if ((mft = mft_parse(&x509, *file, der, len)) == NULL) { 280 free(der); 281 return NULL; 282 } 283 free(der); 284 285 *crl = parse_load_crl_from_mft(entp, mft, DIR_TEMP, crlfile); 286 if (*crl == NULL) 287 *crl = parse_load_crl_from_mft(entp, mft, DIR_VALID, crlfile); 288 289 a = valid_ski_aki(*file, &auths, mft->ski, mft->aki, NULL); 290 if (!valid_x509(*file, ctx, x509, a, *crl, errstr)) { 291 X509_free(x509); 292 mft_free(mft); 293 crl_free(*crl); 294 *crl = NULL; 295 free(*crlfile); 296 *crlfile = NULL; 297 return NULL; 298 } 299 X509_free(x509); 300 301 mft->repoid = entp->repoid; 302 mft->talid = a->cert->talid; 303 304 return mft; 305 } 306 307 /* 308 * Do the end of manifest validation. 309 * Return the mft on success or NULL on failure. 310 */ 311 static struct mft * 312 proc_parser_mft_post(char *file, struct mft *mft, const char *path, 313 const char *errstr) 314 { 315 /* check that now is not before from */ 316 time_t now = get_current_time(); 317 318 if (mft == NULL) { 319 if (errstr == NULL) 320 errstr = "no valid mft available"; 321 warnx("%s: %s", file, errstr); 322 return NULL; 323 } 324 325 /* check that now is not before from */ 326 if (now < mft->thisupdate) { 327 warnx("%s: mft not yet valid %s", file, 328 time2str(mft->thisupdate)); 329 mft->stale = 1; 330 } 331 /* check that now is not after until */ 332 if (now > mft->nextupdate) { 333 warnx("%s: mft expired on %s", file, 334 time2str(mft->nextupdate)); 335 mft->stale = 1; 336 } 337 338 if (path != NULL) 339 if ((mft->path = strdup(path)) == NULL) 340 err(1, NULL); 341 342 if (!mft->stale) 343 if (!proc_parser_mft_check(file, mft)) { 344 mft_free(mft); 345 return NULL; 346 } 347 348 return mft; 349 } 350 351 /* 352 * Load the most recent MFT by opening both options and comparing the two. 353 */ 354 static char * 355 proc_parser_mft(struct entity *entp, struct mft **mp, char **crlfile, 356 time_t *crlmtime) 357 { 358 struct mft *mft1 = NULL, *mft2 = NULL; 359 struct crl *crl, *crl1, *crl2; 360 char *file, *file1, *file2, *crl1file, *crl2file; 361 const char *err1, *err2; 362 363 *mp = NULL; 364 *crlmtime = 0; 365 366 mft1 = proc_parser_mft_pre(entp, DIR_VALID, &file1, &crl1, &crl1file, 367 &err1); 368 mft2 = proc_parser_mft_pre(entp, DIR_TEMP, &file2, &crl2, &crl2file, 369 &err2); 370 371 /* overload error from temp file if it is set */ 372 if (mft1 == NULL && mft2 == NULL) 373 if (err2 != NULL) 374 err1 = err2; 375 376 if (mft_compare(mft1, mft2) == 1) { 377 mft_free(mft2); 378 crl_free(crl2); 379 free(crl2file); 380 free(file2); 381 *mp = proc_parser_mft_post(file1, mft1, entp->path, err1); 382 crl = crl1; 383 file = file1; 384 *crlfile = crl1file; 385 } else { 386 mft_free(mft1); 387 crl_free(crl1); 388 free(crl1file); 389 free(file1); 390 *mp = proc_parser_mft_post(file2, mft2, entp->path, err2); 391 crl = crl2; 392 file = file2; 393 *crlfile = crl2file; 394 } 395 396 if (*mp != NULL) { 397 *crlmtime = crl->lastupdate; 398 if (!crl_insert(&crlt, crl)) { 399 warnx("%s: duplicate AKI %s", file, crl->aki); 400 crl_free(crl); 401 } 402 } else { 403 crl_free(crl); 404 } 405 return file; 406 } 407 408 /* 409 * Certificates are from manifests (has a digest and is signed with 410 * another certificate) Parse the certificate, make sure its 411 * signatures are valid (with CRLs), then validate the RPKI content. 412 * This returns a certificate (which must not be freed) or NULL on 413 * parse failure. 414 */ 415 static struct cert * 416 proc_parser_cert(char *file, const unsigned char *der, size_t len, 417 const char *mftaki) 418 { 419 struct cert *cert; 420 struct crl *crl; 421 struct auth *a; 422 const char *errstr = NULL; 423 424 /* Extract certificate data. */ 425 426 cert = cert_parse_pre(file, der, len); 427 cert = cert_parse(file, cert); 428 if (cert == NULL) 429 return NULL; 430 431 a = valid_ski_aki(file, &auths, cert->ski, cert->aki, mftaki); 432 crl = crl_get(&crlt, a); 433 434 if (!valid_x509(file, ctx, cert->x509, a, crl, &errstr) || 435 !valid_cert(file, a, cert)) { 436 if (errstr != NULL) 437 warnx("%s: %s", file, errstr); 438 cert_free(cert); 439 return NULL; 440 } 441 442 cert->talid = a->cert->talid; 443 444 /* 445 * Add validated CA certs to the RPKI auth tree. 446 */ 447 if (cert->purpose == CERT_PURPOSE_CA) 448 auth_insert(&auths, cert, a); 449 450 return cert; 451 } 452 453 /* 454 * Root certificates come from TALs (has a pkey and is self-signed). 455 * Parse the certificate, ensure that its public key matches the 456 * known public key from the TAL, and then validate the RPKI 457 * content. 458 * 459 * This returns a certificate (which must not be freed) or NULL on 460 * parse failure. 461 */ 462 static struct cert * 463 proc_parser_root_cert(char *file, const unsigned char *der, size_t len, 464 unsigned char *pkey, size_t pkeysz, int talid) 465 { 466 struct cert *cert; 467 468 /* Extract certificate data. */ 469 470 cert = cert_parse_pre(file, der, len); 471 cert = ta_parse(file, cert, pkey, pkeysz); 472 if (cert == NULL) 473 return NULL; 474 475 if (!valid_ta(file, &auths, cert)) { 476 warnx("%s: certificate not a valid ta", file); 477 cert_free(cert); 478 return NULL; 479 } 480 481 cert->talid = talid; 482 483 /* 484 * Add valid roots to the RPKI auth tree. 485 */ 486 auth_insert(&auths, cert, NULL); 487 488 return cert; 489 } 490 491 /* 492 * Parse a ghostbuster record 493 */ 494 static struct gbr * 495 proc_parser_gbr(char *file, const unsigned char *der, size_t len, 496 const char *mftaki) 497 { 498 struct gbr *gbr; 499 X509 *x509; 500 struct crl *crl; 501 struct auth *a; 502 const char *errstr; 503 504 if ((gbr = gbr_parse(&x509, file, der, len)) == NULL) 505 return NULL; 506 507 a = valid_ski_aki(file, &auths, gbr->ski, gbr->aki, mftaki); 508 crl = crl_get(&crlt, a); 509 510 /* return value can be ignored since nothing happens here */ 511 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 512 warnx("%s: %s", file, errstr); 513 X509_free(x509); 514 gbr_free(gbr); 515 return NULL; 516 } 517 X509_free(x509); 518 519 gbr->talid = a->cert->talid; 520 521 return gbr; 522 } 523 524 /* 525 * Parse an ASPA object 526 */ 527 static struct aspa * 528 proc_parser_aspa(char *file, const unsigned char *der, size_t len, 529 const char *mftaki) 530 { 531 struct aspa *aspa; 532 struct auth *a; 533 struct crl *crl; 534 X509 *x509; 535 const char *errstr; 536 537 if ((aspa = aspa_parse(&x509, file, der, len)) == NULL) 538 return NULL; 539 540 a = valid_ski_aki(file, &auths, aspa->ski, aspa->aki, mftaki); 541 crl = crl_get(&crlt, a); 542 543 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 544 warnx("%s: %s", file, errstr); 545 X509_free(x509); 546 aspa_free(aspa); 547 return NULL; 548 } 549 X509_free(x509); 550 551 aspa->talid = a->cert->talid; 552 553 aspa->expires = x509_find_expires(aspa->notafter, a, &crlt); 554 555 return aspa; 556 } 557 558 /* 559 * Parse a TAK object. 560 */ 561 static struct tak * 562 proc_parser_tak(char *file, const unsigned char *der, size_t len, 563 const char *mftaki) 564 { 565 struct tak *tak; 566 X509 *x509; 567 struct crl *crl; 568 struct auth *a; 569 const char *errstr; 570 int rc = 0; 571 572 if ((tak = tak_parse(&x509, file, der, len)) == NULL) 573 return NULL; 574 575 a = valid_ski_aki(file, &auths, tak->ski, tak->aki, mftaki); 576 crl = crl_get(&crlt, a); 577 578 if (!valid_x509(file, ctx, x509, a, crl, &errstr)) { 579 warnx("%s: %s", file, errstr); 580 goto out; 581 } 582 583 /* TAK EE must be signed by self-signed CA */ 584 if (a->parent != NULL) 585 goto out; 586 587 tak->talid = a->cert->talid; 588 rc = 1; 589 out: 590 if (rc == 0) { 591 tak_free(tak); 592 tak = NULL; 593 } 594 X509_free(x509); 595 return tak; 596 } 597 598 /* 599 * Load the file specified by the entity information. 600 */ 601 static char * 602 parse_load_file(struct entity *entp, unsigned char **f, size_t *flen) 603 { 604 char *file; 605 606 file = parse_filepath(entp->repoid, entp->path, entp->file, 607 entp->location); 608 if (file == NULL) 609 errx(1, "no path to file"); 610 611 *f = load_file(file, flen); 612 if (*f == NULL) 613 warn("parse file %s", file); 614 615 return file; 616 } 617 618 /* 619 * Process an entity and responing to parent process. 620 */ 621 static void 622 parse_entity(struct entityq *q, struct msgbuf *msgq) 623 { 624 struct entity *entp; 625 struct tal *tal; 626 struct cert *cert; 627 struct mft *mft; 628 struct roa *roa; 629 struct aspa *aspa; 630 struct gbr *gbr; 631 struct tak *tak; 632 struct ibuf *b; 633 unsigned char *f; 634 time_t mtime, crlmtime; 635 size_t flen; 636 char *file, *crlfile; 637 int c; 638 639 while ((entp = TAILQ_FIRST(q)) != NULL) { 640 TAILQ_REMOVE(q, entp, entries); 641 642 /* handle RTYPE_REPO first */ 643 if (entp->type == RTYPE_REPO) { 644 repo_add(entp->repoid, entp->path, entp->file); 645 entity_free(entp); 646 continue; 647 } 648 649 /* pass back at least type, repoid and filename */ 650 b = io_new_buffer(); 651 io_simple_buffer(b, &entp->type, sizeof(entp->type)); 652 io_simple_buffer(b, &entp->repoid, sizeof(entp->repoid)); 653 io_simple_buffer(b, &entp->talid, sizeof(entp->talid)); 654 655 file = NULL; 656 f = NULL; 657 mtime = 0; 658 crlmtime = 0; 659 660 switch (entp->type) { 661 case RTYPE_TAL: 662 io_str_buffer(b, entp->file); 663 io_simple_buffer(b, &mtime, sizeof(mtime)); 664 if ((tal = tal_parse(entp->file, entp->data, 665 entp->datasz)) == NULL) 666 errx(1, "%s: could not parse tal file", 667 entp->file); 668 tal->id = entp->talid; 669 tal_buffer(b, tal); 670 tal_free(tal); 671 break; 672 case RTYPE_CER: 673 file = parse_load_file(entp, &f, &flen); 674 io_str_buffer(b, file); 675 if (entp->data != NULL) 676 cert = proc_parser_root_cert(file, 677 f, flen, entp->data, entp->datasz, 678 entp->talid); 679 else 680 cert = proc_parser_cert(file, f, flen, 681 entp->mftaki); 682 if (cert != NULL) 683 mtime = cert->notbefore; 684 io_simple_buffer(b, &mtime, sizeof(mtime)); 685 c = (cert != NULL); 686 io_simple_buffer(b, &c, sizeof(int)); 687 if (cert != NULL) { 688 cert->repoid = entp->repoid; 689 cert_buffer(b, cert); 690 } 691 /* 692 * The parsed certificate data "cert" is now 693 * managed in the "auths" table, so don't free 694 * it here. 695 */ 696 break; 697 case RTYPE_MFT: 698 file = proc_parser_mft(entp, &mft, &crlfile, &crlmtime); 699 io_str_buffer(b, file); 700 if (mft != NULL) 701 mtime = mft->signtime; 702 io_simple_buffer(b, &mtime, sizeof(mtime)); 703 c = (mft != NULL); 704 io_simple_buffer(b, &c, sizeof(int)); 705 if (mft != NULL) 706 mft_buffer(b, mft); 707 708 /* Push valid CRL together with the MFT. */ 709 if (crlfile != NULL) { 710 enum rtype type; 711 struct ibuf *b2; 712 713 b2 = io_new_buffer(); 714 type = RTYPE_CRL; 715 io_simple_buffer(b2, &type, sizeof(type)); 716 io_simple_buffer(b2, &entp->repoid, 717 sizeof(entp->repoid)); 718 io_simple_buffer(b2, &entp->talid, 719 sizeof(entp->talid)); 720 io_str_buffer(b2, crlfile); 721 io_simple_buffer(b2, &crlmtime, 722 sizeof(crlmtime)); 723 free(crlfile); 724 725 io_close_buffer(msgq, b2); 726 } 727 mft_free(mft); 728 break; 729 case RTYPE_ROA: 730 file = parse_load_file(entp, &f, &flen); 731 io_str_buffer(b, file); 732 roa = proc_parser_roa(file, f, flen, entp->mftaki); 733 if (roa != NULL) 734 mtime = roa->signtime; 735 io_simple_buffer(b, &mtime, sizeof(mtime)); 736 c = (roa != NULL); 737 io_simple_buffer(b, &c, sizeof(int)); 738 if (roa != NULL) 739 roa_buffer(b, roa); 740 roa_free(roa); 741 break; 742 case RTYPE_GBR: 743 file = parse_load_file(entp, &f, &flen); 744 io_str_buffer(b, file); 745 gbr = proc_parser_gbr(file, f, flen, entp->mftaki); 746 if (gbr != NULL) 747 mtime = gbr->signtime; 748 io_simple_buffer(b, &mtime, sizeof(mtime)); 749 gbr_free(gbr); 750 break; 751 case RTYPE_ASPA: 752 file = parse_load_file(entp, &f, &flen); 753 io_str_buffer(b, file); 754 aspa = proc_parser_aspa(file, f, flen, entp->mftaki); 755 if (aspa != NULL) 756 mtime = aspa->signtime; 757 io_simple_buffer(b, &mtime, sizeof(mtime)); 758 c = (aspa != NULL); 759 io_simple_buffer(b, &c, sizeof(int)); 760 if (aspa != NULL) 761 aspa_buffer(b, aspa); 762 aspa_free(aspa); 763 break; 764 case RTYPE_TAK: 765 file = parse_load_file(entp, &f, &flen); 766 io_str_buffer(b, file); 767 tak = proc_parser_tak(file, f, flen, entp->mftaki); 768 if (tak != NULL) 769 mtime = tak->signtime; 770 io_simple_buffer(b, &mtime, sizeof(mtime)); 771 tak_free(tak); 772 break; 773 case RTYPE_CRL: 774 default: 775 file = parse_filepath(entp->repoid, entp->path, 776 entp->file, entp->location); 777 io_str_buffer(b, file); 778 io_simple_buffer(b, &mtime, sizeof(mtime)); 779 warnx("%s: unhandled type %d", file, entp->type); 780 break; 781 } 782 783 free(f); 784 free(file); 785 io_close_buffer(msgq, b); 786 entity_free(entp); 787 } 788 } 789 790 /* 791 * Process responsible for parsing and validating content. 792 * All this process does is wait to be told about a file to parse, then 793 * it parses it and makes sure that the data being returned is fully 794 * validated and verified. 795 * The process will exit cleanly only when fd is closed. 796 */ 797 void 798 proc_parser(int fd) 799 { 800 struct entityq q; 801 struct msgbuf msgq; 802 struct pollfd pfd; 803 struct entity *entp; 804 struct ibuf *b, *inbuf = NULL; 805 806 /* Only allow access to the cache directory. */ 807 if (unveil(".", "r") == -1) 808 err(1, "unveil cachedir"); 809 if (pledge("stdio rpath", NULL) == -1) 810 err(1, "pledge"); 811 812 ERR_load_crypto_strings(); 813 OpenSSL_add_all_ciphers(); 814 OpenSSL_add_all_digests(); 815 x509_init_oid(); 816 817 if ((ctx = X509_STORE_CTX_new()) == NULL) 818 cryptoerrx("X509_STORE_CTX_new"); 819 820 TAILQ_INIT(&q); 821 822 msgbuf_init(&msgq); 823 msgq.fd = fd; 824 825 pfd.fd = fd; 826 827 for (;;) { 828 pfd.events = POLLIN; 829 if (msgq.queued) 830 pfd.events |= POLLOUT; 831 832 if (poll(&pfd, 1, INFTIM) == -1) { 833 if (errno == EINTR) 834 continue; 835 err(1, "poll"); 836 } 837 if ((pfd.revents & (POLLERR|POLLNVAL))) 838 errx(1, "poll: bad descriptor"); 839 840 /* If the parent closes, return immediately. */ 841 842 if ((pfd.revents & POLLHUP)) 843 break; 844 845 if ((pfd.revents & POLLIN)) { 846 b = io_buf_read(fd, &inbuf); 847 if (b != NULL) { 848 entp = calloc(1, sizeof(struct entity)); 849 if (entp == NULL) 850 err(1, NULL); 851 entity_read_req(b, entp); 852 TAILQ_INSERT_TAIL(&q, entp, entries); 853 ibuf_free(b); 854 } 855 } 856 857 if (pfd.revents & POLLOUT) { 858 switch (msgbuf_write(&msgq)) { 859 case 0: 860 errx(1, "write: connection closed"); 861 case -1: 862 err(1, "write"); 863 } 864 } 865 866 parse_entity(&q, &msgq); 867 } 868 869 while ((entp = TAILQ_FIRST(&q)) != NULL) { 870 TAILQ_REMOVE(&q, entp, entries); 871 entity_free(entp); 872 } 873 874 auth_tree_free(&auths); 875 crl_tree_free(&crlt); 876 877 X509_STORE_CTX_free(ctx); 878 msgbuf_clear(&msgq); 879 880 ibuf_free(inbuf); 881 882 exit(0); 883 } 884