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 <unistd.h> 51263020Sbapt#include <ucl.h> 52234313Sbapt 53257353Sbdrewery#include <openssl/err.h> 54257353Sbdrewery#include <openssl/ssl.h> 55257353Sbdrewery 56243883Sbapt#include "dns_utils.h" 57247841Sbapt#include "config.h" 58234313Sbapt 59257353Sbdrewerystruct sig_cert { 60257353Sbdrewery char *name; 61257353Sbdrewery unsigned char *sig; 62257353Sbdrewery int siglen; 63257353Sbdrewery unsigned char *cert; 64257353Sbdrewery int certlen; 65257353Sbdrewery bool trusted; 66257353Sbdrewery}; 67257353Sbdrewery 68287809Sbaptstruct pubkey { 69287809Sbapt unsigned char *sig; 70287809Sbapt int siglen; 71287809Sbapt}; 72287809Sbapt 73257353Sbdrewerytypedef enum { 74257353Sbdrewery HASH_UNKNOWN, 75257353Sbdrewery HASH_SHA256, 76257353Sbdrewery} hash_t; 77257353Sbdrewery 78257353Sbdrewerystruct fingerprint { 79257353Sbdrewery hash_t type; 80257353Sbdrewery char *name; 81257353Sbdrewery char hash[BUFSIZ]; 82257353Sbdrewery STAILQ_ENTRY(fingerprint) next; 83257353Sbdrewery}; 84257353Sbdrewery 85257353SbdrewerySTAILQ_HEAD(fingerprint_list, fingerprint); 86257353Sbdrewery 87234313Sbaptstatic int 88234313Sbaptextract_pkg_static(int fd, char *p, int sz) 89234313Sbapt{ 90234313Sbapt struct archive *a; 91234313Sbapt struct archive_entry *ae; 92234313Sbapt char *end; 93234313Sbapt int ret, r; 94234313Sbapt 95234351Sbapt ret = -1; 96234313Sbapt a = archive_read_new(); 97234351Sbapt if (a == NULL) { 98234351Sbapt warn("archive_read_new"); 99234351Sbapt return (ret); 100234351Sbapt } 101247060Sbapt archive_read_support_filter_all(a); 102234313Sbapt archive_read_support_format_tar(a); 103234313Sbapt 104234351Sbapt if (lseek(fd, 0, 0) == -1) { 105234351Sbapt warn("lseek"); 106234351Sbapt goto cleanup; 107234351Sbapt } 108234313Sbapt 109234313Sbapt if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 110234351Sbapt warnx("archive_read_open_fd: %s", archive_error_string(a)); 111234313Sbapt goto cleanup; 112234313Sbapt } 113234313Sbapt 114234313Sbapt ae = NULL; 115234313Sbapt while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 116234313Sbapt end = strrchr(archive_entry_pathname(ae), '/'); 117234313Sbapt if (end == NULL) 118234313Sbapt continue; 119234313Sbapt 120234313Sbapt if (strcmp(end, "/pkg-static") == 0) { 121234313Sbapt r = archive_read_extract(a, ae, 122234322Sbapt ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 123234322Sbapt ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 124234322Sbapt ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 125234351Sbapt strlcpy(p, archive_entry_pathname(ae), sz); 126234313Sbapt break; 127234313Sbapt } 128234313Sbapt } 129234313Sbapt 130234351Sbapt if (r == ARCHIVE_OK) 131234351Sbapt ret = 0; 132234351Sbapt else 133269937Sgavin warnx("failed to extract pkg-static: %s", 134269937Sgavin archive_error_string(a)); 135234313Sbapt 136234313Sbaptcleanup: 137247060Sbapt archive_read_free(a); 138234322Sbapt return (ret); 139234313Sbapt 140234313Sbapt} 141234313Sbapt 142234313Sbaptstatic int 143257632Sbdreweryinstall_pkg_static(const char *path, const char *pkgpath, bool force) 144234313Sbapt{ 145234313Sbapt int pstat; 146234313Sbapt pid_t pid; 147234313Sbapt 148234313Sbapt switch ((pid = fork())) { 149234351Sbapt case -1: 150234351Sbapt return (-1); 151234351Sbapt case 0: 152257632Sbdrewery if (force) 153257632Sbdrewery execl(path, "pkg-static", "add", "-f", pkgpath, 154257632Sbdrewery (char *)NULL); 155257632Sbdrewery else 156257632Sbdrewery execl(path, "pkg-static", "add", pkgpath, 157257632Sbdrewery (char *)NULL); 158234351Sbapt _exit(1); 159234351Sbapt default: 160234351Sbapt break; 161234313Sbapt } 162234313Sbapt 163234351Sbapt while (waitpid(pid, &pstat, 0) == -1) 164234313Sbapt if (errno != EINTR) 165234313Sbapt return (-1); 166234313Sbapt 167234351Sbapt if (WEXITSTATUS(pstat)) 168234351Sbapt return (WEXITSTATUS(pstat)); 169234351Sbapt else if (WIFSIGNALED(pstat)) 170234351Sbapt return (128 & (WTERMSIG(pstat))); 171234351Sbapt return (pstat); 172234313Sbapt} 173234313Sbapt 174234313Sbaptstatic int 175257353Sbdreweryfetch_to_fd(const char *url, char *path) 176234313Sbapt{ 177243883Sbapt struct url *u; 178257353Sbdrewery struct dns_srvinfo *mirrors, *current; 179257353Sbdrewery struct url_stat st; 180234313Sbapt FILE *remote; 181243883Sbapt /* To store _https._tcp. + hostname + \0 */ 182257353Sbdrewery int fd; 183257353Sbdrewery int retry, max_retry; 184283793Sbapt ssize_t r; 185257353Sbdrewery char buf[10240]; 186243883Sbapt char zone[MAXHOSTNAMELEN + 13]; 187257353Sbdrewery static const char *mirror_type = NULL; 188234313Sbapt 189243883Sbapt max_retry = 3; 190257353Sbdrewery current = mirrors = NULL; 191234313Sbapt remote = NULL; 192234313Sbapt 193257353Sbdrewery if (mirror_type == NULL && config_string(MIRROR_TYPE, &mirror_type) 194257353Sbdrewery != 0) { 195247841Sbapt warnx("No MIRROR_TYPE defined"); 196247841Sbapt return (-1); 197247841Sbapt } 198257328Sbdrewery 199257353Sbdrewery if ((fd = mkstemp(path)) == -1) { 200234313Sbapt warn("mkstemp()"); 201234322Sbapt return (-1); 202234313Sbapt } 203234313Sbapt 204243883Sbapt retry = max_retry; 205234313Sbapt 206278564Sbapt if ((u = fetchParseURL(url)) == NULL) { 207278564Sbapt warn("fetchParseURL('%s')", url); 208278564Sbapt return (-1); 209278564Sbapt } 210278564Sbapt 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 242283793Sbapt while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) { 243234313Sbapt if (write(fd, buf, r) != r) { 244234313Sbapt warn("write()"); 245257353Sbdrewery goto fetchfail; 246234313Sbapt } 247283793Sbapt } 248234313Sbapt 249283793Sbapt if (r != 0) { 250283793Sbapt warn("An error occurred while fetching pkg(8)"); 251283793Sbapt goto fetchfail; 252234313Sbapt } 253234313Sbapt 254234351Sbapt if (ferror(remote)) 255234351Sbapt goto fetchfail; 256234313Sbapt 257257353Sbdrewery goto cleanup; 258257353Sbdrewery 259257353Sbdreweryfetchfail: 260257353Sbdrewery if (fd != -1) { 261257353Sbdrewery close(fd); 262257353Sbdrewery fd = -1; 263257353Sbdrewery unlink(path); 264257353Sbdrewery } 265257353Sbdrewery 266257353Sbdrewerycleanup: 267257353Sbdrewery if (remote != NULL) 268257353Sbdrewery fclose(remote); 269257353Sbdrewery 270257353Sbdrewery return fd; 271257353Sbdrewery} 272257353Sbdrewery 273257353Sbdrewerystatic struct fingerprint * 274263020Sbaptparse_fingerprint(ucl_object_t *obj) 275257353Sbdrewery{ 276268896Sbapt const ucl_object_t *cur; 277263020Sbapt ucl_object_iter_t it = NULL; 278263020Sbapt const char *function, *fp, *key; 279257353Sbdrewery struct fingerprint *f; 280257353Sbdrewery hash_t fct = HASH_UNKNOWN; 281257353Sbdrewery 282257353Sbdrewery function = fp = NULL; 283257353Sbdrewery 284263020Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 285263020Sbapt key = ucl_object_key(cur); 286263020Sbapt if (cur->type != UCL_STRING) 287257353Sbdrewery continue; 288263020Sbapt if (strcasecmp(key, "function") == 0) { 289263020Sbapt function = ucl_object_tostring(cur); 290263020Sbapt continue; 291257353Sbdrewery } 292263020Sbapt if (strcasecmp(key, "fingerprint") == 0) { 293263020Sbapt fp = ucl_object_tostring(cur); 294257353Sbdrewery continue; 295257353Sbdrewery } 296257353Sbdrewery } 297257353Sbdrewery 298257353Sbdrewery if (fp == NULL || function == NULL) 299257353Sbdrewery return (NULL); 300257353Sbdrewery 301257353Sbdrewery if (strcasecmp(function, "sha256") == 0) 302257353Sbdrewery fct = HASH_SHA256; 303257353Sbdrewery 304257353Sbdrewery if (fct == HASH_UNKNOWN) { 305263020Sbapt warnx("Unsupported hashing function: %s", function); 306257353Sbdrewery return (NULL); 307257353Sbdrewery } 308257353Sbdrewery 309257353Sbdrewery f = calloc(1, sizeof(struct fingerprint)); 310257353Sbdrewery f->type = fct; 311257353Sbdrewery strlcpy(f->hash, fp, sizeof(f->hash)); 312257353Sbdrewery 313257353Sbdrewery return (f); 314257353Sbdrewery} 315257353Sbdrewery 316257353Sbdrewerystatic void 317257353Sbdreweryfree_fingerprint_list(struct fingerprint_list* list) 318257353Sbdrewery{ 319258126Sglebius struct fingerprint *fingerprint, *tmp; 320257353Sbdrewery 321258126Sglebius STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) { 322283788Sbapt free(fingerprint->name); 323257353Sbdrewery free(fingerprint); 324257353Sbdrewery } 325257353Sbdrewery free(list); 326257353Sbdrewery} 327257353Sbdrewery 328257353Sbdrewerystatic struct fingerprint * 329257353Sbdreweryload_fingerprint(const char *dir, const char *filename) 330257353Sbdrewery{ 331263020Sbapt ucl_object_t *obj = NULL; 332263020Sbapt struct ucl_parser *p = NULL; 333257353Sbdrewery struct fingerprint *f; 334257353Sbdrewery char path[MAXPATHLEN]; 335257353Sbdrewery 336257353Sbdrewery f = NULL; 337257353Sbdrewery 338257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/%s", dir, filename); 339257353Sbdrewery 340263020Sbapt p = ucl_parser_new(0); 341263020Sbapt if (!ucl_parser_add_file(p, path)) { 342263020Sbapt warnx("%s: %s", path, ucl_parser_get_error(p)); 343263020Sbapt ucl_parser_free(p); 344257353Sbdrewery return (NULL); 345263020Sbapt } 346257353Sbdrewery 347263020Sbapt obj = ucl_parser_get_object(p); 348257353Sbdrewery 349263020Sbapt if (obj->type == UCL_OBJECT) 350263020Sbapt f = parse_fingerprint(obj); 351257353Sbdrewery 352263020Sbapt if (f != NULL) 353263020Sbapt f->name = strdup(filename); 354257353Sbdrewery 355268896Sbapt ucl_object_unref(obj); 356263020Sbapt ucl_parser_free(p); 357257353Sbdrewery 358257353Sbdrewery return (f); 359257353Sbdrewery} 360257353Sbdrewery 361257353Sbdrewerystatic struct fingerprint_list * 362257353Sbdreweryload_fingerprints(const char *path, int *count) 363257353Sbdrewery{ 364257353Sbdrewery DIR *d; 365257353Sbdrewery struct dirent *ent; 366257353Sbdrewery struct fingerprint *finger; 367257353Sbdrewery struct fingerprint_list *fingerprints; 368257353Sbdrewery 369257353Sbdrewery *count = 0; 370257353Sbdrewery 371257353Sbdrewery fingerprints = calloc(1, sizeof(struct fingerprint_list)); 372257353Sbdrewery if (fingerprints == NULL) 373257353Sbdrewery return (NULL); 374257353Sbdrewery STAILQ_INIT(fingerprints); 375257353Sbdrewery 376278563Sbapt if ((d = opendir(path)) == NULL) { 377278563Sbapt free(fingerprints); 378278563Sbapt 379257353Sbdrewery return (NULL); 380278563Sbapt } 381257353Sbdrewery 382257353Sbdrewery while ((ent = readdir(d))) { 383257353Sbdrewery if (strcmp(ent->d_name, ".") == 0 || 384257353Sbdrewery strcmp(ent->d_name, "..") == 0) 385257353Sbdrewery continue; 386257353Sbdrewery finger = load_fingerprint(path, ent->d_name); 387257353Sbdrewery if (finger != NULL) { 388257353Sbdrewery STAILQ_INSERT_TAIL(fingerprints, finger, next); 389257353Sbdrewery ++(*count); 390257353Sbdrewery } 391257353Sbdrewery } 392257353Sbdrewery 393257353Sbdrewery closedir(d); 394257353Sbdrewery 395257353Sbdrewery return (fingerprints); 396257353Sbdrewery} 397257353Sbdrewery 398257353Sbdrewerystatic void 399257353Sbdrewerysha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH], 400257353Sbdrewery char out[SHA256_DIGEST_LENGTH * 2 + 1]) 401257353Sbdrewery{ 402257353Sbdrewery int i; 403257353Sbdrewery 404257353Sbdrewery for (i = 0; i < SHA256_DIGEST_LENGTH; i++) 405257353Sbdrewery sprintf(out + (i * 2), "%02x", hash[i]); 406257353Sbdrewery 407257353Sbdrewery out[SHA256_DIGEST_LENGTH * 2] = '\0'; 408257353Sbdrewery} 409257353Sbdrewery 410257353Sbdrewerystatic void 411257353Sbdrewerysha256_buf(char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 412257353Sbdrewery{ 413257353Sbdrewery unsigned char hash[SHA256_DIGEST_LENGTH]; 414257353Sbdrewery SHA256_CTX sha256; 415257353Sbdrewery 416257353Sbdrewery out[0] = '\0'; 417257353Sbdrewery 418257353Sbdrewery SHA256_Init(&sha256); 419257353Sbdrewery SHA256_Update(&sha256, buf, len); 420257353Sbdrewery SHA256_Final(hash, &sha256); 421257353Sbdrewery sha256_hash(hash, out); 422257353Sbdrewery} 423257353Sbdrewery 424257353Sbdrewerystatic int 425257353Sbdrewerysha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1]) 426257353Sbdrewery{ 427257353Sbdrewery int my_fd; 428257353Sbdrewery FILE *fp; 429257353Sbdrewery char buffer[BUFSIZ]; 430257353Sbdrewery unsigned char hash[SHA256_DIGEST_LENGTH]; 431257353Sbdrewery size_t r; 432257353Sbdrewery int ret; 433257353Sbdrewery SHA256_CTX sha256; 434257353Sbdrewery 435257353Sbdrewery my_fd = -1; 436257353Sbdrewery fp = NULL; 437257353Sbdrewery r = 0; 438257353Sbdrewery ret = 1; 439257353Sbdrewery 440257353Sbdrewery out[0] = '\0'; 441257353Sbdrewery 442257353Sbdrewery /* Duplicate the fd so that fclose(3) does not close it. */ 443257353Sbdrewery if ((my_fd = dup(fd)) == -1) { 444257353Sbdrewery warnx("dup"); 445257353Sbdrewery goto cleanup; 446257353Sbdrewery } 447257353Sbdrewery 448257353Sbdrewery if ((fp = fdopen(my_fd, "rb")) == NULL) { 449257353Sbdrewery warnx("fdopen"); 450257353Sbdrewery goto cleanup; 451257353Sbdrewery } 452257353Sbdrewery 453257353Sbdrewery SHA256_Init(&sha256); 454257353Sbdrewery 455257353Sbdrewery while ((r = fread(buffer, 1, BUFSIZ, fp)) > 0) 456257353Sbdrewery SHA256_Update(&sha256, buffer, r); 457257353Sbdrewery 458257353Sbdrewery if (ferror(fp) != 0) { 459257353Sbdrewery warnx("fread"); 460257353Sbdrewery goto cleanup; 461257353Sbdrewery } 462257353Sbdrewery 463257353Sbdrewery SHA256_Final(hash, &sha256); 464257353Sbdrewery sha256_hash(hash, out); 465257353Sbdrewery ret = 0; 466257353Sbdrewery 467257353Sbdrewerycleanup: 468257353Sbdrewery if (fp != NULL) 469257353Sbdrewery fclose(fp); 470257353Sbdrewery else if (my_fd != -1) 471257353Sbdrewery close(my_fd); 472257353Sbdrewery (void)lseek(fd, 0, SEEK_SET); 473257353Sbdrewery 474257353Sbdrewery return (ret); 475257353Sbdrewery} 476257353Sbdrewery 477257353Sbdrewerystatic EVP_PKEY * 478287809Sbaptload_public_key_file(const char *file) 479287809Sbapt{ 480287809Sbapt EVP_PKEY *pkey; 481287809Sbapt BIO *bp; 482287809Sbapt char errbuf[1024]; 483287809Sbapt 484287809Sbapt bp = BIO_new_file(file, "r"); 485287809Sbapt if (!bp) 486287809Sbapt errx(EXIT_FAILURE, "Unable to read %s", file); 487287809Sbapt 488287809Sbapt if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 489287809Sbapt warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf)); 490287809Sbapt 491287809Sbapt BIO_free(bp); 492287809Sbapt 493287809Sbapt return (pkey); 494287809Sbapt} 495287809Sbapt 496287809Sbaptstatic EVP_PKEY * 497257353Sbdreweryload_public_key_buf(const unsigned char *cert, int certlen) 498257353Sbdrewery{ 499257353Sbdrewery EVP_PKEY *pkey; 500257353Sbdrewery BIO *bp; 501257353Sbdrewery char errbuf[1024]; 502257353Sbdrewery 503257353Sbdrewery bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen); 504257353Sbdrewery 505257353Sbdrewery if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL) 506257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 507257353Sbdrewery 508257353Sbdrewery BIO_free(bp); 509257353Sbdrewery 510257353Sbdrewery return (pkey); 511257353Sbdrewery} 512257353Sbdrewery 513257353Sbdrewerystatic bool 514287809Sbaptrsa_verify_cert(int fd, const char *sigfile, const unsigned char *key, 515287809Sbapt int keylen, unsigned char *sig, int siglen) 516257353Sbdrewery{ 517257353Sbdrewery EVP_MD_CTX *mdctx; 518257353Sbdrewery EVP_PKEY *pkey; 519257353Sbdrewery char sha256[(SHA256_DIGEST_LENGTH * 2) + 2]; 520257353Sbdrewery char errbuf[1024]; 521257353Sbdrewery bool ret; 522257353Sbdrewery 523257353Sbdrewery pkey = NULL; 524257353Sbdrewery mdctx = NULL; 525257353Sbdrewery ret = false; 526257353Sbdrewery 527287809Sbapt SSL_load_error_strings(); 528287809Sbapt 529257353Sbdrewery /* Compute SHA256 of the package. */ 530257353Sbdrewery if (lseek(fd, 0, 0) == -1) { 531257353Sbdrewery warn("lseek"); 532257353Sbdrewery goto cleanup; 533257353Sbdrewery } 534257353Sbdrewery if ((sha256_fd(fd, sha256)) == -1) { 535257353Sbdrewery warnx("Error creating SHA256 hash for package"); 536257353Sbdrewery goto cleanup; 537257353Sbdrewery } 538257353Sbdrewery 539287809Sbapt if (sigfile != NULL) { 540287809Sbapt if ((pkey = load_public_key_file(sigfile)) == NULL) { 541287809Sbapt warnx("Error reading public key"); 542287809Sbapt goto cleanup; 543287809Sbapt } 544287809Sbapt } else { 545287809Sbapt if ((pkey = load_public_key_buf(key, keylen)) == NULL) { 546287809Sbapt warnx("Error reading public key"); 547287809Sbapt goto cleanup; 548287809Sbapt } 549257353Sbdrewery } 550257353Sbdrewery 551257353Sbdrewery /* Verify signature of the SHA256(pkg) is valid. */ 552257353Sbdrewery if ((mdctx = EVP_MD_CTX_create()) == NULL) { 553257353Sbdrewery warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 554257353Sbdrewery goto error; 555257353Sbdrewery } 556257353Sbdrewery 557257353Sbdrewery if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) { 558287810Sbapt warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 559257353Sbdrewery goto error; 560257353Sbdrewery } 561257353Sbdrewery if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) { 562287810Sbapt warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 563257353Sbdrewery goto error; 564257353Sbdrewery } 565257353Sbdrewery 566257353Sbdrewery if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) { 567287810Sbapt warnx("%s", ERR_error_string(ERR_get_error(), errbuf)); 568257353Sbdrewery goto error; 569257353Sbdrewery } 570257353Sbdrewery 571257353Sbdrewery ret = true; 572257353Sbdrewery printf("done\n"); 573257353Sbdrewery goto cleanup; 574257353Sbdrewery 575257353Sbdreweryerror: 576257353Sbdrewery printf("failed\n"); 577257353Sbdrewery 578257353Sbdrewerycleanup: 579257353Sbdrewery if (pkey) 580257353Sbdrewery EVP_PKEY_free(pkey); 581257353Sbdrewery if (mdctx) 582257353Sbdrewery EVP_MD_CTX_destroy(mdctx); 583257353Sbdrewery ERR_free_strings(); 584257353Sbdrewery 585257353Sbdrewery return (ret); 586257353Sbdrewery} 587257353Sbdrewery 588287809Sbaptstatic struct pubkey * 589287809Sbaptread_pubkey(int fd) 590287809Sbapt{ 591287809Sbapt struct pubkey *pk; 592287809Sbapt struct sbuf *sig; 593287809Sbapt char buf[4096]; 594287809Sbapt int r; 595287809Sbapt 596287809Sbapt if (lseek(fd, 0, 0) == -1) { 597287809Sbapt warn("lseek"); 598287809Sbapt return (NULL); 599287809Sbapt } 600287809Sbapt 601287809Sbapt sig = sbuf_new_auto(); 602287809Sbapt 603287809Sbapt while ((r = read(fd, buf, sizeof(buf))) >0) { 604287809Sbapt sbuf_bcat(sig, buf, r); 605287809Sbapt } 606287809Sbapt 607287809Sbapt sbuf_finish(sig); 608287809Sbapt pk = calloc(1, sizeof(struct pubkey)); 609287809Sbapt pk->siglen = sbuf_len(sig); 610287809Sbapt pk->sig = calloc(1, pk->siglen); 611287809Sbapt memcpy(pk->sig, sbuf_data(sig), pk->siglen); 612287809Sbapt sbuf_delete(sig); 613287809Sbapt 614287809Sbapt return (pk); 615287809Sbapt} 616287809Sbapt 617257353Sbdrewerystatic struct sig_cert * 618257353Sbdreweryparse_cert(int fd) { 619257353Sbdrewery int my_fd; 620257353Sbdrewery struct sig_cert *sc; 621257353Sbdrewery FILE *fp; 622257353Sbdrewery struct sbuf *buf, *sig, *cert; 623257353Sbdrewery char *line; 624257353Sbdrewery size_t linecap; 625257353Sbdrewery ssize_t linelen; 626257353Sbdrewery 627257353Sbdrewery buf = NULL; 628257353Sbdrewery my_fd = -1; 629257353Sbdrewery sc = NULL; 630257353Sbdrewery line = NULL; 631257353Sbdrewery linecap = 0; 632257353Sbdrewery 633257353Sbdrewery if (lseek(fd, 0, 0) == -1) { 634257353Sbdrewery warn("lseek"); 635257353Sbdrewery return (NULL); 636257353Sbdrewery } 637257353Sbdrewery 638257353Sbdrewery /* Duplicate the fd so that fclose(3) does not close it. */ 639257353Sbdrewery if ((my_fd = dup(fd)) == -1) { 640257353Sbdrewery warnx("dup"); 641257353Sbdrewery return (NULL); 642257353Sbdrewery } 643257353Sbdrewery 644257353Sbdrewery if ((fp = fdopen(my_fd, "rb")) == NULL) { 645257353Sbdrewery warn("fdopen"); 646257353Sbdrewery close(my_fd); 647257353Sbdrewery return (NULL); 648257353Sbdrewery } 649257353Sbdrewery 650257353Sbdrewery sig = sbuf_new_auto(); 651257353Sbdrewery cert = sbuf_new_auto(); 652257353Sbdrewery 653257353Sbdrewery while ((linelen = getline(&line, &linecap, fp)) > 0) { 654257353Sbdrewery if (strcmp(line, "SIGNATURE\n") == 0) { 655257353Sbdrewery buf = sig; 656257353Sbdrewery continue; 657257353Sbdrewery } else if (strcmp(line, "CERT\n") == 0) { 658257353Sbdrewery buf = cert; 659257353Sbdrewery continue; 660257353Sbdrewery } else if (strcmp(line, "END\n") == 0) { 661257353Sbdrewery break; 662257353Sbdrewery } 663257353Sbdrewery if (buf != NULL) 664257353Sbdrewery sbuf_bcat(buf, line, linelen); 665257353Sbdrewery } 666257353Sbdrewery 667257353Sbdrewery fclose(fp); 668257353Sbdrewery 669257353Sbdrewery /* Trim out unrelated trailing newline */ 670257353Sbdrewery sbuf_setpos(sig, sbuf_len(sig) - 1); 671257353Sbdrewery 672257353Sbdrewery sbuf_finish(sig); 673257353Sbdrewery sbuf_finish(cert); 674257353Sbdrewery 675257353Sbdrewery sc = calloc(1, sizeof(struct sig_cert)); 676257353Sbdrewery sc->siglen = sbuf_len(sig); 677257353Sbdrewery sc->sig = calloc(1, sc->siglen); 678257353Sbdrewery memcpy(sc->sig, sbuf_data(sig), sc->siglen); 679257353Sbdrewery 680257353Sbdrewery sc->certlen = sbuf_len(cert); 681257353Sbdrewery sc->cert = strdup(sbuf_data(cert)); 682257353Sbdrewery 683257353Sbdrewery sbuf_delete(sig); 684257353Sbdrewery sbuf_delete(cert); 685257353Sbdrewery 686257353Sbdrewery return (sc); 687257353Sbdrewery} 688257353Sbdrewery 689257353Sbdrewerystatic bool 690287809Sbaptverify_pubsignature(int fd_pkg, int fd_sig) 691287809Sbapt{ 692287809Sbapt struct pubkey *pk; 693287809Sbapt const char *pubkey; 694287809Sbapt bool ret; 695287809Sbapt 696287809Sbapt pk = NULL; 697287809Sbapt pubkey = NULL; 698287809Sbapt ret = false; 699287809Sbapt if (config_string(PUBKEY, &pubkey) != 0) { 700287809Sbapt warnx("No CONFIG_PUBKEY defined"); 701287809Sbapt goto cleanup; 702287809Sbapt } 703287809Sbapt 704287809Sbapt if ((pk = read_pubkey(fd_sig)) == NULL) { 705287809Sbapt warnx("Error reading signature"); 706287809Sbapt goto cleanup; 707287809Sbapt } 708287809Sbapt 709287809Sbapt /* Verify the signature. */ 710287809Sbapt printf("Verifying signature with public key %s... ", pubkey); 711287809Sbapt if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig, 712287809Sbapt pk->siglen) == false) { 713287809Sbapt fprintf(stderr, "Signature is not valid\n"); 714287809Sbapt goto cleanup; 715287809Sbapt } 716287809Sbapt 717287809Sbapt ret = true; 718287809Sbapt 719287809Sbaptcleanup: 720287809Sbapt if (pk) { 721287809Sbapt free(pk->sig); 722287809Sbapt free(pk); 723287809Sbapt } 724287809Sbapt 725287809Sbapt return (ret); 726287809Sbapt} 727287809Sbapt 728287809Sbaptstatic bool 729257353Sbdreweryverify_signature(int fd_pkg, int fd_sig) 730257353Sbdrewery{ 731257353Sbdrewery struct fingerprint_list *trusted, *revoked; 732257353Sbdrewery struct fingerprint *fingerprint; 733257353Sbdrewery struct sig_cert *sc; 734257353Sbdrewery bool ret; 735257353Sbdrewery int trusted_count, revoked_count; 736257353Sbdrewery const char *fingerprints; 737257353Sbdrewery char path[MAXPATHLEN]; 738257353Sbdrewery char hash[SHA256_DIGEST_LENGTH * 2 + 1]; 739257353Sbdrewery 740257353Sbdrewery sc = NULL; 741257353Sbdrewery trusted = revoked = NULL; 742257353Sbdrewery ret = false; 743257353Sbdrewery 744257353Sbdrewery /* Read and parse fingerprints. */ 745257353Sbdrewery if (config_string(FINGERPRINTS, &fingerprints) != 0) { 746257353Sbdrewery warnx("No CONFIG_FINGERPRINTS defined"); 747257353Sbdrewery goto cleanup; 748257353Sbdrewery } 749257353Sbdrewery 750257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints); 751257353Sbdrewery if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) { 752257353Sbdrewery warnx("Error loading trusted certificates"); 753257353Sbdrewery goto cleanup; 754257353Sbdrewery } 755257353Sbdrewery 756257353Sbdrewery if (trusted_count == 0 || trusted == NULL) { 757257353Sbdrewery fprintf(stderr, "No trusted certificates found.\n"); 758257353Sbdrewery goto cleanup; 759257353Sbdrewery } 760257353Sbdrewery 761257353Sbdrewery snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints); 762257353Sbdrewery if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) { 763257353Sbdrewery warnx("Error loading revoked certificates"); 764257353Sbdrewery goto cleanup; 765257353Sbdrewery } 766257353Sbdrewery 767257353Sbdrewery /* Read certificate and signature in. */ 768257353Sbdrewery if ((sc = parse_cert(fd_sig)) == NULL) { 769257353Sbdrewery warnx("Error parsing certificate"); 770257353Sbdrewery goto cleanup; 771257353Sbdrewery } 772257353Sbdrewery /* Explicitly mark as non-trusted until proven otherwise. */ 773257353Sbdrewery sc->trusted = false; 774257353Sbdrewery 775257353Sbdrewery /* Parse signature and pubkey out of the certificate */ 776257353Sbdrewery sha256_buf(sc->cert, sc->certlen, hash); 777257353Sbdrewery 778257353Sbdrewery /* Check if this hash is revoked */ 779257353Sbdrewery if (revoked != NULL) { 780257353Sbdrewery STAILQ_FOREACH(fingerprint, revoked, next) { 781257353Sbdrewery if (strcasecmp(fingerprint->hash, hash) == 0) { 782257353Sbdrewery fprintf(stderr, "The package was signed with " 783257353Sbdrewery "revoked certificate %s\n", 784257353Sbdrewery fingerprint->name); 785257353Sbdrewery goto cleanup; 786257353Sbdrewery } 787257353Sbdrewery } 788257353Sbdrewery } 789257353Sbdrewery 790257353Sbdrewery STAILQ_FOREACH(fingerprint, trusted, next) { 791257353Sbdrewery if (strcasecmp(fingerprint->hash, hash) == 0) { 792257353Sbdrewery sc->trusted = true; 793257353Sbdrewery sc->name = strdup(fingerprint->name); 794257353Sbdrewery break; 795257353Sbdrewery } 796257353Sbdrewery } 797257353Sbdrewery 798257353Sbdrewery if (sc->trusted == false) { 799257353Sbdrewery fprintf(stderr, "No trusted fingerprint found matching " 800257353Sbdrewery "package's certificate\n"); 801257353Sbdrewery goto cleanup; 802257353Sbdrewery } 803257353Sbdrewery 804257353Sbdrewery /* Verify the signature. */ 805257353Sbdrewery printf("Verifying signature with trusted certificate %s... ", sc->name); 806287809Sbapt if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig, 807257353Sbdrewery sc->siglen) == false) { 808257353Sbdrewery fprintf(stderr, "Signature is not valid\n"); 809257353Sbdrewery goto cleanup; 810257353Sbdrewery } 811257353Sbdrewery 812257353Sbdrewery ret = true; 813257353Sbdrewery 814257353Sbdrewerycleanup: 815257353Sbdrewery if (trusted) 816257353Sbdrewery free_fingerprint_list(trusted); 817257353Sbdrewery if (revoked) 818257353Sbdrewery free_fingerprint_list(revoked); 819257353Sbdrewery if (sc) { 820283788Sbapt free(sc->cert); 821283788Sbapt free(sc->sig); 822283788Sbapt free(sc->name); 823257353Sbdrewery free(sc); 824257353Sbdrewery } 825257353Sbdrewery 826257353Sbdrewery return (ret); 827257353Sbdrewery} 828257353Sbdrewery 829257353Sbdrewerystatic int 830257632Sbdrewerybootstrap_pkg(bool force) 831257353Sbdrewery{ 832257353Sbdrewery int fd_pkg, fd_sig; 833257353Sbdrewery int ret; 834257353Sbdrewery char url[MAXPATHLEN]; 835257353Sbdrewery char tmppkg[MAXPATHLEN]; 836257353Sbdrewery char tmpsig[MAXPATHLEN]; 837257353Sbdrewery const char *packagesite; 838257353Sbdrewery const char *signature_type; 839257353Sbdrewery char pkgstatic[MAXPATHLEN]; 840257353Sbdrewery 841257353Sbdrewery fd_sig = -1; 842257353Sbdrewery ret = -1; 843257353Sbdrewery 844257353Sbdrewery if (config_string(PACKAGESITE, &packagesite) != 0) { 845257353Sbdrewery warnx("No PACKAGESITE defined"); 846257353Sbdrewery return (-1); 847257353Sbdrewery } 848257353Sbdrewery 849257353Sbdrewery if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 850257353Sbdrewery warnx("Error looking up SIGNATURE_TYPE"); 851257353Sbdrewery return (-1); 852257353Sbdrewery } 853257353Sbdrewery 854257353Sbdrewery printf("Bootstrapping pkg from %s, please wait...\n", packagesite); 855257353Sbdrewery 856257353Sbdrewery /* Support pkg+http:// for PACKAGESITE which is the new format 857257353Sbdrewery in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has 858257353Sbdrewery no A record. */ 859257353Sbdrewery if (strncmp(URL_SCHEME_PREFIX, packagesite, 860257353Sbdrewery strlen(URL_SCHEME_PREFIX)) == 0) 861257353Sbdrewery packagesite += strlen(URL_SCHEME_PREFIX); 862257353Sbdrewery snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite); 863257353Sbdrewery 864257353Sbdrewery snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", 865257353Sbdrewery getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 866257353Sbdrewery 867257353Sbdrewery if ((fd_pkg = fetch_to_fd(url, tmppkg)) == -1) 868257353Sbdrewery goto fetchfail; 869257353Sbdrewery 870257353Sbdrewery if (signature_type != NULL && 871286935Sdelphij strcasecmp(signature_type, "NONE") != 0) { 872287809Sbapt if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 873287809Sbapt 874287809Sbapt snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX", 875287809Sbapt getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 876287809Sbapt snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig", 877287809Sbapt packagesite); 878287809Sbapt 879287809Sbapt if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { 880287809Sbapt fprintf(stderr, "Signature for pkg not " 881287809Sbapt "available.\n"); 882287809Sbapt goto fetchfail; 883287809Sbapt } 884287809Sbapt 885287809Sbapt if (verify_signature(fd_pkg, fd_sig) == false) 886287809Sbapt goto cleanup; 887287809Sbapt } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 888287809Sbapt 889287809Sbapt snprintf(tmpsig, MAXPATHLEN, 890287809Sbapt "%s/pkg.txz.pubkeysig.XXXXXX", 891287809Sbapt getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 892287809Sbapt snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig", 893287809Sbapt packagesite); 894287809Sbapt 895287809Sbapt if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) { 896287809Sbapt fprintf(stderr, "Signature for pkg not " 897287809Sbapt "available.\n"); 898287809Sbapt goto fetchfail; 899287809Sbapt } 900287809Sbapt 901287809Sbapt if (verify_pubsignature(fd_pkg, fd_sig) == false) 902287809Sbapt goto cleanup; 903287809Sbapt } else { 904286935Sdelphij warnx("Signature type %s is not supported for " 905286935Sdelphij "bootstrapping.", signature_type); 906286935Sdelphij goto cleanup; 907286935Sdelphij } 908257353Sbdrewery } 909257353Sbdrewery 910257353Sbdrewery if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 911257632Sbdrewery ret = install_pkg_static(pkgstatic, tmppkg, force); 912234313Sbapt 913234351Sbapt goto cleanup; 914234351Sbapt 915234351Sbaptfetchfail: 916234351Sbapt warnx("Error fetching %s: %s", url, fetchLastErrString); 917257353Sbdrewery fprintf(stderr, "A pre-built version of pkg could not be found for " 918257353Sbdrewery "your system.\n"); 919257353Sbdrewery fprintf(stderr, "Consider changing PACKAGESITE or installing it from " 920257353Sbdrewery "ports: 'ports-mgmt/pkg'.\n"); 921234351Sbapt 922234313Sbaptcleanup: 923257353Sbdrewery if (fd_sig != -1) { 924257353Sbdrewery close(fd_sig); 925257353Sbdrewery unlink(tmpsig); 926257353Sbdrewery } 927234313Sbapt 928278563Sbapt if (fd_pkg != -1) { 929278563Sbapt close(fd_pkg); 930278563Sbapt unlink(tmppkg); 931278563Sbapt } 932278563Sbapt 933234351Sbapt return (ret); 934234313Sbapt} 935234313Sbapt 936238461Skanstatic const char confirmation_message[] = 937238461Skan"The package management tool is not yet installed on your system.\n" 938238461Skan"Do you want to fetch and install it now? [y/N]: "; 939238461Skan 940283790Sbaptstatic const char non_interactive_message[] = 941283790Sbapt"The package management tool is not yet installed on your system.\n" 942283790Sbapt"Please set ASSUME_ALWAYS_YES=yes environment variable to be able to bootstrap " 943283790Sbapt"in non-interactive (stdin not being a tty)\n"; 944283790Sbapt 945238461Skanstatic int 946238461Skanpkg_query_yes_no(void) 947238461Skan{ 948238461Skan int ret, c; 949238461Skan 950238461Skan c = getchar(); 951238461Skan 952238461Skan if (c == 'y' || c == 'Y') 953238461Skan ret = 1; 954238461Skan else 955238461Skan ret = 0; 956238461Skan 957238461Skan while (c != '\n' && c != EOF) 958238461Skan c = getchar(); 959238461Skan 960238461Skan return (ret); 961238461Skan} 962238461Skan 963257353Sbdrewerystatic int 964257632Sbdrewerybootstrap_pkg_local(const char *pkgpath, bool force) 965257353Sbdrewery{ 966257353Sbdrewery char path[MAXPATHLEN]; 967257353Sbdrewery char pkgstatic[MAXPATHLEN]; 968257353Sbdrewery const char *signature_type; 969257353Sbdrewery int fd_pkg, fd_sig, ret; 970257353Sbdrewery 971257353Sbdrewery fd_sig = -1; 972257353Sbdrewery ret = -1; 973257353Sbdrewery 974257353Sbdrewery fd_pkg = open(pkgpath, O_RDONLY); 975257353Sbdrewery if (fd_pkg == -1) 976257353Sbdrewery err(EXIT_FAILURE, "Unable to open %s", pkgpath); 977257353Sbdrewery 978257353Sbdrewery if (config_string(SIGNATURE_TYPE, &signature_type) != 0) { 979257353Sbdrewery warnx("Error looking up SIGNATURE_TYPE"); 980278563Sbapt goto cleanup; 981257353Sbdrewery } 982257353Sbdrewery if (signature_type != NULL && 983286935Sdelphij strcasecmp(signature_type, "NONE") != 0) { 984287809Sbapt if (strcasecmp(signature_type, "FINGERPRINTS") == 0) { 985287809Sbapt 986287809Sbapt snprintf(path, sizeof(path), "%s.sig", pkgpath); 987287809Sbapt 988287809Sbapt if ((fd_sig = open(path, O_RDONLY)) == -1) { 989287809Sbapt fprintf(stderr, "Signature for pkg not " 990287809Sbapt "available.\n"); 991287809Sbapt goto cleanup; 992287809Sbapt } 993287809Sbapt 994287809Sbapt if (verify_signature(fd_pkg, fd_sig) == false) 995287809Sbapt goto cleanup; 996287809Sbapt 997287809Sbapt } else if (strcasecmp(signature_type, "PUBKEY") == 0) { 998287809Sbapt 999287809Sbapt snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath); 1000287809Sbapt 1001287809Sbapt if ((fd_sig = open(path, O_RDONLY)) == -1) { 1002287809Sbapt fprintf(stderr, "Signature for pkg not " 1003287809Sbapt "available.\n"); 1004287809Sbapt goto cleanup; 1005287809Sbapt } 1006287809Sbapt 1007287809Sbapt if (verify_pubsignature(fd_pkg, fd_sig) == false) 1008287809Sbapt goto cleanup; 1009287809Sbapt 1010287809Sbapt } else { 1011286935Sdelphij warnx("Signature type %s is not supported for " 1012286935Sdelphij "bootstrapping.", signature_type); 1013286935Sdelphij goto cleanup; 1014286935Sdelphij } 1015257353Sbdrewery } 1016257353Sbdrewery 1017257353Sbdrewery if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0) 1018257632Sbdrewery ret = install_pkg_static(pkgstatic, pkgpath, force); 1019257353Sbdrewery 1020257353Sbdrewerycleanup: 1021257353Sbdrewery close(fd_pkg); 1022257353Sbdrewery if (fd_sig != -1) 1023257353Sbdrewery close(fd_sig); 1024257353Sbdrewery 1025257353Sbdrewery return (ret); 1026257353Sbdrewery} 1027257353Sbdrewery 1028234313Sbaptint 1029283789Sbaptmain(int argc, char *argv[]) 1030234313Sbapt{ 1031234313Sbapt char pkgpath[MAXPATHLEN]; 1032257632Sbdrewery const char *pkgarg; 1033257632Sbdrewery bool bootstrap_only, force, yes; 1034234313Sbapt 1035257632Sbdrewery bootstrap_only = false; 1036257632Sbdrewery force = false; 1037257632Sbdrewery pkgarg = NULL; 1038257632Sbdrewery yes = false; 1039257632Sbdrewery 1040234313Sbapt snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", 1041234322Sbapt getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 1042234313Sbapt 1043257632Sbdrewery if (argc > 1 && strcmp(argv[1], "bootstrap") == 0) { 1044257632Sbdrewery bootstrap_only = true; 1045257632Sbdrewery if (argc == 3 && strcmp(argv[2], "-f") == 0) 1046257632Sbdrewery force = true; 1047257632Sbdrewery } 1048257632Sbdrewery 1049257632Sbdrewery if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) { 1050244553Smatthew /* 1051244594Smatthew * To allow 'pkg -N' to be used as a reliable test for whether 1052244553Smatthew * a system is configured to use pkg, don't bootstrap pkg 1053244553Smatthew * when that argument is given as argv[1]. 1054244553Smatthew */ 1055244639Smatthew if (argv[1] != NULL && strcmp(argv[1], "-N") == 0) 1056244639Smatthew errx(EXIT_FAILURE, "pkg is not installed"); 1057244553Smatthew 1058257353Sbdrewery config_init(); 1059257353Sbdrewery 1060257632Sbdrewery if (argc > 1 && strcmp(argv[1], "add") == 0) { 1061257632Sbdrewery if (argc > 2 && strcmp(argv[2], "-f") == 0) { 1062257632Sbdrewery force = true; 1063257632Sbdrewery pkgarg = argv[3]; 1064257632Sbdrewery } else 1065257632Sbdrewery pkgarg = argv[2]; 1066257632Sbdrewery if (pkgarg == NULL) { 1067257632Sbdrewery fprintf(stderr, "Path to pkg.txz required\n"); 1068257309Sbapt exit(EXIT_FAILURE); 1069257632Sbdrewery } 1070257632Sbdrewery if (access(pkgarg, R_OK) == -1) { 1071257632Sbdrewery fprintf(stderr, "No such file: %s\n", pkgarg); 1072257632Sbdrewery exit(EXIT_FAILURE); 1073257632Sbdrewery } 1074257632Sbdrewery if (bootstrap_pkg_local(pkgarg, force) != 0) 1075257632Sbdrewery exit(EXIT_FAILURE); 1076257309Sbapt exit(EXIT_SUCCESS); 1077257309Sbapt } 1078238461Skan /* 1079238461Skan * Do not ask for confirmation if either of stdin or stdout is 1080238461Skan * not tty. Check the environment to see if user has answer 1081238461Skan * tucked in there already. 1082238461Skan */ 1083247841Sbapt config_bool(ASSUME_ALWAYS_YES, &yes); 1084247841Sbapt if (!yes) { 1085283790Sbapt if (!isatty(fileno(stdin))) { 1086283790Sbapt fprintf(stderr, non_interactive_message); 1087238461Skan exit(EXIT_FAILURE); 1088283790Sbapt } 1089239664Sbapt 1090283790Sbapt printf("%s", confirmation_message); 1091239664Sbapt if (pkg_query_yes_no() == 0) 1092239663Sbapt exit(EXIT_FAILURE); 1093238461Skan } 1094257632Sbdrewery if (bootstrap_pkg(force) != 0) 1095234351Sbapt exit(EXIT_FAILURE); 1096247841Sbapt config_finish(); 1097257571Sbdrewery 1098257632Sbdrewery if (bootstrap_only) 1099257571Sbdrewery exit(EXIT_SUCCESS); 1100257632Sbdrewery } else if (bootstrap_only) { 1101257632Sbdrewery printf("pkg already bootstrapped at %s\n", pkgpath); 1102257632Sbdrewery exit(EXIT_SUCCESS); 1103238461Skan } 1104234313Sbapt 1105234313Sbapt execv(pkgpath, argv); 1106234313Sbapt 1107234351Sbapt /* NOT REACHED */ 1108234322Sbapt return (EXIT_FAILURE); 1109234313Sbapt} 1110