Commit 0a7991f7 authored by Timo Teräs's avatar Timo Teräs

various: misc fixes

- error codes for verification failure types
- fix some fdb corruption on file migration
- combine some dependency parsing code
- fix versioned dependencies
parent 0dadc27c
......@@ -107,7 +107,7 @@ static int add_main(void *ctx, int argc, char **argv)
apk_default_checksum(), &virtpkg->csum);
virtpkg->version = strdup("0");
virtpkg->description = strdup("virtual meta package");
virtdep = apk_dep_from_pkg(&db, virtpkg);
apk_dep_from_pkg(&virtdep, &db, virtpkg);
virtdep.name->flags |= APK_NAME_TOPLEVEL | APK_NAME_VIRTUAL;
virtpkg = apk_db_pkg_add(&db, virtpkg);
}
......@@ -127,9 +127,12 @@ static int add_main(void *ctx, int argc, char **argv)
goto err;
}
dep = apk_dep_from_pkg(&db, pkg);
} else
dep = apk_dep_from_str(&db, argv[i]);
apk_dep_from_pkg(&dep, &db, pkg);
} else {
r = apk_dep_from_blob(&dep, &db, APK_BLOB_STR(argv[i]));
if (r != 0)
goto err;
}
if (virtpkg) {
apk_deps_add(&virtpkg->depends, &dep);
......
......@@ -363,7 +363,7 @@ int main(int argc, char **argv)
}
r = applet->main(ctx, argc, argv);
if (r == -100)
if (r == -EINVAL)
return usage(applet);
return r;
}
......@@ -60,9 +60,9 @@ extern unsigned int apk_flags;
#define APK_PREFER_AVAILABLE 0x0040
#define APK_UPDATE_CACHE 0x0080
#define apk_error(args...) apk_log("ERROR: ", args);
#define apk_warning(args...) if (apk_verbosity > 0) { apk_log("WARNING: ", args); }
#define apk_message(args...) if (apk_verbosity > 0) { apk_log(NULL, args); }
#define apk_error(args...) do { apk_log("ERROR: ", args); } while (0)
#define apk_warning(args...) do { if (apk_verbosity > 0) { apk_log("WARNING: ", args); } } while (0)
#define apk_message(args...) do { if (apk_verbosity > 0) { apk_log(NULL, args); } } while (0)
void apk_log(const char *prefix, const char *format, ...);
......
......@@ -105,6 +105,10 @@ int apk_sign_ctx_verify_tar(void *ctx, const struct apk_file_info *fi,
struct apk_istream *is);
int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t blob);
int apk_dep_from_blob(struct apk_dependency *dep, struct apk_database *db,
apk_blob_t blob);
void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db,
struct apk_package *pkg);
int apk_deps_add(struct apk_dependency_array **depends,
struct apk_dependency *dep);
void apk_deps_del(struct apk_dependency_array **deps,
......@@ -112,6 +116,7 @@ void apk_deps_del(struct apk_dependency_array **deps,
void apk_deps_parse(struct apk_database *db,
struct apk_dependency_array **depends,
apk_blob_t blob);
int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os);
int apk_script_type(const char *name);
......@@ -136,7 +141,4 @@ int apk_pkg_write_index_entry(struct apk_package *pkg, struct apk_ostream *os);
int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b);
struct apk_dependency apk_dep_from_str(struct apk_database *db, char *str);
struct apk_dependency apk_dep_from_pkg(struct apk_database *db,
struct apk_package *pkg);
#endif
......@@ -9,9 +9,10 @@
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include "apk_defines.h"
#include "apk_applet.h"
......@@ -140,7 +141,7 @@ static int cache_main(void *ctx, int argc, char **argv)
int r;
if (argc != 1)
return -100;
return -EINVAL;
if (strcmp(argv[0], "sync") == 0)
actions = CACHE_CLEAN | CACHE_DOWNLOAD;
......@@ -149,7 +150,7 @@ static int cache_main(void *ctx, int argc, char **argv)
else if (strcmp(argv[0], "download") == 0)
actions = CACHE_DOWNLOAD;
else
return -100;
return -EINVAL;
r = apk_db_open(&db, apk_root,
APK_OPENF_NO_SCRIPTS | APK_OPENF_NO_INSTALLED);
......
......@@ -668,7 +668,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
apk_deps_parse(db, &db->world, blob);
free(blob.ptr);
for (i = 0; i < db->world->num; i++)
for (i = 0; db->world != NULL && i < db->world->num; i++)
db->world->item[i].name->flags |= APK_NAME_TOPLEVEL;
}
......@@ -868,12 +868,14 @@ int apk_db_write_config(struct apk_database *db)
fchdir(db->root_fd);
os = apk_ostream_to_file("var/lib/apk/world", 0644);
os = apk_ostream_to_file("var/lib/apk/world.new", 0644);
if (os == NULL)
return -1;
apk_deps_write(db->world, os);
os->write(os, "\n", 1);
os->close(os);
if (rename("var/lib/apk/world.new", "var/lib/apk/world") < 0)
return -errno;
os = apk_ostream_to_file("var/lib/apk/installed.new", 0644);
if (os == NULL)
......@@ -1061,18 +1063,16 @@ int apk_cache_download(struct apk_database *db, struct apk_checksum *csum,
if (verify != APK_SIGN_NONE) {
struct apk_istream *is;
struct apk_sign_ctx sctx;
int ok;
apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
is = apk_bstream_gunzip_mpart(apk_bstream_from_file(tmp2),
apk_sign_ctx_mpart_cb, &sctx);
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx);
is->close(is);
ok = (r == 0) && sctx.control_verified && sctx.data_verified;
apk_sign_ctx_free(&sctx);
if (!ok) {
if (r != 0) {
unlink(tmp2);
return -10;
return r;
}
}
......@@ -1116,9 +1116,11 @@ int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
r = apk_cache_download(db, &repo->csum, repo->url, apkindex_tar_gz,
APK_SIGN_VERIFY);
if (r == 0 || r == -10) {
if (r == -10)
apk_error("%s: untrusted or bad signature!", repo->url);
if (r == 0 || r == -ENOKEY || r == -EKEYREJECTED) {
if (r == -ENOKEY)
apk_error("%s: verify: UNTRUSTED", repo->url);
else if (r == -EKEYREJECTED)
apk_error("%s: verify: FAILED", repo->url);
apk_cache_delete(db, &repo->csum, apk_index_gz);
return r;
}
......@@ -1126,7 +1128,7 @@ int apk_repository_update(struct apk_database *db, struct apk_repository *repo)
r = apk_cache_download(db, &repo->csum, repo->url, apk_index_gz,
APK_SIGN_NONE);
if (r != 0)
apk_error("Failed to update %s: download failed");
apk_error("Failed to update %s: download failed", repo->url);
return r;
}
......@@ -1454,6 +1456,7 @@ static void apk_db_migrate_files(struct apk_database *db,
struct hlist_node *dc, *dn, *fc, *fn;
unsigned long hash;
char name[1024], tmpname[1024];
int r;
hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
dir = diri->dir;
......@@ -1500,7 +1503,7 @@ static void apk_db_migrate_files(struct apk_database *db,
/* Claim ownership of the file in db */
if (ofile != NULL) {
hlist_del(&ofile->diri_files_list,
&diri->owned_files);
&ofile->diri->owned_files);
apk_hash_delete_hashed(&db->installed.files,
APK_BLOB_BUF(&key), hash);
} else
......
......@@ -86,8 +86,10 @@ int apk_deps_add(struct apk_dependency_array **depends,
if (deps != NULL) {
for (i = 0; i < deps->num; i++) {
if (deps->item[i].name == dep->name)
if (deps->item[i].name == dep->name) {
deps->item[i] = *dep;
return 0;
}
}
}
......@@ -119,17 +121,13 @@ struct parse_depend_ctx {
struct apk_dependency_array **depends;
};
static int parse_depend(void *ctx, apk_blob_t blob)
int apk_dep_from_blob(struct apk_dependency *dep, struct apk_database *db,
apk_blob_t blob)
{
struct parse_depend_ctx *pctx = (struct parse_depend_ctx *) ctx;
struct apk_dependency *dep;
struct apk_name *name;
apk_blob_t bname, bop, bver = APK_BLOB_NULL;
int mask = APK_VERSION_LESS | APK_VERSION_EQUAL | APK_VERSION_GREATER;
if (blob.len == 0)
return 0;
/* [!]name[<,<=,=,>=,>]ver */
if (blob.ptr[0] == '!') {
mask = 0;
......@@ -140,11 +138,12 @@ static int parse_depend(void *ctx, apk_blob_t blob)
int i;
if (mask == 0)
return -1;
return -EINVAL;
if (!apk_blob_spn(bop, "<>=", &bop, &bver))
return -1;
for (i = 0; i < blob.len; i++) {
switch (blob.ptr[i]) {
return -EINVAL;
mask = 0;
for (i = 0; i < bop.len; i++) {
switch (bop.ptr[i]) {
case '<':
mask |= APK_VERSION_LESS;
break;
......@@ -158,25 +157,51 @@ static int parse_depend(void *ctx, apk_blob_t blob)
}
if ((mask & (APK_VERSION_LESS|APK_VERSION_GREATER))
== (APK_VERSION_LESS|APK_VERSION_GREATER))
return -1;
return -EINVAL;
if (!apk_version_validate(bver))
return -1;
return -EINVAL;
blob = bname;
}
name = apk_db_get_name(pctx->db, blob);
name = apk_db_get_name(db, blob);
if (name == NULL)
return -1;
dep = apk_dependency_array_add(pctx->depends);
if (dep == NULL)
return -1;
return -ENOENT;
*dep = (struct apk_dependency){
.name = name,
.version = APK_BLOB_IS_NULL(bver) ? NULL : apk_blob_cstr(bver),
.result_mask = mask,
};
return 0;
}
void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db,
struct apk_package *pkg)
{
*dep = (struct apk_dependency) {
.name = apk_db_get_name(db, APK_BLOB_STR(pkg->name->name)),
.version = pkg->version,
.result_mask = APK_VERSION_EQUAL,
};
}
static int parse_depend(void *ctx, apk_blob_t blob)
{
struct parse_depend_ctx *pctx = (struct parse_depend_ctx *) ctx;
struct apk_dependency *dep, p;
if (blob.len == 0)
return 0;
if (apk_dep_from_blob(&p, pctx->db, blob) < 0)
return -1;
dep = apk_dependency_array_add(pctx->depends);
if (dep == NULL)
return -1;
*dep = p;
return 0;
}
......@@ -435,7 +460,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
sctx->signature.data.len,
sctx->signature.pkey);
if (r != 1)
return -1;
return -EKEYREJECTED;
sctx->control_verified = 1;
EVP_DigestInit_ex(&sctx->mdctx, sctx->md, NULL);
......@@ -444,7 +469,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
/* Package identity is checksum of control block */
sctx->identity.type = EVP_MD_CTX_size(&sctx->mdctx);
EVP_DigestFinal_ex(&sctx->mdctx, sctx->identity.data, NULL);
return -1000;
return -ECANCELED;
} else {
/* Reset digest for hashing data */
EVP_DigestFinal_ex(&sctx->mdctx, calculated, NULL);
......@@ -453,7 +478,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
if (sctx->action == APK_SIGN_VERIFY_IDENTITY) {
if (memcmp(calculated, sctx->identity.data,
sctx->identity.type) != 0)
return -1;
return -EKEYREJECTED;
sctx->control_verified = 1;
}
}
......@@ -465,11 +490,13 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
if (EVP_MD_CTX_size(&sctx->mdctx) == 0 ||
memcmp(calculated, sctx->data_checksum,
EVP_MD_CTX_size(&sctx->mdctx)) != 0)
return -1;
return -EKEYREJECTED;
sctx->data_verified = 1;
if (!sctx->control_verified)
return -ENOKEY;
} else if (sctx->action == APK_SIGN_VERIFY) {
if (sctx->signature.pkey == NULL)
return -1;
return -EKEYREJECTED;
/* Assume that the data is fully signed */
r = EVP_VerifyFinal(&sctx->mdctx,
......@@ -477,7 +504,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
sctx->signature.data.len,
sctx->signature.pkey);
if (r != 1)
return -1;
return -EKEYREJECTED;
sctx->control_verified = 1;
sctx->data_verified = 1;
......@@ -486,7 +513,7 @@ int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t data)
if (EVP_MD_CTX_size(&sctx->mdctx) == 0 ||
memcmp(calculated, sctx->identity.data,
EVP_MD_CTX_size(&sctx->mdctx)) != 0)
return -1;
return -EKEYREJECTED;
sctx->control_verified = 1;
sctx->data_verified = 1;
} else {
......@@ -698,7 +725,7 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file,
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, sctx);
r = apk_tar_parse(tar, read_info_entry, &ctx);
tar->close(tar);
if (r < 0 && r != -1000)
if (r < 0 && r != -ECANCELED)
goto err;
if (ctx.pkg->name == NULL)
goto err;
......@@ -927,35 +954,3 @@ int apk_pkg_version_compare(struct apk_package *a, struct apk_package *b)
{
return apk_version_compare(a->version, b->version);
}
struct apk_dependency apk_dep_from_str(struct apk_database *db,
char *str)
{
apk_blob_t name = APK_BLOB_STR(str);
char *v = str;
int mask = APK_DEPMASK_REQUIRE;
v = strpbrk(str, "<>=");
if (v != NULL) {
name.len = v - str;
mask = apk_version_result_mask(v++);
if (*v == '=')
v++;
}
return (struct apk_dependency) {
.name = apk_db_get_name(db, name),
.version = v,
.result_mask = mask,
};
}
struct apk_dependency apk_dep_from_pkg(struct apk_database *db,
struct apk_package *pkg)
{
return (struct apk_dependency) {
.name = apk_db_get_name(db, APK_BLOB_STR(pkg->name->name)),
.version = pkg->version,
.result_mask = APK_VERSION_EQUAL,
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment