From 31b9b264c1df2fc9a4f5c846d5d1735b5fbd7050 Mon Sep 17 00:00:00 2001 From: Allan McRae Date: Sat, 3 Nov 2012 00:21:48 +1000 Subject: Check keys are in keyring before package validation Keys used to create signatures are checked for presence in the keyring before package validation is performed. Signed-off-by: Allan McRae Conflicts: lib/libalpm/alpm.h Signed-off-by: Allan McRae --- lib/libalpm/alpm.h | 13 +++++++-- lib/libalpm/sync.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/pacman/callback.c | 13 +++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index b6818407..729a4c81 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -361,7 +361,15 @@ typedef enum _alpm_event_t { * The requiring package and its dependency are passed to the callback */ ALPM_EVENT_OPTDEP_REQUIRED, /** A configured repository database is missing */ - ALPM_EVENT_DATABASE_MISSING + ALPM_EVENT_DATABASE_MISSING, + /** Checking keys used to create signatures are in keyring. */ + ALPM_EVENT_KEYRING_START, + /** Keyring checking is finished. */ + ALPM_EVENT_KEYRING_DONE, + /** Downloading missing keys into keyring. */ + ALPM_EVENT_KEY_DOWNLOAD_START, + /** Key downloading is finished. */ + ALPM_EVENT_KEY_DOWNLOAD_DONE } alpm_event_t; /** Event callback */ @@ -395,7 +403,8 @@ typedef enum _alpm_progress_t { ALPM_PROGRESS_CONFLICTS_START, ALPM_PROGRESS_DISKSPACE_START, ALPM_PROGRESS_INTEGRITY_START, - ALPM_PROGRESS_LOAD_START + ALPM_PROGRESS_LOAD_START, + ALPM_PROGRESS_KEYRING_START } alpm_progress_t; /** Progress callback */ diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 6a5cab63..82beb8a2 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -969,6 +969,76 @@ finish: return errors; } +static int check_keyring(alpm_handle_t *handle) +{ + size_t current = 0, numtargs; + alpm_list_t *i, *errors = NULL; + + EVENT(handle, ALPM_EVENT_KEYRING_START, NULL, NULL); + + numtargs = alpm_list_count(handle->trans->add); + + for(i = handle->trans->add; i; i = i->next, current++) { + alpm_pkg_t *pkg = i->data; + alpm_siglevel_t level; + + int percent = (current * 100) / numtargs; + PROGRESS(handle, ALPM_PROGRESS_KEYRING_START, "", percent, + numtargs, current); + + if(pkg->origin == ALPM_PKG_FROM_FILE) { + continue; /* pkg_load() has been already called, this package is valid */ + } + + level = alpm_db_get_siglevel(alpm_pkg_get_db(pkg)); + if((level & ALPM_SIG_PACKAGE) && pkg->base64_sig) { + unsigned char *decoded_sigdata = NULL; + size_t data_len; + int decode_ret = _alpm_decode_signature(pkg->base64_sig, + &decoded_sigdata, &data_len); + if(decode_ret == 0) { + alpm_list_t *keys = NULL; + if(_alpm_extract_keyid(handle, pkg->name, decoded_sigdata, + data_len, &keys) == 0) { + alpm_list_t *k; + for(k = keys; k; k = k->next) { + char *key = k->data; + if(_alpm_key_in_keychain(handle, key) == 0) { + if(!alpm_list_find_str(errors, key)) { + errors = alpm_list_add(errors, strdup(key)); + } + } + } + FREELIST(keys); + } + } + } + } + + PROGRESS(handle, ALPM_PROGRESS_KEYRING_START, "", 100, + numtargs, current); + EVENT(handle, ALPM_EVENT_KEYRING_DONE, NULL, NULL); + + if(errors) { + EVENT(handle, ALPM_EVENT_KEY_DOWNLOAD_START, NULL, NULL); + int fail = 0; + alpm_list_t *k; + for(k = errors; k; k = k->next) { + char *key = k->data; + if(_alpm_key_import(handle, key) == -1) { + fail = 1; + } + } + EVENT(handle, ALPM_EVENT_KEY_DOWNLOAD_DONE, NULL, NULL); + if(fail) { + _alpm_log(handle, ALPM_LOG_ERROR, _("required key missing from keyring\n")); + return -1; + } + } + + return 0; +} + static int check_validity(alpm_handle_t *handle, size_t total, size_t total_bytes) { @@ -1134,6 +1204,13 @@ int _alpm_sync_commit(alpm_handle_t *handle, alpm_list_t **data) return -1; } +#if HAVE_LIBGPGME + /* make sure all required signatures are in keyring */ + if(check_keyring(handle)) { + return -1; + } +#endif + /* get the total size of all packages so we can adjust the progress bar more * realistically if there are small and huge packages involved */ for(i = trans->add; i; i = i->next) { diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 93418db3..edd5b398 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -212,6 +212,14 @@ void cb_event(alpm_event_t event, void *data1, void *data2) printf(_("checking package integrity...\n")); } break; + case ALPM_EVENT_KEYRING_START: + if(config->noprogressbar) { + printf(_("checking keyring...\n")); + } + break; + case ALPM_EVENT_KEY_DOWNLOAD_START: + printf(_("downloading required keys...\n")); + break; case ALPM_EVENT_LOAD_START: if(config->noprogressbar) { printf(_("loading package files...\n")); @@ -259,6 +267,8 @@ void cb_event(alpm_event_t event, void *data1, void *data2) case ALPM_EVENT_RESOLVEDEPS_DONE: case ALPM_EVENT_INTERCONFLICTS_DONE: case ALPM_EVENT_INTEGRITY_DONE: + case ALPM_EVENT_KEYRING_DONE: + case ALPM_EVENT_KEY_DOWNLOAD_DONE: case ALPM_EVENT_LOAD_DONE: case ALPM_EVENT_DELTA_INTEGRITY_DONE: case ALPM_EVENT_DELTA_PATCHES_DONE: @@ -446,6 +456,9 @@ void cb_progress(alpm_progress_t event, const char *pkgname, int percent, case ALPM_PROGRESS_INTEGRITY_START: opr = _("checking package integrity"); break; + case ALPM_PROGRESS_KEYRING_START: + opr = _("checking keys in keyring"); + break; case ALPM_PROGRESS_LOAD_START: opr = _("loading package files"); break; -- cgit v1.2.3-70-g09d2