summaryrefslogtreecommitdiff
path: root/lib
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 /lib
parent198154962beca8707b19f5efb773f1a3ad10e154 (diff)
downloadpacman-31b9b264c1df2fc9a4f5c846d5d1735b5fbd7050.tar.xz
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/libalpm/alpm.h13
-rw-r--r--lib/libalpm/sync.c77
2 files changed, 88 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) {