Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Signature is checked when fetching
Baptiste Daroussin committed 14 years ago
commit 175753ac03e2e43a5dbe9e8718c0a60539db9da5
parent 112717b
5 files changed +79 -8
modified libpkg/pkg.h
@@ -700,6 +700,7 @@ int pkg_delete2(struct pkg *pkg, struct pkgdb *db, int force, int upgrade);
int pkg_upgrade(struct pkgdb *db, struct pkg *pkg, const char *path);

int pkg_repo_fetch(struct pkg *pkg);
+
int pkg_repo_verify(const char *path, unsigned char *sig, unsigned int sig_len);

/**
 * Get the value of a configuration key
modified libpkg/pkg_config.c
@@ -20,6 +20,7 @@ static struct _config {
	{ "PKG_DBDIR", "/var/db/pkg", NULL},
	{ "PKG_CACHEDIR", "/var/cache/pkg", NULL},
	{ "PORTSDIR", "/usr/ports", NULL },
+
	{ "PUBKEY", "/etc/ssl/pkg.pub", NULL },
	{ NULL, NULL, NULL}
};

modified libpkg/pkg_create_repo.c
@@ -407,7 +407,7 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)
			return EPKG_FATAL;
		}

-
		packing_append_buffer(pack, sigret, "signature", max_len);
+
		packing_append_buffer(pack, sigret, "signature", siglen + 1);

		free(sigret);
		RSA_free(rsa);
modified libpkg/pkg_repo.c
@@ -1,6 +1,9 @@
#include <assert.h>
#include <errno.h>
#include <libgen.h>
+
#include <openssl/err.h>
+
#include <openssl/rsa.h>
+
#include <openssl/ssl.h>
#include <string.h>
#include <unistd.h>

@@ -58,3 +61,53 @@ pkg_repo_fetch(struct pkg *pkg)

	return (retcode);
}
+

+
static RSA *
+
load_rsa_public_key(const char *rsa_key_path)
+
{
+
	FILE *fp;
+
	RSA *rsa = NULL;
+
	char errbuf[1024];
+

+
	if ((fp = fopen(rsa_key_path, "rb")) == 0) {
+
		EMIT_ERRNO("Error reading public key(%s)", rsa_key_path);
+
		return (NULL);
+
	}
+

+
	if (!PEM_read_RSA_PUBKEY( fp, &rsa, NULL, NULL )) {
+
		EMIT_PKG_ERROR("Error reading public key(%s): %s", rsa_key_path, ERR_error_string(ERR_get_error(), errbuf));
+
		fclose(fp);
+
		return (NULL);
+
	}
+

+
	fclose(fp);
+
	return (rsa);
+
}
+

+
int
+
pkg_repo_verify(const char *path, unsigned char *sig, unsigned int sig_len)
+
{
+
	char sha256[65];
+
	char errbuf[1024];
+
	RSA *rsa = NULL;
+

+
	sha256_file(path, sha256);
+

+
	SSL_load_error_strings();
+
	OpenSSL_add_all_algorithms();
+
	OpenSSL_add_all_ciphers();
+

+
	rsa = load_rsa_public_key(pkg_config("PUBKEY"));
+
	if (rsa == NULL)
+
		return(EPKG_FATAL);
+

+
	if (RSA_verify(NID_sha1, sha256, 65, sig, sig_len, rsa) == 0) {
+
		EMIT_PKG_ERROR("%s: %s", pkg_config("PUBKEY"), ERR_error_string(ERR_get_error(), errbuf));
+
		return (EPKG_FATAL);
+
	}
+

+
	RSA_free(rsa);
+
	ERR_free_strings();
+

+
	return (EPKG_OK);
+
}
modified pkg/update.c
@@ -2,13 +2,13 @@
#include <sys/types.h>

#include <err.h>
-
#include <stdlib.h>
+
#include <fcntl.h>
+
#include <libutil.h>
#include <stdio.h>
+
#include <stdlib.h>
+
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
-
#include <string.h>
-
#include <fcntl.h>
-
#include <libutil.h>

#include <archive.h>
#include <archive_entry.h>
@@ -37,6 +37,8 @@ exec_update(int argc, char **argv)
	int retcode = EPKG_OK;
	struct archive *a;
	struct archive_entry *ae;
+
	unsigned char *sig = NULL;
+
	int siglen = 0;

	(void)argv;
	if (argc != 1) {
@@ -75,13 +77,27 @@ exec_update(int argc, char **argv)

	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
-
			archive_entry_set_pathname(ae, "/var/db/pkg/repo.sqlite");
+
			archive_entry_set_pathname(ae, "/var/db/pkg/repo.sqlite.unchecked");
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
-
			break;
+
		}
+
		if (strcmp(archive_entry_pathname(ae), "signature") == 0) {
+
			siglen = archive_entry_size(ae);
+
			sig = malloc(siglen);
+
			archive_read_data(a, sig, siglen);
+
		}
+
	}
+

+
	if (sig != NULL) {
+
		if (pkg_repo_verify( "/var/db/pkg/repo.sqlite.unchecked", sig, siglen - 1) != EPKG_OK) {
+
			fprintf(stderr, "Invalid signature removing\n");
+
			unlink("/var/db/pkg/repo.sqlite.unchecked");
+
			free(sig);
+
			return (EPKG_FATAL);
		}
	}
+
	rename("/var/db/pkg/repo.sqlite.unchecked", "/var/db/pkg/repo.sqlite.unchecked");

-
	if ( a != NULL) 
+
	if ( a != NULL)
		archive_read_finish(a);

	unlink(tmp);