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@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