[pacman-dev] [PATCH v3 1/3] signing: move key import confirmation before key_search

Jonas Witschel diabonas at archlinux.org
Wed Oct 2 14:40:54 UTC 2019


Ask the user whether they want to import a missing key before even doing
a search on the keyserver. This will be useful for getting Web Key
Directory support in place: for a WKD, looking up and importing a key
are a single action, so the current key_search -> QUESTION -> key_import
workflow does not apply.

Since only the ID of the package signing key is available before
key_search, we display the packager variable in addition to the key ID
for user convenience.

Signed-off-by: Jonas Witschel <diabonas at archlinux.org>
---
 lib/libalpm/be_package.c | 12 +++++++++-
 lib/libalpm/signing.c    | 50 ++++++++++++++++++++++------------------
 lib/libalpm/signing.h    |  2 +-
 lib/libalpm/sync.c       | 22 +++++++++++++++---
 src/pacman/callback.c    | 13 ++---------
 5 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index ac911bdb..6c93d12b 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -731,6 +731,8 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful
 {
 	int validation = 0;
 	char *sigpath;
+	alpm_pkg_t *pkg_temp;
+	char *packager;
 
 	CHECK_HANDLE(handle, return -1);
 	ASSERT(pkg != NULL, RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
@@ -755,9 +757,17 @@ int SYMEXPORT alpm_pkg_load(alpm_handle_t *handle, const char *filename, int ful
 				for(k = keys; k; k = k->next) {
 					char *key = k->data;
 					if(_alpm_key_in_keychain(handle, key) == 0) {
-						if(_alpm_key_import(handle, key) == -1) {
+						pkg_temp = _alpm_pkg_load_internal(handle, filename, full);
+						if(pkg_temp) {
+							packager = pkg_temp->packager;
+							_alpm_pkg_free(pkg_temp);
+						} else {
+							packager = NULL;
+						}
+						if(_alpm_key_import(handle, packager, key) == -1) {
 							fail = 1;
 						}
+						free(packager);
 					}
 				}
 				FREELIST(keys);
diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index 92598b0e..c1ae5354 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -433,42 +433,45 @@ gpg_error:
 /**
  * Import a key defined by a fingerprint into the local keyring.
  * @param handle the context handle
+ * @param uid a user ID of the key to import
  * @param fpr the fingerprint key ID to import
  * @return 0 on success, -1 on error
  */
-int _alpm_key_import(alpm_handle_t *handle, const char *fpr)
+int _alpm_key_import(alpm_handle_t *handle, const char *uid, const char *fpr)
 {
 	int ret = -1;
 	alpm_pgpkey_t fetch_key;
+
+	if(_alpm_access(handle, handle->gpgdir, "pubring.gpg", W_OK)) {
+		/* no chance of import succeeding if pubring isn't writable */
+		_alpm_log(handle, ALPM_LOG_ERROR, _("keyring is not writable\n"));
+		return -1;
+	}
+
 	memset(&fetch_key, 0, sizeof(fetch_key));
+	STRDUP(fetch_key.uid, uid, return -1);
+	STRDUP(fetch_key.fingerprint, fpr, return -1);
 
-	if(key_search(handle, fpr, &fetch_key) == 1) {
-		_alpm_log(handle, ALPM_LOG_DEBUG,
-				"unknown key, found %s on keyserver\n", fetch_key.uid);
-		if(!_alpm_access(handle, handle->gpgdir, "pubring.gpg", W_OK)) {
-			alpm_question_import_key_t question = {
+	alpm_question_import_key_t question = {
 				.type = ALPM_QUESTION_IMPORT_KEY,
 				.import = 0,
 				.key = &fetch_key
 			};
-			QUESTION(handle, &question);
-			if(question.import) {
-				if(key_import(handle, &fetch_key) == 0) {
-					ret = 0;
-				} else {
-					_alpm_log(handle, ALPM_LOG_ERROR,
-							_("key \"%s\" could not be imported\n"), fetch_key.uid);
-				}
+	QUESTION(handle, &question);
+	if(question.import) {
+		if(key_search(handle, fpr, &fetch_key) == 1) {
+			_alpm_log(handle, ALPM_LOG_DEBUG,
+					_("key \"%s\" on keyserver\n"), fetch_key.uid);
+			if(key_import(handle, &fetch_key) == 0) {
+				ret = 0;
+			} else {
+				_alpm_log(handle, ALPM_LOG_ERROR,
+						_("key \"%s\" could not be imported\n"), fetch_key.uid);
 			}
 		} else {
-			/* keyring directory was not writable, so we don't even try */
-			_alpm_log(handle, ALPM_LOG_WARNING,
-					_("key %s, \"%s\" found on keyserver, keyring is not writable\n"),
-					fetch_key.fingerprint, fetch_key.uid);
+			_alpm_log(handle, ALPM_LOG_ERROR,
+					_("key \"%s\" could not be looked up remotely\n"), fpr);
 		}
-	} else {
-		_alpm_log(handle, ALPM_LOG_ERROR,
-				_("key \"%s\" could not be looked up remotely\n"), fpr);
 	}
 	gpgme_key_unref(fetch_key.data);
 
@@ -714,7 +717,8 @@ int _alpm_key_in_keychain(alpm_handle_t UNUSED *handle, const char UNUSED *fpr)
 	return -1;
 }
 
-int _alpm_key_import(alpm_handle_t UNUSED *handle, const char UNUSED *fpr)
+int _alpm_key_import(alpm_handle_t UNUSED *handle, const char UNUSED *uid,
+		const char UNUSED *fpr)
 {
 	return -1;
 }
@@ -900,7 +904,7 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
 				_alpm_log(handle, ALPM_LOG_ERROR,
 						_("%s: key \"%s\" is unknown\n"), identifier, name);
 
-				if(_alpm_key_import(handle, result->key.fingerprint) == 0) {
+				if(_alpm_key_import(handle, result->key.uid, result->key.fingerprint) == 0) {
 					retry = 1;
 				}
 
diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h
index f8b84b94..36b64384 100644
--- a/lib/libalpm/signing.h
+++ b/lib/libalpm/signing.h
@@ -32,6 +32,6 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
 		alpm_siglist_t *siglist, int optional, int marginal, int unknown);
 
 int _alpm_key_in_keychain(alpm_handle_t *handle, const char *fpr);
-int _alpm_key_import(alpm_handle_t *handle, const char *fpr);
+int _alpm_key_import(alpm_handle_t *handle, const char *uid, const char *fpr);
 
 #endif /* ALPM_SIGNING_H */
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index cbd072e6..dd695877 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -47,6 +47,12 @@
 #include "diskspace.h"
 #include "signing.h"
 
+struct keyinfo_t {
+       char* uid;
+       char* keyid;
+};
+
+
 /** Check for new version of pkg in sync repos
  * (only the first occurrence is considered in sync)
  */
@@ -872,6 +878,7 @@ static int check_keyring(alpm_handle_t *handle)
 	size_t current = 0, numtargs;
 	alpm_list_t *i, *errors = NULL;
 	alpm_event_t event;
+	struct keyinfo_t *keyinfo;
 
 	event.type = ALPM_EVENT_KEYRING_START;
 	EVENT(handle, &event);
@@ -905,7 +912,13 @@ static int check_keyring(alpm_handle_t *handle)
 						char *key = k->data;
 						if(!alpm_list_find_str(errors, key) &&
 								_alpm_key_in_keychain(handle, key) == 0) {
-							errors = alpm_list_add(errors, strdup(key));
+							keyinfo = malloc(sizeof(struct keyinfo_t));
+							if(!keyinfo) {
+								break;
+							}
+							keyinfo->uid = strdup(pkg->packager);
+							keyinfo->keyid = strdup(key);
+							errors = alpm_list_add(errors, keyinfo);
 						}
 					}
 					FREELIST(keys);
@@ -926,10 +939,13 @@ static int check_keyring(alpm_handle_t *handle)
 		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) {
+			keyinfo = k->data;
+				if(_alpm_key_import(handle, keyinfo->uid, keyinfo->keyid) == -1) {
 				fail = 1;
 			}
+			free(keyinfo->uid);
+			free(keyinfo->keyid);
+
 		}
 		event.type = ALPM_EVENT_KEY_DOWNLOAD_DONE;
 		EVENT(handle, &event);
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index fc4ce875..25528100 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -456,17 +456,8 @@ void cb_question(alpm_question_t *question)
 		case ALPM_QUESTION_IMPORT_KEY:
 			{
 				alpm_question_import_key_t *q = &question->import_key;
-				char created[12];
-				time_t time = (time_t)q->key->created;
-				strftime(created, 12, "%Y-%m-%d", localtime(&time));
-
-				if(q->key->revoked) {
-					q->import = yesno(_("Import PGP key %u%c/%s, \"%s\", created: %s (revoked)?"),
-							q->key->length, q->key->pubkey_algo, q->key->fingerprint, q->key->uid, created);
-				} else {
-					q->import = yesno(_("Import PGP key %u%c/%s, \"%s\", created: %s?"),
-							q->key->length, q->key->pubkey_algo, q->key->fingerprint, q->key->uid, created);
-				}
+				q->import = yesno(_("Import PGP key %s, \"%s\"?"),
+						q->key->fingerprint, q->key->uid);
 			}
 			break;
 	}
-- 
2.23.0


More information about the pacman-dev mailing list