Keep repo metadata if possible when updating repodata (xbps-rindex -a/-c).
API/ABI incompat changes, you've been warned.
This commit is contained in:
parent
c6cae9e6ef
commit
d08e76a386
2
COPYING
2
COPYING
@ -1,7 +1,7 @@
|
||||
Almost all code in XBPS uses the following license
|
||||
(some exceptions are shown below):
|
||||
|
||||
/* Copyright (c) 2008-2012 Juan Romero Pardines.
|
||||
/* Copyright (c) 2008-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
14
NEWS
14
NEWS
@ -1,5 +1,19 @@
|
||||
xbps-0.31 (??):
|
||||
|
||||
* Removed 0.27 compat from repodata.
|
||||
|
||||
* If a repository has been signed previously respect its settings
|
||||
in repodata (unless there were new changes). This allows us to
|
||||
accomplish the following:
|
||||
|
||||
$ xbps-rindex repo/*.xbps
|
||||
$ xbps-rindex --sign ... repo
|
||||
$ xbps-rindex repo/new-pkg.xbps
|
||||
|
||||
... and repository is still signed after updating repodata.
|
||||
|
||||
API/ABI incompatible changes, you've been warned :-)
|
||||
|
||||
* xbps-rindex(8): -c [clean] mode now is fully multithread safe.
|
||||
|
||||
* Fixed a double free while downloading binpkgs from remote repositories
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2008-2013 Juan Romero Pardines.
|
||||
* Copyright (c) 2008-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -156,15 +156,25 @@ list_pkgs_pkgdb(struct xbps_handle *xhp)
|
||||
static int
|
||||
repo_list_uri_cb(struct xbps_repo *repo, void *arg _unused, bool *done _unused)
|
||||
{
|
||||
const char *signedby, *hexfp;
|
||||
uint16_t pubkeysize;
|
||||
|
||||
printf("%5zd %s",
|
||||
repo->idx ? (ssize_t)xbps_dictionary_count(repo->idx) : -1,
|
||||
repo->uri);
|
||||
printf(" (RSA %s)\n", repo->is_signed ? "signed" : "unsigned");
|
||||
if (repo->xhp->flags & XBPS_FLAG_VERBOSE) {
|
||||
if (repo->signedby)
|
||||
printf(" Signed-by: %s\n", repo->signedby);
|
||||
if (repo->hexfp)
|
||||
printf(" %u %s\n", repo->pubkey_size, repo->hexfp);
|
||||
xbps_data_t pubkey;
|
||||
|
||||
xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signature-by", &signedby);
|
||||
xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &pubkeysize);
|
||||
pubkey = xbps_dictionary_get(repo->idxmeta, "public-key");
|
||||
hexfp = xbps_pubkey2fp(repo->xhp, pubkey);
|
||||
|
||||
if (signedby)
|
||||
printf(" Signed-by: %s\n", signedby);
|
||||
if (pubkeysize && hexfp)
|
||||
printf(" %u %s\n", pubkeysize, hexfp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2012-2013 Juan Romero Pardines.
|
||||
* Copyright (c) 2012-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -41,7 +41,7 @@ int
|
||||
index_add(struct xbps_handle *xhp, int argc, char **argv, bool force)
|
||||
{
|
||||
xbps_array_t array, pkg_files, pkg_links, pkg_cffiles;
|
||||
xbps_dictionary_t idx, idxfiles, binpkgd, pkg_filesd, curpkgd;
|
||||
xbps_dictionary_t idx, idxmeta, idxfiles, binpkgd, pkg_filesd, curpkgd;
|
||||
xbps_object_t obj, fileobj;
|
||||
struct xbps_repo *repo;
|
||||
struct stat st;
|
||||
@ -62,10 +62,12 @@ index_add(struct xbps_handle *xhp, int argc, char **argv, bool force)
|
||||
if (repo && repo->idx) {
|
||||
xbps_repo_open_idxfiles(repo);
|
||||
idx = xbps_dictionary_copy(repo->idx);
|
||||
idxmeta = xbps_dictionary_copy(repo->idxmeta);
|
||||
idxfiles = xbps_dictionary_copy(repo->idxfiles);
|
||||
xbps_repo_close(repo);
|
||||
} else {
|
||||
idx = xbps_dictionary_create();
|
||||
idxmeta = NULL;
|
||||
idxfiles = xbps_dictionary_create();
|
||||
}
|
||||
|
||||
@ -241,7 +243,7 @@ index_add(struct xbps_handle *xhp, int argc, char **argv, bool force)
|
||||
* Generate repository data files.
|
||||
*/
|
||||
if (flush) {
|
||||
if (!repodata_flush(xhp, repodir, idx, idxfiles, NULL)) {
|
||||
if (!repodata_flush(xhp, repodir, idx, idxfiles, idxmeta)) {
|
||||
fprintf(stderr, "failed to write repodata: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ index_clean(struct xbps_handle *xhp, const char *repodir)
|
||||
struct xbps_repo *repo;
|
||||
struct cbdata cbd;
|
||||
xbps_array_t allkeys;
|
||||
xbps_dictionary_t idx, idxfiles;
|
||||
xbps_dictionary_t idx, idxmeta, idxfiles;
|
||||
char *keyname, *pkgname;
|
||||
int rv = 0;
|
||||
bool flush = false;
|
||||
@ -135,6 +135,7 @@ index_clean(struct xbps_handle *xhp, const char *repodir)
|
||||
}
|
||||
xbps_repo_open_idxfiles(repo);
|
||||
idx = xbps_dictionary_copy(repo->idx);
|
||||
idxmeta = xbps_dictionary_copy(repo->idxmeta);
|
||||
idxfiles = xbps_dictionary_copy(repo->idxfiles);
|
||||
xbps_repo_close(repo);
|
||||
if (idx == NULL || idxfiles == NULL) {
|
||||
@ -185,7 +186,7 @@ index_clean(struct xbps_handle *xhp, const char *repodir)
|
||||
xbps_object_release(allkeys);
|
||||
|
||||
if (flush) {
|
||||
if (!repodata_flush(xhp, repodir, idx, idxfiles, NULL)) {
|
||||
if (!repodata_flush(xhp, repodir, idx, idxfiles, idxmeta)) {
|
||||
fprintf(stderr, "failed to write repodata: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
|
@ -119,14 +119,14 @@ sign_repo(struct xbps_handle *xhp, const char *repodir,
|
||||
struct stat st;
|
||||
struct xbps_repo *repo;
|
||||
xbps_dictionary_t pkgd, meta = NULL;
|
||||
xbps_data_t data = NULL;
|
||||
xbps_data_t data = NULL, rpubkey = NULL;
|
||||
xbps_object_iterator_t iter = NULL;
|
||||
xbps_object_t obj;
|
||||
RSA *rsa = NULL;
|
||||
unsigned char *sig;
|
||||
unsigned int siglen;
|
||||
uint16_t pubkeysize;
|
||||
const char *arch, *pkgver;
|
||||
uint16_t rpubkeysize, pubkeysize;
|
||||
const char *arch, *pkgver, *rsignedby;
|
||||
char *binpkg, *binpkg_sig, *buf, *defprivkey;
|
||||
int binpkg_fd, binpkg_sig_fd, rv = 0;
|
||||
bool flush = false;
|
||||
@ -244,7 +244,7 @@ sign_repo(struct xbps_handle *xhp, const char *repodir,
|
||||
}
|
||||
xbps_object_iterator_release(iter);
|
||||
/*
|
||||
* Check if repository meta contains changes compared to its
|
||||
* Check if repository index-meta contains changes compared to its
|
||||
* current state.
|
||||
*/
|
||||
if ((buf = pubkey_from_privkey(rsa)) == NULL) {
|
||||
@ -254,15 +254,19 @@ sign_repo(struct xbps_handle *xhp, const char *repodir,
|
||||
meta = xbps_dictionary_create();
|
||||
|
||||
data = xbps_data_create_data(buf, strlen(buf));
|
||||
if (!xbps_data_equals(repo->pubkey, data))
|
||||
rpubkey = xbps_dictionary_get(repo->idxmeta, "public-key");
|
||||
if (!xbps_data_equals(rpubkey, data))
|
||||
flush = true;
|
||||
|
||||
free(buf);
|
||||
|
||||
pubkeysize = RSA_size(rsa) * 8;
|
||||
if (repo->pubkey_size != pubkeysize)
|
||||
xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &rpubkeysize);
|
||||
if (rpubkeysize != pubkeysize)
|
||||
flush = true;
|
||||
|
||||
if (repo->signedby == NULL || strcmp(repo->signedby, signedby))
|
||||
xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signedby", &rsignedby);
|
||||
if (rsignedby == NULL || strcmp(rsignedby, signedby))
|
||||
flush = true;
|
||||
|
||||
if (!flush)
|
||||
@ -273,22 +277,7 @@ sign_repo(struct xbps_handle *xhp, const char *repodir,
|
||||
xbps_dictionary_set_cstring_nocopy(meta, "signature-by", signedby);
|
||||
xbps_dictionary_set_cstring_nocopy(meta, "signature-type", "rsa");
|
||||
xbps_object_release(data);
|
||||
/*
|
||||
* Compatibility with 0.27.
|
||||
*/
|
||||
if ((buf = xbps_dictionary_externalize(repo->idx)) == NULL) {
|
||||
rv = errno;
|
||||
fprintf(stderr, "failed to externalize repository index: %s\n", strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (!rsa_sign_buf(rsa, buf, strlen(buf), &sig, &siglen)) {
|
||||
rv = errno;
|
||||
fprintf(stderr, "failed to create repository index signature: %s\n", strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
data = xbps_data_create_data_nocopy(sig, siglen);
|
||||
xbps_dictionary_set(meta, "signature", data);
|
||||
free(buf);
|
||||
data = NULL;
|
||||
|
||||
if (!repodata_flush(xhp, repodir, repo->idx, repo->idxfiles, meta)) {
|
||||
fprintf(stderr, "failed to write repodata: %s\n", strerror(errno));
|
||||
@ -304,10 +293,6 @@ out:
|
||||
RSA_free(rsa);
|
||||
rsa = NULL;
|
||||
}
|
||||
if (data)
|
||||
xbps_object_release(data);
|
||||
if (meta)
|
||||
xbps_object_release(meta);
|
||||
if (repo)
|
||||
xbps_repo_close(repo);
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
*
|
||||
* This header documents the full API for the XBPS Library.
|
||||
*/
|
||||
#define XBPS_API_VERSION "20131224"
|
||||
#define XBPS_API_VERSION "20140130"
|
||||
|
||||
#ifndef XBPS_VERSION
|
||||
#define XBPS_VERSION "UNSET"
|
||||
@ -1123,36 +1123,18 @@ struct xbps_repo {
|
||||
* Proplib dictionary associated with the repository index.
|
||||
*/
|
||||
xbps_dictionary_t idx;
|
||||
/**
|
||||
* @var idxmeta
|
||||
*
|
||||
* Proplib dictionary associated with the repository index-meta.
|
||||
*/
|
||||
xbps_dictionary_t idxmeta;
|
||||
/**
|
||||
* @var idxfiles
|
||||
*
|
||||
* Proplib dictionary associated with the repository index-files.
|
||||
*/
|
||||
xbps_dictionary_t idxfiles;
|
||||
/**
|
||||
* @var pubkey
|
||||
*
|
||||
* RSA public key associated with this repository in a prop_data object.
|
||||
*/
|
||||
xbps_data_t pubkey;
|
||||
/**
|
||||
* @var hexfp
|
||||
*
|
||||
* OpenSSH fingerprint in hexadecimal of the RSA public key.
|
||||
*/
|
||||
char *hexfp;
|
||||
/**
|
||||
* @var signedby;
|
||||
*
|
||||
* The signee of the RSA signature associated with this repository (string).
|
||||
*/
|
||||
const char *signedby;
|
||||
/**
|
||||
* @var pubkey_size;
|
||||
*
|
||||
* Size in bits of the RSA public key associacted with this repository.
|
||||
*/
|
||||
uint16_t pubkey_size;
|
||||
/**
|
||||
* @var uri
|
||||
*
|
||||
|
57
lib/repo.c
57
lib/repo.c
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2012-2013 Juan Romero Pardines.
|
||||
* Copyright (c) 2012-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -106,7 +106,6 @@ repo_get_dict(struct xbps_repo *repo)
|
||||
struct xbps_repo *
|
||||
xbps_repo_open(struct xbps_handle *xhp, const char *url)
|
||||
{
|
||||
xbps_dictionary_t meta;
|
||||
struct xbps_repo *repo;
|
||||
struct stat st;
|
||||
const char *arch;
|
||||
@ -165,15 +164,9 @@ xbps_repo_open(struct xbps_handle *xhp, const char *url)
|
||||
repo->ar = NULL;
|
||||
goto out;
|
||||
}
|
||||
if ((meta = repo_get_dict(repo))) {
|
||||
xbps_dictionary_get_cstring_nocopy(meta, "signature-by", &repo->signedby);
|
||||
xbps_dictionary_get_uint16(meta, "public-key-size", &repo->pubkey_size);
|
||||
repo->pubkey = xbps_dictionary_get(meta, "public-key");
|
||||
if (repo->pubkey) {
|
||||
repo->is_signed = true;
|
||||
repo->hexfp = xbps_pubkey2fp(repo->xhp, repo->pubkey);
|
||||
}
|
||||
}
|
||||
repo->idxmeta = repo_get_dict(repo);
|
||||
if (repo->idxmeta != NULL)
|
||||
repo->is_signed = true;
|
||||
|
||||
out:
|
||||
free(repofile);
|
||||
@ -199,12 +192,14 @@ xbps_repo_close(struct xbps_repo *repo)
|
||||
xbps_object_release(repo->idx);
|
||||
repo->idx = NULL;
|
||||
}
|
||||
if (repo->idxmeta != NULL) {
|
||||
xbps_object_release(repo->idxmeta);
|
||||
repo->idxmeta = NULL;
|
||||
}
|
||||
if (repo->idxfiles != NULL) {
|
||||
xbps_object_release(repo->idxfiles);
|
||||
repo->idxfiles = NULL;
|
||||
}
|
||||
if (repo->hexfp != NULL)
|
||||
free(repo->hexfp);
|
||||
}
|
||||
|
||||
xbps_dictionary_t
|
||||
@ -417,6 +412,9 @@ int
|
||||
xbps_repo_key_import(struct xbps_repo *repo)
|
||||
{
|
||||
xbps_dictionary_t repokeyd = NULL;
|
||||
xbps_data_t pubkey = NULL;
|
||||
uint16_t pubkey_size = 0;
|
||||
const char *hexfp = NULL, *signedby = NULL;
|
||||
char *p, *dbkeyd, *rkeyfile = NULL;
|
||||
int import, rv = 0;
|
||||
|
||||
@ -424,27 +422,34 @@ xbps_repo_key_import(struct xbps_repo *repo)
|
||||
/*
|
||||
* If repository does not have required metadata plist, ignore it.
|
||||
*/
|
||||
if (repo->pubkey == NULL) {
|
||||
if (!xbps_dictionary_count(repo->idxmeta)) {
|
||||
xbps_dbg_printf(repo->xhp,
|
||||
"[repo] `%s' unsigned repository!\n", repo->uri);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check the repository provides a working public-key data object.
|
||||
* Check for required objects in index-meta:
|
||||
* - signature-by (string)
|
||||
* - public-key (data)
|
||||
* - public-key-size (number)
|
||||
*/
|
||||
repo->is_signed = true;
|
||||
if (repo->hexfp == NULL) {
|
||||
xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "signature-by", &signedby);
|
||||
xbps_dictionary_get_uint16(repo->idxmeta, "public-key-size", &pubkey_size);
|
||||
pubkey = xbps_dictionary_get(repo->idxmeta, "public-key");
|
||||
|
||||
if (signedby == NULL || pubkey_size == 0 ||
|
||||
xbps_object_type(pubkey) != XBPS_TYPE_DATA) {
|
||||
xbps_dbg_printf(repo->xhp,
|
||||
"[repo] `%s': invalid hex fingerprint: %s\n",
|
||||
repo->uri, strerror(errno));
|
||||
"[repo] `%s': incomplete signed repository "
|
||||
"(missing objs)\n", repo->uri);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
hexfp = xbps_pubkey2fp(repo->xhp, pubkey);
|
||||
/*
|
||||
* Check if the public key is alredy stored.
|
||||
*/
|
||||
rkeyfile = xbps_xasprintf("%s/keys/%s.plist",
|
||||
repo->xhp->metadir, repo->hexfp);
|
||||
rkeyfile = xbps_xasprintf("%s/keys/%s.plist", repo->xhp->metadir, hexfp);
|
||||
repokeyd = xbps_dictionary_internalize_from_zfile(rkeyfile);
|
||||
if (xbps_object_type(repokeyd) == XBPS_TYPE_DICTIONARY) {
|
||||
xbps_dbg_printf(repo->xhp,
|
||||
@ -457,8 +462,8 @@ xbps_repo_key_import(struct xbps_repo *repo)
|
||||
* to the client.
|
||||
*/
|
||||
import = xbps_set_cb_state(repo->xhp, XBPS_STATE_REPO_KEY_IMPORT, 0,
|
||||
repo->hexfp, "`%s' repository has been RSA signed by \"%s\"",
|
||||
repo->uri, repo->signedby);
|
||||
hexfp, "`%s' repository has been RSA signed by \"%s\"",
|
||||
repo->uri, signedby);
|
||||
if (import <= 0) {
|
||||
rv = EAGAIN;
|
||||
goto out;
|
||||
@ -482,9 +487,9 @@ xbps_repo_key_import(struct xbps_repo *repo)
|
||||
free(p);
|
||||
|
||||
repokeyd = xbps_dictionary_create();
|
||||
xbps_dictionary_set(repokeyd, "public-key", repo->pubkey);
|
||||
xbps_dictionary_set_uint16(repokeyd, "public-key-size", repo->pubkey_size);
|
||||
xbps_dictionary_set_cstring_nocopy(repokeyd, "signature-by", repo->signedby);
|
||||
xbps_dictionary_set(repokeyd, "public-key", pubkey);
|
||||
xbps_dictionary_set_uint16(repokeyd, "public-key-size", pubkey_size);
|
||||
xbps_dictionary_set_cstring_nocopy(repokeyd, "signature-by", signedby);
|
||||
|
||||
if (!xbps_dictionary_externalize_to_zfile(repokeyd, rkeyfile)) {
|
||||
rv = errno;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Juan Romero Pardines.
|
||||
* Copyright (c) 2013-2014 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -82,18 +82,25 @@ xbps_verify_file_signature(struct xbps_repo *repo, const char *fname)
|
||||
xbps_dictionary_t repokeyd = NULL;
|
||||
xbps_data_t pubkey;
|
||||
struct stat st, sig_st;
|
||||
const char *hexfp = NULL;
|
||||
unsigned char *buf = NULL, *sig_buf = NULL;
|
||||
char *rkeyfile = NULL, *sig = NULL;
|
||||
int fd = -1, sig_fd = -1;
|
||||
bool val = false;
|
||||
|
||||
if (!repo->hexfp)
|
||||
if (!xbps_dictionary_count(repo->idxmeta)) {
|
||||
xbps_dbg_printf(repo->xhp, "%s: unsigned repository\n", repo->uri);
|
||||
return false;
|
||||
}
|
||||
xbps_dictionary_get_cstring_nocopy(repo->idxmeta, "hexfp", &hexfp);
|
||||
if (hexfp == NULL) {
|
||||
xbps_dbg_printf(repo->xhp, "%s: incomplete signed repo, missing hexfp obj\n", repo->uri);
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Prepare repository RSA public key to verify fname signature.
|
||||
*/
|
||||
rkeyfile = xbps_xasprintf("%s/keys/%s.plist",
|
||||
repo->xhp->metadir, repo->hexfp);
|
||||
rkeyfile = xbps_xasprintf("%s/keys/%s.plist", repo->xhp->metadir, hexfp);
|
||||
repokeyd = xbps_dictionary_internalize_from_zfile(rkeyfile);
|
||||
if (xbps_object_type(repokeyd) != XBPS_TYPE_DICTIONARY) {
|
||||
xbps_dbg_printf(repo->xhp, "cannot read rkey data at %s: %s\n",
|
||||
|
Loading…
Reference in New Issue
Block a user