FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > ArchLinux > ArchLinux Pacman Development

 
 
LinkBack Thread Tools
 
Old 06-27-2011, 09:39 PM
Dan McGee
 
Default signing: move to new signing verification and return scheme

This gives us more granularity than the former Never/Optional/Always
trifecta. The frontend still uses these values temporarily but that will
be changed in a future patch.

* Use 'siglevel' consistenly in method names, 'level' as variable name
* The level becomes an enum bitmask value for flexibility
* Signature check methods now return a status code rather than a simple
integer success/failure value. This allows callers to determine
whether things such as an unknown signature are valid.
* Specific signature error codes mostly disappear in favor of the above
returned status code; pm_errno is now set only to PKG_INVALID_SIG or
DB_INVALID_SIG as appropriate.

Signed-off-by: Dan McGee <dan@archlinux.org>
---

This is still a slight WIP, but mostly finished. Thoughts? I think this gives
us the flexibility we need to verify everything we need to, as well as allow
frontend validation and useful display of what we found via -Qip with the
return code business.

Outstanding issues:
* Need to correctly handle the UNKNOWN_OK and MARGINAL_OK flags.
* Need to handle multiple sigs. Right now the last one wins; should the return
type be an alpm_list_t instead? Or better yet, an array of enum values with
the size returned in a passed parameter, which would be much more light
weight than the whole linked list.

lib/libalpm/alpm.h | 57 +++++++++++++++++++++++++++++-----------------
lib/libalpm/be_package.c | 25 +++++++++++++-------
lib/libalpm/be_sync.c | 35 ++++++++++++++++------------
lib/libalpm/db.c | 14 +++++-----
lib/libalpm/db.h | 4 +-
lib/libalpm/dload.c | 5 +--
lib/libalpm/error.c | 13 ++++------
lib/libalpm/handle.c | 14 +++++-----
lib/libalpm/handle.h | 2 +-
lib/libalpm/package.h | 2 +-
lib/libalpm/signing.c | 39 +++++++++++++-----------------
lib/libalpm/signing.h | 2 +-
lib/libalpm/sync.c | 6 ++--
src/pacman/conf.c | 38 ++++++++++++++++--------------
src/pacman/conf.h | 2 +-
src/pacman/query.c | 2 +-
src/pacman/sync.c | 2 +-
src/pacman/upgrade.c | 4 +-
src/util/cleanupdelta.c | 3 +-
src/util/pactree.c | 3 +-
src/util/testdb.c | 3 +-
src/util/testpkg.c | 3 +-
22 files changed, 151 insertions(+), 127 deletions(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index ec99541..3fd6a13 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -87,14 +87,31 @@ typedef enum _pmfileconflicttype_t {
} pmfileconflicttype_t;

/**
- * GPG signature verification options
+ * PGP signature verification options
*/
-typedef enum _pgp_verify_t {
- PM_PGP_VERIFY_UNKNOWN,
- PM_PGP_VERIFY_NEVER,
- PM_PGP_VERIFY_OPTIONAL,
- PM_PGP_VERIFY_ALWAYS
-} pgp_verify_t;
+typedef enum _pmsiglevel_t {
+ PM_SIG_PACKAGE = (1 << 0),
+ PM_SIG_PACKAGE_OPTIONAL = (1 << 1),
+ PM_SIG_DATABASE = (1 << 2),
+ PM_SIG_DATABASE_OPTIONAL = (1 << 3),
+ PM_SIG_UNKNOWN_OK = (1 << 4),
+ PM_SIG_MARGINAL_OK = (1 << 5),
+
+ PM_SIG_USE_DEFAULT = (1 << 31),
+} pmsiglevel_t;
+
+/**
+ * PGP signature verification return codes
+ */
+typedef enum _pmsigstatus_t {
+ PM_SIGSTATUS_VALID = 0,
+ PM_SIGSTATUS_FILE_MISSING,
+ PM_SIGSTATUS_SIG_MISSING,
+ PM_SIGSTATUS_INVALID,
+ PM_SIGSTATUS_UNKNOWN,
+ PM_SIGSTATUS_BAD,
+ PM_SIGSTATUS_ERROR
+} pmsigstatus_t;

/*
* Structures
@@ -328,8 +345,8 @@ int alpm_option_set_usedelta(pmhandle_t *handle, int usedelta);
int alpm_option_get_checkspace(pmhandle_t *handle);
int alpm_option_set_checkspace(pmhandle_t *handle, int checkspace);

-pgp_verify_t alpm_option_get_default_sigverify(pmhandle_t *handle);
-int alpm_option_set_default_sigverify(pmhandle_t *handle, pgp_verify_t level);
+pmsiglevel_t alpm_option_get_default_siglevel(pmhandle_t *handle);
+int alpm_option_set_default_siglevel(pmhandle_t *handle, pmsiglevel_t level);

/** @} */

@@ -357,12 +374,12 @@ alpm_list_t *alpm_option_get_syncdbs(pmhandle_t *handle);
/** Register a sync database of packages.
* @param handle the context handle
* @param treename the name of the sync repository
- * @param check_sig what level of signature checking to perform on the
+ * @param level what level of signature checking to perform on the
* database; note that this must be a '.sig' file type verification
* @return a pmdb_t* on success (the value), NULL on error
*/
pmdb_t *alpm_db_register_sync(pmhandle_t *handle, const char *treename,
- pgp_verify_t check_sig);
+ pmsiglevel_t level);

/** Unregister a package database.
* @param db pointer to the package database to unregister
@@ -384,11 +401,11 @@ const char *alpm_db_get_name(const pmdb_t *db);

/** Get the signature verification level for a database.
* Will return the default verification level if this database is set up
- * with PM_PGP_VERIFY_UNKNOWN.
+ * with PM_SIG_USE_DEFAULT.
* @param db pointer to the package database
* @return the signature verification level
*/
-pgp_verify_t alpm_db_get_sigverify_level(pmdb_t *db);
+pmsiglevel_t alpm_db_get_siglevel(pmdb_t *db);

/** Check the validity of a database.
* This is most useful for sync databases and verifying signature status.
@@ -466,13 +483,13 @@ int alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason);
* @param filename location of the package tarball
* @param full whether to stop the load after metadata is read or continue
* through the full archive
- * @param check_sig what level of package signature checking to perform on the
+ * @param level what level of package signature checking to perform on the
* package; note that this must be a '.sig' file type verification
* @param pkg address of the package pointer
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_pkg_load(pmhandle_t *handle, const char *filename, int full,
- pgp_verify_t check_sig, pmpkg_t **pkg);
+ pmsiglevel_t level, pmpkg_t **pkg);

/** Free a package.
* @param pkg package pointer to free
@@ -708,9 +725,9 @@ alpm_list_t *alpm_pkg_unused_deltas(pmpkg_t *pkg);
* Signatures
*/

-int alpm_pkg_check_pgp_signature(pmpkg_t *pkg);
+pmsigstatus_t alpm_pkg_check_pgp_signature(pmpkg_t *pkg);

-int alpm_db_check_pgp_signature(pmdb_t *db);
+pmsigstatus_t alpm_db_check_pgp_signature(pmdb_t *db);

/*
* Groups
@@ -1018,6 +1035,7 @@ enum _pmerrno_t {
PM_ERR_DB_NOT_NULL,
PM_ERR_DB_NOT_FOUND,
PM_ERR_DB_INVALID,
+ PM_ERR_DB_INVALID_SIG,
PM_ERR_DB_VERSION,
PM_ERR_DB_WRITE,
PM_ERR_DB_REMOVE,
@@ -1037,15 +1055,12 @@ enum _pmerrno_t {
PM_ERR_PKG_NOT_FOUND,
PM_ERR_PKG_IGNORED,
PM_ERR_PKG_INVALID,
+ PM_ERR_PKG_INVALID_SIG,
PM_ERR_PKG_OPEN,
PM_ERR_PKG_CANT_REMOVE,
PM_ERR_PKG_INVALID_NAME,
PM_ERR_PKG_INVALID_ARCH,
PM_ERR_PKG_REPO_NOT_FOUND,
- /* Signatures */
- PM_ERR_SIG_MISSINGDIR,
- PM_ERR_SIG_INVALID,
- PM_ERR_SIG_UNKNOWN,
/* Deltas */
PM_ERR_DLT_INVALID,
PM_ERR_DLT_PATCHFAILED,
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 748f27a..2a05c8f 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -233,7 +233,7 @@ static int parse_descfile(pmhandle_t *handle, struct archive *a, pmpkg_t *newpkg
*/
pmpkg_t *_alpm_pkg_load_internal(pmhandle_t *handle, const char *pkgfile,
int full, const char *md5sum, const char *base64_sig,
- pgp_verify_t check_sig)
+ pmsiglevel_t level)
{
int ret;
int config = 0;
@@ -271,13 +271,20 @@ pmpkg_t *_alpm_pkg_load_internal(pmhandle_t *handle, const char *pkgfile,
}

_alpm_log(handle, PM_LOG_DEBUG, "base64_sig: %s
", base64_sig);
- if(check_sig != PM_PGP_VERIFY_NEVER) {
+ if(level & PM_SIG_PACKAGE) {
+ enum _pmsigstatus_t status;
_alpm_log(handle, PM_LOG_DEBUG, "checking signature for %s
", pkgfile);
- ret = _alpm_gpgme_checksig(handle, pkgfile, base64_sig);
- if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) ||
- (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
- alpm_pkg_free(newpkg);
- RET_ERR(handle, PM_ERR_SIG_INVALID, NULL);
+ status = _alpm_gpgme_checksig(handle, pkgfile, base64_sig);
+ switch(status) {
+ case PM_SIGSTATUS_VALID:
+ break;
+ case PM_SIGSTATUS_SIG_MISSING:
+ if(level & PM_SIG_PACKAGE_OPTIONAL) {
+ break;
+ }
+ default:
+ alpm_pkg_free(newpkg);
+ RET_ERR(handle, PM_ERR_PKG_INVALID_SIG, NULL);
}
}

@@ -388,12 +395,12 @@ error:
}

int SYMEXPORT alpm_pkg_load(pmhandle_t *handle, const char *filename, int full,
- pgp_verify_t check_sig, pmpkg_t **pkg)
+ pmsiglevel_t level, pmpkg_t **pkg)
{
CHECK_HANDLE(handle, return -1);
ASSERT(pkg != NULL, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));

- *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, check_sig);
+ *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, level);
if(*pkg == NULL) {
/* pm_errno is set by pkg_load */
return -1;
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index bcd8564..20eb108 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -69,7 +69,7 @@ static char *get_sync_dir(pmhandle_t *handle)

static int sync_db_validate(pmdb_t *db)
{
- pgp_verify_t check_sig;
+ pmsiglevel_t level;

if(db->status & DB_STATUS_VALID) {
return 0;
@@ -77,10 +77,10 @@ static int sync_db_validate(pmdb_t *db)

/* this takes into account the default verification level if UNKNOWN
* was assigned to this db */
- check_sig = alpm_db_get_sigverify_level(db);
+ level = alpm_db_get_siglevel(db);

- if(check_sig != PM_PGP_VERIFY_NEVER) {
- int ret;
+ if(level & PM_SIG_DATABASE) {
+ enum _pmsigstatus_t status;
const char *dbpath = _alpm_db_path(db);
if(!dbpath) {
/* pm_errno set in _alpm_db_path() */
@@ -95,10 +95,16 @@ static int sync_db_validate(pmdb_t *db)

_alpm_log(db->handle, PM_LOG_DEBUG, "checking signature for %s
",
db->treename);
- ret = _alpm_gpgme_checksig(db->handle, dbpath, NULL);
- if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) ||
- (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
- RET_ERR(db->handle, PM_ERR_SIG_INVALID, -1);
+ status = _alpm_gpgme_checksig(db->handle, dbpath, NULL);
+ switch(status) {
+ case PM_SIGSTATUS_VALID:
+ break;
+ case PM_SIGSTATUS_SIG_MISSING:
+ if(level & PM_SIG_DATABASE_OPTIONAL) {
+ break;
+ }
+ default:
+ RET_ERR(db->handle, PM_ERR_DB_INVALID_SIG, 1);
}
}

@@ -149,7 +155,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
int ret = -1;
mode_t oldmask;
pmhandle_t *handle;
- pgp_verify_t check_sig;
+ pmsiglevel_t level;

/* Sanity checks */
ASSERT(db != NULL, return -1);
@@ -166,7 +172,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
/* make sure we have a sane umask */
oldmask = umask(0022);

- check_sig = alpm_db_get_sigverify_level(db);
+ level = alpm_db_get_siglevel(db);

/* attempt to grab a lock */
if(_alpm_handle_lock(handle)) {
@@ -186,8 +192,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)

ret = _alpm_download(handle, fileurl, syncpath, force, 0, 0);

- if(ret == 0 && (check_sig == PM_PGP_VERIFY_ALWAYS ||
- check_sig == PM_PGP_VERIFY_OPTIONAL)) {
+ if(ret == 0 && (level & PM_SIG_DATABASE)) {
/* an existing sig file is no good at this point */
char *sigpath = _alpm_db_sig_path(db);
if(!sigpath) {
@@ -197,7 +202,7 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
unlink(sigpath);
free(sigpath);

- int errors_ok = (check_sig == PM_PGP_VERIFY_OPTIONAL);
+ int errors_ok = (level & PM_SIG_DATABASE_OPTIONAL);
/* if we downloaded a DB, we want the .sig from the same server */
snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename);

@@ -586,7 +591,7 @@ struct db_operations sync_db_ops = {
};

pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
- pgp_verify_t level)
+ pmsiglevel_t level)
{
pmdb_t *db;

@@ -598,7 +603,7 @@ pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
}
db->ops = &sync_db_ops;
db->handle = handle;
- db->pgp_verify = level;
+ db->siglevel = level;

if(sync_db_validate(db)) {
_alpm_db_free(db);
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index ac02740..9435135 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -46,7 +46,7 @@

/** Register a sync database of packages. */
pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename,
- pgp_verify_t check_sig)
+ pmsiglevel_t level)
{
/* Sanity checks */
CHECK_HANDLE(handle, return NULL);
@@ -55,7 +55,7 @@ pmdb_t SYMEXPORT *alpm_db_register_sync(pmhandle_t *handle, const char *treename
/* Do not register a database if a transaction is on-going */
ASSERT(handle->trans == NULL, RET_ERR(handle, PM_ERR_TRANS_NOT_NULL, NULL));

- return _alpm_db_register_sync(handle, treename, check_sig);
+ return _alpm_db_register_sync(handle, treename, level);
}

/* Helper function for alpm_db_unregister{_all} */
@@ -220,13 +220,13 @@ const char SYMEXPORT *alpm_db_get_name(const pmdb_t *db)
}

/** Get the signature verification level for a database. */
-pgp_verify_t SYMEXPORT alpm_db_get_sigverify_level(pmdb_t *db)
+pmsiglevel_t SYMEXPORT alpm_db_get_siglevel(pmdb_t *db)
{
ASSERT(db != NULL, return -1);
- if(db->pgp_verify == PM_PGP_VERIFY_UNKNOWN) {
- return alpm_option_get_default_sigverify(db->handle);
+ if(db->siglevel & PM_SIG_USE_DEFAULT) {
+ return alpm_option_get_default_siglevel(db->handle);
} else {
- return db->pgp_verify;
+ return db->siglevel;
}
}

@@ -323,7 +323,7 @@ pmdb_t *_alpm_db_new(const char *treename, int is_local)
CALLOC(db, 1, sizeof(pmdb_t), return NULL);
STRDUP(db->treename, treename, return NULL);
db->is_local = is_local;
- db->pgp_verify = PM_PGP_VERIFY_UNKNOWN;
+ db->siglevel = 0;

return db;
}
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 5da28bf..60d8c94 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -69,7 +69,7 @@ struct __pmdb_t {
pmpkghash_t *pkgcache;
alpm_list_t *grpcache;
alpm_list_t *servers;
- pgp_verify_t pgp_verify;
+ pmsiglevel_t siglevel;

struct db_operations *ops;
};
@@ -84,7 +84,7 @@ int _alpm_db_cmp(const void *d1, const void *d2);
alpm_list_t *_alpm_db_search(pmdb_t *db, const alpm_list_t *needles);
pmdb_t *_alpm_db_register_local(pmhandle_t *handle);
pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
- pgp_verify_t level);
+ pmsiglevel_t level);
void _alpm_db_unregister(pmdb_t *db);

/* be_*.c, backend specific calls */
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index c7903ff..b1d9b04 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -363,11 +363,10 @@ char SYMEXPORT *alpm_fetch_pkgurl(pmhandle_t *handle, const char *url)
_alpm_log(handle, PM_LOG_DEBUG, "successfully downloaded %s
", url);

/* attempt to download the signature */
- if(ret == 0 && (handle->sigverify == PM_PGP_VERIFY_ALWAYS ||
- handle->sigverify == PM_PGP_VERIFY_OPTIONAL)) {
+ if(ret == 0 && (handle->siglevel & PM_SIG_PACKAGE)) {
char *sig_url;
size_t len;
- int errors_ok = (handle->sigverify == PM_PGP_VERIFY_OPTIONAL);
+ int errors_ok = (handle->siglevel & PM_SIG_PACKAGE_OPTIONAL);

len = strlen(url) + 5;
CALLOC(sig_url, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, NULL));
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 1e4e705..78dce5c 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -72,6 +72,8 @@ const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err)
return _("could not find database");
case PM_ERR_DB_INVALID:
return _("invalid or corrupted database");
+ case PM_ERR_DB_INVALID_SIG:
+ return _("invalid or corrupted database (PGP)");
case PM_ERR_DB_VERSION:
return _("database is incorrect version");
case PM_ERR_DB_WRITE:
@@ -106,7 +108,9 @@ const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err)
case PM_ERR_PKG_IGNORED:
return _("operation cancelled due to ignorepkg");
case PM_ERR_PKG_INVALID:
- return _("invalid or corrupted package");
+ return _("invalid or corrupted package (checksum)");
+ case PM_ERR_PKG_INVALID_SIG:
+ return _("invalid or corrupted package (PGP)");
case PM_ERR_PKG_OPEN:
return _("cannot open package file");
case PM_ERR_PKG_CANT_REMOVE:
@@ -117,13 +121,6 @@ const char SYMEXPORT *alpm_strerror(enum _pmerrno_t err)
return _("package architecture is not valid");
case PM_ERR_PKG_REPO_NOT_FOUND:
return _("could not find repository for target");
- /* Signatures */
- case PM_ERR_SIG_MISSINGDIR:
- return _("signature directory not configured correctly");
- case PM_ERR_SIG_INVALID:
- return _("invalid PGP signature");
- case PM_ERR_SIG_UNKNOWN:
- return _("unknown PGP signature");
/* Deltas */
case PM_ERR_DLT_INVALID:
return _("invalid or corrupted delta");
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index acd3540..b7eae1e 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -45,7 +45,8 @@ pmhandle_t *_alpm_handle_new()

CALLOC(handle, 1, sizeof(pmhandle_t), return NULL);

- handle->sigverify = PM_PGP_VERIFY_OPTIONAL;
+ handle->siglevel = PM_SIG_PACKAGE | PM_SIG_PACKAGE_OPTIONAL |
+ PM_SIG_DATABASE | PM_SIG_DATABASE_OPTIONAL;

return handle;
}
@@ -574,18 +575,17 @@ int SYMEXPORT alpm_option_set_checkspace(pmhandle_t *handle, int checkspace)
return 0;
}

-int SYMEXPORT alpm_option_set_default_sigverify(pmhandle_t *handle, pgp_verify_t level)
+int SYMEXPORT alpm_option_set_default_siglevel(pmhandle_t *handle, pmsiglevel_t level)
{
CHECK_HANDLE(handle, return -1);
- ASSERT(level != PM_PGP_VERIFY_UNKNOWN, RET_ERR(handle, PM_ERR_WRONG_ARGS, -1));
- handle->sigverify = level;
+ handle->siglevel = level;
return 0;
}

-pgp_verify_t SYMEXPORT alpm_option_get_default_sigverify(pmhandle_t *handle)
+pmsiglevel_t SYMEXPORT alpm_option_get_default_siglevel(pmhandle_t *handle)
{
- CHECK_HANDLE(handle, return PM_PGP_VERIFY_UNKNOWN);
- return handle->sigverify;
+ CHECK_HANDLE(handle, return -1);
+ return handle->siglevel;
}

/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 4ffd00c..4196e82 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -69,7 +69,7 @@ struct __pmhandle_t {
char *arch; /* Architecture of packages we should allow */
int usedelta; /* Download deltas if possible */
int checkspace; /* Check disk space before installing */
- pgp_verify_t sigverify; /* Default signature verification level */
+ pmsiglevel_t siglevel; /* Default signature verification level */

/* error code */
enum _pmerrno_t pm_errno;
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index d18020d..9739f96 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -145,7 +145,7 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg);

pmpkg_t *_alpm_pkg_load_internal(pmhandle_t *handle, const char *pkgfile,
int full, const char *md5sum, const char *base64_sig,
- pgp_verify_t check_sig);
+ pmsiglevel_t level);

int _alpm_pkg_cmp(const void *p1, const void *p2);
int _alpm_pkg_compare_versions(pmpkg_t *local_pkg, pmpkg_t *pkg);
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index a19c1cb..f505995 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -117,9 +117,6 @@ static int init_gpgme(pmhandle_t *handle)
}

sigdir = alpm_option_get_gpgdir(handle);
- if(!sigdir) {
- RET_ERR(handle, PM_ERR_SIG_MISSINGDIR, 1);
- }

/* calling gpgme_check_version() returns the current version and runs
* some internal library setup code */
@@ -203,9 +200,9 @@ error:
* @param handle the context handle
* @param path the full path to a file
* @param base64_sig optional PGP signature data in base64 encoding
- * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
+ * @return a value indicating signature check status
*/
-int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
+pmsigstatus_t _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
const char *base64_sig)
{
int ret = 0;
@@ -219,23 +216,24 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
FILE *file = NULL, *sigfile = NULL;

if(!path || access(path, R_OK) != 0) {
- RET_ERR(handle, PM_ERR_NOT_A_FILE, -1);
+ return PM_SIGSTATUS_FILE_MISSING;
}

if(!base64_sig) {
size_t len = strlen(path) + 5;
- CALLOC(sigpath, len, sizeof(char), RET_ERR(handle, PM_ERR_MEMORY, -1));
+ CALLOC(sigpath, len, sizeof(char),
+ RET_ERR(handle, PM_ERR_MEMORY, PM_SIGSTATUS_ERROR));
snprintf(sigpath, len, "%s.sig", path);

if(!access(sigpath, R_OK) == 0) {
FREE(sigpath);
- RET_ERR(handle, PM_ERR_SIG_UNKNOWN, -1);
+ return PM_SIGSTATUS_SIG_MISSING;
}
}

if(init_gpgme(handle)) {
/* pm_errno was set in gpgme_init() */
- return -1;
+ return PM_SIGSTATUS_ERROR;
}

_alpm_log(handle, PM_LOG_DEBUG, "checking signature for %s
", path);
@@ -250,8 +248,7 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
/* create our necessary data objects to verify the signature */
file = fopen(path, "rb");
if(file == NULL) {
- handle->pm_errno = PM_ERR_NOT_A_FILE;
- ret = -1;
+ ret = PM_SIGSTATUS_FILE_MISSING;
goto error;
}
err = gpgme_data_new_from_stream(&filedata, file);
@@ -264,7 +261,7 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
int decode_ret = decode_signature(base64_sig,
&decoded_sigdata, &data_len);
if(decode_ret) {
- ret = -1;
+ ret = PM_SIGSTATUS_INVALID;
goto error;
}
err = gpgme_data_new_from_mem(&sigdata,
@@ -273,8 +270,7 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
/* file-based, it is on disk */
sigfile = fopen(sigpath, "rb");
if(sigfile == NULL) {
- handle->pm_errno = PM_ERR_NOT_A_FILE;
- ret = -1;
+ ret = PM_SIGSTATUS_SIG_MISSING;
goto error;
}
err = gpgme_data_new_from_stream(&sigdata, sigfile);
@@ -311,23 +307,22 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
if(gpgsig->summary & GPGME_SIGSUM_VALID) {
/* definite good signature */
_alpm_log(handle, PM_LOG_DEBUG, "result: valid signature
");
+ ret = PM_SIGSTATUS_VALID;
} else if(gpgsig->summary & GPGME_SIGSUM_GREEN) {
/* good signature */
_alpm_log(handle, PM_LOG_DEBUG, "result: green signature
");
+ ret = PM_SIGSTATUS_VALID;
} else if(gpgsig->summary & GPGME_SIGSUM_RED) {
/* definite bad signature, error */
_alpm_log(handle, PM_LOG_DEBUG, "result: red signature
");
- handle->pm_errno = PM_ERR_SIG_INVALID;
- ret = 1;
+ ret = PM_SIGSTATUS_BAD;
} else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) {
_alpm_log(handle, PM_LOG_DEBUG, "result: signature from unknown key
");
- handle->pm_errno = PM_ERR_SIG_UNKNOWN;
- ret = 1;
+ ret = PM_SIGSTATUS_UNKNOWN;
} else {
/* we'll capture everything else here */
_alpm_log(handle, PM_LOG_DEBUG, "result: invalid signature
");
- handle->pm_errno = PM_ERR_SIG_INVALID;
- ret = 1;
+ ret = PM_SIGSTATUS_BAD;
}

gpgsig = gpgsig->next;
@@ -364,7 +359,7 @@ int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
* @param pkg the package to check
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
*/
-int SYMEXPORT alpm_pkg_check_pgp_signature(pmpkg_t *pkg)
+pmsigstatus_t SYMEXPORT alpm_pkg_check_pgp_signature(pmpkg_t *pkg)
{
ASSERT(pkg != NULL, return -1);
pkg->handle->pm_errno = 0;
@@ -378,7 +373,7 @@ int SYMEXPORT alpm_pkg_check_pgp_signature(pmpkg_t *pkg)
* @param db the database to check
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
*/
-int SYMEXPORT alpm_db_check_pgp_signature(pmdb_t *db)
+pmsigstatus_t SYMEXPORT alpm_db_check_pgp_signature(pmdb_t *db)
{
ASSERT(db != NULL, return -1);
db->handle->pm_errno = 0;
diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h
index 14b2ad7..c8e6220 100644
--- a/lib/libalpm/signing.h
+++ b/lib/libalpm/signing.h
@@ -21,7 +21,7 @@

#include "alpm.h"

-int _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
+enum _pmsigstatus_t _alpm_gpgme_checksig(pmhandle_t *handle, const char *path,
const char *base64_sig);

#endif /* _ALPM_SIGNING_H */
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 0a38a77..9494b91 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -863,7 +863,7 @@ int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data)
int percent = (current * 100) / numtargs;
const char *filename;
char *filepath;
- pgp_verify_t check_sig;
+ pmsiglevel_t level;

PROGRESS(trans, PM_TRANS_PROGRESS_INTEGRITY_START, "", percent,
numtargs, current);
@@ -874,7 +874,7 @@ int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data)
filename = alpm_pkg_get_filename(spkg);
filepath = _alpm_filecache_find(handle, filename);
pmdb_t *sdb = alpm_pkg_get_db(spkg);
- check_sig = alpm_db_get_sigverify_level(sdb);
+ level = alpm_db_get_siglevel(sdb);

/* load the package file and replace pkgcache entry with it in the target list */
/* TODO: alpm_pkg_get_db() will not work on this target anymore */
@@ -882,7 +882,7 @@ int _alpm_sync_commit(pmhandle_t *handle, alpm_list_t **data)
"replacing pkgcache entry with package file for target %s
",
spkg->name);
pmpkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1, spkg->md5sum,
- spkg->base64_sig, check_sig);
+ spkg->base64_sig, level);
if(!pkgfile) {
errors++;
*data = alpm_list_add(*data, strdup(filename));
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 076e854..dcb45f6 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -52,7 +52,7 @@ config_t *config_new(void)
newconfig->op = PM_OP_MAIN;
newconfig->logmask = PM_LOG_ERROR | PM_LOG_WARNING;
newconfig->configfile = strdup(CONFFILE);
- newconfig->sigverify = PM_PGP_VERIFY_UNKNOWN;
+ newconfig->siglevel = PM_SIG_USE_DEFAULT;

return newconfig;
}
@@ -222,17 +222,18 @@ int config_set_arch(const char *arch)
return 0;
}

-static pgp_verify_t option_verifysig(const char *value)
+static pmsiglevel_t option_verifysig(const char *value)
{
- pgp_verify_t level;
+ pmsiglevel_t level;
if(strcmp(value, "Always") == 0) {
- level = PM_PGP_VERIFY_ALWAYS;
+ level = PM_SIG_PACKAGE | PM_SIG_DATABASE;
} else if(strcmp(value, "Optional") == 0) {
- level = PM_PGP_VERIFY_OPTIONAL;
+ level = PM_SIG_PACKAGE | PM_SIG_PACKAGE_OPTIONAL |
+ PM_SIG_DATABASE | PM_SIG_DATABASE_OPTIONAL;
} else if(strcmp(value, "Never") == 0) {
- level = PM_PGP_VERIFY_NEVER;
+ level = 0;
} else {
- level = PM_PGP_VERIFY_UNKNOWN;
+ return -1;
}
pm_printf(PM_LOG_DEBUG, "config: VerifySig = %s (%d)
", value, level);
return level;
@@ -359,9 +360,9 @@ static int _parse_options(const char *key, char *value,
}
FREELIST(methods);
} else if(strcmp(key, "VerifySig") == 0) {
- pgp_verify_t level = option_verifysig(value);
- if(level != PM_PGP_VERIFY_UNKNOWN) {
- config->sigverify = level;
+ pmsiglevel_t level = option_verifysig(value);
+ if(level != -1) {
+ config->siglevel = level;
} else {
pm_printf(PM_LOG_ERROR,
_("config file %s, line %d: directive '%s' has invalid value '%s'
"),
@@ -484,8 +485,8 @@ static int setup_libalpm(void)
alpm_option_set_cachedirs(handle, config->cachedirs);
}

- if(config->sigverify != PM_PGP_VERIFY_UNKNOWN) {
- alpm_option_set_default_sigverify(handle, config->sigverify);
+ if(config->siglevel != PM_SIG_USE_DEFAULT) {
+ alpm_option_set_default_siglevel(handle, config->siglevel);
}

if(config->xfercommand) {
@@ -518,7 +519,7 @@ struct section_t {
char *name;
int is_options;
/* db section option gathering */
- pgp_verify_t sigverify;
+ pmsiglevel_t siglevel;
alpm_list_t *servers;
};

@@ -545,7 +546,7 @@ static int finish_section(struct section_t *section, int parse_options)
}

/* if we are not looking at options sections only, register a db */
- db = alpm_db_register_sync(config->handle, section->name, section->sigverify);
+ db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
if(db == NULL) {
pm_printf(PM_LOG_ERROR, _("could not register '%s' database (%s)
"),
section->name, alpm_strerror(alpm_errno(config->handle)));
@@ -568,7 +569,7 @@ static int finish_section(struct section_t *section, int parse_options)
cleanup:
alpm_list_free(section->servers);
section->servers = NULL;
- section->sigverify = 0;
+ section->siglevel = PM_SIG_USE_DEFAULT;
free(section->name);
section->name = NULL;
return ret;
@@ -726,9 +727,9 @@ static int _parseconfig(const char *file, struct section_t *section,
}
section->servers = alpm_list_add(section->servers, strdup(value));
} else if(strcmp(key, "VerifySig") == 0) {
- pgp_verify_t level = option_verifysig(value);
- if(level != PM_PGP_VERIFY_UNKNOWN) {
- section->sigverify = level;
+ pmsiglevel_t level = option_verifysig(value);
+ if(level != -1) {
+ section->siglevel = level;
} else {
pm_printf(PM_LOG_ERROR,
_("config file %s, line %d: directive '%s' has invalid value '%s'
"),
@@ -763,6 +764,7 @@ int parseconfig(const char *file)
int ret;
struct section_t section;
memset(&section, 0, sizeof(struct section_t));
+ section.siglevel = PM_SIG_USE_DEFAULT;
/* the config parse is a two-pass affair. We first parse the entire thing for
* the [options] section so we can get all default and path options set.
* Next, we go back and parse everything but [options]. */
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 4c44bfd..5e1a5b1 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -71,7 +71,7 @@ typedef struct __config_t {
unsigned short noask;
unsigned int ask;
pmtransflag_t flags;
- pgp_verify_t sigverify;
+ pmsiglevel_t siglevel;

/* conf file options */
/* I Love Candy! */
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 62472cb..566787a 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -549,7 +549,7 @@ int pacman_query(alpm_list_t *targets)
char *strname = alpm_list_getdata(i);

if(config->op_q_isfile) {
- alpm_pkg_load(config->handle, strname, 1, PM_PGP_VERIFY_OPTIONAL, &pkg);
+ alpm_pkg_load(config->handle, strname, 1, 0, &pkg);
} else {
pkg = alpm_db_get_pkg(db_local, strname);
}
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index fa30b8d..218a770 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -220,7 +220,7 @@ static int sync_cleancache(int level)
/* attempt to load the package, prompt removal on failures as we may have
* files here that aren't valid packages. we also don't need a full
* load of the package, just the metadata. */
- if(alpm_pkg_load(config->handle, path, 0, PM_PGP_VERIFY_NEVER, &localpkg) != 0
+ if(alpm_pkg_load(config->handle, path, 0, 0, &localpkg) != 0
|| localpkg == NULL) {
if(yesno(_("File %s does not seem to be a valid package, remove it?"),
path)) {
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index c1f72f6..4a64dd8 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -42,7 +42,7 @@
int pacman_upgrade(alpm_list_t *targets)
{
alpm_list_t *i, *data = NULL;
- pgp_verify_t check_sig = alpm_option_get_default_sigverify(config->handle);
+ pmsiglevel_t level = alpm_option_get_default_siglevel(config->handle);
int retval = 0;

if(targets == NULL) {
@@ -76,7 +76,7 @@ int pacman_upgrade(alpm_list_t *targets)
char *targ = alpm_list_getdata(i);
pmpkg_t *pkg;

- if(alpm_pkg_load(config->handle, targ, 1, check_sig, &pkg) != 0) {
+ if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) {
pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s
",
targ, alpm_strerror(alpm_errno(config->handle)));
trans_release();
diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c
index 5ee59db..3809525 100644
--- a/src/util/cleanupdelta.c
+++ b/src/util/cleanupdelta.c
@@ -71,11 +71,12 @@ static void checkdbs(const char *dbpath, alpm_list_t *dbnames) {
char syncdbpath[PATH_MAX];
pmdb_t *db = NULL;
alpm_list_t *i;
+ const pmsiglevel_t level = PM_SIG_DATABASE | PM_SIG_DATABASE_OPTIONAL;

for(i = dbnames; i; i = alpm_list_next(i)) {
char *dbname = alpm_list_getdata(i);
snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname);
- db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL);
+ db = alpm_db_register_sync(handle, dbname, level);
if(db == NULL) {
fprintf(stderr, "error: could not register sync database (%s)
",
alpm_strerror(alpm_errno(handle)));
diff --git a/src/util/pactree.c b/src/util/pactree.c
index 5beaa5a..f44deb1 100644
--- a/src/util/pactree.c
+++ b/src/util/pactree.c
@@ -124,6 +124,7 @@ static int register_syncs(void) {
FILE *fp;
char *ptr, *section = NULL;
char line[LINE_MAX];
+ const pmsiglevel_t level = PM_SIG_DATABASE | PM_SIG_DATABASE_OPTIONAL;

fp = fopen(CONFFILE, "r");
if(!fp) {
@@ -147,7 +148,7 @@ static int register_syncs(void) {
section = strndup(&line[1], strlen(line) - 2);

if(section && strcmp(section, "options") != 0) {
- alpm_db_register_sync(handle, section, PM_PGP_VERIFY_OPTIONAL);
+ alpm_db_register_sync(handle, section, level);
}
}
}
diff --git a/src/util/testdb.c b/src/util/testdb.c
index af5007e..8eefe30 100644
--- a/src/util/testdb.c
+++ b/src/util/testdb.c
@@ -148,10 +148,11 @@ static int check_syncdbs(alpm_list_t *dbnames) {
int ret = 0;
pmdb_t *db = NULL;
alpm_list_t *i, *pkglist, *syncpkglist = NULL;
+ const pmsiglevel_t level = PM_SIG_DATABASE | PM_SIG_DATABASE_OPTIONAL;

for(i = dbnames; i; i = alpm_list_next(i)) {
char *dbname = alpm_list_getdata(i);
- db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL);
+ db = alpm_db_register_sync(handle, dbname, level);
if(db == NULL) {
fprintf(stderr, "error: could not register sync database (%s)
",
alpm_strerror(alpm_errno(handle)));
diff --git a/src/util/testpkg.c b/src/util/testpkg.c
index d4d058d..984142a 100644
--- a/src/util/testpkg.c
+++ b/src/util/testpkg.c
@@ -43,6 +43,7 @@ int main(int argc, char *argv[])
pmhandle_t *handle;
enum _pmerrno_t err;
pmpkg_t *pkg = NULL;
+ const pmsiglevel_t level = PM_SIG_PACKAGE | PM_SIG_PACKAGE_OPTIONAL;

if(argc != 2) {
fprintf(stderr, "usage: %s <package file>
", BASENAME);
@@ -58,7 +59,7 @@ int main(int argc, char *argv[])
/* let us get log messages from libalpm */
alpm_option_set_logcb(handle, output_cb);

- if(alpm_pkg_load(handle, argv[1], 1, PM_PGP_VERIFY_OPTIONAL, &pkg) == -1
+ if(alpm_pkg_load(handle, argv[1], 1, level, &pkg) == -1
|| pkg == NULL) {
err = alpm_errno(handle);
switch(err) {
--
1.7.5.4
 
Old 07-03-2011, 08:28 PM
Dan McGee
 
Default signing: move to new signing verification and return scheme

This gives us more granularity than the former Never/Optional/Always
trifecta. The frontend still uses these values temporarily but that will
be changed in a future patch.

* Use 'siglevel' consistenly in method names, 'level' as variable name
* The level becomes an enum bitmask value for flexibility
* Signature check methods now return a array of status codes rather than
a simple integer success/failure value. This allows callers to
determine whether things such as an unknown signature are valid.
* Specific signature error codes mostly disappear in favor of the above
returned status code; pm_errno is now set only to PKG_INVALID_SIG or
DB_INVALID_SIG as appropriate.

Signed-off-by: Dan McGee <dan@archlinux.org>
---
lib/libalpm/alpm.h | 64 ++++++++++++------
lib/libalpm/be_package.c | 20 +++---
lib/libalpm/be_sync.c | 30 ++++-----
lib/libalpm/db.c | 16 ++--
lib/libalpm/db.h | 4 +-
lib/libalpm/dload.c | 5 +-
lib/libalpm/error.c | 12 ++--
lib/libalpm/handle.c | 15 ++--
lib/libalpm/handle.h | 2 +-
lib/libalpm/package.h | 2 +-
lib/libalpm/signing.c | 167 ++++++++++++++++++++++++++++++++++++----------
lib/libalpm/signing.h | 5 +-
lib/libalpm/sync.c | 6 +-
src/pacman/conf.c | 38 ++++++-----
src/pacman/conf.h | 2 +-
src/pacman/query.c | 2 +-
src/pacman/sync.c | 2 +-
src/pacman/upgrade.c | 4 +-
src/util/cleanupdelta.c | 3 +-
src/util/pactree.c | 3 +-
src/util/testdb.c | 3 +-
src/util/testpkg.c | 3 +-
22 files changed, 266 insertions(+), 142 deletions(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index e733eb2..db8e8ef 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -87,14 +87,28 @@ typedef enum _alpm_fileconflicttype_t {
} alpm_fileconflicttype_t;

/**
- * GPG signature verification options
+ * PGP signature verification options
*/
-typedef enum _pgp_verify_t {
- PM_PGP_VERIFY_UNKNOWN,
- PM_PGP_VERIFY_NEVER,
- PM_PGP_VERIFY_OPTIONAL,
- PM_PGP_VERIFY_ALWAYS
-} pgp_verify_t;
+typedef enum _alpm_siglevel_t {
+ ALPM_SIG_PACKAGE = (1 << 0),
+ ALPM_SIG_PACKAGE_OPTIONAL = (1 << 1),
+ ALPM_SIG_DATABASE = (1 << 2),
+ ALPM_SIG_DATABASE_OPTIONAL = (1 << 3),
+ ALPM_SIG_UNKNOWN_OK = (1 << 4),
+ ALPM_SIG_MARGINAL_OK = (1 << 5),
+
+ ALPM_SIG_USE_DEFAULT = (1 << 31),
+} alpm_siglevel_t;
+
+/**
+ * PGP signature verification return codes
+ */
+typedef enum _alpm_sigstatus_t {
+ ALPM_SIGSTATUS_VALID = 0,
+ ALPM_SIGSTATUS_MARGINAL,
+ ALPM_SIGSTATUS_UNKNOWN,
+ ALPM_SIGSTATUS_BAD
+} alpm_sigstatus_t;

/*
* Structures
@@ -173,6 +187,15 @@ typedef struct _alpm_backup_t {
char *hash;
} alpm_backup_t;

+/** Signature result. Contains the number of signatures found and pointers to
+ * arrays containing key and status info. All contained arrays have size
+ * #count.*/
+typedef struct _alpm_sigresult_t {
+ int count;
+ alpm_sigstatus_t *status;
+ char **uid;
+} alpm_sigresult_t;
+
/*
* Logging facilities
*/
@@ -335,8 +358,8 @@ int alpm_option_set_usedelta(alpm_handle_t *handle, int usedelta);
int alpm_option_get_checkspace(alpm_handle_t *handle);
int alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace);

-pgp_verify_t alpm_option_get_default_sigverify(alpm_handle_t *handle);
-int alpm_option_set_default_sigverify(alpm_handle_t *handle, pgp_verify_t level);
+alpm_siglevel_t alpm_option_get_default_siglevel(alpm_handle_t *handle);
+int alpm_option_set_default_siglevel(alpm_handle_t *handle, alpm_siglevel_t level);

/** @} */

@@ -364,12 +387,12 @@ alpm_list_t *alpm_option_get_syncdbs(alpm_handle_t *handle);
/** Register a sync database of packages.
* @param handle the context handle
* @param treename the name of the sync repository
- * @param check_sig what level of signature checking to perform on the
+ * @param level what level of signature checking to perform on the
* database; note that this must be a '.sig' file type verification
- * @return a alpm_db_t* on success (the value), NULL on error
+ * @return an alpm_db_t* on success (the value), NULL on error
*/
alpm_db_t *alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
- pgp_verify_t check_sig);
+ alpm_siglevel_t level);

/** Unregister a package database.
* @param db pointer to the package database to unregister
@@ -391,11 +414,11 @@ const char *alpm_db_get_name(const alpm_db_t *db);

/** Get the signature verification level for a database.
* Will return the default verification level if this database is set up
- * with PM_PGP_VERIFY_UNKNOWN.
+ * with ALPM_SIG_USE_DEFAULT.
* @param db pointer to the package database
* @return the signature verification level
*/
-pgp_verify_t alpm_db_get_sigverify_level(alpm_db_t *db);
+alpm_siglevel_t alpm_db_get_siglevel(alpm_db_t *db);

/** Check the validity of a database.
* This is most useful for sync databases and verifying signature status.
@@ -473,13 +496,13 @@ int alpm_db_set_pkgreason(alpm_db_t *db, const char *name, alpm_pkgreason_t reas
* @param filename location of the package tarball
* @param full whether to stop the load after metadata is read or continue
* through the full archive
- * @param check_sig what level of package signature checking to perform on the
+ * @param level what level of package signature checking to perform on the
* package; note that this must be a '.sig' file type verification
* @param pkg address of the package pointer
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full,
- pgp_verify_t check_sig, alpm_pkg_t **pkg);
+ alpm_siglevel_t, alpm_pkg_t **pkg);

/** Free a package.
* @param pkg package pointer to free
@@ -715,9 +738,9 @@ alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg);
* Signatures
*/

-int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg);
+int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_sigresult_t *result);

-int alpm_db_check_pgp_signature(alpm_db_t *db);
+int alpm_db_check_pgp_signature(alpm_db_t *db, alpm_sigresult_t *result);

/*
* Groups
@@ -1025,6 +1048,7 @@ enum _alpm_errno_t {
ALPM_ERR_DB_NOT_NULL,
ALPM_ERR_DB_NOT_FOUND,
ALPM_ERR_DB_INVALID,
+ ALPM_ERR_DB_INVALID_SIG,
ALPM_ERR_DB_VERSION,
ALPM_ERR_DB_WRITE,
ALPM_ERR_DB_REMOVE,
@@ -1044,15 +1068,15 @@ enum _alpm_errno_t {
ALPM_ERR_PKG_NOT_FOUND,
ALPM_ERR_PKG_IGNORED,
ALPM_ERR_PKG_INVALID,
+ ALPM_ERR_PKG_INVALID_SIG,
ALPM_ERR_PKG_OPEN,
ALPM_ERR_PKG_CANT_REMOVE,
ALPM_ERR_PKG_INVALID_NAME,
ALPM_ERR_PKG_INVALID_ARCH,
ALPM_ERR_PKG_REPO_NOT_FOUND,
/* Signatures */
- ALPM_ERR_SIG_MISSINGDIR,
+ ALPM_ERR_SIG_MISSING,
ALPM_ERR_SIG_INVALID,
- ALPM_ERR_SIG_UNKNOWN,
/* Deltas */
ALPM_ERR_DLT_INVALID,
ALPM_ERR_DLT_PATCHFAILED,
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index af21324..2f83610 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -233,7 +233,7 @@ static int parse_descfile(alpm_handle_t *handle, struct archive *a, alpm_pkg_t *
*/
alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile,
int full, const char *md5sum, const char *base64_sig,
- pgp_verify_t check_sig)
+ alpm_siglevel_t level)
{
int ret;
int config = 0;
@@ -271,14 +271,12 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile,
}

_alpm_log(handle, ALPM_LOG_DEBUG, "base64_sig: %s
", base64_sig);
- if(check_sig != PM_PGP_VERIFY_NEVER) {
- _alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s
", pkgfile);
- ret = _alpm_gpgme_checksig(handle, pkgfile, base64_sig);
- if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) ||
- (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
- alpm_pkg_free(newpkg);
- RET_ERR(handle, ALPM_ERR_SIG_INVALID, NULL);
- }
+ if(level & ALPM_SIG_PACKAGE &&
+ _alpm_check_pgp_helper(handle, pkgfile, base64_sig,
+ level & ALPM_SIG_PACKAGE_OPTIONAL, level & ALPM_SIG_MARGINAL_OK,
+ level & ALPM_SIG_UNKNOWN_OK, ALPM_ERR_PKG_INVALID_SIG)) {
+ _alpm_pkg_free(newpkg);
+ return NULL;
}

/* next- try to create an archive object to read in the package */
@@ -396,12 +394,12 @@ error:
}

int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int full,
- pgp_verify_t check_sig, alpm_pkg_t **pkg)
+ alpm_siglevel_t level, alpm_pkg_t **pkg)
{
CHECK_HANDLE(handle, return -1);
ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));

- *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, check_sig);
+ *pkg = _alpm_pkg_load_internal(handle, filename, full, NULL, NULL, level);
if(*pkg == NULL) {
/* pm_errno is set by pkg_load */
return -1;
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index 368acce..2a6cb1b 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -69,7 +69,7 @@ static char *get_sync_dir(alpm_handle_t *handle)

static int sync_db_validate(alpm_db_t *db)
{
- pgp_verify_t check_sig;
+ alpm_siglevel_t level;

if(db->status & DB_STATUS_VALID) {
return 0;
@@ -77,10 +77,9 @@ static int sync_db_validate(alpm_db_t *db)

/* this takes into account the default verification level if UNKNOWN
* was assigned to this db */
- check_sig = alpm_db_get_sigverify_level(db);
+ level = alpm_db_get_siglevel(db);

- if(check_sig != PM_PGP_VERIFY_NEVER) {
- int ret;
+ if(level & ALPM_SIG_DATABASE) {
const char *dbpath = _alpm_db_path(db);
if(!dbpath) {
/* pm_errno set in _alpm_db_path() */
@@ -93,12 +92,10 @@ static int sync_db_validate(alpm_db_t *db)
return 0;
}

- _alpm_log(db->handle, ALPM_LOG_DEBUG, "checking signature for %s
",
- db->treename);
- ret = _alpm_gpgme_checksig(db->handle, dbpath, NULL);
- if((check_sig == PM_PGP_VERIFY_ALWAYS && ret != 0) ||
- (check_sig == PM_PGP_VERIFY_OPTIONAL && ret == 1)) {
- RET_ERR(db->handle, ALPM_ERR_SIG_INVALID, -1);
+ if(_alpm_check_pgp_helper(db->handle, dbpath, NULL,
+ level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_MARGINAL_OK,
+ level & ALPM_SIG_UNKNOWN_OK, ALPM_ERR_DB_INVALID_SIG)) {
+ return 1;
}
}

@@ -149,7 +146,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
int ret = -1;
mode_t oldmask;
alpm_handle_t *handle;
- pgp_verify_t check_sig;
+ alpm_siglevel_t level;

/* Sanity checks */
ASSERT(db != NULL, return -1);
@@ -166,7 +163,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
/* make sure we have a sane umask */
oldmask = umask(0022);

- check_sig = alpm_db_get_sigverify_level(db);
+ level = alpm_db_get_siglevel(db);

/* attempt to grab a lock */
if(_alpm_handle_lock(handle)) {
@@ -186,8 +183,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)

ret = _alpm_download(handle, fileurl, syncpath, force, 0, 0);

- if(ret == 0 && (check_sig == PM_PGP_VERIFY_ALWAYS ||
- check_sig == PM_PGP_VERIFY_OPTIONAL)) {
+ if(ret == 0 && (level & ALPM_SIG_DATABASE)) {
/* an existing sig file is no good at this point */
char *sigpath = _alpm_db_sig_path(db);
if(!sigpath) {
@@ -197,7 +193,7 @@ int SYMEXPORT alpm_db_update(int force, alpm_db_t *db)
unlink(sigpath);
free(sigpath);

- int errors_ok = (check_sig == PM_PGP_VERIFY_OPTIONAL);
+ int errors_ok = (level & ALPM_SIG_DATABASE_OPTIONAL);
/* if we downloaded a DB, we want the .sig from the same server */
snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename);

@@ -586,7 +582,7 @@ struct db_operations sync_db_ops = {
};

alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
- pgp_verify_t level)
+ alpm_siglevel_t level)
{
alpm_db_t *db;

@@ -598,7 +594,7 @@ alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
}
db->ops = &sync_db_ops;
db->handle = handle;
- db->pgp_verify = level;
+ db->siglevel = level;

if(sync_db_validate(db)) {
_alpm_db_free(db);
diff --git a/lib/libalpm/db.c b/lib/libalpm/db.c
index 17f26e9..af27047 100644
--- a/lib/libalpm/db.c
+++ b/lib/libalpm/db.c
@@ -45,8 +45,8 @@
*/

/** Register a sync database of packages. */
-alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
- pgp_verify_t check_sig)
+alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle,
+ const char *treename, alpm_siglevel_t level)
{
/* Sanity checks */
CHECK_HANDLE(handle, return NULL);
@@ -55,7 +55,7 @@ alpm_db_t SYMEXPORT *alpm_db_register_sync(alpm_handle_t *handle, const char *tr
/* Do not register a database if a transaction is on-going */
ASSERT(handle->trans == NULL, RET_ERR(handle, ALPM_ERR_TRANS_NOT_NULL, NULL));

- return _alpm_db_register_sync(handle, treename, check_sig);
+ return _alpm_db_register_sync(handle, treename, level);
}

/* Helper function for alpm_db_unregister{_all} */
@@ -220,13 +220,13 @@ const char SYMEXPORT *alpm_db_get_name(const alpm_db_t *db)
}

/** Get the signature verification level for a database. */
-pgp_verify_t SYMEXPORT alpm_db_get_sigverify_level(alpm_db_t *db)
+alpm_siglevel_t SYMEXPORT alpm_db_get_siglevel(alpm_db_t *db)
{
ASSERT(db != NULL, return -1);
- if(db->pgp_verify == PM_PGP_VERIFY_UNKNOWN) {
- return alpm_option_get_default_sigverify(db->handle);
+ if(db->siglevel & ALPM_SIG_USE_DEFAULT) {
+ return alpm_option_get_default_siglevel(db->handle);
} else {
- return db->pgp_verify;
+ return db->siglevel;
}
}

@@ -323,7 +323,7 @@ alpm_db_t *_alpm_db_new(const char *treename, int is_local)
CALLOC(db, 1, sizeof(alpm_db_t), return NULL);
STRDUP(db->treename, treename, return NULL);
db->is_local = is_local;
- db->pgp_verify = PM_PGP_VERIFY_UNKNOWN;
+ db->siglevel = 0;

return db;
}
diff --git a/lib/libalpm/db.h b/lib/libalpm/db.h
index 0f00f68..a950130 100644
--- a/lib/libalpm/db.h
+++ b/lib/libalpm/db.h
@@ -69,7 +69,7 @@ struct __alpm_db_t {
alpm_pkghash_t *pkgcache;
alpm_list_t *grpcache;
alpm_list_t *servers;
- pgp_verify_t pgp_verify;
+ alpm_siglevel_t siglevel;

struct db_operations *ops;
};
@@ -84,7 +84,7 @@ int _alpm_db_cmp(const void *d1, const void *d2);
alpm_list_t *_alpm_db_search(alpm_db_t *db, const alpm_list_t *needles);
alpm_db_t *_alpm_db_register_local(alpm_handle_t *handle);
alpm_db_t *_alpm_db_register_sync(alpm_handle_t *handle, const char *treename,
- pgp_verify_t level);
+ alpm_siglevel_t level);
void _alpm_db_unregister(alpm_db_t *db);

/* be_*.c, backend specific calls */
diff --git a/lib/libalpm/dload.c b/lib/libalpm/dload.c
index c7a1c2b..4b4d8df 100644
--- a/lib/libalpm/dload.c
+++ b/lib/libalpm/dload.c
@@ -363,11 +363,10 @@ char SYMEXPORT *alpm_fetch_pkgurl(alpm_handle_t *handle, const char *url)
_alpm_log(handle, ALPM_LOG_DEBUG, "successfully downloaded %s
", url);

/* attempt to download the signature */
- if(ret == 0 && (handle->sigverify == PM_PGP_VERIFY_ALWAYS ||
- handle->sigverify == PM_PGP_VERIFY_OPTIONAL)) {
+ if(ret == 0 && (handle->siglevel & ALPM_SIG_PACKAGE)) {
char *sig_url;
size_t len;
- int errors_ok = (handle->sigverify == PM_PGP_VERIFY_OPTIONAL);
+ int errors_ok = (handle->siglevel & ALPM_SIG_PACKAGE_OPTIONAL);

len = strlen(url) + 5;
CALLOC(sig_url, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, NULL));
diff --git a/lib/libalpm/error.c b/lib/libalpm/error.c
index 8716109..7e0e5c8 100644
--- a/lib/libalpm/error.c
+++ b/lib/libalpm/error.c
@@ -72,6 +72,8 @@ const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err)
return _("could not find database");
case ALPM_ERR_DB_INVALID:
return _("invalid or corrupted database");
+ case ALPM_ERR_DB_INVALID_SIG:
+ return _("invalid or corrupted database (PGP signature)");
case ALPM_ERR_DB_VERSION:
return _("database is incorrect version");
case ALPM_ERR_DB_WRITE:
@@ -106,7 +108,9 @@ const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err)
case ALPM_ERR_PKG_IGNORED:
return _("operation cancelled due to ignorepkg");
case ALPM_ERR_PKG_INVALID:
- return _("invalid or corrupted package");
+ return _("invalid or corrupted package (checksum)");
+ case ALPM_ERR_PKG_INVALID_SIG:
+ return _("invalid or corrupted package (PGP signature)");
case ALPM_ERR_PKG_OPEN:
return _("cannot open package file");
case ALPM_ERR_PKG_CANT_REMOVE:
@@ -118,12 +122,10 @@ const char SYMEXPORT *alpm_strerror(enum _alpm_errno_t err)
case ALPM_ERR_PKG_REPO_NOT_FOUND:
return _("could not find repository for target");
/* Signatures */
- case ALPM_ERR_SIG_MISSINGDIR:
- return _("signature directory not configured correctly");
+ case ALPM_ERR_SIG_MISSING:
+ return _("missing PGP signature");
case ALPM_ERR_SIG_INVALID:
return _("invalid PGP signature");
- case ALPM_ERR_SIG_UNKNOWN:
- return _("unknown PGP signature");
/* Deltas */
case ALPM_ERR_DLT_INVALID:
return _("invalid or corrupted delta");
diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 22f3fc8..ddd76a2 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -45,7 +45,8 @@ alpm_handle_t *_alpm_handle_new()

CALLOC(handle, 1, sizeof(alpm_handle_t), return NULL);

- handle->sigverify = PM_PGP_VERIFY_OPTIONAL;
+ handle->siglevel = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
+ ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;

return handle;
}
@@ -574,18 +575,18 @@ int SYMEXPORT alpm_option_set_checkspace(alpm_handle_t *handle, int checkspace)
return 0;
}

-int SYMEXPORT alpm_option_set_default_sigverify(alpm_handle_t *handle, pgp_verify_t level)
+int SYMEXPORT alpm_option_set_default_siglevel(alpm_handle_t *handle,
+ alpm_siglevel_t level)
{
CHECK_HANDLE(handle, return -1);
- ASSERT(level != PM_PGP_VERIFY_UNKNOWN, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
- handle->sigverify = level;
+ handle->siglevel = level;
return 0;
}

-pgp_verify_t SYMEXPORT alpm_option_get_default_sigverify(alpm_handle_t *handle)
+alpm_siglevel_t SYMEXPORT alpm_option_get_default_siglevel(alpm_handle_t *handle)
{
- CHECK_HANDLE(handle, return PM_PGP_VERIFY_UNKNOWN);
- return handle->sigverify;
+ CHECK_HANDLE(handle, return -1);
+ return handle->siglevel;
}

/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index ae8c7c8..9e03858 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -69,7 +69,7 @@ struct __alpm_handle_t {
char *arch; /* Architecture of packages we should allow */
int usedelta; /* Download deltas if possible */
int checkspace; /* Check disk space before installing */
- pgp_verify_t sigverify; /* Default signature verification level */
+ alpm_siglevel_t siglevel; /* Default signature verification level */

/* error code */
enum _alpm_errno_t pm_errno;
diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h
index b602193..f76812b 100644
--- a/lib/libalpm/package.h
+++ b/lib/libalpm/package.h
@@ -151,7 +151,7 @@ void _alpm_pkg_free_trans(alpm_pkg_t *pkg);

alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile,
int full, const char *md5sum, const char *base64_sig,
- pgp_verify_t check_sig);
+ alpm_siglevel_t level);

int _alpm_pkg_cmp(const void *p1, const void *p2);
int _alpm_pkg_compare_versions(alpm_pkg_t *local_pkg, alpm_pkg_t *pkg);
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index 1ac9963..0dc15ad 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -117,9 +117,6 @@ static int init_gpgme(alpm_handle_t *handle)
}

sigdir = alpm_option_get_gpgdir(handle);
- if(!sigdir) {
- RET_ERR(handle, ALPM_ERR_SIG_MISSINGDIR, 1);
- }

/* calling gpgme_check_version() returns the current version and runs
* some internal library setup code */
@@ -196,23 +193,27 @@ error:
* Check the PGP signature for the given file path.
* If base64_sig is provided, it will be used as the signature data after
* decoding. If base64_sig is NULL, expect a signature file next to path
- * (e.g. "%s.sig"). The return value will be 0 if all checked signatures are
- * valid, 1 if there was some sort of problem (but not necessarily rejection),
- * and -1 if an error occurred while checking signatures. If 1 is returned,
- * pm_errno should be checked to see why the signatures did not pass muster.
+ * (e.g. "%s.sig").
+ *
+ * The return value will be 0 if nothing abnormal happened during the signature
+ * check, and -1 if an error occurred while checking signatures or if a
+ * signature could not be found; pm_errno will be set. Note that "abnormal"
+ * does not include a failed signature; the value in #result should be checked
+ * to determine if the signature(s) are good.
* @param handle the context handle
* @param path the full path to a file
* @param base64_sig optional PGP signature data in base64 encoding
- * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
+ * @result
+ * @return 0 in normal cases, -1 if the something failed in the check process
*/
int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
- const char *base64_sig)
+ const char *base64_sig, alpm_sigresult_t *result)
{
- int ret = 0;
+ int ret = -1, sigcount;
gpgme_error_t err;
gpgme_ctx_t ctx;
gpgme_data_t filedata, sigdata;
- gpgme_verify_result_t result;
+ gpgme_verify_result_t verify_result;
gpgme_signature_t gpgsig;
char *sigpath = NULL;
unsigned char *decoded_sigdata = NULL;
@@ -222,14 +223,18 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1);
}

+ if(!result) {
+ RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
+ }
+ result->count = 0;
+
if(!base64_sig) {
size_t len = strlen(path) + 5;
CALLOC(sigpath, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
snprintf(sigpath, len, "%s.sig", path);

if(!access(sigpath, R_OK) == 0) {
- FREE(sigpath);
- RET_ERR(handle, ALPM_ERR_SIG_UNKNOWN, -1);
+ /* sigcount is 0 */
}
}

@@ -251,7 +256,6 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
file = fopen(path, "rb");
if(file == NULL) {
handle->pm_errno = ALPM_ERR_NOT_A_FILE;
- ret = -1;
goto error;
}
err = gpgme_data_new_from_stream(&filedata, file);
@@ -264,7 +268,7 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
int decode_ret = decode_signature(base64_sig,
&decoded_sigdata, &data_len);
if(decode_ret) {
- ret = -1;
+ handle->pm_errno = ALPM_ERR_SIG_INVALID;
goto error;
}
err = gpgme_data_new_from_mem(&sigdata,
@@ -273,8 +277,7 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
/* file-based, it is on disk */
sigfile = fopen(sigpath, "rb");
if(sigfile == NULL) {
- handle->pm_errno = ALPM_ERR_NOT_A_FILE;
- ret = -1;
+ handle->pm_errno = ALPM_ERR_SIG_MISSING;
goto error;
}
err = gpgme_data_new_from_stream(&sigdata, sigfile);
@@ -284,16 +287,28 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
/* here's where the magic happens */
err = gpgme_op_verify(ctx, sigdata, filedata, NULL);
CHECK_ERR();
- result = gpgme_op_verify_result(ctx);
- gpgsig = result->signatures;
- if(!gpgsig) {
+ verify_result = gpgme_op_verify_result(ctx);
+ if(!verify_result->signatures) {
_alpm_log(handle, ALPM_LOG_DEBUG, "no signatures returned
");
- ret = -1;
+ handle->pm_errno = ALPM_ERR_SIG_MISSING;
goto error;
}
+ for(gpgsig = verify_result->signatures, sigcount = 0;
+ gpgsig; gpgsig = gpgsig->next, sigcount++);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned
", sigcount);
+
+ result->status = calloc(sigcount, sizeof(alpm_sigstatus_t));
+ result->uid = calloc(sigcount, sizeof(char*));
+ if(!result->status || !result->uid) {
+ handle->pm_errno = ALPM_ERR_MEMORY;
+ goto error;
+ }
+ result->count = sigcount;

- while(gpgsig) {
+ for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig;
+ gpgsig = gpgsig->next, sigcount++) {
alpm_list_t *summary_list, *summary;
+ alpm_sigstatus_t status;

_alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s
", gpgsig->fpr);
summary_list = list_sigsum(gpgsig->summary);
@@ -308,34 +323,53 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
string_validity(gpgsig->validity),
gpgme_strerror(gpgsig->validity_reason));

- /* Note: this is structured so any bad signature will set the return code
- * to a bad one, but good ones just leave the default value in place; e.g.
- * worst case wins out. */
+ err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0);
+ if(gpg_err_code(err) == GPG_ERR_EOF) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key
");
+ err = GPG_ERR_NO_ERROR;
+ } else {
+ CHECK_ERR();
+ if(key->uids) {
+ const char *uid = key->uids->uid;
+ STRDUP(result->uid[sigcount], uid,
+ handle->pm_errno = ALPM_ERR_MEMORY; goto error);
+ _alpm_log(handle, ALPM_LOG_DEBUG, "key user: %s
", uid);
+ }
+ gpgme_key_unref(key);
+ }
+
if(gpgsig->summary & GPGME_SIGSUM_VALID) {
/* definite good signature */
_alpm_log(handle, ALPM_LOG_DEBUG, "result: valid signature
");
+ status = ALPM_SIGSTATUS_VALID;
} else if(gpgsig->summary & GPGME_SIGSUM_GREEN) {
/* good signature */
_alpm_log(handle, ALPM_LOG_DEBUG, "result: green signature
");
+ status = ALPM_SIGSTATUS_VALID;
} else if(gpgsig->summary & GPGME_SIGSUM_RED) {
/* definite bad signature, error */
_alpm_log(handle, ALPM_LOG_DEBUG, "result: red signature
");
- handle->pm_errno = ALPM_ERR_SIG_INVALID;
- ret = 1;
+ status = ALPM_SIGSTATUS_BAD;
} else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) {
_alpm_log(handle, ALPM_LOG_DEBUG, "result: signature from unknown key
");
- handle->pm_errno = ALPM_ERR_SIG_UNKNOWN;
- ret = 1;
+ status = ALPM_SIGSTATUS_UNKNOWN;
+ } else if(gpgsig->summary & GPGME_SIGSUM_KEY_EXPIRED) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "result: key expired
");
+ status = ALPM_SIGSTATUS_BAD;
+ } else if(gpgsig->summary & GPGME_SIGSUM_SIG_EXPIRED) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "result: signature expired
");
+ status = ALPM_SIGSTATUS_BAD;
} else {
/* we'll capture everything else here */
_alpm_log(handle, ALPM_LOG_DEBUG, "result: invalid signature
");
- handle->pm_errno = ALPM_ERR_SIG_INVALID;
- ret = 1;
+ status = ALPM_SIGSTATUS_BAD;
}

- gpgsig = gpgsig->next;
+ result->status[sigcount] = status;
}

+ ret = 0;
+
error:
gpgme_data_release(sigdata);
gpgme_data_release(filedata);
@@ -362,18 +396,77 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
}
#endif

+int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path,
+ const char *base64_sig, int optional, int marginal, int unknown,
+ enum _alpm_errno_t invalid_err)
+{
+ alpm_sigresult_t result;
+ int ret;
+
+ memset(&result, 0, sizeof(result));
+
+ _alpm_log(handle, ALPM_LOG_DEBUG, "checking signatures for %s
", path);
+ ret = _alpm_gpgme_checksig(handle, path, base64_sig, &result);
+ if(ret && handle->pm_errno == ALPM_ERR_SIG_MISSING) {
+ if(optional) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "missing optional signature
");
+ handle->pm_errno = 0;
+ ret = 0;
+ } else {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "missing required signature
");
+ /* ret will already be -1 */
+ }
+ } else if(ret) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "signature check failed
");
+ /* ret will already be -1 */
+ } else {
+ int num;
+ for(num = result.count; num < result.count; num++) {
+ /* fallthrough in this case block is on purpose. if one allows unknown
+ * signatures, then a marginal signature should be allowed as well, and
+ * if neither of these are allowed we fall all the way through to bad. */
+ switch(result.status[num]) {
+ case ALPM_SIGSTATUS_VALID:
+ _alpm_log(handle, ALPM_LOG_DEBUG, "signature is valid
");
+ break;
+ case ALPM_SIGSTATUS_MARGINAL:
+ if(marginal) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "allowing marginal signature
");
+ break;
+ }
+ case ALPM_SIGSTATUS_UNKNOWN:
+ if(unknown) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "allowing unknown signature
");
+ break;
+ }
+ case ALPM_SIGSTATUS_BAD:
+ default:
+ _alpm_log(handle, ALPM_LOG_DEBUG, "signature is invalid
");
+ handle->pm_errno = invalid_err;
+ ret = -1;
+ }
+ }
+ }
+
+ free(result.status);
+ free(result.uid);
+ return ret;
+}
+
/**
* Check the PGP signature for the given package file.
* @param pkg the package to check
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
*/
-int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg)
+int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg,
+ alpm_sigresult_t *result)
{
ASSERT(pkg != NULL, return -1);
+ ASSERT(result != NULL, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
pkg->handle->pm_errno = 0;

return _alpm_gpgme_checksig(pkg->handle, alpm_pkg_get_filename(pkg),
- pkg->base64_sig);
+ pkg->base64_sig, result);
}

/**
@@ -381,12 +474,14 @@ int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg)
* @param db the database to check
* @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred)
*/
-int SYMEXPORT alpm_db_check_pgp_signature(alpm_db_t *db)
+int SYMEXPORT alpm_db_check_pgp_signature(alpm_db_t *db,
+ alpm_sigresult_t *result)
{
ASSERT(db != NULL, return -1);
+ ASSERT(result != NULL, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1));
db->handle->pm_errno = 0;

- return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL);
+ return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL, result);
}

/* vim: set ts=2 sw=2 noet: */
diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h
index b1b90d7..22f6357 100644
--- a/lib/libalpm/signing.h
+++ b/lib/libalpm/signing.h
@@ -22,7 +22,10 @@
#include "alpm.h"

int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
- const char *base64_sig);
+ const char *base64_sig, alpm_sigresult_t *result);
+int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path,
+ const char *base64_sig, int optional, int marginal, int unknown,
+ enum _alpm_errno_t invalid_err);

#endif /* _ALPM_SIGNING_H */

diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index d6b54ba..783c728 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -863,7 +863,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
int percent = (current * 100) / numtargs;
const char *filename;
char *filepath;
- pgp_verify_t check_sig;
+ alpm_siglevel_t level;

PROGRESS(trans, ALPM_TRANS_PROGRESS_INTEGRITY_START, "", percent,
numtargs, current);
@@ -874,7 +874,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
filename = alpm_pkg_get_filename(spkg);
filepath = _alpm_filecache_find(handle, filename);
alpm_db_t *sdb = alpm_pkg_get_db(spkg);
- check_sig = alpm_db_get_sigverify_level(sdb);
+ level = alpm_db_get_siglevel(sdb);

/* load the package file and replace pkgcache entry with it in the target list */
/* TODO: alpm_pkg_get_db() will not work on this target anymore */
@@ -882,7 +882,7 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data)
"replacing pkgcache entry with package file for target %s
",
spkg->name);
alpm_pkg_t *pkgfile =_alpm_pkg_load_internal(handle, filepath, 1, spkg->md5sum,
- spkg->base64_sig, check_sig);
+ spkg->base64_sig, level);
if(!pkgfile) {
errors++;
*data = alpm_list_add(*data, strdup(filename));
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index f2df260..3af3fa5 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -52,7 +52,7 @@ config_t *config_new(void)
newconfig->op = PM_OP_MAIN;
newconfig->logmask = ALPM_LOG_ERROR | ALPM_LOG_WARNING;
newconfig->configfile = strdup(CONFFILE);
- newconfig->sigverify = PM_PGP_VERIFY_UNKNOWN;
+ newconfig->siglevel = ALPM_SIG_USE_DEFAULT;

return newconfig;
}
@@ -222,17 +222,18 @@ int config_set_arch(const char *arch)
return 0;
}

-static pgp_verify_t option_verifysig(const char *value)
+static alpm_siglevel_t option_verifysig(const char *value)
{
- pgp_verify_t level;
+ alpm_siglevel_t level;
if(strcmp(value, "Always") == 0) {
- level = PM_PGP_VERIFY_ALWAYS;
+ level = ALPM_SIG_PACKAGE | ALPM_SIG_DATABASE;
} else if(strcmp(value, "Optional") == 0) {
- level = PM_PGP_VERIFY_OPTIONAL;
+ level = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL |
+ ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;
} else if(strcmp(value, "Never") == 0) {
- level = PM_PGP_VERIFY_NEVER;
+ level = 0;
} else {
- level = PM_PGP_VERIFY_UNKNOWN;
+ return -1;
}
pm_printf(ALPM_LOG_DEBUG, "config: VerifySig = %s (%d)
", value, level);
return level;
@@ -359,9 +360,9 @@ static int _parse_options(const char *key, char *value,
}
FREELIST(methods);
} else if(strcmp(key, "VerifySig") == 0) {
- pgp_verify_t level = option_verifysig(value);
- if(level != PM_PGP_VERIFY_UNKNOWN) {
- config->sigverify = level;
+ alpm_siglevel_t level = option_verifysig(value);
+ if(level != -1) {
+ config->siglevel = level;
} else {
pm_printf(ALPM_LOG_ERROR,
_("config file %s, line %d: directive '%s' has invalid value '%s'
"),
@@ -484,8 +485,8 @@ static int setup_libalpm(void)
alpm_option_set_cachedirs(handle, config->cachedirs);
}

- if(config->sigverify != PM_PGP_VERIFY_UNKNOWN) {
- alpm_option_set_default_sigverify(handle, config->sigverify);
+ if(config->siglevel != ALPM_SIG_USE_DEFAULT) {
+ alpm_option_set_default_siglevel(handle, config->siglevel);
}

if(config->xfercommand) {
@@ -518,7 +519,7 @@ struct section_t {
char *name;
int is_options;
/* db section option gathering */
- pgp_verify_t sigverify;
+ alpm_siglevel_t siglevel;
alpm_list_t *servers;
};

@@ -545,7 +546,7 @@ static int finish_section(struct section_t *section, int parse_options)
}

/* if we are not looking at options sections only, register a db */
- db = alpm_db_register_sync(config->handle, section->name, section->sigverify);
+ db = alpm_db_register_sync(config->handle, section->name, section->siglevel);
if(db == NULL) {
pm_printf(ALPM_LOG_ERROR, _("could not register '%s' database (%s)
"),
section->name, alpm_strerror(alpm_errno(config->handle)));
@@ -568,7 +569,7 @@ static int finish_section(struct section_t *section, int parse_options)
cleanup:
alpm_list_free(section->servers);
section->servers = NULL;
- section->sigverify = 0;
+ section->siglevel = ALPM_SIG_USE_DEFAULT;
free(section->name);
section->name = NULL;
return ret;
@@ -726,9 +727,9 @@ static int _parseconfig(const char *file, struct section_t *section,
}
section->servers = alpm_list_add(section->servers, strdup(value));
} else if(strcmp(key, "VerifySig") == 0) {
- pgp_verify_t level = option_verifysig(value);
- if(level != PM_PGP_VERIFY_UNKNOWN) {
- section->sigverify = level;
+ alpm_siglevel_t level = option_verifysig(value);
+ if(level != -1) {
+ section->siglevel = level;
} else {
pm_printf(ALPM_LOG_ERROR,
_("config file %s, line %d: directive '%s' has invalid value '%s'
"),
@@ -763,6 +764,7 @@ int parseconfig(const char *file)
int ret;
struct section_t section;
memset(&section, 0, sizeof(struct section_t));
+ section.siglevel = ALPM_SIG_USE_DEFAULT;
/* the config parse is a two-pass affair. We first parse the entire thing for
* the [options] section so we can get all default and path options set.
* Next, we go back and parse everything but [options]. */
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 64b911a..bce42ab 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -71,7 +71,7 @@ typedef struct __config_t {
unsigned short noask;
unsigned int ask;
alpm_transflag_t flags;
- pgp_verify_t sigverify;
+ alpm_siglevel_t siglevel;

/* conf file options */
/* I Love Candy! */
diff --git a/src/pacman/query.c b/src/pacman/query.c
index 045dc7f..5dff03f 100644
--- a/src/pacman/query.c
+++ b/src/pacman/query.c
@@ -551,7 +551,7 @@ int pacman_query(alpm_list_t *targets)
char *strname = alpm_list_getdata(i);

if(config->op_q_isfile) {
- alpm_pkg_load(config->handle, strname, 1, PM_PGP_VERIFY_OPTIONAL, &pkg);
+ alpm_pkg_load(config->handle, strname, 1, 0, &pkg);
} else {
pkg = alpm_db_get_pkg(db_local, strname);
}
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index ad6d5e5..5f67236 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -220,7 +220,7 @@ static int sync_cleancache(int level)
/* attempt to load the package, prompt removal on failures as we may have
* files here that aren't valid packages. we also don't need a full
* load of the package, just the metadata. */
- if(alpm_pkg_load(config->handle, path, 0, PM_PGP_VERIFY_NEVER, &localpkg) != 0
+ if(alpm_pkg_load(config->handle, path, 0, 0, &localpkg) != 0
|| localpkg == NULL) {
if(yesno(_("File %s does not seem to be a valid package, remove it?"),
path)) {
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index 95b17cc..11d00e7 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -42,7 +42,7 @@
int pacman_upgrade(alpm_list_t *targets)
{
alpm_list_t *i, *data = NULL;
- pgp_verify_t check_sig = alpm_option_get_default_sigverify(config->handle);
+ alpm_siglevel_t level = alpm_option_get_default_siglevel(config->handle);
int retval = 0;

if(targets == NULL) {
@@ -76,7 +76,7 @@ int pacman_upgrade(alpm_list_t *targets)
char *targ = alpm_list_getdata(i);
alpm_pkg_t *pkg;

- if(alpm_pkg_load(config->handle, targ, 1, check_sig, &pkg) != 0) {
+ if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) {
pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s
",
targ, alpm_strerror(alpm_errno(config->handle)));
trans_release();
diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c
index 08d8a55..a45efdc 100644
--- a/src/util/cleanupdelta.c
+++ b/src/util/cleanupdelta.c
@@ -71,11 +71,12 @@ static void checkdbs(const char *dbpath, alpm_list_t *dbnames) {
char syncdbpath[PATH_MAX];
alpm_db_t *db = NULL;
alpm_list_t *i;
+ const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;

for(i = dbnames; i; i = alpm_list_next(i)) {
char *dbname = alpm_list_getdata(i);
snprintf(syncdbpath, PATH_MAX, "%s/sync/%s", dbpath, dbname);
- db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL);
+ db = alpm_db_register_sync(handle, dbname, level);
if(db == NULL) {
fprintf(stderr, "error: could not register sync database (%s)
",
alpm_strerror(alpm_errno(handle)));
diff --git a/src/util/pactree.c b/src/util/pactree.c
index 7b87ac1..9b67863 100644
--- a/src/util/pactree.c
+++ b/src/util/pactree.c
@@ -124,6 +124,7 @@ static int register_syncs(void) {
FILE *fp;
char *ptr, *section = NULL;
char line[LINE_MAX];
+ const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;

fp = fopen(CONFFILE, "r");
if(!fp) {
@@ -147,7 +148,7 @@ static int register_syncs(void) {
section = strndup(&line[1], strlen(line) - 2);

if(section && strcmp(section, "options") != 0) {
- alpm_db_register_sync(handle, section, PM_PGP_VERIFY_OPTIONAL);
+ alpm_db_register_sync(handle, section, level);
}
}
}
diff --git a/src/util/testdb.c b/src/util/testdb.c
index 642890b..ee169df 100644
--- a/src/util/testdb.c
+++ b/src/util/testdb.c
@@ -148,10 +148,11 @@ static int check_syncdbs(alpm_list_t *dbnames) {
int ret = 0;
alpm_db_t *db = NULL;
alpm_list_t *i, *pkglist, *syncpkglist = NULL;
+ const alpm_siglevel_t level = ALPM_SIG_DATABASE | ALPM_SIG_DATABASE_OPTIONAL;

for(i = dbnames; i; i = alpm_list_next(i)) {
char *dbname = alpm_list_getdata(i);
- db = alpm_db_register_sync(handle, dbname, PM_PGP_VERIFY_OPTIONAL);
+ db = alpm_db_register_sync(handle, dbname, level);
if(db == NULL) {
fprintf(stderr, "error: could not register sync database (%s)
",
alpm_strerror(alpm_errno(handle)));
diff --git a/src/util/testpkg.c b/src/util/testpkg.c
index 03234ed..ac2dde2 100644
--- a/src/util/testpkg.c
+++ b/src/util/testpkg.c
@@ -43,6 +43,7 @@ int main(int argc, char *argv[])
alpm_handle_t *handle;
enum _alpm_errno_t err;
alpm_pkg_t *pkg = NULL;
+ const alpm_siglevel_t level = ALPM_SIG_PACKAGE | ALPM_SIG_PACKAGE_OPTIONAL;

if(argc != 2) {
fprintf(stderr, "usage: %s <package file>
", BASENAME);
@@ -58,7 +59,7 @@ int main(int argc, char *argv[])
/* let us get log messages from libalpm */
alpm_option_set_logcb(handle, output_cb);

- if(alpm_pkg_load(handle, argv[1], 1, PM_PGP_VERIFY_OPTIONAL, &pkg) == -1
+ if(alpm_pkg_load(handle, argv[1], 1, level, &pkg) == -1
|| pkg == NULL) {
err = alpm_errno(handle);
switch(err) {
--
1.7.6
 

Thread Tools




All times are GMT. The time now is 01:02 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org