1/*-
2 * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org>
3 * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/types.h>
34#include <sys/sbuf.h>
35#include <sys/wait.h>
36
37#define _WITH_GETLINE
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 <paths.h>
46#include <stdbool.h>
47#include <stdlib.h>
48#include <stdio.h>
49#include <string.h>
50#include <time.h>
51#include <unistd.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
60struct sig_cert {
61	char *name;
62	unsigned char *sig;
63	int siglen;
64	unsigned char *cert;
65	int certlen;
66	bool trusted;
67};
68
69struct pubkey {
70	unsigned char *sig;
71	int siglen;
72};
73
74typedef enum {
75       HASH_UNKNOWN,
76       HASH_SHA256,
77} hash_t;
78
79struct fingerprint {
80       hash_t type;
81       char *name;
82       char hash[BUFSIZ];
83       STAILQ_ENTRY(fingerprint) next;
84};
85
86STAILQ_HEAD(fingerprint_list, fingerprint);
87
88static int
89extract_pkg_static(int fd, char *p, int sz)
90{
91	struct archive *a;
92	struct archive_entry *ae;
93	char *end;
94	int ret, r;
95
96	ret = -1;
97	a = archive_read_new();
98	if (a == NULL) {
99		warn("archive_read_new");
100		return (ret);
101	}
102	archive_read_support_filter_all(a);
103	archive_read_support_format_tar(a);
104
105	if (lseek(fd, 0, 0) == -1) {
106		warn("lseek");
107		goto cleanup;
108	}
109
110	if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) {
111		warnx("archive_read_open_fd: %s", archive_error_string(a));
112		goto cleanup;
113	}
114
115	ae = NULL;
116	while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
117		end = strrchr(archive_entry_pathname(ae), '/');
118		if (end == NULL)
119			continue;
120
121		if (strcmp(end, "/pkg-static") == 0) {
122			r = archive_read_extract(a, ae,
123			    ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM |
124			    ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL |
125			    ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR);
126			strlcpy(p, archive_entry_pathname(ae), sz);
127			break;
128		}
129	}
130
131	if (r == ARCHIVE_OK)
132		ret = 0;
133	else
134		warnx("failed to extract pkg-static: %s",
135		    archive_error_string(a));
136
137cleanup:
138	archive_read_free(a);
139	return (ret);
140
141}
142
143static int
144install_pkg_static(const char *path, const char *pkgpath, bool force)
145{
146	int pstat;
147	pid_t pid;
148
149	switch ((pid = fork())) {
150	case -1:
151		return (-1);
152	case 0:
153		if (force)
154			execl(path, "pkg-static", "add", "-f", pkgpath,
155			    (char *)NULL);
156		else
157			execl(path, "pkg-static", "add", pkgpath,
158			    (char *)NULL);
159		_exit(1);
160	default:
161		break;
162	}
163
164	while (waitpid(pid, &pstat, 0) == -1)
165		if (errno != EINTR)
166			return (-1);
167
168	if (WEXITSTATUS(pstat))
169		return (WEXITSTATUS(pstat));
170	else if (WIFSIGNALED(pstat))
171		return (128 & (WTERMSIG(pstat)));
172	return (pstat);
173}
174
175static int
176fetch_to_fd(const char *url, char *path)
177{
178	struct url *u;
179	struct dns_srvinfo *mirrors, *current;
180	struct url_stat st;
181	FILE *remote;
182	/* To store _https._tcp. + hostname + \0 */
183	int fd;
184	int retry, max_retry;
185	off_t done, r;
186	time_t now, last;
187	char buf[10240];
188	char zone[MAXHOSTNAMELEN + 13];
189	static const char *mirror_type = NULL;
190
191	done = 0;
192	last = 0;
193	max_retry = 3;
194	current = mirrors = NULL;
195	remote = NULL;
196
197	if (mirror_type == NULL && config_string(MIRROR_TYPE, &mirror_type)
198	    != 0) {
199		warnx("No MIRROR_TYPE defined");
200		return (-1);
201	}
202
203	if ((fd = mkstemp(path)) == -1) {
204		warn("mkstemp()");
205		return (-1);
206	}
207
208	retry = max_retry;
209
210	u = fetchParseURL(url);
211	while (remote == NULL) {
212		if (retry == max_retry) {
213			if (strcmp(u->scheme, "file") != 0 &&
214			    strcasecmp(mirror_type, "srv") == 0) {
215				snprintf(zone, sizeof(zone),
216				    "_%s._tcp.%s", u->scheme, u->host);
217				mirrors = dns_getsrvinfo(zone);
218				current = mirrors;
219			}
220		}
221
222		if (mirrors != NULL) {
223			strlcpy(u->host, current->host, sizeof(u->host));
224			u->port = current->port;
225		}
226
227		remote = fetchXGet(u, &st, "");
228		if (remote == NULL) {
229			--retry;
230			if (retry <= 0)
231				goto fetchfail;
232			if (mirrors == NULL) {
233				sleep(1);
234			} else {
235				current = current->next;
236				if (current == NULL)
237					current = mirrors;
238			}
239		}
240	}
241
242	if (remote == NULL)
243		goto fetchfail;
244
245	while (done < st.size) {
246		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
247			break;
248
249		if (write(fd, buf, r) != r) {
250			warn("write()");
251			goto fetchfail;
252		}
253
254		done += r;
255		now = time(NULL);
256		if (now > last || done == st.size)
257			last = now;
258	}
259
260	if (ferror(remote))
261		goto fetchfail;
262
263	goto cleanup;
264
265fetchfail:
266	if (fd != -1) {
267		close(fd);
268		fd = -1;
269		unlink(path);
270	}
271
272cleanup:
273	if (remote != NULL)
274		fclose(remote);
275
276	return fd;
277}
278
279static struct fingerprint *
280parse_fingerprint(ucl_object_t *obj)
281{
282	const ucl_object_t *cur;
283	ucl_object_iter_t it = NULL;
284	const char *function, *fp, *key;
285	struct fingerprint *f;
286	hash_t fct = HASH_UNKNOWN;
287
288	function = fp = NULL;
289
290	while ((cur = ucl_iterate_object(obj, &it, true))) {
291		key = ucl_object_key(cur);
292		if (cur->type != UCL_STRING)
293			continue;
294		if (strcasecmp(key, "function") == 0) {
295			function = ucl_object_tostring(cur);
296			continue;
297		}
298		if (strcasecmp(key, "fingerprint") == 0) {
299			fp = ucl_object_tostring(cur);
300			continue;
301		}
302	}
303
304	if (fp == NULL || function == NULL)
305		return (NULL);
306
307	if (strcasecmp(function, "sha256") == 0)
308		fct = HASH_SHA256;
309
310	if (fct == HASH_UNKNOWN) {
311		warnx("Unsupported hashing function: %s", function);
312		return (NULL);
313	}
314
315	f = calloc(1, sizeof(struct fingerprint));
316	f->type = fct;
317	strlcpy(f->hash, fp, sizeof(f->hash));
318
319	return (f);
320}
321
322static void
323free_fingerprint_list(struct fingerprint_list* list)
324{
325	struct fingerprint *fingerprint, *tmp;
326
327	STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) {
328		if (fingerprint->name)
329			free(fingerprint->name);
330		free(fingerprint);
331	}
332	free(list);
333}
334
335static struct fingerprint *
336load_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
368static struct fingerprint_list *
369load_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		return (NULL);
385
386	while ((ent = readdir(d))) {
387		if (strcmp(ent->d_name, ".") == 0 ||
388		    strcmp(ent->d_name, "..") == 0)
389			continue;
390		finger = load_fingerprint(path, ent->d_name);
391		if (finger != NULL) {
392			STAILQ_INSERT_TAIL(fingerprints, finger, next);
393			++(*count);
394		}
395	}
396
397	closedir(d);
398
399	return (fingerprints);
400}
401
402static void
403sha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH],
404    char out[SHA256_DIGEST_LENGTH * 2 + 1])
405{
406	int i;
407
408	for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
409		sprintf(out + (i * 2), "%02x", hash[i]);
410
411	out[SHA256_DIGEST_LENGTH * 2] = '\0';
412}
413
414static void
415sha256_buf(char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1])
416{
417	unsigned char hash[SHA256_DIGEST_LENGTH];
418	SHA256_CTX sha256;
419
420	out[0] = '\0';
421
422	SHA256_Init(&sha256);
423	SHA256_Update(&sha256, buf, len);
424	SHA256_Final(hash, &sha256);
425	sha256_hash(hash, out);
426}
427
428static int
429sha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1])
430{
431	int my_fd;
432	FILE *fp;
433	char buffer[BUFSIZ];
434	unsigned char hash[SHA256_DIGEST_LENGTH];
435	size_t r;
436	int ret;
437	SHA256_CTX sha256;
438
439	my_fd = -1;
440	fp = NULL;
441	r = 0;
442	ret = 1;
443
444	out[0] = '\0';
445
446	/* Duplicate the fd so that fclose(3) does not close it. */
447	if ((my_fd = dup(fd)) == -1) {
448		warnx("dup");
449		goto cleanup;
450	}
451
452	if ((fp = fdopen(my_fd, "rb")) == NULL) {
453		warnx("fdopen");
454		goto cleanup;
455	}
456
457	SHA256_Init(&sha256);
458
459	while ((r = fread(buffer, 1, BUFSIZ, fp)) > 0)
460		SHA256_Update(&sha256, buffer, r);
461
462	if (ferror(fp) != 0) {
463		warnx("fread");
464		goto cleanup;
465	}
466
467	SHA256_Final(hash, &sha256);
468	sha256_hash(hash, out);
469	ret = 0;
470
471cleanup:
472	if (fp != NULL)
473		fclose(fp);
474	else if (my_fd != -1)
475		close(my_fd);
476	(void)lseek(fd, 0, SEEK_SET);
477
478	return (ret);
479}
480
481static EVP_PKEY *
482load_public_key_file(const char *file)
483{
484	EVP_PKEY *pkey;
485	BIO *bp;
486	char errbuf[1024];
487
488	bp = BIO_new_file(file, "r");
489	if (!bp)
490		errx(EXIT_FAILURE, "Unable to read %s", file);
491
492	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
493		warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf));
494
495	BIO_free(bp);
496
497	return (pkey);
498}
499
500static EVP_PKEY *
501load_public_key_buf(const unsigned char *cert, int certlen)
502{
503	EVP_PKEY *pkey;
504	BIO *bp;
505	char errbuf[1024];
506
507	bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen);
508
509	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
510		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
511
512	BIO_free(bp);
513
514	return (pkey);
515}
516
517static bool
518rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key,
519    int keylen, unsigned char *sig, int siglen)
520{
521	EVP_MD_CTX *mdctx;
522	EVP_PKEY *pkey;
523	char sha256[(SHA256_DIGEST_LENGTH * 2) + 2];
524	char errbuf[1024];
525	bool ret;
526
527	pkey = NULL;
528	mdctx = NULL;
529	ret = false;
530
531	SSL_load_error_strings();
532
533	/* Compute SHA256 of the package. */
534	if (lseek(fd, 0, 0) == -1) {
535		warn("lseek");
536		goto cleanup;
537	}
538	if ((sha256_fd(fd, sha256)) == -1) {
539		warnx("Error creating SHA256 hash for package");
540		goto cleanup;
541	}
542
543	if (sigfile != NULL) {
544		if ((pkey = load_public_key_file(sigfile)) == NULL) {
545			warnx("Error reading public key");
546			goto cleanup;
547		}
548	} else {
549		if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
550			warnx("Error reading public key");
551			goto cleanup;
552		}
553	}
554
555	/* Verify signature of the SHA256(pkg) is valid. */
556	if ((mdctx = EVP_MD_CTX_create()) == NULL) {
557		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
558		goto error;
559	}
560
561	if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
562		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
563		goto error;
564	}
565	if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) {
566		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
567		goto error;
568	}
569
570	if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) {
571		warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
572		goto error;
573	}
574
575	ret = true;
576	printf("done\n");
577	goto cleanup;
578
579error:
580	printf("failed\n");
581
582cleanup:
583	if (pkey)
584		EVP_PKEY_free(pkey);
585	if (mdctx)
586		EVP_MD_CTX_destroy(mdctx);
587	ERR_free_strings();
588
589	return (ret);
590}
591
592static struct pubkey *
593read_pubkey(int fd)
594{
595	struct pubkey *pk;
596	struct sbuf *sig;
597	char buf[4096];
598	int r;
599
600	if (lseek(fd, 0, 0) == -1) {
601		warn("lseek");
602		return (NULL);
603	}
604
605	sig = sbuf_new_auto();
606
607	while ((r = read(fd, buf, sizeof(buf))) >0) {
608		sbuf_bcat(sig, buf, r);
609	}
610
611	sbuf_finish(sig);
612	pk = calloc(1, sizeof(struct pubkey));
613	pk->siglen = sbuf_len(sig);
614	pk->sig = calloc(1, pk->siglen);
615	memcpy(pk->sig, sbuf_data(sig), pk->siglen);
616	sbuf_delete(sig);
617
618	return (pk);
619}
620
621static struct sig_cert *
622parse_cert(int fd) {
623	int my_fd;
624	struct sig_cert *sc;
625	FILE *fp;
626	struct sbuf *buf, *sig, *cert;
627	char *line;
628	size_t linecap;
629	ssize_t linelen;
630
631	buf = NULL;
632	my_fd = -1;
633	sc = NULL;
634	line = NULL;
635	linecap = 0;
636
637	if (lseek(fd, 0, 0) == -1) {
638		warn("lseek");
639		return (NULL);
640	}
641
642	/* Duplicate the fd so that fclose(3) does not close it. */
643	if ((my_fd = dup(fd)) == -1) {
644		warnx("dup");
645		return (NULL);
646	}
647
648	if ((fp = fdopen(my_fd, "rb")) == NULL) {
649		warn("fdopen");
650		close(my_fd);
651		return (NULL);
652	}
653
654	sig = sbuf_new_auto();
655	cert = sbuf_new_auto();
656
657	while ((linelen = getline(&line, &linecap, fp)) > 0) {
658		if (strcmp(line, "SIGNATURE\n") == 0) {
659			buf = sig;
660			continue;
661		} else if (strcmp(line, "CERT\n") == 0) {
662			buf = cert;
663			continue;
664		} else if (strcmp(line, "END\n") == 0) {
665			break;
666		}
667		if (buf != NULL)
668			sbuf_bcat(buf, line, linelen);
669	}
670
671	fclose(fp);
672
673	/* Trim out unrelated trailing newline */
674	sbuf_setpos(sig, sbuf_len(sig) - 1);
675
676	sbuf_finish(sig);
677	sbuf_finish(cert);
678
679	sc = calloc(1, sizeof(struct sig_cert));
680	sc->siglen = sbuf_len(sig);
681	sc->sig = calloc(1, sc->siglen);
682	memcpy(sc->sig, sbuf_data(sig), sc->siglen);
683
684	sc->certlen = sbuf_len(cert);
685	sc->cert = strdup(sbuf_data(cert));
686
687	sbuf_delete(sig);
688	sbuf_delete(cert);
689
690	return (sc);
691}
692
693static bool
694verify_pubsignature(int fd_pkg, int fd_sig)
695{
696	struct pubkey *pk;
697	const char *pubkey;
698	bool ret;
699
700	pk = NULL;
701	pubkey = NULL;
702	ret = false;
703	if (config_string(PUBKEY, &pubkey) != 0) {
704		warnx("No CONFIG_PUBKEY defined");
705		goto cleanup;
706	}
707
708	if ((pk = read_pubkey(fd_sig)) == NULL) {
709		warnx("Error reading signature");
710		goto cleanup;
711	}
712
713	/* Verify the signature. */
714	printf("Verifying signature with public key %s... ", pubkey);
715	if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig,
716	    pk->siglen) == false) {
717		fprintf(stderr, "Signature is not valid\n");
718		goto cleanup;
719	}
720
721	ret = true;
722
723cleanup:
724	if (pk) {
725		free(pk->sig);
726		free(pk);
727	}
728
729	return (ret);
730}
731
732static bool
733verify_signature(int fd_pkg, int fd_sig)
734{
735	struct fingerprint_list *trusted, *revoked;
736	struct fingerprint *fingerprint;
737	struct sig_cert *sc;
738	bool ret;
739	int trusted_count, revoked_count;
740	const char *fingerprints;
741	char path[MAXPATHLEN];
742	char hash[SHA256_DIGEST_LENGTH * 2 + 1];
743
744	sc = NULL;
745	trusted = revoked = NULL;
746	ret = false;
747
748	/* Read and parse fingerprints. */
749	if (config_string(FINGERPRINTS, &fingerprints) != 0) {
750		warnx("No CONFIG_FINGERPRINTS defined");
751		goto cleanup;
752	}
753
754	snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints);
755	if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) {
756		warnx("Error loading trusted certificates");
757		goto cleanup;
758	}
759
760	if (trusted_count == 0 || trusted == NULL) {
761		fprintf(stderr, "No trusted certificates found.\n");
762		goto cleanup;
763	}
764
765	snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints);
766	if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) {
767		warnx("Error loading revoked certificates");
768		goto cleanup;
769	}
770
771	/* Read certificate and signature in. */
772	if ((sc = parse_cert(fd_sig)) == NULL) {
773		warnx("Error parsing certificate");
774		goto cleanup;
775	}
776	/* Explicitly mark as non-trusted until proven otherwise. */
777	sc->trusted = false;
778
779	/* Parse signature and pubkey out of the certificate */
780	sha256_buf(sc->cert, sc->certlen, hash);
781
782	/* Check if this hash is revoked */
783	if (revoked != NULL) {
784		STAILQ_FOREACH(fingerprint, revoked, next) {
785			if (strcasecmp(fingerprint->hash, hash) == 0) {
786				fprintf(stderr, "The package was signed with "
787				    "revoked certificate %s\n",
788				    fingerprint->name);
789				goto cleanup;
790			}
791		}
792	}
793
794	STAILQ_FOREACH(fingerprint, trusted, next) {
795		if (strcasecmp(fingerprint->hash, hash) == 0) {
796			sc->trusted = true;
797			sc->name = strdup(fingerprint->name);
798			break;
799		}
800	}
801
802	if (sc->trusted == false) {
803		fprintf(stderr, "No trusted fingerprint found matching "
804		    "package's certificate\n");
805		goto cleanup;
806	}
807
808	/* Verify the signature. */
809	printf("Verifying signature with trusted certificate %s... ", sc->name);
810	if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig,
811	    sc->siglen) == false) {
812		fprintf(stderr, "Signature is not valid\n");
813		goto cleanup;
814	}
815
816	ret = true;
817
818cleanup:
819	if (trusted)
820		free_fingerprint_list(trusted);
821	if (revoked)
822		free_fingerprint_list(revoked);
823	if (sc) {
824		if (sc->cert)
825			free(sc->cert);
826		if (sc->sig)
827			free(sc->sig);
828		if (sc->name)
829			free(sc->name);
830		free(sc);
831	}
832
833	return (ret);
834}
835
836static int
837bootstrap_pkg(bool force)
838{
839	int fd_pkg, fd_sig;
840	int ret;
841	char url[MAXPATHLEN];
842	char tmppkg[MAXPATHLEN];
843	char tmpsig[MAXPATHLEN];
844	const char *packagesite;
845	const char *signature_type;
846	char pkgstatic[MAXPATHLEN];
847
848	fd_sig = -1;
849	ret = -1;
850
851	if (config_string(PACKAGESITE, &packagesite) != 0) {
852		warnx("No PACKAGESITE defined");
853		return (-1);
854	}
855
856	if (config_string(SIGNATURE_TYPE, &signature_type) != 0) {
857		warnx("Error looking up SIGNATURE_TYPE");
858		return (-1);
859	}
860
861	printf("Bootstrapping pkg from %s, please wait...\n", packagesite);
862
863	/* Support pkg+http:// for PACKAGESITE which is the new format
864	   in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has
865	   no A record. */
866	if (strncmp(URL_SCHEME_PREFIX, packagesite,
867	    strlen(URL_SCHEME_PREFIX)) == 0)
868		packagesite += strlen(URL_SCHEME_PREFIX);
869	snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite);
870
871	snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX",
872	    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
873
874	if ((fd_pkg = fetch_to_fd(url, tmppkg)) == -1)
875		goto fetchfail;
876
877	if (signature_type != NULL &&
878	    strcasecmp(signature_type, "NONE") != 0) {
879		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
880
881			snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
882			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
883			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
884			    packagesite);
885
886			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
887				fprintf(stderr, "Signature for pkg not "
888				    "available.\n");
889				goto fetchfail;
890			}
891
892			if (verify_signature(fd_pkg, fd_sig) == false)
893				goto cleanup;
894		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
895
896			snprintf(tmpsig, MAXPATHLEN,
897			    "%s/pkg.txz.pubkeysig.XXXXXX",
898			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
899			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig",
900			    packagesite);
901
902			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
903				fprintf(stderr, "Signature for pkg not "
904				    "available.\n");
905				goto fetchfail;
906			}
907
908			if (verify_pubsignature(fd_pkg, fd_sig) == false)
909				goto cleanup;
910		} else {
911			warnx("Signature type %s is not supported for "
912			    "bootstrapping.", signature_type);
913			goto cleanup;
914		}
915	}
916
917	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
918		ret = install_pkg_static(pkgstatic, tmppkg, force);
919
920	goto cleanup;
921
922fetchfail:
923	warnx("Error fetching %s: %s", url, fetchLastErrString);
924	fprintf(stderr, "A pre-built version of pkg could not be found for "
925	    "your system.\n");
926	fprintf(stderr, "Consider changing PACKAGESITE or installing it from "
927	    "ports: 'ports-mgmt/pkg'.\n");
928
929cleanup:
930	if (fd_sig != -1) {
931		close(fd_sig);
932		unlink(tmpsig);
933	}
934	close(fd_pkg);
935	unlink(tmppkg);
936
937	return (ret);
938}
939
940static const char confirmation_message[] =
941"The package management tool is not yet installed on your system.\n"
942"Do you want to fetch and install it now? [y/N]: ";
943
944static int
945pkg_query_yes_no(void)
946{
947	int ret, c;
948
949	c = getchar();
950
951	if (c == 'y' || c == 'Y')
952		ret = 1;
953	else
954		ret = 0;
955
956	while (c != '\n' && c != EOF)
957		c = getchar();
958
959	return (ret);
960}
961
962static int
963bootstrap_pkg_local(const char *pkgpath, bool force)
964{
965	char path[MAXPATHLEN];
966	char pkgstatic[MAXPATHLEN];
967	const char *signature_type;
968	int fd_pkg, fd_sig, ret;
969
970	fd_sig = -1;
971	ret = -1;
972
973	fd_pkg = open(pkgpath, O_RDONLY);
974	if (fd_pkg == -1)
975		err(EXIT_FAILURE, "Unable to open %s", pkgpath);
976
977	if (config_string(SIGNATURE_TYPE, &signature_type) != 0) {
978		warnx("Error looking up SIGNATURE_TYPE");
979		return (-1);
980	}
981	if (signature_type != NULL &&
982	    strcasecmp(signature_type, "NONE") != 0) {
983		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
984
985			snprintf(path, sizeof(path), "%s.sig", pkgpath);
986
987			if ((fd_sig = open(path, O_RDONLY)) == -1) {
988				fprintf(stderr, "Signature for pkg not "
989				    "available.\n");
990				goto cleanup;
991			}
992
993			if (verify_signature(fd_pkg, fd_sig) == false)
994				goto cleanup;
995
996		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
997
998			snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath);
999
1000			if ((fd_sig = open(path, O_RDONLY)) == -1) {
1001				fprintf(stderr, "Signature for pkg not "
1002				    "available.\n");
1003				goto cleanup;
1004			}
1005
1006			if (verify_pubsignature(fd_pkg, fd_sig) == false)
1007				goto cleanup;
1008
1009		} else {
1010			warnx("Signature type %s is not supported for "
1011			    "bootstrapping.", signature_type);
1012			goto cleanup;
1013		}
1014	}
1015
1016	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
1017		ret = install_pkg_static(pkgstatic, pkgpath, force);
1018
1019cleanup:
1020	close(fd_pkg);
1021	if (fd_sig != -1)
1022		close(fd_sig);
1023
1024	return (ret);
1025}
1026
1027int
1028main(__unused int argc, char *argv[])
1029{
1030	char pkgpath[MAXPATHLEN];
1031	const char *pkgarg;
1032	bool bootstrap_only, force, yes;
1033
1034	bootstrap_only = false;
1035	force = false;
1036	pkgarg = NULL;
1037	yes = false;
1038
1039	snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg",
1040	    getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
1041
1042	if (argc > 1 && strcmp(argv[1], "bootstrap") == 0) {
1043		bootstrap_only = true;
1044		if (argc == 3 && strcmp(argv[2], "-f") == 0)
1045			force = true;
1046	}
1047
1048	if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) {
1049		/*
1050		 * To allow 'pkg -N' to be used as a reliable test for whether
1051		 * a system is configured to use pkg, don't bootstrap pkg
1052		 * when that argument is given as argv[1].
1053		 */
1054		if (argv[1] != NULL && strcmp(argv[1], "-N") == 0)
1055			errx(EXIT_FAILURE, "pkg is not installed");
1056
1057		config_init();
1058
1059		if (argc > 1 && strcmp(argv[1], "add") == 0) {
1060			if (argc > 2 && strcmp(argv[2], "-f") == 0) {
1061				force = true;
1062				pkgarg = argv[3];
1063			} else
1064				pkgarg = argv[2];
1065			if (pkgarg == NULL) {
1066				fprintf(stderr, "Path to pkg.txz required\n");
1067				exit(EXIT_FAILURE);
1068			}
1069			if (access(pkgarg, R_OK) == -1) {
1070				fprintf(stderr, "No such file: %s\n", pkgarg);
1071				exit(EXIT_FAILURE);
1072			}
1073			if (bootstrap_pkg_local(pkgarg, force) != 0)
1074				exit(EXIT_FAILURE);
1075			exit(EXIT_SUCCESS);
1076		}
1077		/*
1078		 * Do not ask for confirmation if either of stdin or stdout is
1079		 * not tty. Check the environment to see if user has answer
1080		 * tucked in there already.
1081		 */
1082		config_bool(ASSUME_ALWAYS_YES, &yes);
1083		if (!yes) {
1084			printf("%s", confirmation_message);
1085			if (!isatty(fileno(stdin)))
1086				exit(EXIT_FAILURE);
1087
1088			if (pkg_query_yes_no() == 0)
1089				exit(EXIT_FAILURE);
1090		}
1091		if (bootstrap_pkg(force) != 0)
1092			exit(EXIT_FAILURE);
1093		config_finish();
1094
1095		if (bootstrap_only)
1096			exit(EXIT_SUCCESS);
1097	} else if (bootstrap_only) {
1098		printf("pkg already bootstrapped at %s\n", pkgpath);
1099		exit(EXIT_SUCCESS);
1100	}
1101
1102	execv(pkgpath, argv);
1103
1104	/* NOT REACHED */
1105	return (EXIT_FAILURE);
1106}
1107