summaryrefslogtreecommitdiff
path: root/lib/libalpm/be_sync.c
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-06-07 17:29:55 -0500
committerDan McGee <dan@archlinux.org>2011-06-24 02:34:50 -0500
commitdb3b86e7f34f4c3ccb42e98465f2069aa642a85f (patch)
tree34ee212bbcc0385674908f0d427779732f9aadfb /lib/libalpm/be_sync.c
parent94d22f93096e210cd00d2e9c97c65f77d49ae387 (diff)
downloadpacman-db3b86e7f34f4c3ccb42e98465f2069aa642a85f.tar.xz
Do database signature checking at load time
This is the ideal place to do it as all clients should be checking the return value and ensuring there are no errors. This is similar to pkg_load(). We also add an additional step of validation after we download a new database; a subsequent '-y' operation can potentially invalidate the original check at registration time. Note that this implementation is still a bit naive; if a signature is invalid it is currently impossible to refresh and re-download the file without manually deleting it first. Similarly, if one downloads a database and the check fails, the database object is still there and can be used. These shortcomings will be addressed in a future commit. Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib/libalpm/be_sync.c')
-rw-r--r--lib/libalpm/be_sync.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
index e5fc6a70..2cf90544 100644
--- a/lib/libalpm/be_sync.c
+++ b/lib/libalpm/be_sync.c
@@ -20,7 +20,9 @@
#include "config.h"
+#include <errno.h>
#include <sys/stat.h>
+#include <unistd.h>
/* libarchive */
#include <archive.h>
@@ -65,6 +67,37 @@ static char *get_sync_dir(pmhandle_t *handle)
return syncpath;
}
+static int sync_db_validate(pmdb_t *db)
+{
+ /* this takes into account the default verification level if UNKNOWN
+ * was assigned to this db */
+ pgp_verify_t check_sig = _alpm_db_get_sigverify_level(db);
+
+ if(check_sig != PM_PGP_VERIFY_NEVER) {
+ int ret;
+ const char *dbpath = _alpm_db_path(db);
+ if(!dbpath) {
+ /* pm_errno set in _alpm_db_path() */
+ return -1;
+ }
+
+ /* we can skip any validation if the database doesn't exist */
+ if(access(dbpath, R_OK) != 0 && errno == ENOENT) {
+ return 0;
+ }
+
+ _alpm_log(db->handle, PM_LOG_DEBUG, "checking signature for %s\n",
+ 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);
+ }
+ }
+
+ return 0;
+}
+
/** Update a package database
*
* An update of the package database \a db will be attempted. Unless
@@ -144,6 +177,15 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
if(ret == 0 && (check_sig == PM_PGP_VERIFY_ALWAYS ||
check_sig == PM_PGP_VERIFY_OPTIONAL)) {
+ /* an existing sig file is no good at this point */
+ char *sigpath = _alpm_db_sig_path(db);
+ if(!sigpath) {
+ ret = -1;
+ break;
+ }
+ unlink(sigpath);
+ free(sigpath);
+
int errors_ok = (check_sig == PM_PGP_VERIFY_OPTIONAL);
/* if we downloaded a DB, we want the .sig from the same server */
snprintf(fileurl, len, "%s/%s.db.sig", server, db->treename);
@@ -173,6 +215,11 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
/* Cache needs to be rebuilt */
_alpm_db_free_pkgcache(db);
+ if(sync_db_validate(db)) {
+ /* pm_errno should be set */
+ ret = -1;
+ }
+
cleanup:
free(syncpath);
@@ -523,7 +570,8 @@ struct db_operations sync_db_ops = {
.version = sync_db_version,
};
-pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename)
+pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename,
+ pgp_verify_t level)
{
pmdb_t *db;
@@ -535,6 +583,12 @@ pmdb_t *_alpm_db_register_sync(pmhandle_t *handle, const char *treename)
}
db->ops = &sync_db_ops;
db->handle = handle;
+ db->pgp_verify = level;
+
+ if(sync_db_validate(db)) {
+ _alpm_db_free(db);
+ return NULL;
+ }
handle->dbs_sync = alpm_list_add(handle->dbs_sync, db);
return db;