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/param.h>
31 #include <sys/queue.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34
35 #include <archive.h>
36 #include <archive_entry.h>
37 #include <assert.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 "pkg.h"
53
54 #include "dns_utils.h"
55 #include "config.h"
56 #include "hash.h"
57
58 #define PKGSIGN_MARKER "$PKGSIGN:"
59
60 static const struct pkgsign_impl {
61 const char *pi_name;
62 const struct pkgsign_ops *pi_ops;
63 } pkgsign_builtins[] = {
64 {
65 .pi_name = "rsa",
66 .pi_ops = &pkgsign_rsa,
67 },
68 {
69 .pi_name = "ecc",
70 .pi_ops = &pkgsign_ecc,
71 },
72 {
73 .pi_name = "ecdsa",
74 .pi_ops = &pkgsign_ecc,
75 },
76 {
77 .pi_name = "eddsa",
78 .pi_ops = &pkgsign_ecc,
79 },
80 };
81
82 typedef enum {
83 HASH_UNKNOWN,
84 HASH_SHA256,
85 } hash_t;
86
87 struct fingerprint {
88 hash_t type;
89 char *name;
90 char hash[BUFSIZ];
91 STAILQ_ENTRY(fingerprint) next;
92 };
93
94 static const char *bootstrap_name = "pkg.pkg";
95
96 STAILQ_HEAD(fingerprint_list, fingerprint);
97
98 static int debug;
99
100 static int
pkgsign_new(const char * name,struct pkgsign_ctx ** ctx)101 pkgsign_new(const char *name, struct pkgsign_ctx **ctx)
102 {
103 const struct pkgsign_impl *impl;
104 const struct pkgsign_ops *ops;
105 struct pkgsign_ctx *nctx;
106 size_t ctx_size;
107 int ret;
108
109 assert(*ctx == NULL);
110 ops = NULL;
111 for (size_t i = 0; i < nitems(pkgsign_builtins); i++) {
112 impl = &pkgsign_builtins[i];
113
114 if (strcmp(name, impl->pi_name) == 0) {
115 ops = impl->pi_ops;
116 break;
117 }
118 }
119
120 if (ops == NULL)
121 return (ENOENT);
122
123 ctx_size = ops->pkgsign_ctx_size;
124 if (ctx_size == 0)
125 ctx_size = sizeof(*nctx);
126 assert(ctx_size >= sizeof(*nctx));
127
128 nctx = calloc(1, ctx_size);
129 if (nctx == NULL)
130 err(EXIT_FAILURE, "calloc");
131 nctx->impl = impl;
132
133 ret = 0;
134 if (ops->pkgsign_new != NULL)
135 ret = (*ops->pkgsign_new)(name, nctx);
136
137 if (ret != 0) {
138 free(nctx);
139 return (ret);
140 }
141
142 *ctx = nctx;
143 return (0);
144 }
145
146 static bool
pkgsign_verify_cert(const struct pkgsign_ctx * ctx,int fd,const char * sigfile,const unsigned char * key,int keylen,unsigned char * sig,int siglen)147 pkgsign_verify_cert(const struct pkgsign_ctx *ctx, int fd, const char *sigfile,
148 const unsigned char *key, int keylen, unsigned char *sig, int siglen)
149 {
150
151 return ((*ctx->impl->pi_ops->pkgsign_verify_cert)(ctx, fd, sigfile,
152 key, keylen, sig, siglen));
153 }
154
155 static bool
pkgsign_verify_data(const struct pkgsign_ctx * ctx,const char * data,size_t datasz,const char * sigfile,const unsigned char * key,int keylen,unsigned char * sig,int siglen)156 pkgsign_verify_data(const struct pkgsign_ctx *ctx, const char *data,
157 size_t datasz, const char *sigfile, const unsigned char *key, int keylen,
158 unsigned char *sig, int siglen)
159 {
160
161 return ((*ctx->impl->pi_ops->pkgsign_verify_data)(ctx, data, datasz,
162 sigfile, key, keylen, sig, siglen));
163 }
164
165
166 static int
extract_pkg_static(int fd,char * p,int sz)167 extract_pkg_static(int fd, char *p, int sz)
168 {
169 struct archive *a;
170 struct archive_entry *ae;
171 char *end;
172 int ret, r;
173
174 ret = -1;
175 a = archive_read_new();
176 if (a == NULL) {
177 warn("archive_read_new");
178 return (ret);
179 }
180 archive_read_support_filter_all(a);
181 archive_read_support_format_tar(a);
182
183 if (lseek(fd, 0, 0) == -1) {
184 warn("lseek");
185 goto cleanup;
186 }
187
188 if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) {
189 warnx("archive_read_open_fd: %s", archive_error_string(a));
190 goto cleanup;
191 }
192
193 ae = NULL;
194 while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
195 end = strrchr(archive_entry_pathname(ae), '/');
196 if (end == NULL)
197 continue;
198
199 if (strcmp(end, "/pkg-static") == 0) {
200 r = archive_read_extract(a, ae,
201 ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM |
202 ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL |
203 ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR);
204 strlcpy(p, archive_entry_pathname(ae), sz);
205 break;
206 }
207 }
208
209 if (r == ARCHIVE_OK)
210 ret = 0;
211 else
212 warnx("failed to extract pkg-static: %s",
213 archive_error_string(a));
214
215 cleanup:
216 archive_read_free(a);
217 return (ret);
218
219 }
220
221 static int
install_pkg_static(const char * path,const char * pkgpath,bool force)222 install_pkg_static(const char *path, const char *pkgpath, bool force)
223 {
224 int pstat;
225 pid_t pid;
226
227 switch ((pid = fork())) {
228 case -1:
229 return (-1);
230 case 0:
231 if (force)
232 execl(path, "pkg-static", "add", "-f", pkgpath,
233 (char *)NULL);
234 else
235 execl(path, "pkg-static", "add", pkgpath,
236 (char *)NULL);
237 _exit(1);
238 default:
239 break;
240 }
241
242 while (waitpid(pid, &pstat, 0) == -1)
243 if (errno != EINTR)
244 return (-1);
245
246 if (WEXITSTATUS(pstat))
247 return (WEXITSTATUS(pstat));
248 else if (WIFSIGNALED(pstat))
249 return (128 & (WTERMSIG(pstat)));
250 return (pstat);
251 }
252
253 static int
fetch_to_fd(struct repository * repo,const char * url,char * path,const char * fetchOpts)254 fetch_to_fd(struct repository *repo, const char *url, char *path, const char *fetchOpts)
255 {
256 struct url *u;
257 struct dns_srvinfo *mirrors, *current;
258 struct url_stat st;
259 FILE *remote;
260 /* To store _https._tcp. + hostname + \0 */
261 int fd;
262 int retry, max_retry;
263 ssize_t r;
264 char buf[10240];
265 char zone[MAXHOSTNAMELEN + 13];
266
267 max_retry = 3;
268 current = mirrors = NULL;
269 remote = NULL;
270
271 if ((fd = mkstemp(path)) == -1) {
272 warn("mkstemp()");
273 return (-1);
274 }
275
276 retry = max_retry;
277
278 if ((u = fetchParseURL(url)) == NULL) {
279 warn("fetchParseURL('%s')", url);
280 return (-1);
281 }
282
283 while (remote == NULL) {
284 if (retry == max_retry) {
285 if (strcmp(u->scheme, "file") != 0 &&
286 repo->mirror_type == MIRROR_SRV) {
287 snprintf(zone, sizeof(zone),
288 "_%s._tcp.%s", u->scheme, u->host);
289 mirrors = dns_getsrvinfo(zone);
290 current = mirrors;
291 }
292 }
293
294 if (mirrors != NULL) {
295 strlcpy(u->host, current->host, sizeof(u->host));
296 u->port = current->port;
297 }
298
299 remote = fetchXGet(u, &st, fetchOpts);
300 if (remote == NULL) {
301 --retry;
302 if (retry <= 0)
303 goto fetchfail;
304 if (mirrors != NULL) {
305 current = current->next;
306 if (current == NULL)
307 current = mirrors;
308 }
309 }
310 }
311
312 while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) {
313 if (write(fd, buf, r) != r) {
314 warn("write()");
315 goto fetchfail;
316 }
317 }
318
319 if (r != 0) {
320 warn("An error occurred while fetching pkg(8)");
321 goto fetchfail;
322 }
323
324 if (ferror(remote))
325 goto fetchfail;
326
327 goto cleanup;
328
329 fetchfail:
330 if (fd != -1) {
331 close(fd);
332 fd = -1;
333 unlink(path);
334 }
335
336 cleanup:
337 fetchFreeURL(u);
338 while (mirrors != NULL) {
339 current = mirrors;
340 mirrors = mirrors->next;
341 free(current);
342 }
343 if (remote != NULL)
344 fclose(remote);
345
346 return fd;
347 }
348
349 static struct fingerprint *
parse_fingerprint(ucl_object_t * obj)350 parse_fingerprint(ucl_object_t *obj)
351 {
352 const ucl_object_t *cur;
353 ucl_object_iter_t it = NULL;
354 const char *function, *fp, *key;
355 struct fingerprint *f;
356 hash_t fct = HASH_UNKNOWN;
357
358 function = fp = NULL;
359
360 while ((cur = ucl_iterate_object(obj, &it, true))) {
361 key = ucl_object_key(cur);
362 if (cur->type != UCL_STRING)
363 continue;
364 if (strcasecmp(key, "function") == 0) {
365 function = ucl_object_tostring(cur);
366 continue;
367 }
368 if (strcasecmp(key, "fingerprint") == 0) {
369 fp = ucl_object_tostring(cur);
370 continue;
371 }
372 }
373
374 if (fp == NULL || function == NULL)
375 return (NULL);
376
377 if (strcasecmp(function, "sha256") == 0)
378 fct = HASH_SHA256;
379
380 if (fct == HASH_UNKNOWN) {
381 warnx("Unsupported hashing function: %s", function);
382 return (NULL);
383 }
384
385 f = calloc(1, sizeof(struct fingerprint));
386 f->type = fct;
387 strlcpy(f->hash, fp, sizeof(f->hash));
388
389 return (f);
390 }
391
392 static void
free_fingerprint_list(struct fingerprint_list * list)393 free_fingerprint_list(struct fingerprint_list* list)
394 {
395 struct fingerprint *fingerprint, *tmp;
396
397 STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) {
398 free(fingerprint->name);
399 free(fingerprint);
400 }
401 free(list);
402 }
403
404 static struct fingerprint *
load_fingerprint(const char * dir,const char * filename)405 load_fingerprint(const char *dir, const char *filename)
406 {
407 ucl_object_t *obj = NULL;
408 struct ucl_parser *p = NULL;
409 struct fingerprint *f;
410 char path[MAXPATHLEN];
411
412 f = NULL;
413
414 snprintf(path, MAXPATHLEN, "%s/%s", dir, filename);
415
416 p = ucl_parser_new(0);
417 if (!ucl_parser_add_file(p, path)) {
418 warnx("%s: %s", path, ucl_parser_get_error(p));
419 ucl_parser_free(p);
420 return (NULL);
421 }
422
423 obj = ucl_parser_get_object(p);
424
425 if (obj->type == UCL_OBJECT)
426 f = parse_fingerprint(obj);
427
428 if (f != NULL)
429 f->name = strdup(filename);
430
431 ucl_object_unref(obj);
432 ucl_parser_free(p);
433
434 return (f);
435 }
436
437 static struct fingerprint_list *
load_fingerprints(const char * path,int * count)438 load_fingerprints(const char *path, int *count)
439 {
440 DIR *d;
441 struct dirent *ent;
442 struct fingerprint *finger;
443 struct fingerprint_list *fingerprints;
444
445 *count = 0;
446
447 fingerprints = calloc(1, sizeof(struct fingerprint_list));
448 if (fingerprints == NULL)
449 return (NULL);
450 STAILQ_INIT(fingerprints);
451
452 if ((d = opendir(path)) == NULL) {
453 free(fingerprints);
454
455 return (NULL);
456 }
457
458 while ((ent = readdir(d))) {
459 if (strcmp(ent->d_name, ".") == 0 ||
460 strcmp(ent->d_name, "..") == 0)
461 continue;
462 finger = load_fingerprint(path, ent->d_name);
463 if (finger != NULL) {
464 STAILQ_INSERT_TAIL(fingerprints, finger, next);
465 ++(*count);
466 }
467 }
468
469 closedir(d);
470
471 return (fingerprints);
472 }
473
474 char *
pkg_read_fd(int fd,size_t * osz)475 pkg_read_fd(int fd, size_t *osz)
476 {
477 char *obuf;
478 char buf[4096];
479 FILE *fp;
480 ssize_t r;
481
482 obuf = NULL;
483 *osz = 0;
484 fp = open_memstream(&obuf, osz);
485 if (fp == NULL)
486 err(EXIT_FAILURE, "open_memstream()");
487
488 while ((r = read(fd, buf, sizeof(buf))) >0) {
489 fwrite(buf, 1, r, fp);
490 }
491
492 if (ferror(fp))
493 errx(EXIT_FAILURE, "reading file");
494
495 fclose(fp);
496
497 return (obuf);
498 }
499
500 /*
501 * Returns a copy of the signature type stored on the heap, and advances *bufp
502 * past the type.
503 */
504 static char *
parse_sigtype(char ** bufp,size_t * bufszp)505 parse_sigtype(char **bufp, size_t *bufszp)
506 {
507 char *buf = *bufp;
508 char *endp;
509 char *sigtype;
510 size_t bufsz = *bufszp;
511
512 if (bufsz <= sizeof(PKGSIGN_MARKER) - 1 ||
513 strncmp(buf, PKGSIGN_MARKER, sizeof(PKGSIGN_MARKER) - 1) != 0)
514 goto dflt;
515
516 buf += sizeof(PKGSIGN_MARKER) - 1;
517 endp = strchr(buf, '$');
518 if (endp == NULL)
519 goto dflt;
520
521 sigtype = strndup(buf, endp - buf);
522 *bufp = endp + 1;
523 *bufszp -= *bufp - buf;
524
525 return (sigtype);
526 dflt:
527 return (strdup("rsa"));
528 }
529
530 static struct pubkey *
read_pubkey(int fd)531 read_pubkey(int fd)
532 {
533 struct pubkey *pk;
534 char *osigb, *sigb, *sigtype;
535 size_t sigsz;
536
537 if (lseek(fd, 0, 0) == -1) {
538 warn("lseek");
539 return (NULL);
540 }
541
542 osigb = sigb = pkg_read_fd(fd, &sigsz);
543 sigtype = parse_sigtype(&sigb, &sigsz);
544
545 pk = calloc(1, sizeof(struct pubkey));
546 pk->siglen = sigsz;
547 pk->sig = calloc(1, pk->siglen);
548 memcpy(pk->sig, sigb, pk->siglen);
549 pk->sigtype = sigtype;
550 free(osigb);
551
552 return (pk);
553 }
554
555 static struct sig_cert *
parse_cert(int fd)556 parse_cert(int fd) {
557 int my_fd;
558 struct sig_cert *sc;
559 FILE *fp, *sigfp, *certfp, *tmpfp, *typefp;
560 char *line;
561 char *sig, *cert, *type;
562 size_t linecap, sigsz, certsz, typesz;
563 ssize_t linelen;
564 bool end_seen;
565
566 sc = NULL;
567 line = NULL;
568 linecap = 0;
569 sig = cert = type = NULL;
570 sigfp = certfp = tmpfp = typefp = NULL;
571
572 if (lseek(fd, 0, 0) == -1) {
573 warn("lseek");
574 return (NULL);
575 }
576
577 /* Duplicate the fd so that fclose(3) does not close it. */
578 if ((my_fd = dup(fd)) == -1) {
579 warnx("dup");
580 return (NULL);
581 }
582
583 if ((fp = fdopen(my_fd, "rb")) == NULL) {
584 warn("fdopen");
585 close(my_fd);
586 return (NULL);
587 }
588
589 sigsz = certsz = typesz = 0;
590 sigfp = open_memstream(&sig, &sigsz);
591 if (sigfp == NULL)
592 err(EXIT_FAILURE, "open_memstream()");
593 certfp = open_memstream(&cert, &certsz);
594 if (certfp == NULL)
595 err(EXIT_FAILURE, "open_memstream()");
596 typefp = open_memstream(&type, &typesz);
597 if (typefp == NULL)
598 err(EXIT_FAILURE, "open_memstream()");
599
600 end_seen = false;
601 while ((linelen = getline(&line, &linecap, fp)) > 0) {
602 if (strcmp(line, "SIGNATURE\n") == 0) {
603 tmpfp = sigfp;
604 continue;
605 } else if (strcmp(line, "TYPE\n") == 0) {
606 tmpfp = typefp;
607 continue;
608 } else if (strcmp(line, "CERT\n") == 0) {
609 tmpfp = certfp;
610 continue;
611 } else if (strcmp(line, "END\n") == 0) {
612 end_seen = true;
613 break;
614 }
615 if (tmpfp != NULL)
616 fwrite(line, 1, linelen, tmpfp);
617 }
618
619 fclose(fp);
620 fclose(sigfp);
621 fclose(certfp);
622 fclose(typefp);
623
624 sc = calloc(1, sizeof(struct sig_cert));
625 sc->siglen = sigsz -1; /* Trim out unrelated trailing newline */
626 sc->sig = sig;
627
628 if (typesz == 0) {
629 sc->type = strdup("rsa");
630 free(type);
631 } else {
632 assert(type[typesz - 1] == '\n');
633 type[typesz - 1] = '\0';
634 sc->type = type;
635 }
636
637 /*
638 * cert could be DER-encoded rather than PEM, so strip off any trailing
639 * END marker if we ran over it.
640 */
641 if (!end_seen && certsz > 4 &&
642 strcmp(&cert[certsz - 4], "END\n") == 0)
643 certsz -= 4;
644 sc->certlen = certsz;
645 sc->cert = cert;
646
647 return (sc);
648 }
649
650 static bool
verify_pubsignature(int fd_pkg,int fd_sig,struct repository * r)651 verify_pubsignature(int fd_pkg, int fd_sig, struct repository *r)
652 {
653 struct pubkey *pk;
654 char *data;
655 struct pkgsign_ctx *sctx;
656 size_t datasz;
657 bool ret;
658 const char *pubkey;
659
660 pk = NULL;
661 sctx = NULL;
662 data = NULL;
663 ret = false;
664
665 if (r != NULL) {
666 if (r->pubkey == NULL) {
667 warnx("No CONFIG_PUBKEY defined for %s", r->name);
668 goto cleanup;
669 }
670 pubkey = r->pubkey;
671 } else {
672 if (config_string(PUBKEY, &pubkey) != 0) {
673 warnx("No CONFIG_PUBKEY defined");
674 goto cleanup;
675 }
676 }
677
678 if ((pk = read_pubkey(fd_sig)) == NULL) {
679 warnx("Error reading signature");
680 goto cleanup;
681 }
682
683 if (lseek(fd_pkg, 0, SEEK_SET) == -1) {
684 warn("lseek");
685 goto cleanup;
686 }
687
688 if (strcmp(pk->sigtype, "rsa") == 0) {
689 /* Future types shouldn't do this. */
690 if ((data = sha256_fd(fd_pkg)) == NULL) {
691 warnx("Error creating SHA256 hash for package");
692 goto cleanup;
693 }
694
695 datasz = strlen(data);
696 } else {
697 if ((data = pkg_read_fd(fd_pkg, &datasz)) == NULL) {
698 warnx("Failed to read package data");
699 goto cleanup;
700 }
701 }
702
703 if (pkgsign_new(pk->sigtype, &sctx) != 0) {
704 warnx("Failed to fetch '%s' signer", pk->sigtype);
705 goto cleanup;
706 }
707
708 /* Verify the signature. */
709 printf("Verifying signature with public key %s.a.. ", r->pubkey);
710 if (pkgsign_verify_data(sctx, data, datasz, r->pubkey, NULL, 0, pk->sig,
711 pk->siglen) == false) {
712 fprintf(stderr, "Signature is not valid\n");
713 goto cleanup;
714 }
715
716 ret = true;
717
718 cleanup:
719 free(data);
720 if (pk) {
721 free(pk->sig);
722 free(pk);
723 }
724
725 return (ret);
726 }
727
728 static bool
verify_signature(int fd_pkg,int fd_sig,struct repository * r)729 verify_signature(int fd_pkg, int fd_sig, struct repository *r)
730 {
731 struct fingerprint_list *trusted, *revoked;
732 struct fingerprint *fingerprint;
733 struct sig_cert *sc;
734 struct pkgsign_ctx *sctx;
735 bool ret;
736 int trusted_count, revoked_count;
737 const char *fingerprints;
738 char path[MAXPATHLEN];
739 char *hash;
740
741 hash = NULL;
742 sc = NULL;
743 sctx = NULL;
744 trusted = revoked = NULL;
745 ret = false;
746
747 /* Read and parse fingerprints. */
748 if (r != NULL) {
749 if (r->fingerprints == NULL) {
750 warnx("No FINGERPRINTS defined for %s", r->name);
751 goto cleanup;
752 }
753 fingerprints = r->fingerprints;
754 } else {
755 if (config_string(FINGERPRINTS, &fingerprints) != 0) {
756 warnx("No FINGERPRINTS defined");
757 goto cleanup;
758 }
759 }
760
761 snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints);
762 if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) {
763 warnx("Error loading trusted certificates");
764 goto cleanup;
765 }
766
767 if (trusted_count == 0 || trusted == NULL) {
768 fprintf(stderr, "No trusted certificates found.\n");
769 goto cleanup;
770 }
771
772 snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints);
773 if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) {
774 warnx("Error loading revoked certificates");
775 goto cleanup;
776 }
777
778 /* Read certificate and signature in. */
779 if ((sc = parse_cert(fd_sig)) == NULL) {
780 warnx("Error parsing certificate");
781 goto cleanup;
782 }
783 /* Explicitly mark as non-trusted until proven otherwise. */
784 sc->trusted = false;
785
786 /* Parse signature and pubkey out of the certificate */
787 hash = sha256_buf(sc->cert, sc->certlen);
788
789 /* Check if this hash is revoked */
790 if (revoked != NULL) {
791 STAILQ_FOREACH(fingerprint, revoked, next) {
792 if (strcasecmp(fingerprint->hash, hash) == 0) {
793 fprintf(stderr, "The package was signed with "
794 "revoked certificate %s\n",
795 fingerprint->name);
796 goto cleanup;
797 }
798 }
799 }
800
801 STAILQ_FOREACH(fingerprint, trusted, next) {
802 if (strcasecmp(fingerprint->hash, hash) == 0) {
803 sc->trusted = true;
804 sc->name = strdup(fingerprint->name);
805 break;
806 }
807 }
808
809 if (sc->trusted == false) {
810 fprintf(stderr, "No trusted fingerprint found matching "
811 "package's certificate\n");
812 goto cleanup;
813 }
814
815 if (pkgsign_new(sc->type, &sctx) != 0) {
816 fprintf(stderr, "Failed to fetch 'rsa' signer\n");
817 goto cleanup;
818 }
819
820 /* Verify the signature. */
821 printf("Verifying signature with trusted certificate %s... ", sc->name);
822 if (pkgsign_verify_cert(sctx, fd_pkg, NULL, sc->cert, sc->certlen,
823 sc->sig, sc->siglen) == false) {
824 fprintf(stderr, "Signature is not valid\n");
825 goto cleanup;
826 }
827
828 ret = true;
829
830 cleanup:
831 free(hash);
832 if (trusted)
833 free_fingerprint_list(trusted);
834 if (revoked)
835 free_fingerprint_list(revoked);
836 if (sc) {
837 free(sc->cert);
838 free(sc->sig);
839 free(sc->name);
840 free(sc);
841 }
842
843 return (ret);
844 }
845
846 static int
bootstrap_pkg(bool force,const char * fetchOpts,struct repository * repo)847 bootstrap_pkg(bool force, const char *fetchOpts, struct repository *repo)
848 {
849 int fd_pkg, fd_sig;
850 int ret;
851 char url[MAXPATHLEN];
852 char tmppkg[MAXPATHLEN];
853 char tmpsig[MAXPATHLEN];
854 const char *packagesite;
855 char pkgstatic[MAXPATHLEN];
856
857 fd_sig = -1;
858 ret = -1;
859
860 printf("Bootstrapping pkg from %s, please wait...\n", repo->url);
861
862 /* Support pkg+http:// for PACKAGESITE which is the new format
863 in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has
864 no A record. */
865 packagesite = repo->url;
866 if (strncmp(URL_SCHEME_PREFIX, packagesite,
867 strlen(URL_SCHEME_PREFIX)) == 0)
868 packagesite += strlen(URL_SCHEME_PREFIX);
869
870 snprintf(url, MAXPATHLEN, "%s/Latest/%s", packagesite, bootstrap_name);
871 snprintf(tmppkg, MAXPATHLEN, "%s/%s.XXXXXX",
872 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP,
873 bootstrap_name);
874 if ((fd_pkg = fetch_to_fd(repo, url, tmppkg, fetchOpts)) == -1)
875 goto fetchfail;
876
877 if (repo->signature_type == SIGNATURE_FINGERPRINT) {
878 snprintf(tmpsig, MAXPATHLEN, "%s/%s.sig.XXXXXX",
879 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP,
880 bootstrap_name);
881 snprintf(url, MAXPATHLEN, "%s/Latest/%s.sig",
882 packagesite, bootstrap_name);
883
884 if ((fd_sig = fetch_to_fd(repo, url, tmpsig, fetchOpts)) == -1) {
885 fprintf(stderr, "Signature for pkg not "
886 "available.\n");
887 goto fetchfail;
888 }
889
890 if (verify_signature(fd_pkg, fd_sig, repo) == false)
891 goto cleanup;
892 } else if (repo->signature_type == SIGNATURE_PUBKEY) {
893 snprintf(tmpsig, MAXPATHLEN,
894 "%s/%s.pubkeysig.XXXXXX",
895 getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP,
896 bootstrap_name);
897 snprintf(url, MAXPATHLEN, "%s/Latest/%s.pubkeysig",
898 packagesite, bootstrap_name);
899
900 if ((fd_sig = fetch_to_fd(repo, url, tmpsig, fetchOpts)) == -1) {
901 fprintf(stderr, "Signature for pkg not "
902 "available.\n");
903 goto fetchfail;
904 }
905
906 if (verify_pubsignature(fd_pkg, fd_sig, repo) == false)
907 goto cleanup;
908 }
909
910 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
911 ret = install_pkg_static(pkgstatic, tmppkg, force);
912
913 goto cleanup;
914
915 fetchfail:
916 warnx("Error fetching %s: %s", url, fetchLastErrString);
917 if (fetchLastErrCode == FETCH_RESOLV) {
918 fprintf(stderr, "Address resolution failed for %s.\n", packagesite);
919 } else {
920 fprintf(stderr, "A pre-built version of pkg could not be found for "
921 "your system.\n");
922 }
923
924 cleanup:
925 if (fd_sig != -1) {
926 close(fd_sig);
927 unlink(tmpsig);
928 }
929
930 if (fd_pkg != -1) {
931 close(fd_pkg);
932 unlink(tmppkg);
933 }
934
935 return (ret);
936 }
937
938 static const char confirmation_message[] =
939 "The package management tool is not yet installed on your system.\n"
940 "Do you want to fetch and install it now? [y/N]: ";
941
942 static const char non_interactive_message[] =
943 "The package management tool is not yet installed on your system.\n"
944 "Please set ASSUME_ALWAYS_YES=yes environment variable to be able to bootstrap "
945 "in non-interactive (stdin not being a tty)\n";
946
947 static const char args_bootstrap_message[] =
948 "Too many arguments\n"
949 "Usage: pkg [-4|-6] bootstrap [-f] [-y]\n";
950
951 static int
pkg_query_yes_no(void)952 pkg_query_yes_no(void)
953 {
954 int ret, c;
955
956 fflush(stdout);
957 c = getchar();
958
959 if (c == 'y' || c == 'Y')
960 ret = 1;
961 else
962 ret = 0;
963
964 while (c != '\n' && c != EOF)
965 c = getchar();
966
967 return (ret);
968 }
969
970 static int
bootstrap_pkg_local(const char * pkgpath,bool force)971 bootstrap_pkg_local(const char *pkgpath, bool force)
972 {
973 char path[MAXPATHLEN];
974 char pkgstatic[MAXPATHLEN];
975 const char *signature_type;
976 int fd_pkg, fd_sig, ret;
977
978 fd_sig = -1;
979 ret = -1;
980
981 fd_pkg = open(pkgpath, O_RDONLY);
982 if (fd_pkg == -1)
983 err(EXIT_FAILURE, "Unable to open %s", pkgpath);
984
985 if (config_string(SIGNATURE_TYPE, &signature_type) != 0) {
986 warnx("Error looking up SIGNATURE_TYPE");
987 goto cleanup;
988 }
989 if (signature_type != NULL &&
990 strcasecmp(signature_type, "NONE") != 0) {
991 if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
992
993 snprintf(path, sizeof(path), "%s.sig", pkgpath);
994
995 if ((fd_sig = open(path, O_RDONLY)) == -1) {
996 fprintf(stderr, "Signature for pkg not "
997 "available.\n");
998 goto cleanup;
999 }
1000
1001 if (verify_signature(fd_pkg, fd_sig, NULL) == false)
1002 goto cleanup;
1003
1004 } else if (strcasecmp(signature_type, "PUBKEY") == 0) {
1005
1006 snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath);
1007
1008 if ((fd_sig = open(path, O_RDONLY)) == -1) {
1009 fprintf(stderr, "Signature for pkg not "
1010 "available.\n");
1011 goto cleanup;
1012 }
1013
1014 if (verify_pubsignature(fd_pkg, fd_sig, NULL) == false)
1015 goto cleanup;
1016
1017 } else {
1018 warnx("Signature type %s is not supported for "
1019 "bootstrapping.", signature_type);
1020 goto cleanup;
1021 }
1022 }
1023
1024 if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
1025 ret = install_pkg_static(pkgstatic, pkgpath, force);
1026
1027 cleanup:
1028 close(fd_pkg);
1029 if (fd_sig != -1)
1030 close(fd_sig);
1031
1032 return (ret);
1033 }
1034
1035 #define PKG_NAME "pkg"
1036 #define PKG_DEVEL_NAME PKG_NAME "-devel"
1037 #define PKG_PKG PKG_NAME "."
1038
1039 static bool
pkg_is_pkg_pkg(const char * pkg)1040 pkg_is_pkg_pkg(const char *pkg)
1041 {
1042 char *vstart, *basename;
1043 size_t namelen;
1044
1045 /* Strip path. */
1046 if ((basename = strrchr(pkg, '/')) != NULL)
1047 pkg = basename + 1;
1048
1049 /*
1050 * Chop off the final "-" (version delimiter) and check the name that
1051 * precedes it. If we didn't have a version delimiter, it must be the
1052 * pkg.$archive short form but we'll check it anyways. pkg-devel short
1053 * form will look like a pkg archive with 'devel' version, but that's
1054 * OK. We otherwise assumed that non-pkg packages will always have a
1055 * version component.
1056 */
1057 vstart = strrchr(pkg, '-');
1058 if (vstart == NULL) {
1059 return (strlen(pkg) > sizeof(PKG_PKG) - 1 &&
1060 strncmp(pkg, PKG_PKG, sizeof(PKG_PKG) - 1) == 0);
1061 }
1062
1063 namelen = vstart - pkg;
1064 if (namelen == sizeof(PKG_NAME) - 1 &&
1065 strncmp(pkg, PKG_NAME, sizeof(PKG_NAME) - 1) == 0)
1066 return (true);
1067 if (namelen == sizeof(PKG_DEVEL_NAME) - 1 &&
1068 strncmp(pkg, PKG_DEVEL_NAME, sizeof(PKG_DEVEL_NAME) - 1) == 0)
1069 return (true);
1070 return (false);
1071 }
1072
1073 int
main(int argc,char * argv[])1074 main(int argc, char *argv[])
1075 {
1076 char pkgpath[MAXPATHLEN];
1077 char **original_argv;
1078 const char *pkgarg, *repo_name;
1079 bool activation_test, add_pkg, bootstrap_only, force, yes;
1080 signed char ch;
1081 const char *fetchOpts;
1082 struct repositories *repositories;
1083
1084 activation_test = false;
1085 add_pkg = false;
1086 bootstrap_only = false;
1087 fetchOpts = "";
1088 force = false;
1089 original_argv = argv;
1090 pkgarg = NULL;
1091 repo_name = NULL;
1092 yes = false;
1093
1094 struct option longopts[] = {
1095 { "debug", no_argument, NULL, 'd' },
1096 { "only-ipv4", no_argument, NULL, '4' },
1097 { "only-ipv6", no_argument, NULL, '6' },
1098 { NULL, 0, NULL, 0 },
1099 };
1100
1101 snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", getlocalbase());
1102
1103 while ((ch = getopt_long(argc, argv, "+:dN46", longopts, NULL)) != -1) {
1104 switch (ch) {
1105 case 'd':
1106 debug++;
1107 break;
1108 case 'N':
1109 activation_test = true;
1110 break;
1111 case '4':
1112 fetchOpts = "4";
1113 break;
1114 case '6':
1115 fetchOpts = "6";
1116 break;
1117 default:
1118 break;
1119 }
1120 }
1121 if (debug > 1)
1122 fetchDebug = 1;
1123
1124 argc -= optind;
1125 argv += optind;
1126
1127 if (argc >= 1) {
1128 if (strcmp(argv[0], "bootstrap") == 0) {
1129 bootstrap_only = true;
1130 } else if (strcmp(argv[0], "add") == 0) {
1131 add_pkg = true;
1132 }
1133
1134 optreset = 1;
1135 optind = 1;
1136 if (bootstrap_only || add_pkg) {
1137 struct option sub_longopts[] = {
1138 { "force", no_argument, NULL, 'f' },
1139 { "yes", no_argument, NULL, 'y' },
1140 { NULL, 0, NULL, 0 },
1141 };
1142 while ((ch = getopt_long(argc, argv, "+:fr:y",
1143 sub_longopts, NULL)) != -1) {
1144 switch (ch) {
1145 case 'f':
1146 force = true;
1147 break;
1148 case 'r':
1149 repo_name = optarg;
1150 break;
1151 case 'y':
1152 yes = true;
1153 break;
1154 case ':':
1155 fprintf(stderr, "Option -%c requires an argument\n", optopt);
1156 exit(EXIT_FAILURE);
1157 break;
1158 default:
1159 break;
1160 }
1161 }
1162 } else {
1163 /*
1164 * Parse -y and --yes regardless of the pkg subcommand
1165 * specified. This is necessary to make, for example,
1166 * `pkg install -y foobar` work as expected when pkg is
1167 * not yet bootstrapped.
1168 */
1169 struct option sub_longopts[] = {
1170 { "yes", no_argument, NULL, 'y' },
1171 { NULL, 0, NULL, 0 },
1172 };
1173 while ((ch = getopt_long(argc, argv, "+:y",
1174 sub_longopts, NULL)) != -1) {
1175 switch (ch) {
1176 case 'y':
1177 yes = true;
1178 break;
1179 default:
1180 break;
1181 }
1182 }
1183
1184 }
1185 argc -= optind;
1186 argv += optind;
1187
1188 if (bootstrap_only && argc > 0) {
1189 fprintf(stderr, args_bootstrap_message);
1190 exit(EXIT_FAILURE);
1191 }
1192
1193 if (add_pkg) {
1194 if (argc < 1) {
1195 fprintf(stderr, "Path to pkg.pkg required\n");
1196 exit(EXIT_FAILURE);
1197 } else if (argc == 1 && pkg_is_pkg_pkg(argv[0])) {
1198 pkgarg = argv[0];
1199 } else {
1200 /*
1201 * If the target package is not pkg.pkg
1202 * or there is more than one target package,
1203 * this is not a local bootstrap request.
1204 */
1205 add_pkg = false;
1206 }
1207 }
1208 }
1209
1210 if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) {
1211 struct repository *repo;
1212 int ret = 0;
1213 /*
1214 * To allow 'pkg -N' to be used as a reliable test for whether
1215 * a system is configured to use pkg, don't bootstrap pkg
1216 * when that option is passed.
1217 */
1218 if (activation_test)
1219 errx(EXIT_FAILURE, "pkg is not installed");
1220
1221 config_init(repo_name);
1222
1223 if (add_pkg) {
1224 assert(pkgarg != NULL);
1225 if (access(pkgarg, R_OK) == -1) {
1226 fprintf(stderr, "No such file: %s\n", pkgarg);
1227 exit(EXIT_FAILURE);
1228 }
1229 if (bootstrap_pkg_local(pkgarg, force) != 0)
1230 exit(EXIT_FAILURE);
1231 exit(EXIT_SUCCESS);
1232 }
1233 /*
1234 * Do not ask for confirmation if either of stdin or stdout is
1235 * not tty. Check the environment to see if user has answer
1236 * tucked in there already.
1237 */
1238 if (!yes)
1239 config_bool(ASSUME_ALWAYS_YES, &yes);
1240 if (!yes) {
1241 if (!isatty(fileno(stdin))) {
1242 fprintf(stderr, non_interactive_message);
1243 exit(EXIT_FAILURE);
1244 }
1245
1246 printf("%s", confirmation_message);
1247 if (pkg_query_yes_no() == 0)
1248 exit(EXIT_FAILURE);
1249 }
1250 repositories = config_get_repositories();
1251 STAILQ_FOREACH(repo, repositories, next) {
1252 if ((ret = bootstrap_pkg(force, fetchOpts, repo)) == 0)
1253 break;
1254 }
1255 if (ret != 0)
1256 exit(EXIT_FAILURE);
1257 config_finish();
1258
1259 if (bootstrap_only)
1260 exit(EXIT_SUCCESS);
1261 } else if (bootstrap_only) {
1262 printf("pkg already bootstrapped at %s\n", pkgpath);
1263 exit(EXIT_SUCCESS);
1264 }
1265
1266 execv(pkgpath, original_argv);
1267
1268 /* NOT REACHED */
1269 return (EXIT_FAILURE);
1270 }
1271