1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #include <sys/param.h> 32 #include <sys/queue.h> 33 #include <sys/types.h> 34 #include <sys/wait.h> 35 36 #include <archive.h> 37 #include <archive_entry.h> 38 #include <dirent.h> 39 #include <err.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <fetch.h> 43 #include <getopt.h> 44 #include <libutil.h> 45 #include <paths.h> 46 #include <stdbool.h> 47 #include <stdlib.h> 48 #include <stdio.h> 49 #include <string.h> 50 #include <ucl.h> 51 52 #include <openssl/err.h> 53 #include <openssl/ssl.h> 54 55 #include "dns_utils.h" 56 #include "config.h" 57 #include "hash.h" 58 59 struct sig_cert { 60 char *name; 61 unsigned char *sig; 62 int siglen; 63 unsigned char *cert; 64 int certlen; 65 bool trusted; 66 }; 67 68 struct pubkey { 69 unsigned char *sig; 70 int siglen; 71 }; 72 73 typedef enum { 74 HASH_UNKNOWN, 75 HASH_SHA256, 76 } hash_t; 77 78 struct fingerprint { 79 hash_t type; 80 char *name; 81 char hash[BUFSIZ]; 82 STAILQ_ENTRY(fingerprint) next; 83 }; 84 85 static const char *bootstrap_names [] = { 86 "pkg.pkg", 87 "pkg.txz", 88 NULL 89 }; 90 91 STAILQ_HEAD(fingerprint_list, fingerprint); 92 93 static int debug; 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 current = current->next; 242 if (current == NULL) 243 current = mirrors; 244 } 245 } 246 } 247 248 while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) { 249 if (write(fd, buf, r) != r) { 250 warn("write()"); 251 goto fetchfail; 252 } 253 } 254 255 if (r != 0) { 256 warn("An error occurred while fetching pkg(8)"); 257 goto fetchfail; 258 } 259 260 if (ferror(remote)) 261 goto fetchfail; 262 263 goto cleanup; 264 265 fetchfail: 266 if (fd != -1) { 267 close(fd); 268 fd = -1; 269 unlink(path); 270 } 271 272 cleanup: 273 if (remote != NULL) 274 fclose(remote); 275 276 return fd; 277 } 278 279 static struct fingerprint * 280 parse_fingerprint(ucl_object_t *obj) 281 { 282 const ucl_object_t *cur; 283 ucl_object_iter_t it = NULL; 284 const char *function, *fp, *key; 285 struct fingerprint *f; 286 hash_t fct = HASH_UNKNOWN; 287 288 function = fp = NULL; 289 290 while ((cur = ucl_iterate_object(obj, &it, true))) { 291 key = ucl_object_key(cur); 292 if (cur->type != UCL_STRING) 293 continue; 294 if (strcasecmp(key, "function") == 0) { 295 function = ucl_object_tostring(cur); 296 continue; 297 } 298 if (strcasecmp(key, "fingerprint") == 0) { 299 fp = ucl_object_tostring(cur); 300 continue; 301 } 302 } 303 304 if (fp == NULL || function == NULL) 305 return (NULL); 306 307 if (strcasecmp(function, "sha256") == 0) 308 fct = HASH_SHA256; 309 310 if (fct == HASH_UNKNOWN) { 311 warnx("Unsupported hashing function: %s", function); 312 return (NULL); 313 } 314 315 f = calloc(1, sizeof(struct fingerprint)); 316 f->type = fct; 317 strlcpy(f->hash, fp, sizeof(f->hash)); 318 319 return (f); 320 } 321 322 static void 323 free_fingerprint_list(struct fingerprint_list* list) 324 { 325 struct fingerprint *fingerprint, *tmp; 326 327 STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) { 328 free(fingerprint->name); 329 free(fingerprint); 330 } 331 free(list); 332 } 333 334 static struct fingerprint * 335 load_fingerprint(const char *dir, const char *filename) 336 { 337 ucl_object_t *obj = NULL; 338 struct ucl_parser *p = NULL; 339 struct fingerprint *f; 340 char path[MAXPATHLEN]; 341 342 f = NULL; 343 344 snprintf(path, MAXPATHLEN, "%s/%s", dir, filename); 345 346 p = ucl_parser_new(0); 347 if (!ucl_parser_add_file(p, path)) { 348 warnx("%s: %s", path, ucl_parser_get_error(p)); 349 ucl_parser_free(p); 350 return (NULL); 351 } 352 353 obj = ucl_parser_get_object(p); 354 355 if (obj->type == UCL_OBJECT) 356 f = parse_fingerprint(obj); 357 358 if (f != NULL) 359 f->name = strdup(filename); 360 361 ucl_object_unref(obj); 362 ucl_parser_free(p); 363 364 return (f); 365 } 366 367 static struct fingerprint_list * 368 load_fingerprints(const char *path, int *count) 369 { 370 DIR *d; 371 struct dirent *ent; 372 struct fingerprint *finger; 373 struct fingerprint_list *fingerprints; 374 375 *count = 0; 376 377 fingerprints = calloc(1, sizeof(struct fingerprint_list)); 378 if (fingerprints == NULL) 379 return (NULL); 380 STAILQ_INIT(fingerprints); 381 382 if ((d = opendir(path)) == NULL) { 383 free(fingerprints); 384 385 return (NULL); 386 } 387 388 while ((ent = readdir(d))) { 389 if (strcmp(ent->d_name, ".") == 0 || 390 strcmp(ent->d_name, "..") == 0) 391 continue; 392 finger = load_fingerprint(path, ent->d_name); 393 if (finger != NULL) { 394 STAILQ_INSERT_TAIL(fingerprints, finger, next); 395 ++(*count); 396 } 397 } 398 399 closedir(d); 400 401 return (fingerprints); 402 } 403 404 static EVP_PKEY * 405 load_public_key_file(const char *file) 406 { 407 EVP_PKEY *pkey; 408 BIO *bp; 409 char errbuf[1024]; 410 411 bp = BIO_new_file(file, "r"); 412 if (!bp) 413 errx(EXIT_FAILURE, "Unable to read %s", file); 414 415 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 416 warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 417 418 BIO_free(bp); 419 420 return (pkey); 421 } 422 423 static EVP_PKEY * 424 load_public_key_buf(const unsigned char *cert, int certlen) 425 { 426 EVP_PKEY *pkey; 427 BIO *bp; 428 char errbuf[1024]; 429 430 bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 431 432 if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 433 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 434 435 BIO_free(bp); 436 437 return (pkey); 438 } 439 440 static bool 441 rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key, 442 int keylen, unsigned char *sig, int siglen) 443 { 444 EVP_MD_CTX *mdctx; 445 EVP_PKEY *pkey; 446 char *sha256; 447 char errbuf[1024]; 448 bool ret; 449 450 sha256 = NULL; 451 pkey = NULL; 452 mdctx = NULL; 453 ret = false; 454 455 SSL_load_error_strings(); 456 457 /* Compute SHA256 of the package. */ 458 if (lseek(fd, 0, 0) == -1) { 459 warn("lseek"); 460 goto cleanup; 461 } 462 if ((sha256 = sha256_fd(fd)) == NULL) { 463 warnx("Error creating SHA256 hash for package"); 464 goto cleanup; 465 } 466 467 if (sigfile != NULL) { 468 if ((pkey = load_public_key_file(sigfile)) == NULL) { 469 warnx("Error reading public key"); 470 goto cleanup; 471 } 472 } else { 473 if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 474 warnx("Error reading public key"); 475 goto cleanup; 476 } 477 } 478 479 /* Verify signature of the SHA256(pkg) is valid. */ 480 if ((mdctx = EVP_MD_CTX_create()) == NULL) { 481 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 482 goto error; 483 } 484 485 if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 486 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 487 goto error; 488 } 489 if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) { 490 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 491 goto error; 492 } 493 494 if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 495 warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 496 goto error; 497 } 498 499 ret = true; 500 printf("done\n"); 501 goto cleanup; 502 503 error: 504 printf("failed\n"); 505 506 cleanup: 507 free(sha256); 508 if (pkey) 509 EVP_PKEY_free(pkey); 510 if (mdctx) 511 EVP_MD_CTX_destroy(mdctx); 512 ERR_free_strings(); 513 514 return (ret); 515 } 516 517 static struct pubkey * 518 read_pubkey(int fd) 519 { 520 struct pubkey *pk; 521 char *sigb; 522 size_t sigsz; 523 FILE *sig; 524 char buf[4096]; 525 int r; 526 527 if (lseek(fd, 0, 0) == -1) { 528 warn("lseek"); 529 return (NULL); 530 } 531 532 sigsz = 0; 533 sigb = NULL; 534 sig = open_memstream(&sigb, &sigsz); 535 if (sig == NULL) 536 err(EXIT_FAILURE, "open_memstream()"); 537 538 while ((r = read(fd, buf, sizeof(buf))) >0) { 539 fwrite(buf, 1, r, sig); 540 } 541 542 fclose(sig); 543 pk = calloc(1, sizeof(struct pubkey)); 544 pk->siglen = sigsz; 545 pk->sig = calloc(1, pk->siglen); 546 memcpy(pk->sig, sigb, pk->siglen); 547 free(sigb); 548 549 return (pk); 550 } 551 552 static struct sig_cert * 553 parse_cert(int fd) { 554 int my_fd; 555 struct sig_cert *sc; 556 FILE *fp, *sigfp, *certfp, *tmpfp; 557 char *line; 558 char *sig, *cert; 559 size_t linecap, sigsz, certsz; 560 ssize_t linelen; 561 562 sc = NULL; 563 line = NULL; 564 linecap = 0; 565 sig = cert = NULL; 566 sigfp = certfp = tmpfp = NULL; 567 568 if (lseek(fd, 0, 0) == -1) { 569 warn("lseek"); 570 return (NULL); 571 } 572 573 /* Duplicate the fd so that fclose(3) does not close it. */ 574 if ((my_fd = dup(fd)) == -1) { 575 warnx("dup"); 576 return (NULL); 577 } 578 579 if ((fp = fdopen(my_fd, "rb")) == NULL) { 580 warn("fdopen"); 581 close(my_fd); 582 return (NULL); 583 } 584 585 sigsz = certsz = 0; 586 sigfp = open_memstream(&sig, &sigsz); 587 if (sigfp == NULL) 588 err(EXIT_FAILURE, "open_memstream()"); 589 certfp = open_memstream(&cert, &certsz); 590 if (certfp == NULL) 591 err(EXIT_FAILURE, "open_memstream()"); 592 593 while ((linelen = getline(&line, &linecap, fp)) > 0) { 594 if (strcmp(line, "SIGNATURE\n") == 0) { 595 tmpfp = sigfp; 596 continue; 597 } else if (strcmp(line, "CERT\n") == 0) { 598 tmpfp = certfp; 599 continue; 600 } else if (strcmp(line, "END\n") == 0) { 601 break; 602 } 603 if (tmpfp != NULL) 604 fwrite(line, 1, linelen, tmpfp); 605 } 606 607 fclose(fp); 608 fclose(sigfp); 609 fclose(certfp); 610 611 sc = calloc(1, sizeof(struct sig_cert)); 612 sc->siglen = sigsz -1; /* Trim out unrelated trailing newline */ 613 sc->sig = sig; 614 615 sc->certlen = certsz; 616 sc->cert = cert; 617 618 return (sc); 619 } 620 621 static bool 622 verify_pubsignature(int fd_pkg, int fd_sig) 623 { 624 struct pubkey *pk; 625 const char *pubkey; 626 bool ret; 627 628 pk = NULL; 629 pubkey = NULL; 630 ret = false; 631 if (config_string(PUBKEY, &pubkey) != 0) { 632 warnx("No CONFIG_PUBKEY defined"); 633 goto cleanup; 634 } 635 636 if ((pk = read_pubkey(fd_sig)) == NULL) { 637 warnx("Error reading signature"); 638 goto cleanup; 639 } 640 641 /* Verify the signature. */ 642 printf("Verifying signature with public key %s... ", pubkey); 643 if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig, 644 pk->siglen) == false) { 645 fprintf(stderr, "Signature is not valid\n"); 646 goto cleanup; 647 } 648 649 ret = true; 650 651 cleanup: 652 if (pk) { 653 free(pk->sig); 654 free(pk); 655 } 656 657 return (ret); 658 } 659 660 static bool 661 verify_signature(int fd_pkg, int fd_sig) 662 { 663 struct fingerprint_list *trusted, *revoked; 664 struct fingerprint *fingerprint; 665 struct sig_cert *sc; 666 bool ret; 667 int trusted_count, revoked_count; 668 const char *fingerprints; 669 char path[MAXPATHLEN]; 670 char *hash; 671 672 hash = NULL; 673 sc = NULL; 674 trusted = revoked = NULL; 675 ret = false; 676 677 /* Read and parse fingerprints. */ 678 if (config_string(FINGERPRINTS, &fingerprints) != 0) { 679 warnx("No CONFIG_FINGERPRINTS defined"); 680 goto cleanup; 681 } 682 683 snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints); 684 if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) { 685 warnx("Error loading trusted certificates"); 686 goto cleanup; 687 } 688 689 if (trusted_count == 0 || trusted == NULL) { 690 fprintf(stderr, "No trusted certificates found.\n"); 691 goto cleanup; 692 } 693 694 snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints); 695 if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) { 696 warnx("Error loading revoked certificates"); 697 goto cleanup; 698 } 699 700 /* Read certificate and signature in. */ 701 if ((sc = parse_cert(fd_sig)) == NULL) { 702 warnx("Error parsing certificate"); 703 goto cleanup; 704 } 705 /* Explicitly mark as non-trusted until proven otherwise. */ 706 sc->trusted = false; 707 708 /* Parse signature and pubkey out of the certificate */ 709 hash = sha256_buf(sc->cert, sc->certlen); 710 711 /* Check if this hash is revoked */ 712 if (revoked != NULL) { 713 STAILQ_FOREACH(fingerprint, revoked, next) { 714 if (strcasecmp(fingerprint->hash, hash) == 0) { 715 fprintf(stderr, "The package was signed with " 716 "revoked certificate %s\n", 717 fingerprint->name); 718 goto cleanup; 719 } 720 } 721 } 722 723 STAILQ_FOREACH(fingerprint, trusted, next) { 724 if (strcasecmp(fingerprint->hash, hash) == 0) { 725 sc->trusted = true; 726 sc->name = strdup(fingerprint->name); 727 break; 728 } 729 } 730 731 if (sc->trusted == false) { 732 fprintf(stderr, "No trusted fingerprint found matching " 733 "package's certificate\n"); 734 goto cleanup; 735 } 736 737 /* Verify the signature. */ 738 printf("Verifying signature with trusted certificate %s... ", sc->name); 739 if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig, 740 sc->siglen) == false) { 741 fprintf(stderr, "Signature is not valid\n"); 742 goto cleanup; 743 } 744 745 ret = true; 746 747 cleanup: 748 free(hash); 749 if (trusted) 750 free_fingerprint_list(trusted); 751 if (revoked) 752 free_fingerprint_list(revoked); 753 if (sc) { 754 free(sc->cert); 755 free(sc->sig); 756 free(sc->name); 757 free(sc); 758 } 759 760 return (ret); 761 } 762 763 static int 764 bootstrap_pkg(bool force, const char *fetchOpts) 765 { 766 int fd_pkg, fd_sig; 767 int ret; 768 char url[MAXPATHLEN]; 769 char tmppkg[MAXPATHLEN]; 770 char tmpsig[MAXPATHLEN]; 771 const char *packagesite; 772 const char *signature_type; 773 char pkgstatic[MAXPATHLEN]; 774 const char *bootstrap_name; 775 776 fd_sig = -1; 777 ret = -1; 778 779 if (config_string(PACKAGESITE, &packagesite) != 0) { 780 warnx("No PACKAGESITE defined"); 781 return (-1); 782 } 783 784 if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 785 warnx("Error looking up SIGNATURE_TYPE"); 786 return (-1); 787 } 788 789 printf("Bootstrapping pkg from %s, please wait...\n", packagesite); 790 791 /* Support pkg+http:// for PACKAGESITE which is the new format 792 in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has 793 no A record. */ 794 if (strncmp(URL_SCHEME_PREFIX, packagesite, 795 strlen(URL_SCHEME_PREFIX)) == 0) 796 packagesite += strlen(URL_SCHEME_PREFIX); 797 for (int j = 0; bootstrap_names[j] != NULL; j++) { 798 bootstrap_name = bootstrap_names[j]; 799 800 snprintf(url, MAXPATHLEN, "%s/Latest/%s", packagesite, bootstrap_name); 801 snprintf(tmppkg, MAXPATHLEN, "%s/%s.XXXXXX", 802 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 803 bootstrap_name); 804 if ((fd_pkg = fetch_to_fd(url, tmppkg, fetchOpts)) != -1) 805 break; 806 bootstrap_name = NULL; 807 } 808 if (bootstrap_name == NULL) 809 goto fetchfail; 810 811 if (signature_type != NULL && 812 strcasecmp(signature_type, "NONE") != 0) { 813 if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 814 815 snprintf(tmpsig, MAXPATHLEN, "%s/%s.sig.XXXXXX", 816 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 817 bootstrap_name); 818 snprintf(url, MAXPATHLEN, "%s/Latest/%s.sig", 819 packagesite, bootstrap_name); 820 821 if ((fd_sig = fetch_to_fd(url, tmpsig, fetchOpts)) == -1) { 822 fprintf(stderr, "Signature for pkg not " 823 "available.\n"); 824 goto fetchfail; 825 } 826 827 if (verify_signature(fd_pkg, fd_sig) == false) 828 goto cleanup; 829 } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 830 831 snprintf(tmpsig, MAXPATHLEN, 832 "%s/%s.pubkeysig.XXXXXX", 833 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP, 834 bootstrap_name); 835 snprintf(url, MAXPATHLEN, "%s/Latest/%s.pubkeysig", 836 packagesite, bootstrap_name); 837 838 if ((fd_sig = fetch_to_fd(url, tmpsig, fetchOpts)) == -1) { 839 fprintf(stderr, "Signature for pkg not " 840 "available.\n"); 841 goto fetchfail; 842 } 843 844 if (verify_pubsignature(fd_pkg, fd_sig) == false) 845 goto cleanup; 846 } else { 847 warnx("Signature type %s is not supported for " 848 "bootstrapping.", signature_type); 849 goto cleanup; 850 } 851 } 852 853 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 854 ret = install_pkg_static(pkgstatic, tmppkg, force); 855 856 goto cleanup; 857 858 fetchfail: 859 warnx("Error fetching %s: %s", url, fetchLastErrString); 860 if (fetchLastErrCode == FETCH_RESOLV) { 861 fprintf(stderr, "Address resolution failed for %s.\n", packagesite); 862 fprintf(stderr, "Consider changing PACKAGESITE.\n"); 863 } else { 864 fprintf(stderr, "A pre-built version of pkg could not be found for " 865 "your system.\n"); 866 fprintf(stderr, "Consider changing PACKAGESITE or installing it from " 867 "ports: 'ports-mgmt/pkg'.\n"); 868 } 869 870 cleanup: 871 if (fd_sig != -1) { 872 close(fd_sig); 873 unlink(tmpsig); 874 } 875 876 if (fd_pkg != -1) { 877 close(fd_pkg); 878 unlink(tmppkg); 879 } 880 881 return (ret); 882 } 883 884 static const char confirmation_message[] = 885 "The package management tool is not yet installed on your system.\n" 886 "Do you want to fetch and install it now? [y/N]: "; 887 888 static const char non_interactive_message[] = 889 "The package management tool is not yet installed on your system.\n" 890 "Please set ASSUME_ALWAYS_YES=yes environment variable to be able to bootstrap " 891 "in non-interactive (stdin not being a tty)\n"; 892 893 static const char args_bootstrap_message[] = 894 "Too many arguments\n" 895 "Usage: pkg [-4|-6] bootstrap [-f] [-y]\n"; 896 897 static const char args_add_message[] = 898 "Too many arguments\n" 899 "Usage: pkg add [-f] [-y] {pkg.txz}\n"; 900 901 static int 902 pkg_query_yes_no(void) 903 { 904 int ret, c; 905 906 fflush(stdout); 907 c = getchar(); 908 909 if (c == 'y' || c == 'Y') 910 ret = 1; 911 else 912 ret = 0; 913 914 while (c != '\n' && c != EOF) 915 c = getchar(); 916 917 return (ret); 918 } 919 920 static int 921 bootstrap_pkg_local(const char *pkgpath, bool force) 922 { 923 char path[MAXPATHLEN]; 924 char pkgstatic[MAXPATHLEN]; 925 const char *signature_type; 926 int fd_pkg, fd_sig, ret; 927 928 fd_sig = -1; 929 ret = -1; 930 931 fd_pkg = open(pkgpath, O_RDONLY); 932 if (fd_pkg == -1) 933 err(EXIT_FAILURE, "Unable to open %s", pkgpath); 934 935 if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 936 warnx("Error looking up SIGNATURE_TYPE"); 937 goto cleanup; 938 } 939 if (signature_type != NULL && 940 strcasecmp(signature_type, "NONE") != 0) { 941 if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 942 943 snprintf(path, sizeof(path), "%s.sig", pkgpath); 944 945 if ((fd_sig = open(path, O_RDONLY)) == -1) { 946 fprintf(stderr, "Signature for pkg not " 947 "available.\n"); 948 goto cleanup; 949 } 950 951 if (verify_signature(fd_pkg, fd_sig) == false) 952 goto cleanup; 953 954 } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 955 956 snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath); 957 958 if ((fd_sig = open(path, O_RDONLY)) == -1) { 959 fprintf(stderr, "Signature for pkg not " 960 "available.\n"); 961 goto cleanup; 962 } 963 964 if (verify_pubsignature(fd_pkg, fd_sig) == false) 965 goto cleanup; 966 967 } else { 968 warnx("Signature type %s is not supported for " 969 "bootstrapping.", signature_type); 970 goto cleanup; 971 } 972 } 973 974 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 975 ret = install_pkg_static(pkgstatic, pkgpath, force); 976 977 cleanup: 978 close(fd_pkg); 979 if (fd_sig != -1) 980 close(fd_sig); 981 982 return (ret); 983 } 984 985 #define PKG_NAME "pkg" 986 #define PKG_DEVEL_NAME PKG_NAME "-devel" 987 #define PKG_PKG PKG_NAME "." 988 989 static bool 990 pkg_is_pkg_pkg(const char *pkg) 991 { 992 char *vstart, *basename; 993 size_t namelen; 994 995 /* Strip path. */ 996 if ((basename = strrchr(pkg, '/')) != NULL) 997 pkg = basename + 1; 998 999 /* 1000 * Chop off the final "-" (version delimiter) and check the name that 1001 * precedes it. If we didn't have a version delimiter, it must be the 1002 * pkg.$archive short form but we'll check it anyways. pkg-devel short 1003 * form will look like a pkg archive with 'devel' version, but that's 1004 * OK. We otherwise assumed that non-pkg packages will always have a 1005 * version component. 1006 */ 1007 vstart = strrchr(pkg, '-'); 1008 if (vstart == NULL) { 1009 return (strlen(pkg) > sizeof(PKG_PKG) - 1 && 1010 strncmp(pkg, PKG_PKG, sizeof(PKG_PKG) - 1) == 0); 1011 } 1012 1013 namelen = vstart - pkg; 1014 if (namelen == sizeof(PKG_NAME) - 1 && 1015 strncmp(pkg, PKG_NAME, sizeof(PKG_NAME) - 1) == 0) 1016 return (true); 1017 if (namelen == sizeof(PKG_DEVEL_NAME) - 1 && 1018 strncmp(pkg, PKG_DEVEL_NAME, sizeof(PKG_DEVEL_NAME) - 1) == 0) 1019 return (true); 1020 return (false); 1021 } 1022 1023 int 1024 main(int argc, char *argv[]) 1025 { 1026 char pkgpath[MAXPATHLEN]; 1027 const char *pkgarg, *repo_name; 1028 bool activation_test, add_pkg, bootstrap_only, force, yes; 1029 signed char ch; 1030 const char *fetchOpts; 1031 char *command; 1032 1033 activation_test = false; 1034 add_pkg = false; 1035 bootstrap_only = false; 1036 command = NULL; 1037 fetchOpts = ""; 1038 force = false; 1039 pkgarg = NULL; 1040 repo_name = NULL; 1041 yes = false; 1042 1043 struct option longopts[] = { 1044 { "debug", no_argument, NULL, 'd' }, 1045 { "force", no_argument, NULL, 'f' }, 1046 { "only-ipv4", no_argument, NULL, '4' }, 1047 { "only-ipv6", no_argument, NULL, '6' }, 1048 { "yes", no_argument, NULL, 'y' }, 1049 { NULL, 0, NULL, 0 }, 1050 }; 1051 1052 snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", getlocalbase()); 1053 1054 while ((ch = getopt_long(argc, argv, "-:dfr::yN46", longopts, NULL)) != -1) { 1055 switch (ch) { 1056 case 'd': 1057 debug++; 1058 break; 1059 case 'f': 1060 force = true; 1061 break; 1062 case 'N': 1063 activation_test = true; 1064 break; 1065 case 'y': 1066 yes = true; 1067 break; 1068 case '4': 1069 fetchOpts = "4"; 1070 break; 1071 case '6': 1072 fetchOpts = "6"; 1073 break; 1074 case 'r': 1075 /* 1076 * The repository can only be specified for an explicit 1077 * bootstrap request at this time, so that we don't 1078 * confuse the user if they're trying to use a verb that 1079 * has some other conflicting meaning but we need to 1080 * bootstrap. 1081 * 1082 * For that reason, we specify that -r has an optional 1083 * argument above and process the next index ourselves. 1084 * This is mostly significant because getopt(3) will 1085 * otherwise eat the next argument, which could be 1086 * something we need to try and make sense of. 1087 * 1088 * At worst this gets us false positives that we ignore 1089 * in other contexts, and we have to do a little fudging 1090 * in order to support separating -r from the reponame 1091 * with a space since it's not actually optional in 1092 * the bootstrap/add sense. 1093 */ 1094 if (add_pkg || bootstrap_only) { 1095 if (optarg != NULL) { 1096 repo_name = optarg; 1097 } else if (optind < argc) { 1098 repo_name = argv[optind]; 1099 } 1100 1101 if (repo_name == NULL || *repo_name == '\0') { 1102 fprintf(stderr, 1103 "Must specify a repository with -r!\n"); 1104 exit(EXIT_FAILURE); 1105 } 1106 1107 if (optarg == NULL) { 1108 /* Advance past repo name. */ 1109 optreset = 1; 1110 optind++; 1111 } 1112 } 1113 break; 1114 case 1: 1115 // Non-option arguments, first one is the command 1116 if (command == NULL) { 1117 command = argv[optind-1]; 1118 if (strcmp(command, "add") == 0) { 1119 add_pkg = true; 1120 } 1121 else if (strcmp(command, "bootstrap") == 0) { 1122 bootstrap_only = true; 1123 } 1124 } 1125 // bootstrap doesn't accept other arguments 1126 else if (bootstrap_only) { 1127 fprintf(stderr, args_bootstrap_message); 1128 exit(EXIT_FAILURE); 1129 } 1130 else if (add_pkg && pkgarg != NULL) { 1131 /* 1132 * Additional arguments also means it's not a 1133 * local bootstrap request. 1134 */ 1135 add_pkg = false; 1136 } 1137 else if (add_pkg) { 1138 /* 1139 * If it's not a request for pkg or pkg-devel, 1140 * then we must assume they were trying to 1141 * install some other local package and we 1142 * should try to bootstrap from the repo. 1143 */ 1144 if (!pkg_is_pkg_pkg(argv[optind-1])) { 1145 add_pkg = false; 1146 } else { 1147 pkgarg = argv[optind-1]; 1148 } 1149 } 1150 break; 1151 default: 1152 break; 1153 } 1154 } 1155 if (debug > 1) 1156 fetchDebug = 1; 1157 1158 if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) { 1159 /* 1160 * To allow 'pkg -N' to be used as a reliable test for whether 1161 * a system is configured to use pkg, don't bootstrap pkg 1162 * when that option is passed. 1163 */ 1164 if (activation_test) 1165 errx(EXIT_FAILURE, "pkg is not installed"); 1166 1167 config_init(repo_name); 1168 1169 if (add_pkg) { 1170 if (pkgarg == NULL) { 1171 fprintf(stderr, "Path to pkg.txz required\n"); 1172 exit(EXIT_FAILURE); 1173 } 1174 if (access(pkgarg, R_OK) == -1) { 1175 fprintf(stderr, "No such file: %s\n", pkgarg); 1176 exit(EXIT_FAILURE); 1177 } 1178 if (bootstrap_pkg_local(pkgarg, force) != 0) 1179 exit(EXIT_FAILURE); 1180 exit(EXIT_SUCCESS); 1181 } 1182 /* 1183 * Do not ask for confirmation if either of stdin or stdout is 1184 * not tty. Check the environment to see if user has answer 1185 * tucked in there already. 1186 */ 1187 if (!yes) 1188 config_bool(ASSUME_ALWAYS_YES, &yes); 1189 if (!yes) { 1190 if (!isatty(fileno(stdin))) { 1191 fprintf(stderr, non_interactive_message); 1192 exit(EXIT_FAILURE); 1193 } 1194 1195 printf("%s", confirmation_message); 1196 if (pkg_query_yes_no() == 0) 1197 exit(EXIT_FAILURE); 1198 } 1199 if (bootstrap_pkg(force, fetchOpts) != 0) 1200 exit(EXIT_FAILURE); 1201 config_finish(); 1202 1203 if (bootstrap_only) 1204 exit(EXIT_SUCCESS); 1205 } else if (bootstrap_only) { 1206 printf("pkg already bootstrapped at %s\n", pkgpath); 1207 exit(EXIT_SUCCESS); 1208 } 1209 1210 execv(pkgpath, argv); 1211 1212 /* NOT REACHED */ 1213 return (EXIT_FAILURE); 1214 } 1215