svn commit: r287873 - in releng: 10.1 10.1/sys/conf 10.1/usr.sbin/pkg 9.3 9.3/sys/conf 9.3/usr.sbin/pkg

Xin LI delphij at FreeBSD.org
Wed Sep 16 21:00:24 UTC 2015


Author: delphij
Date: Wed Sep 16 21:00:21 2015
New Revision: 287873
URL: https://svnweb.freebsd.org/changeset/base/287873

Log:
  Implement pubkey support for pkg(7) bootstrap. [EN-15:18]
  
  Approved by:	so

Modified:
  releng/10.1/UPDATING
  releng/10.1/sys/conf/newvers.sh
  releng/10.1/usr.sbin/pkg/config.c
  releng/10.1/usr.sbin/pkg/config.h
  releng/10.1/usr.sbin/pkg/pkg.c
  releng/9.3/UPDATING
  releng/9.3/sys/conf/newvers.sh
  releng/9.3/usr.sbin/pkg/config.c
  releng/9.3/usr.sbin/pkg/config.h
  releng/9.3/usr.sbin/pkg/pkg.c

Modified: releng/10.1/UPDATING
==============================================================================
--- releng/10.1/UPDATING	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/10.1/UPDATING	Wed Sep 16 21:00:21 2015	(r287873)
@@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITH
 stable/10, and then rebuild without this option. The bootstrap process from
 older version of current is a bit fragile.
 
+20150916:	p20	FreeBSD-EN-15:18.pkg
+
+	Implement pubkey support for pkg(7) bootstrap. [EN-15:18]
+
 20150825:	p19	FreeBSD-SA-15:21.amd64
 			FreeBSD-SA-15:22.openssh
 			FreeBSD-EN-15:14.ixgbe

Modified: releng/10.1/sys/conf/newvers.sh
==============================================================================
--- releng/10.1/sys/conf/newvers.sh	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/10.1/sys/conf/newvers.sh	Wed Sep 16 21:00:21 2015	(r287873)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="10.1"
-BRANCH="RELEASE-p19"
+BRANCH="RELEASE-p20"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/10.1/usr.sbin/pkg/config.c
==============================================================================
--- releng/10.1/usr.sbin/pkg/config.c	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/10.1/usr.sbin/pkg/config.c	Wed Sep 16 21:00:21 2015	(r287873)
@@ -133,6 +133,15 @@ static struct config_entry c[] = {
 		false,
 		true,
 	},
+	[PUBKEY] = {
+		PKG_CONFIG_STRING,
+		"PUBKEY",
+		NULL,
+		NULL,
+		NULL,
+		false,
+		false
+	}
 };
 
 static const char *
@@ -550,6 +559,8 @@ config_parse(const ucl_object_t *obj, pk
 				sbuf_cpy(buf, "SIGNATURE_TYPE");
 			else if (strcasecmp(key, "fingerprints") == 0)
 				sbuf_cpy(buf, "FINGERPRINTS");
+			else if (strcasecmp(key, "pubkey") == 0)
+				sbuf_cpy(buf, "PUBKEY");
 			else if (strcasecmp(key, "enabled") == 0) {
 				if ((cur->type != UCL_BOOLEAN) ||
 				    !ucl_object_toboolean(cur))

Modified: releng/10.1/usr.sbin/pkg/config.h
==============================================================================
--- releng/10.1/usr.sbin/pkg/config.h	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/10.1/usr.sbin/pkg/config.h	Wed Sep 16 21:00:21 2015	(r287873)
@@ -40,6 +40,7 @@ typedef enum {
 	SIGNATURE_TYPE,
 	FINGERPRINTS,
 	REPOS_DIR,
+	PUBKEY,
 	CONFIG_SIZE
 } pkg_config_key;
 

Modified: releng/10.1/usr.sbin/pkg/pkg.c
==============================================================================
--- releng/10.1/usr.sbin/pkg/pkg.c	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/10.1/usr.sbin/pkg/pkg.c	Wed Sep 16 21:00:21 2015	(r287873)
@@ -66,6 +66,11 @@ struct sig_cert {
 	bool trusted;
 };
 
+struct pubkey {
+	unsigned char *sig;
+	int siglen;
+};
+
 typedef enum {
        HASH_UNKNOWN,
        HASH_SHA256,
@@ -474,6 +479,25 @@ cleanup:
 }
 
 static EVP_PKEY *
+load_public_key_file(const char *file)
+{
+	EVP_PKEY *pkey;
+	BIO *bp;
+	char errbuf[1024];
+
+	bp = BIO_new_file(file, "r");
+	if (!bp)
+		errx(EXIT_FAILURE, "Unable to read %s", file);
+
+	if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
+		warnx("ici: %s", ERR_error_string(ERR_get_error(), errbuf));
+
+	BIO_free(bp);
+
+	return (pkey);
+}
+
+static EVP_PKEY *
 load_public_key_buf(const unsigned char *cert, int certlen)
 {
 	EVP_PKEY *pkey;
@@ -491,8 +515,8 @@ load_public_key_buf(const unsigned char 
 }
 
 static bool
-rsa_verify_cert(int fd, const unsigned char *key, int keylen,
-    unsigned char *sig, int siglen)
+rsa_verify_cert(int fd, const char *sigfile, const unsigned char *key,
+    int keylen, unsigned char *sig, int siglen)
 {
 	EVP_MD_CTX *mdctx;
 	EVP_PKEY *pkey;
@@ -504,6 +528,8 @@ rsa_verify_cert(int fd, const unsigned c
 	mdctx = NULL;
 	ret = false;
 
+	SSL_load_error_strings();
+
 	/* Compute SHA256 of the package. */
 	if (lseek(fd, 0, 0) == -1) {
 		warn("lseek");
@@ -514,9 +540,16 @@ rsa_verify_cert(int fd, const unsigned c
 		goto cleanup;
 	}
 
-	if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
-		warnx("Error reading public key");
-		goto cleanup;
+	if (sigfile != NULL) {
+		if ((pkey = load_public_key_file(sigfile)) == NULL) {
+			warnx("Error reading public key");
+			goto cleanup;
+		}
+	} else {
+		if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
+			warnx("Error reading public key");
+			goto cleanup;
+		}
 	}
 
 	/* Verify signature of the SHA256(pkg) is valid. */
@@ -556,6 +589,35 @@ cleanup:
 	return (ret);
 }
 
+static struct pubkey *
+read_pubkey(int fd)
+{
+	struct pubkey *pk;
+	struct sbuf *sig;
+	char buf[4096];
+	int r;
+
+	if (lseek(fd, 0, 0) == -1) {
+		warn("lseek");
+		return (NULL);
+	}
+
+	sig = sbuf_new_auto();
+
+	while ((r = read(fd, buf, sizeof(buf))) >0) {
+		sbuf_bcat(sig, buf, r);
+	}
+
+	sbuf_finish(sig);
+	pk = calloc(1, sizeof(struct pubkey));
+	pk->siglen = sbuf_len(sig);
+	pk->sig = calloc(1, pk->siglen);
+	memcpy(pk->sig, sbuf_data(sig), pk->siglen);
+	sbuf_delete(sig);
+
+	return (pk);
+}
+
 static struct sig_cert *
 parse_cert(int fd) {
 	int my_fd;
@@ -629,6 +691,45 @@ parse_cert(int fd) {
 }
 
 static bool
+verify_pubsignature(int fd_pkg, int fd_sig)
+{
+	struct pubkey *pk;
+	const char *pubkey;
+	bool ret;
+
+	pk = NULL;
+	pubkey = NULL;
+	ret = false;
+	if (config_string(PUBKEY, &pubkey) != 0) {
+		warnx("No CONFIG_PUBKEY defined");
+		goto cleanup;
+	}
+
+	if ((pk = read_pubkey(fd_sig)) == NULL) {
+		warnx("Error reading signature");
+		goto cleanup;
+	}
+
+	/* Verify the signature. */
+	printf("Verifying signature with public key %s... ", pubkey);
+	if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig,
+	    pk->siglen) == false) {
+		fprintf(stderr, "Signature is not valid\n");
+		goto cleanup;
+	}
+
+	ret = true;
+
+cleanup:
+	if (pk) {
+		free(pk->sig);
+		free(pk);
+	}
+
+	return (ret);
+}
+
+static bool
 verify_signature(int fd_pkg, int fd_sig)
 {
 	struct fingerprint_list *trusted, *revoked;
@@ -706,7 +807,7 @@ verify_signature(int fd_pkg, int fd_sig)
 
 	/* Verify the signature. */
 	printf("Verifying signature with trusted certificate %s... ", sc->name);
-	if (rsa_verify_cert(fd_pkg, sc->cert, sc->certlen, sc->sig,
+	if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig,
 	    sc->siglen) == false) {
 		fprintf(stderr, "Signature is not valid\n");
 		goto cleanup;
@@ -775,24 +876,42 @@ bootstrap_pkg(bool force)
 
 	if (signature_type != NULL &&
 	    strcasecmp(signature_type, "NONE") != 0) {
-		if (strcasecmp(signature_type, "FINGERPRINTS") != 0) {
-			warnx("Signature type %s is not supported for "
-			    "bootstrapping.", signature_type);
-			goto cleanup;
-		}
+		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
+
+			snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
+			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
+			    packagesite);
+
+			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto fetchfail;
+			}
 
-		snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
-		    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
-		snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
-		    packagesite);
+			if (verify_signature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
 
-		if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
-			fprintf(stderr, "Signature for pkg not available.\n");
-			goto fetchfail;
-		}
+			snprintf(tmpsig, MAXPATHLEN,
+			    "%s/pkg.txz.pubkeysig.XXXXXX",
+			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig",
+			    packagesite);
+
+			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto fetchfail;
+			}
 
-		if (verify_signature(fd_pkg, fd_sig) == false)
+			if (verify_pubsignature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+		} else {
+			warnx("Signature type %s is not supported for "
+			    "bootstrapping.", signature_type);
 			goto cleanup;
+		}
 	}
 
 	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
@@ -861,21 +980,37 @@ bootstrap_pkg_local(const char *pkgpath,
 	}
 	if (signature_type != NULL &&
 	    strcasecmp(signature_type, "NONE") != 0) {
-		if (strcasecmp(signature_type, "FINGERPRINTS") != 0) {
-			warnx("Signature type %s is not supported for "
-			    "bootstrapping.", signature_type);
-			goto cleanup;
-		}
+		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
 
-		snprintf(path, sizeof(path), "%s.sig", pkgpath);
+			snprintf(path, sizeof(path), "%s.sig", pkgpath);
 
-		if ((fd_sig = open(path, O_RDONLY)) == -1) {
-			fprintf(stderr, "Signature for pkg not available.\n");
-			goto cleanup;
-		}
+			if ((fd_sig = open(path, O_RDONLY)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto cleanup;
+			}
 
-		if (verify_signature(fd_pkg, fd_sig) == false)
+			if (verify_signature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+
+		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
+
+			snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath);
+
+			if ((fd_sig = open(path, O_RDONLY)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto cleanup;
+			}
+
+			if (verify_pubsignature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+
+		} else {
+			warnx("Signature type %s is not supported for "
+			    "bootstrapping.", signature_type);
 			goto cleanup;
+		}
 	}
 
 	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)

Modified: releng/9.3/UPDATING
==============================================================================
--- releng/9.3/UPDATING	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/9.3/UPDATING	Wed Sep 16 21:00:21 2015	(r287873)
@@ -11,6 +11,10 @@ handbook:
 Items affecting the ports and packages system can be found in
 /usr/ports/UPDATING.  Please read that file before running portupgrade.
 
+20150916:	p26	FreeBSD-EN-15:18.pkg
+
+	Implement pubkey support for pkg(7) bootstrap. [EN-15:18]
+
 20150902:	p25	FreeBSD-SA-15:23.bind
 
 	Fix BIND remote denial of service vulnerability. [SA-15:23]

Modified: releng/9.3/sys/conf/newvers.sh
==============================================================================
--- releng/9.3/sys/conf/newvers.sh	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/9.3/sys/conf/newvers.sh	Wed Sep 16 21:00:21 2015	(r287873)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="9.3"
-BRANCH="RELEASE-p25"
+BRANCH="RELEASE-p26"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
 	BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/9.3/usr.sbin/pkg/config.c
==============================================================================
--- releng/9.3/usr.sbin/pkg/config.c	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/9.3/usr.sbin/pkg/config.c	Wed Sep 16 21:00:21 2015	(r287873)
@@ -131,6 +131,15 @@ static struct config_entry c[] = {
 		false,
 		true,
 	},
+	[PUBKEY] = {
+		PKG_CONFIG_STRING,
+		"PUBKEY",
+		NULL,
+		NULL,
+		NULL,
+		false,
+		false
+	}
 };
 
 static const char *
@@ -347,6 +356,8 @@ config_parse(ucl_object_t *obj, pkg_conf
 				sbuf_cpy(buf, "SIGNATURE_TYPE");
 			else if (strcasecmp(key, "fingerprints") == 0)
 				sbuf_cpy(buf, "FINGERPRINTS");
+			else if (strcasecmp(key, "pubkey") == 0)
+				sbuf_cpy(buf, "PUBKEY");
 			else if (strcasecmp(key, "enabled") == 0) {
 				if ((cur->type != UCL_BOOLEAN) ||
 				    !ucl_object_toboolean(cur))

Modified: releng/9.3/usr.sbin/pkg/config.h
==============================================================================
--- releng/9.3/usr.sbin/pkg/config.h	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/9.3/usr.sbin/pkg/config.h	Wed Sep 16 21:00:21 2015	(r287873)
@@ -40,6 +40,7 @@ typedef enum {
 	SIGNATURE_TYPE,
 	FINGERPRINTS,
 	REPOS_DIR,
+	PUBKEY,
 	CONFIG_SIZE
 } pkg_config_key;
 

Modified: releng/9.3/usr.sbin/pkg/pkg.c
==============================================================================
--- releng/9.3/usr.sbin/pkg/pkg.c	Wed Sep 16 20:59:41 2015	(r287872)
+++ releng/9.3/usr.sbin/pkg/pkg.c	Wed Sep 16 21:00:21 2015	(r287873)
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <time.h>
 #include <unistd.h>
 #include <ucl.h>
 
@@ -66,6 +65,11 @@ struct sig_cert {
 	bool trusted;
 };
 
+struct pubkey {
+	unsigned char *sig;
+	int siglen;
+};
+
 typedef enum {
        HASH_UNKNOWN,
        HASH_SHA256,
@@ -176,14 +180,11 @@ fetch_to_fd(const char *url, char *path)
 	/* To store _https._tcp. + hostname + \0 */
 	int fd;
 	int retry, max_retry;
-	off_t done, r;
-	time_t now, last;
+	ssize_t r;
 	char buf[10240];
 	char zone[MAXHOSTNAMELEN + 13];
 	static const char *mirror_type = NULL;
 
-	done = 0;
-	last = 0;
 	max_retry = 3;
 	current = mirrors = NULL;
 	remote = NULL;
@@ -233,19 +234,16 @@ fetch_to_fd(const char *url, char *path)
 		}
 	}
 
-	while (done < st.size) {
-		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
-			break;
-
+	while ((r = fread(buf, 1, sizeof(buf), remote)) > 0) {
 		if (write(fd, buf, r) != r) {
 			warn("write()");
 			goto fetchfail;
 		}
+	}
 
-		done += r;
-		now = time(NULL);
-		if (now > last || done == st.size)
-			last = now;
+	if (r != 0) {
+		warn("An error occurred while fetching pkg(8)");
+		goto fetchfail;
 	}
 
 	if (ferror(remote))
@@ -480,6 +478,29 @@ cleanup:
 }
 
 static RSA *
+load_rsa_public_key_file(const char *file)
+{
+	RSA *rsa = NULL;
+	BIO *bp;
+	char errbuf[1024];
+
+	bp = BIO_new_file(file, "r");
+	if (!bp)
+		errx(EXIT_FAILURE, "Unable to read %s", file);
+
+	if (!PEM_read_bio_RSA_PUBKEY(bp, &rsa, NULL, NULL)) {
+		warn("error reading public key: %s",
+		    ERR_error_string(ERR_get_error(), errbuf));
+		BIO_free(bp);
+		return (NULL);
+	}
+
+	BIO_free(bp);
+
+	return (rsa);
+}
+
+static RSA *
 load_rsa_public_key_buf(unsigned char *cert, int certlen)
 {
 	RSA *rsa = NULL;
@@ -499,8 +520,8 @@ load_rsa_public_key_buf(unsigned char *c
 
 
 static bool
-rsa_verify_cert(int fd, unsigned char *key, int keylen,
-    unsigned char *sig, int siglen)
+rsa_verify_cert(int fd, const char *sigfile, unsigned char *key,
+    int keylen, unsigned char *sig, int siglen)
 {
 	char sha256[SHA256_DIGEST_LENGTH *2 +1];
 	char hash[SHA256_DIGEST_LENGTH];
@@ -517,7 +538,11 @@ rsa_verify_cert(int fd, unsigned char *k
 
 	sha256_buf_bin(sha256, strlen(sha256), hash);
 
-	rsa = load_rsa_public_key_buf(key, keylen);
+	if (sigfile != NULL) {
+		rsa = load_rsa_public_key_file(sigfile);
+	} else {
+		rsa = load_rsa_public_key_buf(key, keylen);
+	}
 	if (rsa == NULL)
 		return (false);
 	ret = RSA_verify(NID_sha256, hash, sizeof(hash), sig, siglen, rsa);
@@ -532,6 +557,35 @@ rsa_verify_cert(int fd, unsigned char *k
 	return (true);
 }
 
+static struct pubkey *
+read_pubkey(int fd)
+{
+	struct pubkey *pk;
+	struct sbuf *sig;
+	char buf[4096];
+	int r;
+
+	if (lseek(fd, 0, 0) == -1) {
+		warn("lseek");
+		return (NULL);
+	}
+
+	sig = sbuf_new_auto();
+
+	while ((r = read(fd, buf, sizeof(buf))) >0) {
+		sbuf_bcat(sig, buf, r);
+	}
+
+	sbuf_finish(sig);
+	pk = calloc(1, sizeof(struct pubkey));
+	pk->siglen = sbuf_len(sig);
+	pk->sig = calloc(1, pk->siglen);
+	memcpy(pk->sig, sbuf_data(sig), pk->siglen);
+	sbuf_delete(sig);
+
+	return (pk);
+}
+
 static struct sig_cert *
 parse_cert(int fd) {
 	int my_fd;
@@ -605,6 +659,45 @@ parse_cert(int fd) {
 }
 
 static bool
+verify_pubsignature(int fd_pkg, int fd_sig)
+{
+	struct pubkey *pk;
+	const char *pubkey;
+	bool ret;
+
+	pk = NULL;
+	pubkey = NULL;
+	ret = false;
+	if (config_string(PUBKEY, &pubkey) != 0) {
+		warnx("No CONFIG_PUBKEY defined");
+		goto cleanup;
+	}
+
+	if ((pk = read_pubkey(fd_sig)) == NULL) {
+		warnx("Error reading signature");
+		goto cleanup;
+	}
+
+	/* Verify the signature. */
+	printf("Verifying signature with public key %s... ", pubkey);
+	if (rsa_verify_cert(fd_pkg, pubkey, NULL, 0, pk->sig,
+	    pk->siglen) == false) {
+		fprintf(stderr, "Signature is not valid\n");
+		goto cleanup;
+	}
+
+	ret = true;
+
+cleanup:
+	if (pk) {
+		free(pk->sig);
+		free(pk);
+	}
+
+	return (ret);
+}
+
+static bool
 verify_signature(int fd_pkg, int fd_sig)
 {
 	struct fingerprint_list *trusted, *revoked;
@@ -682,7 +775,7 @@ verify_signature(int fd_pkg, int fd_sig)
 
 	/* Verify the signature. */
 	printf("Verifying signature with trusted certificate %s... ", sc->name);
-	if (rsa_verify_cert(fd_pkg, sc->cert, sc->certlen, sc->sig,
+	if (rsa_verify_cert(fd_pkg, NULL, sc->cert, sc->certlen, sc->sig,
 	    sc->siglen) == false) {
 		printf("failed\n");
 		fprintf(stderr, "Signature is not valid\n");
@@ -750,24 +843,42 @@ bootstrap_pkg(bool force)
 
 	if (signature_type != NULL &&
 	    strcasecmp(signature_type, "NONE") != 0) {
-		if (strcasecmp(signature_type, "FINGERPRINTS") != 0) {
-			warnx("Signature type %s is not supported for "
-			    "bootstrapping.", signature_type);
-			goto cleanup;
-		}
+		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
 
-		snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
-		    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
-		snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
-		    packagesite);
+			snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
+			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
+			    packagesite);
+
+			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto fetchfail;
+			}
 
-		if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
-			fprintf(stderr, "Signature for pkg not available.\n");
-			goto fetchfail;
-		}
+			if (verify_signature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
+
+			snprintf(tmpsig, MAXPATHLEN,
+			    "%s/pkg.txz.pubkeysig.XXXXXX",
+			    getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+			snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.pubkeysig",
+			    packagesite);
+
+			if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto fetchfail;
+			}
 
-		if (verify_signature(fd_pkg, fd_sig) == false)
+			if (verify_pubsignature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+		} else {
+			warnx("Signature type %s is not supported for "
+			    "bootstrapping.", signature_type);
 			goto cleanup;
+		}
 	}
 
 	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
@@ -841,21 +952,37 @@ bootstrap_pkg_local(const char *pkgpath,
 	}
 	if (signature_type != NULL &&
 	    strcasecmp(signature_type, "NONE") != 0) {
-		if (strcasecmp(signature_type, "FINGERPRINTS") != 0) {
-			warnx("Signature type %s is not supported for "
-			    "bootstrapping.", signature_type);
-			goto cleanup;
-		}
+		if (strcasecmp(signature_type, "FINGERPRINTS") == 0) {
 
-		snprintf(path, sizeof(path), "%s.sig", pkgpath);
+			snprintf(path, sizeof(path), "%s.sig", pkgpath);
 
-		if ((fd_sig = open(path, O_RDONLY)) == -1) {
-			fprintf(stderr, "Signature for pkg not available.\n");
-			goto cleanup;
-		}
+			if ((fd_sig = open(path, O_RDONLY)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto cleanup;
+			}
+
+			if (verify_signature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+
+		} else if (strcasecmp(signature_type, "PUBKEY") == 0) {
 
-		if (verify_signature(fd_pkg, fd_sig) == false)
+			snprintf(path, sizeof(path), "%s.pubkeysig", pkgpath);
+
+			if ((fd_sig = open(path, O_RDONLY)) == -1) {
+				fprintf(stderr, "Signature for pkg not "
+				    "available.\n");
+				goto cleanup;
+			}
+
+			if (verify_pubsignature(fd_pkg, fd_sig) == false)
+				goto cleanup;
+
+		} else {
+			warnx("Signature type %s is not supported for "
+			    "bootstrapping.", signature_type);
 			goto cleanup;
+		}
 	}
 
 	if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)


More information about the svn-src-all mailing list