1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org> 5 * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/queue.h> 35 #include <sys/types.h> 36 #include <sys/sbuf.h> 37 #include <sys/wait.h> 38 39 #include <archive.h> 40 #include <archive_entry.h> 41 #include <dirent.h> 42 #include <err.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <fetch.h> 46 #include <getopt.h> 47 #include <libutil.h> 48 #include <paths.h> 49 #include <stdbool.h> 50 #include <stdlib.h> 51 #include <stdio.h> 52 #include <string.h> 53 #include <ucl.h> 54 55 #include <openssl/err.h> 56 #include <openssl/ssl.h> 57 58 #include "dns_utils.h" 59 #include "config.h" 60 61 struct sig_cert { 62 char *name; 63 unsigned char *sig; 64 int siglen; 65 unsigned char *cert; 66 int certlen; 67 bool trusted; 68 }; 69 70 struct pubkey { 71 unsigned char *sig; 72 int siglen; 73 }; 74 75 typedef enum { 76 HASH_UNKNOWN, 77 HASH_SHA256, 78 } hash_t; 79 80 struct fingerprint { 81 hash_t type; 82 char *name; 83 char hash[BUFSIZ]; 84 STAILQ_ENTRY(fingerprint) next; 85 }; 86 87 static const char *bootstrap_names [] = { 88 "pkg.pkg", 89 "pkg.txz", 90 NULL 91 }; 92 93 STAILQ_HEAD(fingerprint_list, fingerprint); 94 95 static int 96 extract_pkg_static(int fd, char *p, int sz) 97 { 98 struct archive *a; 99 struct archive_entry *ae; 100 char *end; 101 int ret, r; 102 103 ret = -1; 104 a = archive_read_new(); 105 if (a == NULL) { 106 warn("archive_read_new"); 107 return (ret); 108 } 109 archive_read_support_filter_all(a); 110 archive_read_support_format_tar(a); 111 112 if (lseek(fd, 0, 0) == -1) { 113 warn("lseek"); 114 goto cleanup; 115 } 116 117 if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 118 warnx("archive_read_open_fd: %s", archive_error_string(a)); 119 goto cleanup; 120 } 121 122 ae = NULL; 123 while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 124 end = strrchr(archive_entry_pathname(ae), '/'); 125 if (end == NULL) 126 continue; 127 128 if (strcmp(end, "/pkg-static") == 0) { 129 r = archive_read_extract(a, ae, 130 ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 131 ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 132 ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 133 strlcpy(p, archive_entry_pathname(ae), sz); 134 break; 135 } 136 } 137 138 if (r == ARCHIVE_OK) 139 ret = 0; 140 else 141 warnx("failed to extract pkg-static: %s", 142 archive_error_string(a)); 143 144 cleanup: 145 archive_read_free(a); 146 return (ret); 147 148 } 149 150 static int 151 install_pkg_static(const char *path, const char *pkgpath, bool force) 152 { 153 int pstat; 154 pid_t pid; 155 156 switch ((pid = fork())) { 157 case -1: 158 return (-1); 159 case 0: 160 if (force) 161 execl(path, "pkg-static", "add", "-f", pkgpath, 162 (char *)NULL); 163 else 164 execl(path, "pkg-static", "add", pkgpath, 165 (char *)NULL); 166 _exit(1); 167 default: 168 break; 169 } 170 171 while (waitpid(pid, &pstat, 0) == -1) 172 if (errno != EINTR) 173 return (-1); 174 175 if (WEXITSTATUS(pstat)) 176 return (WEXITSTATUS(pstat)); 177 else if (WIFSIGNALED(pstat)) 178 return (128 & (WTERMSIG(pstat))); 179 return (pstat); 180 } 181 182 static int 183 fetch_to_fd(const char *url, char *path, const char *fetchOpts) 184 { 185 struct url *u; 186 struct dns_srvinfo *mirrors, *current; 187 struct url_stat st; 188 FILE *remote; 189 /* To store _https._tcp. + hostname + \0 */ 190 int fd; 191 int retry, max_retry; 192 ssize_t r; 193 char buf[10240]; 194 char zone[MAXHOSTNAMELEN + 13]; 195 static const char *mirror_type = NULL; 196 197 max_retry = 3; 198 current = mirrors = NULL; 199 remote = NULL; 200 201 if (mirror_type == NULL && config_string(MIRROR_TYPE, &mirror_type) 202 != 0) { 203 warnx("No MIRROR_TYPE defined"); 204 return (-1); 205 } 206 207 if ((fd = mkstemp(path)) == -1) { 208 warn("mkstemp()"); 209 return (-1); 210 } 211 212 retry = max_retry; 213 214 if ((u = fetchParseURL(url)) == NULL) { 215 warn("fetchParseURL('%s')", url); 216 return (-1); 217 } 218 219 while (remote == NULL) { 220 if (retry == max_retry) { 221 if (strcmp(u->scheme, "file") != 0 && 222 strcasecmp(mirror_type, "srv") == 0) { 223 snprintf(zone, sizeof(zone), 224 "_%s._tcp.%s", u->scheme, u->host); 225 mirrors = dns_getsrvinfo(zone); 226 current = mirrors; 227 } 228 } 229 230 if (mirrors != NULL) { 231 strlcpy(u->host, current->host, sizeof(u->host)); 232 u->port = current->port; 233 } 234 235 remote = fetchXGet(u, &st, fetchOpts); 236 if (remote == NULL) { 237 --retry; 238 if (retry <= 0) 239 goto fetchfail; 240 if (mirrors == NULL) { 241 sleep(1); 242 } else { 243 current = current->next; 244 if (current == NULL) 245 current = mirrors; 246 } 247 } 248 } 249 250 while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) { 251 if (write(fd, buf, r) != r) { 252 warn("write()"); 253 goto fetchfail; 254 } 255 } 256 257 if (r != 0) { 258 warn("An error occurred while fetching pkg(8)"); 259 goto fetchfail; 260 } 261 262 if (ferror(remote)) 263 goto fetchfail; 264 265 goto cleanup; 266 267 fetchfail: 268 if (fd != -1) { 269 close(fd); 270 fd = -1; 271 unlink(path); 272 } 273 274 cleanup: 275 if (remote != NULL) 276 fclose(remote); 277 278 return fd; 279 } 280 281 static struct fingerprint * 282 parse_fingerprint(ucl_object_t *obj) 283 { 284 const ucl_object_t *cur; 285 ucl_object_iter_t it = NULL; 286 const char *function, *fp, *key; 287 struct fingerprint *f; 288 hash_t fct = HASH_UNKNOWN; 289 290 function = fp = NULL; 291 292 while ((cur = ucl_iterate_object(obj, &it, true))) { 293 key = ucl_object_key(cur); 294 if (cur->type != UCL_STRING) 295 continue; 296 if (strcasecmp(key, "function") == 0) { 297 function = ucl_object_tostring(cur); 298 continue; 299 } 300 if (strcasecmp(key, "fingerprint") == 0) { 301 fp = ucl_object_tostring(cur); 302 continue; 303 } 304 } 305 306 if (fp == NULL || function == NULL) 307 return (NULL); 308 309 if (strcasecmp(function, "sha256") == 0) 310 fct = HASH_SHA256; 311 312 if (fct == HASH_UNKNOWN) { 313 warnx("Unsupported hashing function: %s", function); 314 return (NULL); 315 } 316 317 f = calloc(1, sizeof(struct fingerprint)); 318 f->type = fct; 319 strlcpy(f->hash, fp, sizeof(f->hash)); 320 321 return (f); 322 } 323 324 static void 325 free_fingerprint_list(struct fingerprint_list* list) 326 { 327 struct fingerprint *fingerprint, *tmp; 328 329 STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) { 330 free(fingerprint->name); 331 free(fingerprint); 332 } 333 free(list); 334 } 335 336 static struct fingerprint * 337 load_fingerprint(const char *dir, const char *filename) 338 { 339 ucl_object_t *obj = NULL; 340 struct ucl_parser *p = NULL; 341 struct fingerprint *f; 342 char path[MAXPATHLEN]; 343 344 f = NULL; 345 346 snprintf(path, MAXPATHLEN, "%s/%s", dir, filename); 347 348 p = ucl_parser_new(0); 349 if (!ucl_parser_add_file(p, path)) { 350 warnx("%s: %s", path, ucl_parser_get_error(p)); 351 ucl_parser_free(p); 352 return (NULL); 353 } 354 355 obj = ucl_parser_get_object(p); 356 357 if (obj->type == UCL_OBJECT) 358 f = parse_fingerprint(obj); 359 360 if (f != NULL) 361 f->name = strdup(filename); 362 363 ucl_object_unref(obj); 364 ucl_parser_free(p); 365 366 return (f); 367 } 368 369 static struct fingerprint_list * 370 load_fingerprints(const char *path, int *count) 371 { 372 DIR *d; 373 struct dirent *ent; 374 struct fingerprint *finger; 375 struct fingerprint_list *fingerprints; 376 377 *count = 0; 378 379 fingerprints = calloc(1, sizeof(struct fingerprint_list)); 380 if (fingerprints == NULL) 381 return (NULL); 382 STAILQ_INIT(fingerprints); 383 384 if ((d = opendir(path)) == NULL) { 385 free(fingerprints); 386 387 return (NULL); 388 } 389 390 while ((ent = readdir(d))) { 391 if (strcmp(ent->d_name, ".") == 0 || 392 strcmp(ent->d_name, "..") == 0) 393 continue; 394 finger = load_fingerprint(path, ent->d_name); 395 if (finger != NULL) { 396 STAILQ_INSERT_TAIL(fingerprints, finger, next); 397 ++(*count); 398 } 399 } 400 401 closedir(d); 402 403 return (fingerprints); 404 } 405 406 static void 407 sha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH], 408 char out[SHA256_DIGEST_LENGTH * 2 + 1]) 409 { 410 int i; 411 412 for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 413 sprintf(out + (i * 2), "%02x", hash[i]); 414 415 out[SHA256_DIGEST_LENGTH * 2] = '\0'; 416 } 417 418 static void 419 sha256_buf(char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 420 { 421 unsigned char hash[SHA256_DIGEST_LENGTH]; 422 SHA256_CTX sha256; 423 424 out[0] = '\0'; 425 426 SHA256_Init(&sha256); 427 SHA256_Update(&sha256, buf, len); 428 SHA256_Final(hash, &sha256); 429 sha256_hash(hash, out); 430 } 431 432 static int 433 sha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 434 { 435 int my_fd; 436 FILE *fp; 437 char buffer[BUFSIZ]; 438 unsigned char hash[SHA256_DIGEST_LENGTH]; 439 size_t r; 440 int ret; 441 SHA256_CTX sha256; 442 443 fp = NULL; 444 ret = 1; 445 446 out[0] = '\0'; 447 448 /* Duplicate the fd so that fclose(3) does not close it. */ 449 if ((my_fd = dup(fd)) == -1) { 450 warnx("dup"); 451 goto cleanup; 452 } 453 454 if ((fp = fdopen(my_fd, "rb")) == NULL) { 455 warnx("fdopen"); 456 goto cleanup; 457 } 458 459 SHA256_Init(&sha256); 460 461 while ((r = fread(buffer, 1, BUFSIZ, fp)) > 0) 462 SHA256_Update(&sha256, buffer, r); 463 464 if (ferror(fp) != 0) { 465 warnx("fread"); 466 goto cleanup; 467 } 468 469 SHA256_Final(hash, &sha256); 470 sha256_hash(hash, out); 471 ret = 0; 472 473 cleanup: 474 if (fp != NULL) 475 fclose(fp); 476 else if (my_fd != -1) 477 close(my_fd); 478 (void)lseek(fd, 0, SEEK_SET); 479 480 return (ret); 481 } 482 483 static EVP_PKEY * 484 load_public_key_file(const char *file) 485 { 486 EVP_PKEY *pkey; 487 BIO *bp; 488 char errbuf[1024]; 489 490 bp = BIO_new_file(file, "r"); 491 if (!bp) 492 errx(EXIT_FAILURE, "Unable to read %s", file); 493 494 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 495 warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 496 497 BIO_free(bp); 498 499 return (pkey); 500 } 501 502 static EVP_PKEY * 503 load_public_key_buf(const unsigned char *cert, int certlen) 504 { 505 EVP_PKEY *pkey; 506 BIO *bp; 507 char errbuf[1024]; 508 509 bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 510 511 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 512 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 513 514 BIO_free(bp); 515 516 return (pkey); 517 } 518 519 static bool 520 rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key, 521 int keylen, unsigned char *sig, int siglen) 522 { 523 EVP_MD_CTX *mdctx; 524 EVP_PKEY *pkey; 525 char sha256[(SHA256_DIGEST_LENGTH * 2) + 2]; 526 char errbuf[1024]; 527 bool ret; 528 529 pkey = NULL; 530 mdctx = NULL; 531 ret = false; 532 533 SSL_load_error_strings(); 534 535 /* Compute SHA256 of the package. */ 536 if (lseek(fd, 0, 0) == -1) { 537 warn("lseek"); 538 goto cleanup; 539 } 540 if ((sha256_fd(fd, sha256)) == -1) { 541 warnx("Error creating SHA256 hash for package"); 542 goto cleanup; 543 } 544 545 if (sigfile != NULL) { 546 if ((pkey = load_public_key_file(sigfile)) == NULL) { 547 warnx("Error reading public key"); 548 goto cleanup; 549 } 550 } else { 551 if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 552 warnx("Error reading public key"); 553 goto cleanup; 554 } 555 } 556 557 /* Verify signature of the SHA256(pkg) is valid. */ 558 if ((mdctx = EVP_MD_CTX_create()) == NULL) { 559 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 560 goto error; 561 } 562 563 if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 564 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 565 goto error; 566 } 567 if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) { 568 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 569 goto error; 570 } 571 572 if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 573 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 574 goto error; 575 } 576 577 ret = true; 578 printf("done\n"); 579 goto cleanup; 580 581 error: 582 printf("failed\n"); 583 584 cleanup: 585 if (pkey) 586 EVP_PKEY_free(pkey); 587 if (mdctx) 588 EVP_MD_CTX_destroy(mdctx); 589 ERR_free_strings(); 590 591 return (ret); 592 } 593 594 static struct pubkey * 595 read_pubkey(int fd) 596 { 597 struct pubkey *pk; 598 struct sbuf *sig; 599 char buf[4096]; 600 int r; 601 602 if (lseek(fd, 0, 0) == -1) { 603 warn("lseek"); 604 return (NULL); 605 } 606 607 sig = sbuf_new_auto(); 608 609 while ((r = read(fd, buf, sizeof(buf))) >0) { 610 sbuf_bcat(sig, buf, r); 611 } 612 613 sbuf_finish(sig); 614 pk = calloc(1, sizeof(struct pubkey)); 615 pk->siglen = sbuf_len(sig); 616 pk->sig = calloc(1, pk->siglen); 617 memcpy(pk->sig, sbuf_data(sig), pk->siglen); 618 sbuf_delete(sig); 619 620 return (pk); 621 } 622 623 static struct sig_cert * 624 parse_cert(int fd) { 625 int my_fd; 626 struct sig_cert *sc; 627 FILE *fp; 628 struct sbuf *buf, *sig, *cert; 629 char *line; 630 size_t linecap; 631 ssize_t linelen; 632 633 buf = NULL; 634 sc = NULL; 635 line = NULL; 636 linecap = 0; 637 638 if (lseek(fd, 0, 0) == -1) { 639 warn("lseek"); 640 return (NULL); 641 } 642 643 /* Duplicate the fd so that fclose(3) does not close it. */ 644 if ((my_fd = dup(fd)) == -1) { 645 warnx("dup"); 646 return (NULL); 647 } 648 649 if ((fp = fdopen(my_fd, "rb")) == NULL) { 650 warn("fdopen"); 651 close(my_fd); 652 return (NULL); 653 } 654 655 sig = sbuf_new_auto(); 656 cert = sbuf_new_auto(); 657 658 while ((linelen = getline(&line, &linecap, fp)) > 0) { 659 if (strcmp(line, "SIGNATURE\n") == 0) { 660 buf = sig; 661 continue; 662 } else if (strcmp(line, "CERT\n") == 0) { 663 buf = cert; 664 continue; 665 } else if (strcmp(line, "END\n") == 0) { 666 break; 667 } 668 if (buf != NULL) 669 sbuf_bcat(buf, line, linelen); 670 } 671 672 fclose(fp); 673 674 /* Trim out unrelated trailing newline */ 675 sbuf_setpos(sig, sbuf_len(sig) - 1); 676 677 sbuf_finish(sig); 678 sbuf_finish(cert); 679 680 sc = calloc(1, sizeof(struct sig_cert)); 681 sc->siglen = sbuf_len(sig); 682 sc->sig = calloc(1, sc->siglen); 683 memcpy(sc->sig, sbuf_data(sig), sc->siglen); 684 685 sc->certlen = sbuf_len(cert); 686 sc->cert = strdup(sbuf_data(cert)); 687 688 sbuf_delete(sig); 689 sbuf_delete(cert); 690 691 return (sc); 692 } 693 694 static bool 695 verify_pubsignature(int fd_pkg, int fd_sig) 696 { 697 struct pubkey *pk; 698 const char *pubkey; 699 bool ret; 700 701 pk = NULL; 702 pubkey = NULL; 703 ret = false; 704 if (config_string(PUBKEY, &pubkey) != 0) { 705 warnx("No CONFIG_PUBKEY defined"); 706 goto cleanup; 707 } 708 709 if ((pk = read_pubkey(fd_sig)) == NULL) { 710 warnx("Error reading signature"); 711 goto cleanup; 712 } 713 714 /* Verify the signature. */ 715 printf("Verifying signature with public key %s... ", pubkey); 716 if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig, 717 pk->siglen) == false) { 718 fprintf(stderr, "Signature is not valid\n"); 719 goto cleanup; 720 } 721 722 ret = true; 723 724 cleanup: 725 if (pk) { 726 free(pk->sig); 727 free(pk); 728 } 729 730 return (ret); 731 } 732 733 static bool 734 verify_signature(int fd_pkg, int fd_sig) 735 { 736 struct fingerprint_list *trusted, *revoked; 737 struct fingerprint *fingerprint; 738 struct sig_cert *sc; 739 bool ret; 740 int trusted_count, revoked_count; 741 const char *fingerprints; 742 char path[MAXPATHLEN]; 743 char hash[SHA256_DIGEST_LENGTH * 2 + 1]; 744 745 sc = NULL; 746 trusted = revoked = NULL; 747 ret = false; 748 749 /* Read and parse fingerprints. */ 750 if (config_string(FINGERPRINTS, &fingerprints) != 0) { 751 warnx("No CONFIG_FINGERPRINTS defined"); 752 goto cleanup; 753 } 754 755 snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints); 756 if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) { 757 warnx("Error loading trusted certificates"); 758 goto cleanup; 759 } 760 761 if (trusted_count == 0 || trusted == NULL) { 762 fprintf(stderr, "No trusted certificates found.\n"); 763 goto cleanup; 764 } 765 766 snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints); 767 if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) { 768 warnx("Error loading revoked certificates"); 769 goto cleanup; 770 } 771 772 /* Read certificate and signature in. */ 773 if ((sc = parse_cert(fd_sig)) == NULL) { 774 warnx("Error parsing certificate"); 775 goto cleanup; 776 } 777 /* Explicitly mark as non-trusted until proven otherwise. */ 778 sc->trusted = false; 779 780 /* Parse signature and pubkey out of the certificate */ 781 sha256_buf(sc->cert, sc->certlen, hash); 782 783 /* Check if this hash is revoked */ 784 if (revoked != NULL) { 785 STAILQ_FOREACH(fingerprint, revoked, next) { 786 if (strcasecmp(fingerprint->hash, hash) == 0) { 787 fprintf(stderr, "The package was signed with " 788 "revoked certificate %s\n", 789 fingerprint->name); 790 goto cleanup; 791 } 792 } 793 } 794 795 STAILQ_FOREACH(fingerprint, trusted, next) { 796 if (strcasecmp(fingerprint->hash, hash) == 0) { 797 sc->trusted = true; 798 sc->name = strdup(fingerprint->name); 799 break; 800 } 801 } 802 803 if (sc->trusted == false) { 804 fprintf(stderr, "No trusted fingerprint found matching " 805 "package's certificate\n"); 806 goto cleanup; 807 } 808 809 /* Verify the signature. */ 810 printf("Verifying signature with trusted certificate %s... ", sc->name); 811 if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig, 812 sc->siglen) == false) { 813 fprintf(stderr, "Signature is not valid\n"); 814 goto cleanup; 815 } 816 817 ret = true; 818 819 cleanup: 820 if (trusted) 821 free_fingerprint_list(trusted); 822 if (revoked) 823 free_fingerprint_list(revoked); 824 if (sc) { 825 free(sc->cert); 826 free(sc->sig); 827 free(sc->name); 828 free(sc); 829 } 830 831 return (ret); 832 } 833 834 static int 835 bootstrap_pkg(bool force, const char *fetchOpts) 836 { 837 int fd_pkg, fd_sig; 838 int ret; 839 char url[MAXPATHLEN]; 840 char tmppkg[MAXPATHLEN]; 841 char tmpsig[MAXPATHLEN]; 842 const char *packagesite; 843 const char *signature_type; 844 char pkgstatic[MAXPATHLEN]; 845 const char *bootstrap_name; 846 847 fd_sig = -1; 848 ret = -1; 849 850 if (config_string(PACKAGESITE, &packagesite) != 0) { 851 warnx("No PACKAGESITE defined"); 852 return (-1); 853 } 854 855 if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 856 warnx("Error looking up SIGNATURE_TYPE"); 857 return (-1); 858 } 859 860 printf("Bootstrapping pkg from %s, please wait...\n", packagesite); 861 862 /* Support pkg+http:// for PACKAGESITE which is the new format 863 in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has 864 no A record. */ 865 if (strncmp(URL_SCHEME_PREFIX, packagesite, 866 strlen(URL_SCHEME_PREFIX)) == 0) 867 packagesite += strlen(URL_SCHEME_PREFIX); 868 for (int j = 0; bootstrap_names[j] != NULL; j++) { 869 bootstrap_name = bootstrap_names[j]; 870 871 snprintf(url, MAXPATHLEN, "%s/Latest/%s", packagesite, bootstrap_name); 872 snprintf(tmppkg, MAXPATHLEN, "%s/%s.XXXXXX", 873 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 874 bootstrap_name); 875 if ((fd_pkg = fetch_to_fd(url, tmppkg, fetchOpts)) != -1) 876 break; 877 bootstrap_name = NULL; 878 } 879 if (bootstrap_name == NULL) 880 goto fetchfail; 881 882 if (signature_type != NULL && 883 strcasecmp(signature_type, "NONE") != 0) { 884 if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 885 886 snprintf(tmpsig, MAXPATHLEN, "%s/%s.sig.XXXXXX", 887 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 888 bootstrap_name); 889 snprintf(url, MAXPATHLEN, "%s/Latest/%s.sig", 890 packagesite, bootstrap_name); 891 892 if ((fd_sig = fetch_to_fd(url, tmpsig, fetchOpts)) == -1) { 893 fprintf(stderr, "Signature for pkg not " 894 "available.\n"); 895 goto fetchfail; 896 } 897 898 if (verify_signature(fd_pkg, fd_sig) == false) 899 goto cleanup; 900 } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 901 902 snprintf(tmpsig, MAXPATHLEN, 903 "%s/%s.pubkeysig.XXXXXX", 904 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 905 bootstrap_name); 906 snprintf(url, MAXPATHLEN, "%s/Latest/%s.pubkeysig", 907 packagesite, bootstrap_name); 908 909 if ((fd_sig = fetch_to_fd(url, tmpsig, fetchOpts)) == -1) { 910 fprintf(stderr, "Signature for pkg not " 911 "available.\n"); 912 goto fetchfail; 913 } 914 915 if (verify_pubsignature(fd_pkg, fd_sig) == false) 916 goto cleanup; 917 } else { 918 warnx("Signature type %s is not supported for " 919 "bootstrapping.", signature_type); 920 goto cleanup; 921 } 922 } 923 924 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 925 ret = install_pkg_static(pkgstatic, tmppkg, force); 926 927 goto cleanup; 928 929 fetchfail: 930 warnx("Error fetching %s: %s", url, fetchLastErrString); 931 if (fetchLastErrCode == FETCH_RESOLV) { 932 fprintf(stderr, "Address resolution failed for %s.\n", packagesite); 933 fprintf(stderr, "Consider changing PACKAGESITE.\n"); 934 } else { 935 fprintf(stderr, "A pre-built version of pkg could not be found for " 936 "your system.\n"); 937 fprintf(stderr, "Consider changing PACKAGESITE or installing it from " 938 "ports: 'ports-mgmt/pkg'.\n"); 939 } 940 941 cleanup: 942 if (fd_sig != -1) { 943 close(fd_sig); 944 unlink(tmpsig); 945 } 946 947 if (fd_pkg != -1) { 948 close(fd_pkg); 949 unlink(tmppkg); 950 } 951 952 return (ret); 953 } 954 955 static const char confirmation_message[] = 956 "The package management tool is not yet installed on your system.\n" 957 "Do you want to fetch and install it now? [y/N]: "; 958 959 static const char non_interactive_message[] = 960 "The package management tool is not yet installed on your system.\n" 961 "Please set ASSUME_ALWAYS_YES=yes environment variable to be able to bootstrap " 962 "in non-interactive (stdin not being a tty)\n"; 963 964 static const char args_bootstrap_message[] = 965 "Too many arguments\n" 966 "Usage: pkg [-4|-6] bootstrap [-f] [-y]\n"; 967 968 static const char args_add_message[] = 969 "Too many arguments\n" 970 "Usage: pkg add [-f] [-y] {pkg.txz}\n"; 971 972 static int 973 pkg_query_yes_no(void) 974 { 975 int ret, c; 976 977 fflush(stdout); 978 c = getchar(); 979 980 if (c == 'y' || c == 'Y') 981 ret = 1; 982 else 983 ret = 0; 984 985 while (c != '\n' && c != EOF) 986 c = getchar(); 987 988 return (ret); 989 } 990 991 static int 992 bootstrap_pkg_local(const char *pkgpath, bool force) 993 { 994 char path[MAXPATHLEN]; 995 char pkgstatic[MAXPATHLEN]; 996 const char *signature_type; 997 int fd_pkg, fd_sig, ret; 998 999 fd_sig = -1; 1000 ret = -1; 1001 1002 fd_pkg = open(pkgpath, O_RDONLY); 1003 if (fd_pkg == -1) 1004 err(EXIT_FAILURE, "Unable to open %s", pkgpath); 1005 1006 if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 1007 warnx("Error looking up SIGNATURE_TYPE"); 1008 goto cleanup; 1009 } 1010 if (signature_type != NULL && 1011 strcasecmp(signature_type, "NONE") != 0) { 1012 if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 1013 1014 snprintf(path, sizeof(path), "%s.sig", pkgpath); 1015 1016 if ((fd_sig = open(path, O_RDONLY)) == -1) { 1017 fprintf(stderr, "Signature for pkg not " 1018 "available.\n"); 1019 goto cleanup; 1020 } 1021 1022 if (verify_signature(fd_pkg, fd_sig) == false) 1023 goto cleanup; 1024 1025 } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 1026 1027 snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath); 1028 1029 if ((fd_sig = open(path, O_RDONLY)) == -1) { 1030 fprintf(stderr, "Signature for pkg not " 1031 "available.\n"); 1032 goto cleanup; 1033 } 1034 1035 if (verify_pubsignature(fd_pkg, fd_sig) == false) 1036 goto cleanup; 1037 1038 } else { 1039 warnx("Signature type %s is not supported for " 1040 "bootstrapping.", signature_type); 1041 goto cleanup; 1042 } 1043 } 1044 1045 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 1046 ret = install_pkg_static(pkgstatic, pkgpath, force); 1047 1048 cleanup: 1049 close(fd_pkg); 1050 if (fd_sig != -1) 1051 close(fd_sig); 1052 1053 return (ret); 1054 } 1055 1056 int 1057 main(int argc, char *argv[]) 1058 { 1059 char pkgpath[MAXPATHLEN]; 1060 const char *pkgarg, *repo_name; 1061 bool activation_test, add_pkg, bootstrap_only, force, yes; 1062 signed char ch; 1063 const char *fetchOpts; 1064 char *command; 1065 1066 activation_test = false; 1067 add_pkg = false; 1068 bootstrap_only = false; 1069 command = NULL; 1070 fetchOpts = ""; 1071 force = false; 1072 pkgarg = NULL; 1073 repo_name = NULL; 1074 yes = false; 1075 1076 struct option longopts[] = { 1077 { "force", no_argument, NULL, 'f' }, 1078 { "only-ipv4", no_argument, NULL, '4' }, 1079 { "only-ipv6", no_argument, NULL, '6' }, 1080 { "yes", no_argument, NULL, 'y' }, 1081 { NULL, 0, NULL, 0 }, 1082 }; 1083 1084 snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", getlocalbase()); 1085 1086 while ((ch = getopt_long(argc, argv, "-:fr::yN46", longopts, NULL)) != -1) { 1087 switch (ch) { 1088 case 'f': 1089 force = true; 1090 break; 1091 case 'N': 1092 activation_test = true; 1093 break; 1094 case 'y': 1095 yes = true; 1096 break; 1097 case '4': 1098 fetchOpts = "4"; 1099 break; 1100 case '6': 1101 fetchOpts = "6"; 1102 break; 1103 case 'r': 1104 /* 1105 * The repository can only be specified for an explicit 1106 * bootstrap request at this time, so that we don't 1107 * confuse the user if they're trying to use a verb that 1108 * has some other conflicting meaning but we need to 1109 * bootstrap. 1110 * 1111 * For that reason, we specify that -r has an optional 1112 * argument above and process the next index ourselves. 1113 * This is mostly significant because getopt(3) will 1114 * otherwise eat the next argument, which could be 1115 * something we need to try and make sense of. 1116 * 1117 * At worst this gets us false positives that we ignore 1118 * in other contexts, and we have to do a little fudging 1119 * in order to support separating -r from the reponame 1120 * with a space since it's not actually optional in 1121 * the bootstrap/add sense. 1122 */ 1123 if (add_pkg || bootstrap_only) { 1124 if (optarg != NULL) { 1125 repo_name = optarg; 1126 } else if (optind < argc) { 1127 repo_name = argv[optind]; 1128 } 1129 1130 if (repo_name == NULL || *repo_name == '\0') { 1131 fprintf(stderr, 1132 "Must specify a repository with -r!\n"); 1133 exit(EXIT_FAILURE); 1134 } 1135 1136 if (optarg == NULL) { 1137 /* Advance past repo name. */ 1138 optreset = 1; 1139 optind++; 1140 } 1141 } 1142 break; 1143 case 1: 1144 // Non-option arguments, first one is the command 1145 if (command == NULL) { 1146 command = argv[optind-1]; 1147 if (strcmp(command, "add") == 0) { 1148 add_pkg = true; 1149 } 1150 else if (strcmp(command, "bootstrap") == 0) { 1151 bootstrap_only = true; 1152 } 1153 } 1154 // bootstrap doesn't accept other arguments 1155 else if (bootstrap_only) { 1156 fprintf(stderr, args_bootstrap_message); 1157 exit(EXIT_FAILURE); 1158 } 1159 // For add, we accept exactly one further argument 1160 else if (add_pkg && pkgarg != NULL) { 1161 fprintf(stderr, args_add_message); 1162 exit(EXIT_FAILURE); 1163 } 1164 else if (add_pkg) { 1165 pkgarg = argv[optind-1]; 1166 } 1167 break; 1168 default: 1169 break; 1170 } 1171 } 1172 1173 if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) { 1174 /* 1175 * To allow 'pkg -N' to be used as a reliable test for whether 1176 * a system is configured to use pkg, don't bootstrap pkg 1177 * when that that option is passed. 1178 */ 1179 if (activation_test) 1180 errx(EXIT_FAILURE, "pkg is not installed"); 1181 1182 config_init(repo_name); 1183 1184 if (add_pkg) { 1185 if (pkgarg == NULL) { 1186 fprintf(stderr, "Path to pkg.txz required\n"); 1187 exit(EXIT_FAILURE); 1188 } 1189 if (access(pkgarg, R_OK) == -1) { 1190 fprintf(stderr, "No such file: %s\n", pkgarg); 1191 exit(EXIT_FAILURE); 1192 } 1193 if (bootstrap_pkg_local(pkgarg, force) != 0) 1194 exit(EXIT_FAILURE); 1195 exit(EXIT_SUCCESS); 1196 } 1197 /* 1198 * Do not ask for confirmation if either of stdin or stdout is 1199 * not tty. Check the environment to see if user has answer 1200 * tucked in there already. 1201 */ 1202 if (!yes) 1203 config_bool(ASSUME_ALWAYS_YES, &yes); 1204 if (!yes) { 1205 if (!isatty(fileno(stdin))) { 1206 fprintf(stderr, non_interactive_message); 1207 exit(EXIT_FAILURE); 1208 } 1209 1210 printf("%s", confirmation_message); 1211 if (pkg_query_yes_no() == 0) 1212 exit(EXIT_FAILURE); 1213 } 1214 if (bootstrap_pkg(force, fetchOpts) != 0) 1215 exit(EXIT_FAILURE); 1216 config_finish(); 1217 1218 if (bootstrap_only) 1219 exit(EXIT_SUCCESS); 1220 } else if (bootstrap_only) { 1221 printf("pkg already bootstrapped at %s\n", pkgpath); 1222 exit(EXIT_SUCCESS); 1223 } 1224 1225 execv(pkgpath, argv); 1226 1227 /* NOT REACHED */ 1228 return (EXIT_FAILURE); 1229 } 1230