1234313Sbapt/*- 2263020Sbapt * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org> 3257353Sbdrewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 4234313Sbapt * All rights reserved. 5234313Sbapt * 6234313Sbapt * Redistribution and use in source and binary forms, with or without 7234313Sbapt * modification, are permitted provided that the following conditions 8234313Sbapt * are met: 9234313Sbapt * 1. Redistributions of source code must retain the above copyright 10234313Sbapt * notice, this list of conditions and the following disclaimer. 11234313Sbapt * 2. Redistributions in binary form must reproduce the above copyright 12234313Sbapt * notice, this list of conditions and the following disclaimer in the 13234313Sbapt * documentation and/or other materials provided with the distribution. 14234313Sbapt * 15234313Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16234313Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17234313Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18234313Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19234313Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20234313Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21234313Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22234313Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23234313Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24234313Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25234313Sbapt * SUCH DAMAGE. 26234313Sbapt */ 27234313Sbapt 28234313Sbapt#include <sys/cdefs.h> 29234313Sbapt__FBSDID("$FreeBSD$"); 30234313Sbapt 31234313Sbapt#include <sys/param.h> 32257353Sbdrewery#include <sys/queue.h> 33257353Sbdrewery#include <sys/types.h> 34257353Sbdrewery#include <sys/sbuf.h> 35234322Sbapt#include <sys/wait.h> 36234313Sbapt 37257353Sbdrewery#define _WITH_GETLINE 38234313Sbapt#include <archive.h> 39234313Sbapt#include <archive_entry.h> 40257353Sbdrewery#include <dirent.h> 41234313Sbapt#include <err.h> 42234313Sbapt#include <errno.h> 43257309Sbapt#include <fcntl.h> 44234322Sbapt#include <fetch.h> 45234351Sbapt#include <paths.h> 46247841Sbapt#include <stdbool.h> 47234313Sbapt#include <stdlib.h> 48234313Sbapt#include <stdio.h> 49234313Sbapt#include <string.h> 50234313Sbapt#include <time.h> 51234313Sbapt#include <unistd.h> 52263020Sbapt#include <ucl.h> 53234313Sbapt 54257353Sbdrewery#include <openssl/err.h> 55257353Sbdrewery#include <openssl/ssl.h> 56257353Sbdrewery 57243883Sbapt#include "dns_utils.h" 58247841Sbapt#include "config.h" 59234313Sbapt 60257353Sbdrewerystruct sig_cert { 61257353Sbdrewery char *name; 62257353Sbdrewery unsigned char *sig; 63257353Sbdrewery int siglen; 64257353Sbdrewery unsigned char *cert; 65257353Sbdrewery int certlen; 66257353Sbdrewery bool trusted; 67257353Sbdrewery}; 68257353Sbdrewery 69287873Sdelphijstruct pubkey { 70287873Sdelphij unsigned char *sig; 71287873Sdelphij int siglen; 72287873Sdelphij}; 73287873Sdelphij 74257353Sbdrewerytypedef enum { 75257353Sbdrewery HASH_UNKNOWN, 76257353Sbdrewery HASH_SHA256, 77257353Sbdrewery} hash_t; 78257353Sbdrewery 79257353Sbdrewerystruct fingerprint { 80257353Sbdrewery hash_t type; 81257353Sbdrewery char *name; 82257353Sbdrewery char hash[BUFSIZ]; 83257353Sbdrewery STAILQ_ENTRY(fingerprint) next; 84257353Sbdrewery}; 85257353Sbdrewery 86257353SbdrewerySTAILQ_HEAD(fingerprint_list, fingerprint); 87257353Sbdrewery 88234313Sbaptstatic int 89234313Sbaptextract_pkg_static(int fd, char *p, int sz) 90234313Sbapt{ 91234313Sbapt struct archive *a; 92234313Sbapt struct archive_entry *ae; 93234313Sbapt char *end; 94234313Sbapt int ret, r; 95234313Sbapt 96234351Sbapt ret = -1; 97234313Sbapt a = archive_read_new(); 98234351Sbapt if (a == NULL) { 99234351Sbapt warn("archive_read_new"); 100234351Sbapt return (ret); 101234351Sbapt } 102247060Sbapt archive_read_support_filter_all(a); 103234313Sbapt archive_read_support_format_tar(a); 104234313Sbapt 105234351Sbapt if (lseek(fd, 0, 0) == -1) { 106234351Sbapt warn("lseek"); 107234351Sbapt goto cleanup; 108234351Sbapt } 109234313Sbapt 110234313Sbapt if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 111234351Sbapt warnx("archive_read_open_fd: %s", archive_error_string(a)); 112234313Sbapt goto cleanup; 113234313Sbapt } 114234313Sbapt 115234313Sbapt ae = NULL; 116234313Sbapt while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 117234313Sbapt end = strrchr(archive_entry_pathname(ae), '/'); 118234313Sbapt if (end == NULL) 119234313Sbapt continue; 120234313Sbapt 121234313Sbapt if (strcmp(end, "/pkg-static") == 0) { 122234313Sbapt r = archive_read_extract(a, ae, 123234322Sbapt ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 124234322Sbapt ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 125234322Sbapt ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 126234351Sbapt strlcpy(p, archive_entry_pathname(ae), sz); 127234313Sbapt break; 128234313Sbapt } 129234313Sbapt } 130234313Sbapt 131234351Sbapt if (r == ARCHIVE_OK) 132234351Sbapt ret = 0; 133234351Sbapt else 134269937Sgavin warnx("failed to extract pkg-static: %s", 135269937Sgavin archive_error_string(a)); 136234313Sbapt 137234313Sbaptcleanup: 138247060Sbapt archive_read_free(a); 139234322Sbapt return (ret); 140234313Sbapt 141234313Sbapt} 142234313Sbapt 143234313Sbaptstatic int 144257632Sbdreweryinstall_pkg_static(const char *path, const char *pkgpath, bool force) 145234313Sbapt{ 146234313Sbapt int pstat; 147234313Sbapt pid_t pid; 148234313Sbapt 149234313Sbapt switch ((pid = fork())) { 150234351Sbapt case -1: 151234351Sbapt return (-1); 152234351Sbapt case 0: 153257632Sbdrewery if (force) 154257632Sbdrewery execl(path, "pkg-static", "add", "-f", pkgpath, 155257632Sbdrewery (char *)NULL); 156257632Sbdrewery else 157257632Sbdrewery execl(path, "pkg-static", "add", pkgpath, 158257632Sbdrewery (char *)NULL); 159234351Sbapt _exit(1); 160234351Sbapt default: 161234351Sbapt break; 162234313Sbapt } 163234313Sbapt 164234351Sbapt while (waitpid(pid, &pstat, 0) == -1) 165234313Sbapt if (errno != EINTR) 166234313Sbapt return (-1); 167234313Sbapt 168234351Sbapt if (WEXITSTATUS(pstat)) 169234351Sbapt return (WEXITSTATUS(pstat)); 170234351Sbapt else if (WIFSIGNALED(pstat)) 171234351Sbapt return (128 & (WTERMSIG(pstat))); 172234351Sbapt return (pstat); 173234313Sbapt} 174234313Sbapt 175234313Sbaptstatic int 176257353Sbdreweryfetch_to_fd(const char *url, char *path) 177234313Sbapt{ 178243883Sbapt struct url *u; 179257353Sbdrewery struct dns_srvinfo *mirrors, *current; 180257353Sbdrewery struct url_stat st; 181234313Sbapt FILE *remote; 182243883Sbapt /* To store _https._tcp. + hostname + \0 */ 183257353Sbdrewery int fd; 184257353Sbdrewery int retry, max_retry; 185257353Sbdrewery off_t done, r; 186257353Sbdrewery time_t now, last; 187257353Sbdrewery char buf[10240]; 188243883Sbapt char zone[MAXHOSTNAMELEN + 13]; 189257353Sbdrewery static const char *mirror_type = NULL; 190234313Sbapt 191234313Sbapt done = 0; 192234351Sbapt last = 0; 193243883Sbapt max_retry = 3; 194257353Sbdrewery current = mirrors = NULL; 195234313Sbapt remote = NULL; 196234313Sbapt 197257353Sbdrewery if (mirror_type == NULL && config_string(MIRROR_TYPE, &mirror_type) 198257353Sbdrewery != 0) { 199247841Sbapt warnx("No MIRROR_TYPE defined"); 200247841Sbapt return (-1); 201247841Sbapt } 202257328Sbdrewery 203257353Sbdrewery if ((fd = mkstemp(path)) == -1) { 204234313Sbapt warn("mkstemp()"); 205234322Sbapt return (-1); 206234313Sbapt } 207234313Sbapt 208243883Sbapt retry = max_retry; 209234313Sbapt 210243883Sbapt u = fetchParseURL(url); 211243883Sbapt while (remote == NULL) { 212243883Sbapt if (retry == max_retry) { 213247841Sbapt if (strcmp(u->scheme, "file") != 0 && 214247841Sbapt strcasecmp(mirror_type, "srv") == 0) { 215243883Sbapt snprintf(zone, sizeof(zone), 216243883Sbapt "_%s._tcp.%s", u->scheme, u->host); 217243883Sbapt mirrors = dns_getsrvinfo(zone); 218243883Sbapt current = mirrors; 219243883Sbapt } 220243883Sbapt } 221243883Sbapt 222257309Sbapt if (mirrors != NULL) { 223243883Sbapt strlcpy(u->host, current->host, sizeof(u->host)); 224257309Sbapt u->port = current->port; 225257309Sbapt } 226243883Sbapt 227243883Sbapt remote = fetchXGet(u, &st, ""); 228243883Sbapt if (remote == NULL) { 229243883Sbapt --retry; 230243883Sbapt if (retry <= 0) 231243883Sbapt goto fetchfail; 232243883Sbapt if (mirrors == NULL) { 233243883Sbapt sleep(1); 234243883Sbapt } else { 235243883Sbapt current = current->next; 236243883Sbapt if (current == NULL) 237243883Sbapt current = mirrors; 238243883Sbapt } 239243883Sbapt } 240243883Sbapt } 241243883Sbapt 242234351Sbapt if (remote == NULL) 243234351Sbapt goto fetchfail; 244234351Sbapt 245234313Sbapt while (done < st.size) { 246234313Sbapt if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) 247234313Sbapt break; 248234313Sbapt 249234313Sbapt if (write(fd, buf, r) != r) { 250234313Sbapt warn("write()"); 251257353Sbdrewery goto fetchfail; 252234313Sbapt } 253234313Sbapt 254234313Sbapt done += r; 255234313Sbapt now = time(NULL); 256234351Sbapt if (now > last || done == st.size) 257234313Sbapt last = now; 258234313Sbapt } 259234313Sbapt 260234351Sbapt if (ferror(remote)) 261234351Sbapt goto fetchfail; 262234313Sbapt 263257353Sbdrewery goto cleanup; 264257353Sbdrewery 265257353Sbdreweryfetchfail: 266257353Sbdrewery if (fd != -1) { 267257353Sbdrewery close(fd); 268257353Sbdrewery fd = -1; 269257353Sbdrewery unlink(path); 270257353Sbdrewery } 271257353Sbdrewery 272257353Sbdrewerycleanup: 273257353Sbdrewery if (remote != NULL) 274257353Sbdrewery fclose(remote); 275257353Sbdrewery 276257353Sbdrewery return fd; 277257353Sbdrewery} 278257353Sbdrewery 279257353Sbdrewerystatic struct fingerprint * 280263020Sbaptparse_fingerprint(ucl_object_t *obj) 281257353Sbdrewery{ 282268896Sbapt const ucl_object_t *cur; 283263020Sbapt ucl_object_iter_t it = NULL; 284263020Sbapt const char *function, *fp, *key; 285257353Sbdrewery struct fingerprint *f; 286257353Sbdrewery hash_t fct = HASH_UNKNOWN; 287257353Sbdrewery 288257353Sbdrewery function = fp = NULL; 289257353Sbdrewery 290263020Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 291263020Sbapt key = ucl_object_key(cur); 292263020Sbapt if (cur->type != UCL_STRING) 293257353Sbdrewery continue; 294263020Sbapt if (strcasecmp(key, "function") == 0) { 295263020Sbapt function = ucl_object_tostring(cur); 296263020Sbapt continue; 297257353Sbdrewery } 298263020Sbapt if (strcasecmp(key, "fingerprint") == 0) { 299263020Sbapt fp = ucl_object_tostring(cur); 300257353Sbdrewery continue; 301257353Sbdrewery } 302257353Sbdrewery } 303257353Sbdrewery 304257353Sbdrewery if (fp == NULL || function == NULL) 305257353Sbdrewery return (NULL); 306257353Sbdrewery 307257353Sbdrewery if (strcasecmp(function, "sha256") == 0) 308257353Sbdrewery fct = HASH_SHA256; 309257353Sbdrewery 310257353Sbdrewery if (fct == HASH_UNKNOWN) { 311263020Sbapt warnx("Unsupported hashing function: %s", function); 312257353Sbdrewery return (NULL); 313257353Sbdrewery } 314257353Sbdrewery 315257353Sbdrewery f = calloc(1, sizeof(struct fingerprint)); 316257353Sbdrewery f->type = fct; 317257353Sbdrewery strlcpy(f->hash, fp, sizeof(f->hash)); 318257353Sbdrewery 319257353Sbdrewery return (f); 320257353Sbdrewery} 321257353Sbdrewery 322257353Sbdrewerystatic void 323257353Sbdreweryfree_fingerprint_list(struct fingerprint_list* list) 324257353Sbdrewery{ 325258126Sglebius struct fingerprint *fingerprint, *tmp; 326257353Sbdrewery 327258126Sglebius STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) { 328257353Sbdrewery if (fingerprint->name) 329257353Sbdrewery free(fingerprint->name); 330257353Sbdrewery free(fingerprint); 331257353Sbdrewery } 332257353Sbdrewery free(list); 333257353Sbdrewery} 334257353Sbdrewery 335257353Sbdrewerystatic struct fingerprint * 336257353Sbdreweryload_fingerprint(const char *dir, const char *filename) 337257353Sbdrewery{ 338263020Sbapt ucl_object_t *obj = NULL; 339263020Sbapt struct ucl_parser *p = NULL; 340257353Sbdrewery struct fingerprint *f; 341257353Sbdrewery char path[MAXPATHLEN]; 342257353Sbdrewery 343257353Sbdrewery f = NULL; 344257353Sbdrewery 345257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/%s", dir, filename); 346257353Sbdrewery 347263020Sbapt p = ucl_parser_new(0); 348263020Sbapt if (!ucl_parser_add_file(p, path)) { 349263020Sbapt warnx("%s: %s", path, ucl_parser_get_error(p)); 350263020Sbapt ucl_parser_free(p); 351257353Sbdrewery return (NULL); 352263020Sbapt } 353257353Sbdrewery 354263020Sbapt obj = ucl_parser_get_object(p); 355257353Sbdrewery 356263020Sbapt if (obj->type == UCL_OBJECT) 357263020Sbapt f = parse_fingerprint(obj); 358257353Sbdrewery 359263020Sbapt if (f != NULL) 360263020Sbapt f->name = strdup(filename); 361257353Sbdrewery 362268896Sbapt ucl_object_unref(obj); 363263020Sbapt ucl_parser_free(p); 364257353Sbdrewery 365257353Sbdrewery return (f); 366257353Sbdrewery} 367257353Sbdrewery 368257353Sbdrewerystatic struct fingerprint_list * 369257353Sbdreweryload_fingerprints(const char *path, int *count) 370257353Sbdrewery{ 371257353Sbdrewery DIR *d; 372257353Sbdrewery struct dirent *ent; 373257353Sbdrewery struct fingerprint *finger; 374257353Sbdrewery struct fingerprint_list *fingerprints; 375257353Sbdrewery 376257353Sbdrewery *count = 0; 377257353Sbdrewery 378257353Sbdrewery fingerprints = calloc(1, sizeof(struct fingerprint_list)); 379257353Sbdrewery if (fingerprints == NULL) 380257353Sbdrewery return (NULL); 381257353Sbdrewery STAILQ_INIT(fingerprints); 382257353Sbdrewery 383257353Sbdrewery if ((d = opendir(path)) == NULL) 384257353Sbdrewery return (NULL); 385257353Sbdrewery 386257353Sbdrewery while ((ent = readdir(d))) { 387257353Sbdrewery if (strcmp(ent->d_name, ".") == 0 || 388257353Sbdrewery strcmp(ent->d_name, "..") == 0) 389257353Sbdrewery continue; 390257353Sbdrewery finger = load_fingerprint(path, ent->d_name); 391257353Sbdrewery if (finger != NULL) { 392257353Sbdrewery STAILQ_INSERT_TAIL(fingerprints, finger, next); 393257353Sbdrewery ++(*count); 394257353Sbdrewery } 395257353Sbdrewery } 396257353Sbdrewery 397257353Sbdrewery closedir(d); 398257353Sbdrewery 399257353Sbdrewery return (fingerprints); 400257353Sbdrewery} 401257353Sbdrewery 402257353Sbdrewerystatic void 403257353Sbdrewerysha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH], 404257353Sbdrewery char out[SHA256_DIGEST_LENGTH * 2 + 1]) 405257353Sbdrewery{ 406257353Sbdrewery int i; 407257353Sbdrewery 408257353Sbdrewery for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 409257353Sbdrewery sprintf(out + (i * 2), "%02x", hash[i]); 410257353Sbdrewery 411257353Sbdrewery out[SHA256_DIGEST_LENGTH * 2] = '\0'; 412257353Sbdrewery} 413257353Sbdrewery 414257353Sbdrewerystatic void 415257353Sbdrewerysha256_buf(char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 416257353Sbdrewery{ 417257353Sbdrewery unsigned char hash[SHA256_DIGEST_LENGTH]; 418257353Sbdrewery SHA256_CTX sha256; 419257353Sbdrewery 420257353Sbdrewery out[0] = '\0'; 421257353Sbdrewery 422257353Sbdrewery SHA256_Init(&sha256); 423257353Sbdrewery SHA256_Update(&sha256, buf, len); 424257353Sbdrewery SHA256_Final(hash, &sha256); 425257353Sbdrewery sha256_hash(hash, out); 426257353Sbdrewery} 427257353Sbdrewery 428257353Sbdrewerystatic int 429257353Sbdrewerysha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 430257353Sbdrewery{ 431257353Sbdrewery int my_fd; 432257353Sbdrewery FILE *fp; 433257353Sbdrewery char buffer[BUFSIZ]; 434257353Sbdrewery unsigned char hash[SHA256_DIGEST_LENGTH]; 435257353Sbdrewery size_t r; 436257353Sbdrewery int ret; 437257353Sbdrewery SHA256_CTX sha256; 438257353Sbdrewery 439257353Sbdrewery my_fd = -1; 440257353Sbdrewery fp = NULL; 441257353Sbdrewery r = 0; 442257353Sbdrewery ret = 1; 443257353Sbdrewery 444257353Sbdrewery out[0] = '\0'; 445257353Sbdrewery 446257353Sbdrewery /* Duplicate the fd so that fclose(3) does not close it. */ 447257353Sbdrewery if ((my_fd = dup(fd)) == -1) { 448257353Sbdrewery warnx("dup"); 449257353Sbdrewery goto cleanup; 450257353Sbdrewery } 451257353Sbdrewery 452257353Sbdrewery if ((fp = fdopen(my_fd, "rb")) == NULL) { 453257353Sbdrewery warnx("fdopen"); 454257353Sbdrewery goto cleanup; 455257353Sbdrewery } 456257353Sbdrewery 457257353Sbdrewery SHA256_Init(&sha256); 458257353Sbdrewery 459257353Sbdrewery while ((r = fread(buffer, 1, BUFSIZ, fp)) > 0) 460257353Sbdrewery SHA256_Update(&sha256, buffer, r); 461257353Sbdrewery 462257353Sbdrewery if (ferror(fp) != 0) { 463257353Sbdrewery warnx("fread"); 464257353Sbdrewery goto cleanup; 465257353Sbdrewery } 466257353Sbdrewery 467257353Sbdrewery SHA256_Final(hash, &sha256); 468257353Sbdrewery sha256_hash(hash, out); 469257353Sbdrewery ret = 0; 470257353Sbdrewery 471257353Sbdrewerycleanup: 472257353Sbdrewery if (fp != NULL) 473257353Sbdrewery fclose(fp); 474257353Sbdrewery else if (my_fd != -1) 475257353Sbdrewery close(my_fd); 476257353Sbdrewery (void)lseek(fd, 0, SEEK_SET); 477257353Sbdrewery 478257353Sbdrewery return (ret); 479257353Sbdrewery} 480257353Sbdrewery 481257353Sbdrewerystatic EVP_PKEY * 482287873Sdelphijload_public_key_file(const char *file) 483287873Sdelphij{ 484287873Sdelphij EVP_PKEY *pkey; 485287873Sdelphij BIO *bp; 486287873Sdelphij char errbuf[1024]; 487287873Sdelphij 488287873Sdelphij bp = BIO_new_file(file, "r"); 489287873Sdelphij if (!bp) 490287873Sdelphij errx(EXIT_FAILURE, "Unable to read %s", file); 491287873Sdelphij 492287873Sdelphij if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 493287873Sdelphij warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 494287873Sdelphij 495287873Sdelphij BIO_free(bp); 496287873Sdelphij 497287873Sdelphij return (pkey); 498287873Sdelphij} 499287873Sdelphij 500287873Sdelphijstatic EVP_PKEY * 501257353Sbdreweryload_public_key_buf(const unsigned char *cert, int certlen) 502257353Sbdrewery{ 503257353Sbdrewery EVP_PKEY *pkey; 504257353Sbdrewery BIO *bp; 505257353Sbdrewery char errbuf[1024]; 506257353Sbdrewery 507257353Sbdrewery bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 508257353Sbdrewery 509257353Sbdrewery if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 510257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 511257353Sbdrewery 512257353Sbdrewery BIO_free(bp); 513257353Sbdrewery 514257353Sbdrewery return (pkey); 515257353Sbdrewery} 516257353Sbdrewery 517257353Sbdrewerystatic bool 518287873Sdelphijrsa_verify_cert(int fd, const char *sigfile, const unsigned char *key, 519287873Sdelphij int keylen, unsigned char *sig, int siglen) 520257353Sbdrewery{ 521257353Sbdrewery EVP_MD_CTX *mdctx; 522257353Sbdrewery EVP_PKEY *pkey; 523257353Sbdrewery char sha256[(SHA256_DIGEST_LENGTH * 2) + 2]; 524257353Sbdrewery char errbuf[1024]; 525257353Sbdrewery bool ret; 526257353Sbdrewery 527257353Sbdrewery pkey = NULL; 528257353Sbdrewery mdctx = NULL; 529257353Sbdrewery ret = false; 530257353Sbdrewery 531287873Sdelphij SSL_load_error_strings(); 532287873Sdelphij 533257353Sbdrewery /* Compute SHA256 of the package. */ 534257353Sbdrewery if (lseek(fd, 0, 0) == -1) { 535257353Sbdrewery warn("lseek"); 536257353Sbdrewery goto cleanup; 537257353Sbdrewery } 538257353Sbdrewery if ((sha256_fd(fd, sha256)) == -1) { 539257353Sbdrewery warnx("Error creating SHA256 hash for package"); 540257353Sbdrewery goto cleanup; 541257353Sbdrewery } 542257353Sbdrewery 543287873Sdelphij if (sigfile != NULL) { 544287873Sdelphij if ((pkey = load_public_key_file(sigfile)) == NULL) { 545287873Sdelphij warnx("Error reading public key"); 546287873Sdelphij goto cleanup; 547287873Sdelphij } 548287873Sdelphij } else { 549287873Sdelphij if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 550287873Sdelphij warnx("Error reading public key"); 551287873Sdelphij goto cleanup; 552287873Sdelphij } 553257353Sbdrewery } 554257353Sbdrewery 555257353Sbdrewery /* Verify signature of the SHA256(pkg) is valid. */ 556257353Sbdrewery if ((mdctx = EVP_MD_CTX_create()) == NULL) { 557257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 558257353Sbdrewery goto error; 559257353Sbdrewery } 560257353Sbdrewery 561257353Sbdrewery if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 562257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 563257353Sbdrewery goto error; 564257353Sbdrewery } 565257353Sbdrewery if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) { 566257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 567257353Sbdrewery goto error; 568257353Sbdrewery } 569257353Sbdrewery 570257353Sbdrewery if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 571257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 572257353Sbdrewery goto error; 573257353Sbdrewery } 574257353Sbdrewery 575257353Sbdrewery ret = true; 576257353Sbdrewery printf("done\n"); 577257353Sbdrewery goto cleanup; 578257353Sbdrewery 579257353Sbdreweryerror: 580257353Sbdrewery printf("failed\n"); 581257353Sbdrewery 582257353Sbdrewerycleanup: 583257353Sbdrewery if (pkey) 584257353Sbdrewery EVP_PKEY_free(pkey); 585257353Sbdrewery if (mdctx) 586257353Sbdrewery EVP_MD_CTX_destroy(mdctx); 587257353Sbdrewery ERR_free_strings(); 588257353Sbdrewery 589257353Sbdrewery return (ret); 590257353Sbdrewery} 591257353Sbdrewery 592287873Sdelphijstatic struct pubkey * 593287873Sdelphijread_pubkey(int fd) 594287873Sdelphij{ 595287873Sdelphij struct pubkey *pk; 596287873Sdelphij struct sbuf *sig; 597287873Sdelphij char buf[4096]; 598287873Sdelphij int r; 599287873Sdelphij 600287873Sdelphij if (lseek(fd, 0, 0) == -1) { 601287873Sdelphij warn("lseek"); 602287873Sdelphij return (NULL); 603287873Sdelphij } 604287873Sdelphij 605287873Sdelphij sig = sbuf_new_auto(); 606287873Sdelphij 607287873Sdelphij while ((r = read(fd, buf, sizeof(buf))) >0) { 608287873Sdelphij sbuf_bcat(sig, buf, r); 609287873Sdelphij } 610287873Sdelphij 611287873Sdelphij sbuf_finish(sig); 612287873Sdelphij pk = calloc(1, sizeof(struct pubkey)); 613287873Sdelphij pk->siglen = sbuf_len(sig); 614287873Sdelphij pk->sig = calloc(1, pk->siglen); 615287873Sdelphij memcpy(pk->sig, sbuf_data(sig), pk->siglen); 616287873Sdelphij sbuf_delete(sig); 617287873Sdelphij 618287873Sdelphij return (pk); 619287873Sdelphij} 620287873Sdelphij 621257353Sbdrewerystatic struct sig_cert * 622257353Sbdreweryparse_cert(int fd) { 623257353Sbdrewery int my_fd; 624257353Sbdrewery struct sig_cert *sc; 625257353Sbdrewery FILE *fp; 626257353Sbdrewery struct sbuf *buf, *sig, *cert; 627257353Sbdrewery char *line; 628257353Sbdrewery size_t linecap; 629257353Sbdrewery ssize_t linelen; 630257353Sbdrewery 631257353Sbdrewery buf = NULL; 632257353Sbdrewery my_fd = -1; 633257353Sbdrewery sc = NULL; 634257353Sbdrewery line = NULL; 635257353Sbdrewery linecap = 0; 636257353Sbdrewery 637257353Sbdrewery if (lseek(fd, 0, 0) == -1) { 638257353Sbdrewery warn("lseek"); 639257353Sbdrewery return (NULL); 640257353Sbdrewery } 641257353Sbdrewery 642257353Sbdrewery /* Duplicate the fd so that fclose(3) does not close it. */ 643257353Sbdrewery if ((my_fd = dup(fd)) == -1) { 644257353Sbdrewery warnx("dup"); 645257353Sbdrewery return (NULL); 646257353Sbdrewery } 647257353Sbdrewery 648257353Sbdrewery if ((fp = fdopen(my_fd, "rb")) == NULL) { 649257353Sbdrewery warn("fdopen"); 650257353Sbdrewery close(my_fd); 651257353Sbdrewery return (NULL); 652257353Sbdrewery } 653257353Sbdrewery 654257353Sbdrewery sig = sbuf_new_auto(); 655257353Sbdrewery cert = sbuf_new_auto(); 656257353Sbdrewery 657257353Sbdrewery while ((linelen = getline(&line, &linecap, fp)) > 0) { 658257353Sbdrewery if (strcmp(line, "SIGNATURE\n") == 0) { 659257353Sbdrewery buf = sig; 660257353Sbdrewery continue; 661257353Sbdrewery } else if (strcmp(line, "CERT\n") == 0) { 662257353Sbdrewery buf = cert; 663257353Sbdrewery continue; 664257353Sbdrewery } else if (strcmp(line, "END\n") == 0) { 665257353Sbdrewery break; 666257353Sbdrewery } 667257353Sbdrewery if (buf != NULL) 668257353Sbdrewery sbuf_bcat(buf, line, linelen); 669257353Sbdrewery } 670257353Sbdrewery 671257353Sbdrewery fclose(fp); 672257353Sbdrewery 673257353Sbdrewery /* Trim out unrelated trailing newline */ 674257353Sbdrewery sbuf_setpos(sig, sbuf_len(sig) - 1); 675257353Sbdrewery 676257353Sbdrewery sbuf_finish(sig); 677257353Sbdrewery sbuf_finish(cert); 678257353Sbdrewery 679257353Sbdrewery sc = calloc(1, sizeof(struct sig_cert)); 680257353Sbdrewery sc->siglen = sbuf_len(sig); 681257353Sbdrewery sc->sig = calloc(1, sc->siglen); 682257353Sbdrewery memcpy(sc->sig, sbuf_data(sig), sc->siglen); 683257353Sbdrewery 684257353Sbdrewery sc->certlen = sbuf_len(cert); 685257353Sbdrewery sc->cert = strdup(sbuf_data(cert)); 686257353Sbdrewery 687257353Sbdrewery sbuf_delete(sig); 688257353Sbdrewery sbuf_delete(cert); 689257353Sbdrewery 690257353Sbdrewery return (sc); 691257353Sbdrewery} 692257353Sbdrewery 693257353Sbdrewerystatic bool 694287873Sdelphijverify_pubsignature(int fd_pkg, int fd_sig) 695287873Sdelphij{ 696287873Sdelphij struct pubkey *pk; 697287873Sdelphij const char *pubkey; 698287873Sdelphij bool ret; 699287873Sdelphij 700287873Sdelphij pk = NULL; 701287873Sdelphij pubkey = NULL; 702287873Sdelphij ret = false; 703287873Sdelphij if (config_string(PUBKEY, &pubkey) != 0) { 704287873Sdelphij warnx("No CONFIG_PUBKEY defined"); 705287873Sdelphij goto cleanup; 706287873Sdelphij } 707287873Sdelphij 708287873Sdelphij if ((pk = read_pubkey(fd_sig)) == NULL) { 709287873Sdelphij warnx("Error reading signature"); 710287873Sdelphij goto cleanup; 711287873Sdelphij } 712287873Sdelphij 713287873Sdelphij /* Verify the signature. */ 714287873Sdelphij printf("Verifying signature with public key %s... ", pubkey); 715287873Sdelphij if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig, 716287873Sdelphij pk->siglen) == false) { 717287873Sdelphij fprintf(stderr, "Signature is not valid\n"); 718287873Sdelphij goto cleanup; 719287873Sdelphij } 720287873Sdelphij 721287873Sdelphij ret = true; 722287873Sdelphij 723287873Sdelphijcleanup: 724287873Sdelphij if (pk) { 725287873Sdelphij free(pk->sig); 726287873Sdelphij free(pk); 727287873Sdelphij } 728287873Sdelphij 729287873Sdelphij return (ret); 730287873Sdelphij} 731287873Sdelphij 732287873Sdelphijstatic bool 733257353Sbdreweryverify_signature(int fd_pkg, int fd_sig) 734257353Sbdrewery{ 735257353Sbdrewery struct fingerprint_list *trusted, *revoked; 736257353Sbdrewery struct fingerprint *fingerprint; 737257353Sbdrewery struct sig_cert *sc; 738257353Sbdrewery bool ret; 739257353Sbdrewery int trusted_count, revoked_count; 740257353Sbdrewery const char *fingerprints; 741257353Sbdrewery char path[MAXPATHLEN]; 742257353Sbdrewery char hash[SHA256_DIGEST_LENGTH * 2 + 1]; 743257353Sbdrewery 744257353Sbdrewery sc = NULL; 745257353Sbdrewery trusted = revoked = NULL; 746257353Sbdrewery ret = false; 747257353Sbdrewery 748257353Sbdrewery /* Read and parse fingerprints. */ 749257353Sbdrewery if (config_string(FINGERPRINTS, &fingerprints) != 0) { 750257353Sbdrewery warnx("No CONFIG_FINGERPRINTS defined"); 751257353Sbdrewery goto cleanup; 752257353Sbdrewery } 753257353Sbdrewery 754257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints); 755257353Sbdrewery if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) { 756257353Sbdrewery warnx("Error loading trusted certificates"); 757257353Sbdrewery goto cleanup; 758257353Sbdrewery } 759257353Sbdrewery 760257353Sbdrewery if (trusted_count == 0 || trusted == NULL) { 761257353Sbdrewery fprintf(stderr, "No trusted certificates found.\n"); 762257353Sbdrewery goto cleanup; 763257353Sbdrewery } 764257353Sbdrewery 765257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints); 766257353Sbdrewery if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) { 767257353Sbdrewery warnx("Error loading revoked certificates"); 768257353Sbdrewery goto cleanup; 769257353Sbdrewery } 770257353Sbdrewery 771257353Sbdrewery /* Read certificate and signature in. */ 772257353Sbdrewery if ((sc = parse_cert(fd_sig)) == NULL) { 773257353Sbdrewery warnx("Error parsing certificate"); 774257353Sbdrewery goto cleanup; 775257353Sbdrewery } 776257353Sbdrewery /* Explicitly mark as non-trusted until proven otherwise. */ 777257353Sbdrewery sc->trusted = false; 778257353Sbdrewery 779257353Sbdrewery /* Parse signature and pubkey out of the certificate */ 780257353Sbdrewery sha256_buf(sc->cert, sc->certlen, hash); 781257353Sbdrewery 782257353Sbdrewery /* Check if this hash is revoked */ 783257353Sbdrewery if (revoked != NULL) { 784257353Sbdrewery STAILQ_FOREACH(fingerprint, revoked, next) { 785257353Sbdrewery if (strcasecmp(fingerprint->hash, hash) == 0) { 786257353Sbdrewery fprintf(stderr, "The package was signed with " 787257353Sbdrewery "revoked certificate %s\n", 788257353Sbdrewery fingerprint->name); 789257353Sbdrewery goto cleanup; 790257353Sbdrewery } 791257353Sbdrewery } 792257353Sbdrewery } 793257353Sbdrewery 794257353Sbdrewery STAILQ_FOREACH(fingerprint, trusted, next) { 795257353Sbdrewery if (strcasecmp(fingerprint->hash, hash) == 0) { 796257353Sbdrewery sc->trusted = true; 797257353Sbdrewery sc->name = strdup(fingerprint->name); 798257353Sbdrewery break; 799257353Sbdrewery } 800257353Sbdrewery } 801257353Sbdrewery 802257353Sbdrewery if (sc->trusted == false) { 803257353Sbdrewery fprintf(stderr, "No trusted fingerprint found matching " 804257353Sbdrewery "package's certificate\n"); 805257353Sbdrewery goto cleanup; 806257353Sbdrewery } 807257353Sbdrewery 808257353Sbdrewery /* Verify the signature. */ 809257353Sbdrewery printf("Verifying signature with trusted certificate %s... ", sc->name); 810287873Sdelphij if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig, 811257353Sbdrewery sc->siglen) == false) { 812257353Sbdrewery fprintf(stderr, "Signature is not valid\n"); 813257353Sbdrewery goto cleanup; 814257353Sbdrewery } 815257353Sbdrewery 816257353Sbdrewery ret = true; 817257353Sbdrewery 818257353Sbdrewerycleanup: 819257353Sbdrewery if (trusted) 820257353Sbdrewery free_fingerprint_list(trusted); 821257353Sbdrewery if (revoked) 822257353Sbdrewery free_fingerprint_list(revoked); 823257353Sbdrewery if (sc) { 824257353Sbdrewery if (sc->cert) 825257353Sbdrewery free(sc->cert); 826257353Sbdrewery if (sc->sig) 827257353Sbdrewery free(sc->sig); 828257353Sbdrewery if (sc->name) 829257353Sbdrewery free(sc->name); 830257353Sbdrewery free(sc); 831257353Sbdrewery } 832257353Sbdrewery 833257353Sbdrewery return (ret); 834257353Sbdrewery} 835257353Sbdrewery 836257353Sbdrewerystatic int 837257632Sbdrewerybootstrap_pkg(bool force) 838257353Sbdrewery{ 839257353Sbdrewery int fd_pkg, fd_sig; 840257353Sbdrewery int ret; 841257353Sbdrewery char url[MAXPATHLEN]; 842257353Sbdrewery char tmppkg[MAXPATHLEN]; 843257353Sbdrewery char tmpsig[MAXPATHLEN]; 844257353Sbdrewery const char *packagesite; 845257353Sbdrewery const char *signature_type; 846257353Sbdrewery char pkgstatic[MAXPATHLEN]; 847257353Sbdrewery 848257353Sbdrewery fd_sig = -1; 849257353Sbdrewery ret = -1; 850257353Sbdrewery 851257353Sbdrewery if (config_string(PACKAGESITE, &packagesite) != 0) { 852257353Sbdrewery warnx("No PACKAGESITE defined"); 853257353Sbdrewery return (-1); 854257353Sbdrewery } 855257353Sbdrewery 856257353Sbdrewery if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 857257353Sbdrewery warnx("Error looking up SIGNATURE_TYPE"); 858257353Sbdrewery return (-1); 859257353Sbdrewery } 860257353Sbdrewery 861257353Sbdrewery printf("Bootstrapping pkg from %s, please wait...\n", packagesite); 862257353Sbdrewery 863257353Sbdrewery /* Support pkg+http:// for PACKAGESITE which is the new format 864257353Sbdrewery in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has 865257353Sbdrewery no A record. */ 866257353Sbdrewery if (strncmp(URL_SCHEME_PREFIX, packagesite, 867257353Sbdrewery strlen(URL_SCHEME_PREFIX)) == 0) 868257353Sbdrewery packagesite += strlen(URL_SCHEME_PREFIX); 869257353Sbdrewery snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite); 870257353Sbdrewery 871257353Sbdrewery snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", 872257353Sbdrewery getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 873257353Sbdrewery 874257353Sbdrewery if ((fd_pkg = fetch_to_fd(url, tmppkg)) == -1) 875257353Sbdrewery goto fetchfail; 876257353Sbdrewery 877257353Sbdrewery if (signature_type != NULL && 878287146Sdelphij strcasecmp(signature_type, "NONE") != 0) { 879287873Sdelphij if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 880287873Sdelphij 881287873Sdelphij snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX", 882287873Sdelphij getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 883287873Sdelphij snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig", 884287873Sdelphij packagesite); 885287873Sdelphij 886287873Sdelphij if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { 887287873Sdelphij fprintf(stderr, "Signature for pkg not " 888287873Sdelphij "available.\n"); 889287873Sdelphij goto fetchfail; 890287873Sdelphij } 891287873Sdelphij 892287873Sdelphij if (verify_signature(fd_pkg, fd_sig) == false) 893287873Sdelphij goto cleanup; 894287873Sdelphij } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 895287873Sdelphij 896287873Sdelphij snprintf(tmpsig, MAXPATHLEN, 897287873Sdelphij "%s/pkg.txz.pubkeysig.XXXXXX", 898287873Sdelphij getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 899287873Sdelphij snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig", 900287873Sdelphij packagesite); 901287873Sdelphij 902287873Sdelphij if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { 903287873Sdelphij fprintf(stderr, "Signature for pkg not " 904287873Sdelphij "available.\n"); 905287873Sdelphij goto fetchfail; 906287873Sdelphij } 907287873Sdelphij 908287873Sdelphij if (verify_pubsignature(fd_pkg, fd_sig) == false) 909287873Sdelphij goto cleanup; 910287873Sdelphij } else { 911287146Sdelphij warnx("Signature type %s is not supported for " 912287146Sdelphij "bootstrapping.", signature_type); 913287146Sdelphij goto cleanup; 914287146Sdelphij } 915257353Sbdrewery } 916257353Sbdrewery 917257353Sbdrewery if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 918257632Sbdrewery ret = install_pkg_static(pkgstatic, tmppkg, force); 919234313Sbapt 920234351Sbapt goto cleanup; 921234351Sbapt 922234351Sbaptfetchfail: 923234351Sbapt warnx("Error fetching %s: %s", url, fetchLastErrString); 924257353Sbdrewery fprintf(stderr, "A pre-built version of pkg could not be found for " 925257353Sbdrewery "your system.\n"); 926257353Sbdrewery fprintf(stderr, "Consider changing PACKAGESITE or installing it from " 927257353Sbdrewery "ports: 'ports-mgmt/pkg'.\n"); 928234351Sbapt 929234313Sbaptcleanup: 930257353Sbdrewery if (fd_sig != -1) { 931257353Sbdrewery close(fd_sig); 932257353Sbdrewery unlink(tmpsig); 933257353Sbdrewery } 934257353Sbdrewery close(fd_pkg); 935234313Sbapt unlink(tmppkg); 936234313Sbapt 937234351Sbapt return (ret); 938234313Sbapt} 939234313Sbapt 940238461Skanstatic const char confirmation_message[] = 941238461Skan"The package management tool is not yet installed on your system.\n" 942238461Skan"Do you want to fetch and install it now? [y/N]: "; 943238461Skan 944238461Skanstatic int 945238461Skanpkg_query_yes_no(void) 946238461Skan{ 947238461Skan int ret, c; 948238461Skan 949238461Skan c = getchar(); 950238461Skan 951238461Skan if (c == 'y' || c == 'Y') 952238461Skan ret = 1; 953238461Skan else 954238461Skan ret = 0; 955238461Skan 956238461Skan while (c != '\n' && c != EOF) 957238461Skan c = getchar(); 958238461Skan 959238461Skan return (ret); 960238461Skan} 961238461Skan 962257353Sbdrewerystatic int 963257632Sbdrewerybootstrap_pkg_local(const char *pkgpath, bool force) 964257353Sbdrewery{ 965257353Sbdrewery char path[MAXPATHLEN]; 966257353Sbdrewery char pkgstatic[MAXPATHLEN]; 967257353Sbdrewery const char *signature_type; 968257353Sbdrewery int fd_pkg, fd_sig, ret; 969257353Sbdrewery 970257353Sbdrewery fd_sig = -1; 971257353Sbdrewery ret = -1; 972257353Sbdrewery 973257353Sbdrewery fd_pkg = open(pkgpath, O_RDONLY); 974257353Sbdrewery if (fd_pkg == -1) 975257353Sbdrewery err(EXIT_FAILURE, "Unable to open %s", pkgpath); 976257353Sbdrewery 977257353Sbdrewery if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 978257353Sbdrewery warnx("Error looking up SIGNATURE_TYPE"); 979257353Sbdrewery return (-1); 980257353Sbdrewery } 981257353Sbdrewery if (signature_type != NULL && 982287146Sdelphij strcasecmp(signature_type, "NONE") != 0) { 983287873Sdelphij if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 984287873Sdelphij 985287873Sdelphij snprintf(path, sizeof(path), "%s.sig", pkgpath); 986287873Sdelphij 987287873Sdelphij if ((fd_sig = open(path, O_RDONLY)) == -1) { 988287873Sdelphij fprintf(stderr, "Signature for pkg not " 989287873Sdelphij "available.\n"); 990287873Sdelphij goto cleanup; 991287873Sdelphij } 992287873Sdelphij 993287873Sdelphij if (verify_signature(fd_pkg, fd_sig) == false) 994287873Sdelphij goto cleanup; 995287873Sdelphij 996287873Sdelphij } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 997287873Sdelphij 998287873Sdelphij snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath); 999287873Sdelphij 1000287873Sdelphij if ((fd_sig = open(path, O_RDONLY)) == -1) { 1001287873Sdelphij fprintf(stderr, "Signature for pkg not " 1002287873Sdelphij "available.\n"); 1003287873Sdelphij goto cleanup; 1004287873Sdelphij } 1005287873Sdelphij 1006287873Sdelphij if (verify_pubsignature(fd_pkg, fd_sig) == false) 1007287873Sdelphij goto cleanup; 1008287873Sdelphij 1009287873Sdelphij } else { 1010287146Sdelphij warnx("Signature type %s is not supported for " 1011287146Sdelphij "bootstrapping.", signature_type); 1012287146Sdelphij goto cleanup; 1013287146Sdelphij } 1014257353Sbdrewery } 1015257353Sbdrewery 1016257353Sbdrewery if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 1017257632Sbdrewery ret = install_pkg_static(pkgstatic, pkgpath, force); 1018257353Sbdrewery 1019257353Sbdrewerycleanup: 1020257353Sbdrewery close(fd_pkg); 1021257353Sbdrewery if (fd_sig != -1) 1022257353Sbdrewery close(fd_sig); 1023257353Sbdrewery 1024257353Sbdrewery return (ret); 1025257353Sbdrewery} 1026257353Sbdrewery 1027234313Sbaptint 1028234322Sbaptmain(__unused int argc, char *argv[]) 1029234313Sbapt{ 1030234313Sbapt char pkgpath[MAXPATHLEN]; 1031257632Sbdrewery const char *pkgarg; 1032257632Sbdrewery bool bootstrap_only, force, yes; 1033234313Sbapt 1034257632Sbdrewery bootstrap_only = false; 1035257632Sbdrewery force = false; 1036257632Sbdrewery pkgarg = NULL; 1037257632Sbdrewery yes = false; 1038257632Sbdrewery 1039234313Sbapt snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", 1040234322Sbapt getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 1041234313Sbapt 1042257632Sbdrewery if (argc > 1 && strcmp(argv[1], "bootstrap") == 0) { 1043257632Sbdrewery bootstrap_only = true; 1044257632Sbdrewery if (argc == 3 && strcmp(argv[2], "-f") == 0) 1045257632Sbdrewery force = true; 1046257632Sbdrewery } 1047257632Sbdrewery 1048257632Sbdrewery if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) { 1049244553Smatthew /* 1050244594Smatthew * To allow 'pkg -N' to be used as a reliable test for whether 1051244553Smatthew * a system is configured to use pkg, don't bootstrap pkg 1052244553Smatthew * when that argument is given as argv[1]. 1053244553Smatthew */ 1054244639Smatthew if (argv[1] != NULL && strcmp(argv[1], "-N") == 0) 1055244639Smatthew errx(EXIT_FAILURE, "pkg is not installed"); 1056244553Smatthew 1057257353Sbdrewery config_init(); 1058257353Sbdrewery 1059257632Sbdrewery if (argc > 1 && strcmp(argv[1], "add") == 0) { 1060257632Sbdrewery if (argc > 2 && strcmp(argv[2], "-f") == 0) { 1061257632Sbdrewery force = true; 1062257632Sbdrewery pkgarg = argv[3]; 1063257632Sbdrewery } else 1064257632Sbdrewery pkgarg = argv[2]; 1065257632Sbdrewery if (pkgarg == NULL) { 1066257632Sbdrewery fprintf(stderr, "Path to pkg.txz required\n"); 1067257309Sbapt exit(EXIT_FAILURE); 1068257632Sbdrewery } 1069257632Sbdrewery if (access(pkgarg, R_OK) == -1) { 1070257632Sbdrewery fprintf(stderr, "No such file: %s\n", pkgarg); 1071257632Sbdrewery exit(EXIT_FAILURE); 1072257632Sbdrewery } 1073257632Sbdrewery if (bootstrap_pkg_local(pkgarg, force) != 0) 1074257632Sbdrewery exit(EXIT_FAILURE); 1075257309Sbapt exit(EXIT_SUCCESS); 1076257309Sbapt } 1077238461Skan /* 1078238461Skan * Do not ask for confirmation if either of stdin or stdout is 1079238461Skan * not tty. Check the environment to see if user has answer 1080238461Skan * tucked in there already. 1081238461Skan */ 1082247841Sbapt config_bool(ASSUME_ALWAYS_YES, &yes); 1083247841Sbapt if (!yes) { 1084238461Skan printf("%s", confirmation_message); 1085239664Sbapt if (!isatty(fileno(stdin))) 1086238461Skan exit(EXIT_FAILURE); 1087239664Sbapt 1088239664Sbapt if (pkg_query_yes_no() == 0) 1089239663Sbapt exit(EXIT_FAILURE); 1090238461Skan } 1091257632Sbdrewery if (bootstrap_pkg(force) != 0) 1092234351Sbapt exit(EXIT_FAILURE); 1093247841Sbapt config_finish(); 1094257571Sbdrewery 1095257632Sbdrewery if (bootstrap_only) 1096257571Sbdrewery exit(EXIT_SUCCESS); 1097257632Sbdrewery } else if (bootstrap_only) { 1098257632Sbdrewery printf("pkg already bootstrapped at %s\n", pkgpath); 1099257632Sbdrewery exit(EXIT_SUCCESS); 1100238461Skan } 1101234313Sbapt 1102234313Sbapt execv(pkgpath, argv); 1103234313Sbapt 1104234351Sbapt /* NOT REACHED */ 1105234322Sbapt return (EXIT_FAILURE); 1106234313Sbapt} 1107