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