Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Refactored update code.
Julien Laffaye committed 13 years ago
commit 05e2e36950cd70f6ed0f19c8c6f5d4f72321ad9d
parent f337969
8 files changed +346 -245
modified libpkg/Makefile
@@ -27,7 +27,9 @@ SRCS= backup.c \
		pkg_version.c \
		pkgdb.c \
		rcscripts.c \
+
		rsa.c \
		scripts.c \
+
		update.c \
		usergroup.c \
		utils.c

modified libpkg/pkg.h
@@ -610,7 +610,7 @@ int pkg_is_installed(struct pkgdb *db, const char *origin);
 * @param sum An 65 long char array to receive the sha256 sum
 */
int pkg_create_repo(char *path, void (*callback)(struct pkg *, void *), void *);
-
int pkg_finish_repo(char *patj, pem_password_cb *cb, char *rsa_key_path);
+
int pkg_finish_repo(char *path, pem_password_cb *cb, char *rsa_key_path);

/**
 * Open the local package database.
@@ -778,7 +778,10 @@ int pkg_create_installed(const char *, pkg_formats, const char *, struct pkg *);
 */
int pkg_create_fakeroot(const char *, pkg_formats, const char *, const char *);

-
int pkg_repo_verify(const char *path, unsigned char *sig, unsigned int sig_len);
+
/**
+
 * Download the latest repo db file and checks its signature if any
+
 */
+
int pkg_update(const char *name, const char *packagesite);

/**
 * Get the value of a configuration key
modified libpkg/pkg_config.c
@@ -89,7 +89,7 @@ static struct config_entry c[] = {
	[PKG_CONFIG_REPOKEY] = {
		STRING,
		"PUBKEY",
-
		"/etc/ssl/pkg.pub",
+
		NULL,
		{ NULL }
	},
	[PKG_CONFIG_MULTIREPOS] = {
@@ -242,9 +242,6 @@ pkg_config_string(pkg_config_key key, const char **val)
	if (*val == NULL)
		*val = c[key].def;

-
	if (*val == NULL)
-
		return (EPKG_FATAL);
-

	return (EPKG_OK);
}

modified libpkg/pkg_repo.c
@@ -37,13 +37,9 @@
#include <stdbool.h>
#include <unistd.h>

-
#include <openssl/err.h>
-
#include <openssl/sha.h>
-
#include <openssl/rsa.h>
-
#include <openssl/ssl.h>
-

#include "pkg.h"
#include "private/event.h"
+
#include "private/utils.h"
#include "private/pkg.h"

int
@@ -137,85 +133,6 @@ pkg_repo_fetch(struct pkg *pkg)
	return (retcode);
}

-
static RSA *
-
load_rsa_private_key(char *rsa_key_path, pem_password_cb *password_cb)
-
{
-
	FILE *fp;
-
	RSA *rsa = NULL;
-

-
	if ((fp = fopen(rsa_key_path, "r")) == 0)
-
		return (NULL);
-

-
	if ((rsa = RSA_new()) == NULL) {
-
		fclose(fp);
-
		return (NULL);
-
	}
-

-
	if ((rsa = PEM_read_RSAPrivateKey(fp, 0, password_cb, rsa_key_path)) == NULL) {
-
		fclose(fp);
-
		return (NULL);
-
	}
-

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

-
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) {
-
		pkg_emit_errno("fopen", rsa_key_path);
-
		return (NULL);
-
	}
-

-
	if (!PEM_read_RSA_PUBKEY( fp, &rsa, NULL, NULL )) {
-
		pkg_emit_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[SHA256_DIGEST_LENGTH *2 +1];
-
	char errbuf[1024];
-
	const char *repokey = NULL;
-
	RSA *rsa = NULL;
-

-
	sha256_file(path, sha256);
-

-
	SSL_load_error_strings();
-
	OpenSSL_add_all_algorithms();
-
	OpenSSL_add_all_ciphers();
-

-
	if (pkg_config_string(PKG_CONFIG_REPOKEY, &repokey) != EPKG_OK)
-
		return (EPKG_FATAL);
-

-
	rsa = load_rsa_public_key(repokey);
-
	if (rsa == NULL)
-
		return(EPKG_FATAL);
-

-
	if (RSA_verify(NID_sha1, sha256, sizeof(sha256), sig, sig_len, rsa) == 0) {
-
		pkg_emit_error("%s: %s", repokey,
-
					   ERR_error_string(ERR_get_error(), errbuf));
-
		return (EPKG_FATAL);
-
	}
-

-
	RSA_free(rsa);
-
	ERR_free_strings();
-

-
	return (EPKG_OK);
-
}
-

static void
file_exists(sqlite3_context *ctx, int argc, __unused sqlite3_value **argv)
{
@@ -731,45 +648,20 @@ pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)
	char repo_path[MAXPATHLEN + 1];
	char repo_archive[MAXPATHLEN + 1];
	struct packing *pack;
-
	int max_len = 0;
	unsigned char *sigret = NULL;
-
	int siglen = 0;
-
	RSA *rsa = NULL;
-
	char sha256[SHA256_DIGEST_LENGTH * 2 +1];
+
	unsigned int siglen = 0;

	snprintf(repo_path, sizeof(repo_path), "%s/repo.sqlite", path);
	snprintf(repo_archive, sizeof(repo_archive), "%s/repo", path);

	packing_init(&pack, repo_archive, TXZ);
	if (rsa_key_path != NULL) {
-
		if (access(rsa_key_path, R_OK) == -1) {
-
			pkg_emit_errno("access", rsa_key_path);
-
			return EPKG_FATAL;
-
		}
-

-
		SSL_load_error_strings();
-

-
		OpenSSL_add_all_algorithms();
-
		OpenSSL_add_all_ciphers();
-

-
		rsa = load_rsa_private_key(rsa_key_path, password_cb);
-
		max_len = RSA_size(rsa);
-
		sigret = malloc(max_len + 1);
-
		memset(sigret, 0, max_len);
-

-
		sha256_file(repo_path, sha256);
-

-
		if (RSA_sign(NID_sha1, sha256, sizeof(sha256), sigret, &siglen, rsa) == 0) {
-
			/* XXX pass back RSA errors correctly */
-
			pkg_emit_error("%s: %lu", rsa_key_path, ERR_get_error());
-
			return EPKG_FATAL;
-
		}
+
		rsa_sign(repo_path, password_cb, rsa_key_path, &sigret,
+
				&siglen);

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

		free(sigret);
-
		RSA_free(rsa);
-
		ERR_free_strings();
	}
	packing_append_file(pack, repo_path, "repo.sqlite");
	unlink(repo_path);
modified libpkg/private/utils.h
@@ -62,5 +62,10 @@ int is_conf_file(const char *path, char *newpath, size_t len);
int sha256_file(const char *, char[SHA256_DIGEST_LENGTH * 2 +1]);
void sha256_str(const char *, char[SHA256_DIGEST_LENGTH * 2 +1]);

+
int rsa_sign(char *path, pem_password_cb *password_cb, char *rsa_key_path,
+
		 unsigned char **sigret, unsigned int *siglen);
+
int rsa_verify(const char *path, const char *key,
+
		unsigned char *sig, unsigned int sig_len);
+

bool is_hardlink(struct hardlinks *hl, struct stat *st);
#endif
added libpkg/rsa.c
@@ -0,0 +1,148 @@
+
/*
+
 * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
+
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
+
 * All rights reserved.
+
 * 
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions
+
 * are met:
+
 * 1. Redistributions of source code must retain the above copyright
+
 *    notice, this list of conditions and the following disclaimer
+
 *    in this position and unchanged.
+
 * 2. Redistributions in binary form must reproduce the above copyright
+
 *    notice, this list of conditions and the following disclaimer in the
+
 *    documentation and/or other materials provided with the distribution.
+
 * 
+
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+
#include <openssl/err.h>
+
#include <openssl/sha.h>
+
#include <openssl/rsa.h>
+
#include <openssl/ssl.h>
+

+
#include "pkg.h"
+
#include "private/event.h"
+
#include "private/pkg.h"
+

+
static RSA *
+
_load_rsa_private_key(char *rsa_key_path, pem_password_cb *password_cb)
+
{
+
	FILE *fp;
+
	RSA *rsa = NULL;
+

+
	if ((fp = fopen(rsa_key_path, "r")) == 0)
+
		return (NULL);
+

+
	if ((rsa = RSA_new()) == NULL) {
+
		fclose(fp);
+
		return (NULL);
+
	}
+

+
	if ((rsa = PEM_read_RSAPrivateKey(fp, 0, password_cb, rsa_key_path)) == NULL) {
+
		fclose(fp);
+
		return (NULL);
+
	}
+

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

+
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) {
+
		pkg_emit_errno("fopen", rsa_key_path);
+
		return (NULL);
+
	}
+

+
	if (!PEM_read_RSA_PUBKEY( fp, &rsa, NULL, NULL )) {
+
		pkg_emit_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
+
rsa_verify(const char *path, const char *key, unsigned char *sig, unsigned int sig_len)
+
{
+
	char sha256[SHA256_DIGEST_LENGTH *2 +1];
+
	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(key);
+
	if (rsa == NULL)
+
		return(EPKG_FATAL);
+

+
	if (RSA_verify(NID_sha1, sha256, sizeof(sha256), sig, sig_len, rsa) == 0) {
+
		pkg_emit_error("%s: %s", key,
+
					   ERR_error_string(ERR_get_error(), errbuf));
+
		return (EPKG_FATAL);
+
	}
+

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

+
	return (EPKG_OK);
+
}
+

+
int
+
rsa_sign(char *path, pem_password_cb *password_cb, char *rsa_key_path,
+
		unsigned char **sigret, unsigned int *siglen)
+
{
+
	char errbuf[1024];
+
	int max_len = 0;
+
	RSA *rsa = NULL;
+
	char sha256[SHA256_DIGEST_LENGTH * 2 +1];
+

+
	if (access(rsa_key_path, R_OK) == -1) {
+
		pkg_emit_errno("access", rsa_key_path);
+
		return EPKG_FATAL;
+
	}
+

+
	SSL_load_error_strings();
+

+
	OpenSSL_add_all_algorithms();
+
	OpenSSL_add_all_ciphers();
+

+
	rsa = _load_rsa_private_key(rsa_key_path, password_cb);
+
	max_len = RSA_size(rsa);
+
	*sigret = calloc(1, max_len + 1);
+

+
	sha256_file(path, sha256);
+

+
	if (RSA_sign(NID_sha1, sha256, sizeof(sha256), *sigret, siglen, rsa) == 0) {
+
		/* XXX pass back RSA errors correctly */
+
		pkg_emit_error("%s: %s", rsa_key_path,
+
					   ERR_error_string(ERR_get_error(), errbuf));
+
		return EPKG_FATAL;
+
	}
+

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

+
	return (EPKG_OK);
+
}
added libpkg/update.c
@@ -0,0 +1,179 @@
+
/*
+
 * Copyright (c) 2012 Julien Laffaye <jlaffaye@FreeBSD.org>
+
 * All rights reserved.
+
 * 
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions
+
 * are met:
+
 * 1. Redistributions of source code must retain the above copyright
+
 *    notice, this list of conditions and the following disclaimer
+
 *    in this position and unchanged.
+
 * 2. Redistributions in binary form must reproduce the above copyright
+
 *    notice, this list of conditions and the following disclaimer in the
+
 *    documentation and/or other materials provided with the distribution.
+
 * 
+
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+
#include <sys/stat.h>
+
#include <sys/param.h>
+

+
#include <stdio.h>
+
#include <stdlib.h>
+
#include <string.h>
+
#include <unistd.h>
+

+
#include <archive.h>
+
#include <archive_entry.h>
+

+
#include "pkg.h"
+
#include "private/event.h"
+
#include "private/utils.h"
+

+
#define EXTRACT_ARCHIVE_FLAGS  (ARCHIVE_EXTRACT_OWNER |ARCHIVE_EXTRACT_PERM)
+

+
/* Add indexes to the repo */
+
static int
+
remote_add_indexes(const char *reponame)
+
{
+
	struct pkgdb *db = NULL;
+
	int ret = EPKG_FATAL;
+

+
	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK)
+
		goto cleanup;
+

+
	/* Initialize the remote remote */
+
	if (pkgdb_remote_init(db, reponame) != EPKG_OK)
+
		goto cleanup;
+

+
	ret = EPKG_OK;
+

+
	cleanup:
+
	if (db)
+
		pkgdb_close(db);
+
	return (ret);
+
}
+

+
int
+
pkg_update(const char *name, const char *packagesite)
+
{
+
	char url[MAXPATHLEN];
+
	struct archive *a = NULL;
+
	struct archive_entry *ae = NULL;
+
	char repofile[MAXPATHLEN];
+
	char repofile_unchecked[MAXPATHLEN];
+
	char tmp[21];
+
	const char *dbdir = NULL;
+
	const char *repokey;
+
	unsigned char *sig = NULL;
+
	int siglen = 0;
+
	int rc = EPKG_FATAL;
+
	bool alwayssigned = false;
+
	struct stat st;
+
	time_t t = 0;
+

+
	snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);
+

+
	pkg_config_bool(PKG_CONFIG_SIGNED_REPOS, &alwayssigned);
+
	(void)strlcpy(tmp, "/tmp/repo.txz.XXXXXX", sizeof(tmp));
+
	if (mktemp(tmp) == NULL) {
+
		pkg_emit_error("Could not create temporary file %s, aborting update.\n", tmp);
+
		return (EPKG_FATAL);
+
	}
+

+
	if (pkg_config_string(PKG_CONFIG_DBDIR, &dbdir) != EPKG_OK) {
+
		pkg_emit_error("Cant get dbdir config entry");
+
		return (EPKG_FATAL);
+
	}
+

+
	snprintf(repofile, sizeof(repofile), "%s/%s.sqlite", dbdir, name);
+
	if (stat(repofile, &st) != -1) {
+
		t = st.st_mtime;
+
		/* add 10 minutes to the timestap because repo.sqlite is
+
		 * always newer than repo.txz, 10 minutes should be enough
+
		 */
+
		t += 600;
+
	}
+

+
	if ((rc = pkg_fetch_file(url, tmp, t)) != EPKG_OK) {
+
		/*
+
		 * No need to unlink(tmp) here as it is already
+
		 * done in pkg_fetch_file() in case fetch failed.
+
		 */
+
		return (rc);
+
	}
+

+
	a = archive_read_new();
+
	archive_read_support_compression_all(a);
+
	archive_read_support_format_tar(a);
+

+
	archive_read_open_filename(a, tmp, 4096);
+

+
	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
+
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
+
			snprintf(repofile_unchecked, sizeof(repofile_unchecked), "%s.unchecked", repofile);
+
			archive_entry_set_pathname(ae, repofile_unchecked);
+

+
			/*
+
			 * The repo should be owned by root and not writable
+
			 */
+
			archive_entry_set_uid(ae, 0);
+
			archive_entry_set_gid(ae, 0);
+
			archive_entry_set_perm(ae, 0644);
+

+
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
+
		}
+
		if (strcmp(archive_entry_pathname(ae), "signature") == 0) {
+
			siglen = archive_entry_size(ae);
+
			sig = malloc(siglen);
+
			archive_read_data(a, sig, siglen);
+
		}
+
	}
+

+
	if (pkg_config_string(PKG_CONFIG_REPOKEY, &repokey) != EPKG_OK)
+
		return (EPKG_FATAL);
+

+
	if (repokey != NULL) {
+
		if (sig != NULL) {
+
			if (rsa_verify(repofile_unchecked, repokey, sig, siglen - 1) != EPKG_OK) {
+
				pkg_emit_error("Invalid signature, removing repository.\n");
+
				unlink(repofile_unchecked);
+
				free(sig);
+
				rc = EPKG_FATAL;
+
				goto cleanup;
+
			}
+
		} else {
+
			pkg_emit_error("No signature found in the repository, this is mandatory");
+
			rc = EPKG_FATAL;
+
			unlink(repofile_unchecked);
+
			goto cleanup;
+
		}
+
	}
+

+
	if (rename(repofile_unchecked, repofile) != 0) {
+
		pkg_emit_errno("rename", "");
+
		goto cleanup;
+
	}
+

+
	if ((rc = remote_add_indexes(name)) != EPKG_OK)
+
		goto cleanup;
+

+
	rc = EPKG_OK;
+

+
	cleanup:
+
	if (a != NULL)
+
		archive_read_finish(a);
+

+
	(void)unlink(tmp);
+

+
	return (rc);
+
}
modified pkg/update.c
@@ -36,135 +36,10 @@
#include <sysexits.h>
#include <unistd.h>

-
#include <archive.h>
-
#include <archive_entry.h>
-

#include <pkg.h>

#include "pkgcli.h"

-
#define EXTRACT_ARCHIVE_FLAGS  (ARCHIVE_EXTRACT_OWNER |ARCHIVE_EXTRACT_PERM| \
-
		ARCHIVE_EXTRACT_TIME  |ARCHIVE_EXTRACT_ACL | \
-
		ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR)
-

-
static int update_from_remote_repo(const char *name, const char *url);
-

-
/* Add indexes to the repo */
-
static int
-
remote_add_indexes(const char *reponame)
-
{
-
	struct pkgdb *db = NULL;
-
	int ret = EPKG_FATAL;
-

-
	if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK)
-
		goto cleanup;
-

-
	/* Initialize the remote remote */
-
	if (pkgdb_remote_init(db, reponame) != EPKG_OK)
-
		goto cleanup;
-

-
	ret = EPKG_OK;
-
cleanup:
-
	if (db)
-
		pkgdb_close(db);
-
	return (ret);
-
}
-

-
static int
-
update_from_remote_repo(const char *name, const char *url)
-
{
-
	struct archive *a = NULL;
-
	struct archive_entry *ae = NULL;
-
	char repofile[MAXPATHLEN];
-
	char repofile_unchecked[MAXPATHLEN];
-
	char tmp[21];
-
	const char *dbdir = NULL;
-
	unsigned char *sig = NULL;
-
	int siglen = 0;
-
	int rc = EPKG_OK;
-
	bool alwayssigned = false;
-
	struct stat st;
-
	time_t t = 0;
-

-
	pkg_config_bool(PKG_CONFIG_SIGNED_REPOS, &alwayssigned);
-
	(void)strlcpy(tmp, "/tmp/repo.txz.XXXXXX", sizeof(tmp));
-
	if (mktemp(tmp) == NULL) {
-
		warnx("Could not create temporary file %s, aborting update.\n", tmp);
-
		return (EPKG_FATAL);
-
	}
-

-
	if (pkg_config_string(PKG_CONFIG_DBDIR, &dbdir) != EPKG_OK) {
-
		warnx("Cant get dbdir config entry");
-
		return (EPKG_FATAL);
-
	}
-

-
	snprintf(repofile, sizeof(repofile), "%s/%s.sqlite", dbdir, name);
-
	if (stat(repofile, &st) != -1) {
-
		t = st.st_mtime;
-
		/* add 10 minutes to the timestap because repo.sqlite is
-
		 * always newer than repo.txz, 10 minutes should be enough
-
		 */
-
		t += 600;
-
	}
-

-
	if ((rc = pkg_fetch_file(url, tmp, t)) != EPKG_OK) {
-
		/*
-
		 * No need to unlink(tmp) here as it is already
-
		 * done in pkg_fetch_file() in case fetch failed.
-
		 */
-
		return (rc);
-
	}
-

-
	a = archive_read_new();
-
	archive_read_support_compression_all(a);
-
	archive_read_support_format_tar(a);
-

-
	archive_read_open_filename(a, tmp, 4096);
-

-
	while (archive_read_next_header(a, &ae) == ARCHIVE_OK) {
-
		if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) {
-
			snprintf(repofile_unchecked, sizeof(repofile_unchecked), "%s.unchecked", repofile);
-
			archive_entry_set_pathname(ae, repofile_unchecked);
-
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
-
		}
-
		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(repofile_unchecked, sig, siglen - 1) != EPKG_OK) {
-
			warnx("Invalid signature, removing repository.\n");
-
			unlink(repofile_unchecked);
-
			free(sig);
-
			rc = EPKG_FATAL;
-
			goto cleanup;
-
		}
-
	} else {
-
		if (alwayssigned) {
-
			warnx("No signature found in the repository, this is mandatory");
-
			rc = EPKG_FATAL;
-
			unlink(repofile_unchecked);
-
			goto cleanup;
-
		}
-

-
	}
-

-
	rename(repofile_unchecked, repofile);
-

-
	if ((rc = remote_add_indexes(name)) != EPKG_OK)
-
		goto cleanup;
-
cleanup:
-
	if (a != NULL)
-
		archive_read_finish(a);
-

-
	(void)unlink(tmp);
-

-
	return (rc);
-
}
-

void
usage_update(void)
{
@@ -230,7 +105,7 @@ exec_update(int argc, char **argv)
		else
			snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

-
		retcode = update_from_remote_repo("repo", url);
+
		retcode = pkg_update("repo", url);
		if (retcode == EPKG_UPTODATE) {
			if (!quiet)
				printf("Remote repository up-to-date, no need to upgrade\n");
@@ -247,7 +122,7 @@ exec_update(int argc, char **argv)
			else
				snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite);

-
			retcode = update_from_remote_repo(repo_name, url);
+
			retcode = pkg_update(repo_name, url);
			if (retcode == EPKG_UPTODATE) {
				if (!quiet)
					printf("%s repository up-to-date, no need to upgrade\n", repo_name);