summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan McRae <allan@archlinux.org>2012-11-03 00:21:48 +1000
committerAllan McRae <allan@archlinux.org>2013-02-09 12:43:37 +1000
commit31b9b264c1df2fc9a4f5c846d5d1735b5fbd7050 (patch)
treeba3ebb711439a9f9ecf39618d1876bd147e14f69
parent198154962beca8707b19f5efb773f1a3ad10e154 (diff)
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 <allan@archlinux.org> Conflicts: lib/libalpm/alpm.h Signed-off-by: Allan McRae <allan@archlinux.org>
-rw-r--r--lib/libalpm/alpm.h13
-rw-r--r--lib/libalpm/sync.c77
-rw-r--r--src/pacman/callback.c13
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;