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