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