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 <[email protected]>
---
 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

Reply via email to