[pacman-dev] [PATCH 5/8] Check keys are in keyring before package validation

Allan McRae allan at archlinux.org
Fri Nov 2 11:28:19 EDT 2012


Keys used to create signatures are checked for presence in the keyring
before package validation is performed.

Signed-off-by: Allan McRae <allan at archlinux.org>
---
 lib/libalpm/alpm.h    |  9 +++++--
 lib/libalpm/sync.c    | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pacman/callback.c |  9 +++++++
 3 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 1d6a8c6..8f3cfb0 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -347,7 +347,11 @@ typedef enum _alpm_event_t {
 	/** Disk space usage will be computed for a package */
 	ALPM_EVENT_DISKSPACE_START,
 	/** Disk space usage was computed for a package */
-	ALPM_EVENT_DISKSPACE_DONE
+	ALPM_EVENT_DISKSPACE_DONE,
+	/** Checking keys used to create signatures are in keyring. */
+	ALPM_EVENT_KEYRING_START,
+	/** Keyring checking is finished. */
+	ALPM_EVENT_KEYRING_DONE
 } alpm_event_t;
 
 /** Event callback */
@@ -381,7 +385,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 ca6b507..dcfefd1 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -969,6 +969,71 @@ 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(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) {
+							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) {
+		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;
+			}
+		}
+		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 +1199,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 01c6b61..4e2f153 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -208,6 +208,11 @@ 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_LOAD_START:
 			if(config->noprogressbar) {
 				printf(_("loading package files...\n"));
@@ -245,6 +250,7 @@ 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_LOAD_DONE:
 		case ALPM_EVENT_DELTA_INTEGRITY_DONE:
 		case ALPM_EVENT_DELTA_PATCHES_DONE:
@@ -432,6 +438,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;
-- 
1.8.0



More information about the pacman-dev mailing list