[pacman-dev] [PATCH 1/5] Remove trans is NULL check in QUESTION/EVENT/PROGRESS macros
trans cannot (and better not) be NULL at any point when these are being called. Signed-off-by: Dan McGee <dan@archlinux.org> --- lib/libalpm/trans.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h index 9a60e71..6d5c08d 100644 --- a/lib/libalpm/trans.h +++ b/lib/libalpm/trans.h @@ -49,19 +49,19 @@ struct __alpm_trans_t { #define EVENT(t, e, d1, d2) \ do { \ - if((t) && (t)->cb_event) { \ + if((t)->cb_event) { \ (t)->cb_event(e, d1, d2); \ } \ } while(0) #define QUESTION(t, q, d1, d2, d3, r) \ do { \ - if((t) && (t)->cb_conv) { \ + if((t)->cb_conv) { \ (t)->cb_conv(q, d1, d2, d3, r); \ } \ } while(0) #define PROGRESS(t, e, p, per, h, r) \ do { \ - if((t) && (t)->cb_progress) { \ + if((t)->cb_progress) { \ (t)->cb_progress(e, p, per, h, r); \ } \ } while(0) -- 1.7.6
I was trying to take a shortcut and not introduce a wrapper struct for the signature results, so packed it all into alpm_sigresult_t in the first iteration. However, this is painful when one wants to add new fields or only return information regarding a single signature. Refactor the type into a few components which are exposed to the end user, and will allow a lot more future flexibility. This also exposes more information regarding the key to the frontend than was previously available. The "private" void *data pointer is used by the library to store the actual key object returned by gpgme; it is typed this way so the frontend has no expectations of what is there, and so we don't have any hard gpgme requirement in our public API. Signed-off-by: Dan McGee <dan@archlinux.org> --- lib/libalpm/alpm.h | 28 +++++++++++---- lib/libalpm/signing.c | 94 ++++++++++++++++++++++++------------------------ lib/libalpm/signing.h | 2 +- src/pacman/package.c | 8 ++-- src/pacman/util.c | 15 ++++---- src/pacman/util.h | 2 +- 6 files changed, 82 insertions(+), 67 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index fc8f0bc..c94cdf7 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -209,16 +209,30 @@ typedef struct _alpm_backup_t { char *hash; } alpm_backup_t; +typedef struct _alpm_pgpkey_t { + void *data; + char *fingerprint; + char *uid; + char *name; + char *email; + time_t created; + time_t expires; +} alpm_pgpkey_t; + /** Signature result. Contains the number of signatures found and pointers to * arrays containing key and status info. All contained arrays have size * #count.*/ typedef struct _alpm_sigresult_t { - int count; - alpm_sigstatus_t *status; - alpm_sigvalidity_t *validity; - char **uid; + alpm_pgpkey_t key; + alpm_sigstatus_t status; + alpm_sigvalidity_t validity; } alpm_sigresult_t; +typedef struct _alpm_siglist_t { + size_t count; + alpm_sigresult_t *results; +} alpm_siglist_t; + /* * Logging facilities */ @@ -776,11 +790,11 @@ alpm_list_t *alpm_pkg_unused_deltas(alpm_pkg_t *pkg); * Signatures */ -int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_sigresult_t *result); +int alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, alpm_siglist_t *siglist); -int alpm_db_check_pgp_signature(alpm_db_t *db, alpm_sigresult_t *result); +int alpm_db_check_pgp_signature(alpm_db_t *db, alpm_siglist_t *siglist); -int alpm_sigresult_cleanup(alpm_sigresult_t *result); +int alpm_siglist_cleanup(alpm_siglist_t *siglist); /* * Groups diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index 4428b54..8af8a99 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -195,16 +195,16 @@ error: * The return value will be 0 if nothing abnormal happened during the signature * check, and -1 if an error occurred while checking signatures or if a * signature could not be found; pm_errno will be set. Note that "abnormal" - * does not include a failed signature; the value in #result should be checked + * does not include a failed signature; the value in #siglist should be checked * to determine if the signature(s) are good. * @param handle the context handle * @param path the full path to a file * @param base64_sig optional PGP signature data in base64 encoding - * @result + * @param siglist a pointer to storage for signature results * @return 0 in normal cases, -1 if the something failed in the check process */ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, - const char *base64_sig, alpm_sigresult_t *result) + const char *base64_sig, alpm_siglist_t *siglist) { int ret = -1, sigcount; gpgme_error_t err; @@ -220,10 +220,10 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1); } - if(!result) { + if(!siglist) { RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1); } - result->count = 0; + siglist->count = 0; if(!base64_sig) { sigpath = _alpm_sigpath(handle, path); @@ -293,14 +293,9 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, gpgsig; gpgsig = gpgsig->next, sigcount++); _alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned\n", sigcount); - result->status = calloc(sigcount, sizeof(alpm_sigstatus_t)); - result->validity = calloc(sigcount, sizeof(alpm_sigvalidity_t)); - result->uid = calloc(sigcount, sizeof(char*)); - if(!result->status || !result->validity || !result->uid) { - handle->pm_errno = ALPM_ERR_MEMORY; - goto error; - } - result->count = sigcount; + CALLOC(siglist->results, sigcount, sizeof(alpm_sigresult_t), + handle->pm_errno = ALPM_ERR_MEMORY; goto error); + siglist->count = sigcount; for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig; gpgsig = gpgsig->next, sigcount++) { @@ -308,6 +303,7 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, alpm_sigstatus_t status; alpm_sigvalidity_t validity; gpgme_key_t key; + alpm_sigresult_t *result; _alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr); summary_list = list_sigsum(gpgsig->summary); @@ -322,21 +318,26 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, string_validity(gpgsig->validity), gpgme_strerror(gpgsig->validity_reason)); + result = siglist->results + sigcount; err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0); if(gpg_err_code(err) == GPG_ERR_EOF) { _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); err = GPG_ERR_NO_ERROR; - STRDUP(result->uid[sigcount], gpgsig->fpr, + /* we dupe the fpr in this case since we have no key to point at */ + STRDUP(result->key.fingerprint, gpgsig->fpr, handle->pm_errno = ALPM_ERR_MEMORY; goto error); } else { CHECK_ERR(); if(key->uids) { - const char *uid = key->uids->uid; - STRDUP(result->uid[sigcount], uid, - handle->pm_errno = ALPM_ERR_MEMORY; goto error); - _alpm_log(handle, ALPM_LOG_DEBUG, "key user: %s\n", uid); + result->key.data = key; + result->key.fingerprint = key->subkeys->fpr; + result->key.uid = key->uids->uid; + result->key.name = key->uids->name; + result->key.email = key->uids->email; + result->key.created = key->subkeys->timestamp; + result->key.expires = key->subkeys->expires; + _alpm_log(handle, ALPM_LOG_DEBUG, "key user: %s\n", key->uids->uid); } - gpgme_key_unref(key); } switch(gpg_err_code(gpgsig->status)) { @@ -383,8 +384,8 @@ int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, validity = ALPM_SIGVALIDITY_NEVER; } - result->status[sigcount] = status; - result->validity[sigcount] = validity; + result->status = status; + result->validity = validity; } ret = 0; @@ -440,13 +441,13 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, const char *base64_sig, int optional, int marginal, int unknown, enum _alpm_errno_t invalid_err) { - alpm_sigresult_t result; + alpm_siglist_t siglist; int ret; - memset(&result, 0, sizeof(result)); + memset(&siglist, 0, sizeof(alpm_siglist_t)); _alpm_log(handle, ALPM_LOG_DEBUG, "checking signatures for %s\n", path); - ret = _alpm_gpgme_checksig(handle, path, base64_sig, &result); + ret = _alpm_gpgme_checksig(handle, path, base64_sig, &siglist); if(ret && handle->pm_errno == ALPM_ERR_SIG_MISSING) { if(optional) { _alpm_log(handle, ALPM_LOG_DEBUG, "missing optional signature\n"); @@ -460,13 +461,13 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, _alpm_log(handle, ALPM_LOG_DEBUG, "signature check failed\n"); /* ret will already be -1 */ } else { - int num; - for(num = 0; !ret && num < result.count; num++) { - switch(result.status[num]) { + size_t num; + for(num = 0; !ret && num < siglist.count; num++) { + switch(siglist.results[num].status) { case ALPM_SIGSTATUS_VALID: case ALPM_SIGSTATUS_KEY_EXPIRED: _alpm_log(handle, ALPM_LOG_DEBUG, "signature is valid\n"); - switch(result.validity[num]) { + switch(siglist.results[num].validity) { case ALPM_SIGVALIDITY_FULL: _alpm_log(handle, ALPM_LOG_DEBUG, "signature is fully trusted\n"); break; @@ -502,7 +503,7 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, } } - alpm_sigresult_cleanup(&result); + alpm_siglist_cleanup(&siglist); return ret; } @@ -512,14 +513,14 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) */ int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, - alpm_sigresult_t *result) + alpm_siglist_t *siglist) { ASSERT(pkg != NULL, return -1); - ASSERT(result != NULL, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(siglist != NULL, RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1)); pkg->handle->pm_errno = 0; return _alpm_gpgme_checksig(pkg->handle, alpm_pkg_get_filename(pkg), - pkg->base64_sig, result); + pkg->base64_sig, siglist); } /** @@ -528,30 +529,29 @@ int SYMEXPORT alpm_pkg_check_pgp_signature(alpm_pkg_t *pkg, * @return a int value : 0 (valid), 1 (invalid), -1 (an error occurred) */ int SYMEXPORT alpm_db_check_pgp_signature(alpm_db_t *db, - alpm_sigresult_t *result) + alpm_siglist_t *siglist) { ASSERT(db != NULL, return -1); - ASSERT(result != NULL, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); + ASSERT(siglist != NULL, RET_ERR(db->handle, ALPM_ERR_WRONG_ARGS, -1)); db->handle->pm_errno = 0; - return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL, result); + return _alpm_gpgme_checksig(db->handle, _alpm_db_path(db), NULL, siglist); } -int SYMEXPORT alpm_sigresult_cleanup(alpm_sigresult_t *result) +int SYMEXPORT alpm_siglist_cleanup(alpm_siglist_t *siglist) { - ASSERT(result != NULL, return -1); - /* Because it is likely result is on the stack, uid and status may have bogus - * values in the struct. Only look at them if count is greater than 0. */ - if(result->count > 0) { - free(result->status); - if(result->uid) { - int i; - for(i = 0; i < result->count; i++) { - free(result->uid[i]); - } - free(result->uid); + ASSERT(siglist != NULL, return -1); + size_t num; + for(num = 0; num < siglist->count; num++) { + alpm_sigresult_t *result = siglist->results + num; + if(result->key.data) { + gpgme_key_unref(result->key.data); + } else { + free(result->key.fingerprint); } } + FREE(siglist->results); + siglist->count = 0; return 0; } diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h index d07057a..6cb1656 100644 --- a/lib/libalpm/signing.h +++ b/lib/libalpm/signing.h @@ -23,7 +23,7 @@ char *_alpm_sigpath(alpm_handle_t *handle, const char *path); int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, - const char *base64_sig, alpm_sigresult_t *result); + const char *base64_sig, alpm_siglist_t *result); int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, const char *base64_sig, int optional, int marginal, int unknown, enum _alpm_errno_t invalid_err); diff --git a/src/pacman/package.c b/src/pacman/package.c index 7fe33a9..47b6623 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -149,17 +149,17 @@ void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra) alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("None")); } if(from == PKG_FROM_FILE) { - alpm_sigresult_t result; - int err = alpm_pkg_check_pgp_signature(pkg, &result); + alpm_siglist_t siglist; + int err = alpm_pkg_check_pgp_signature(pkg, &siglist); if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) { string_display(_("Signatures :"), _("None")); } else if(err) { string_display(_("Signatures :"), alpm_strerror(alpm_errno(config->handle))); } else { - signature_display(_("Signatures :"), &result); + signature_display(_("Signatures :"), &siglist); } - alpm_sigresult_cleanup(&result); + alpm_siglist_cleanup(&siglist); } string_display(_("Description :"), alpm_pkg_get_desc(pkg)); diff --git a/src/pacman/util.c b/src/pacman/util.c index d2aa29b..585f402 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -664,7 +664,7 @@ void list_display_linebreak(const char *title, const alpm_list_t *list) } } -void signature_display(const char *title, alpm_sigresult_t *result) +void signature_display(const char *title, alpm_siglist_t *siglist) { int len = 0; @@ -672,13 +672,14 @@ void signature_display(const char *title, alpm_sigresult_t *result) len = string_length(title) + 1; printf("%s ", title); } - if(result->count == 0) { + if(siglist->count == 0) { printf(_("None")); } else { - int i; - for(i = 0; i < result->count; i++) { + size_t i; + for(i = 0; i < siglist->count; i++) { char sigline[PATH_MAX]; const char *status, *validity, *name; + alpm_sigresult_t *result = siglist->results + i; /* Don't re-indent the first result */ if(i != 0) { int j; @@ -686,7 +687,7 @@ void signature_display(const char *title, alpm_sigresult_t *result) printf(" "); } } - switch(result->status[i]) { + switch(result->status) { case ALPM_SIGSTATUS_VALID: status = _("Valid"); break; @@ -706,7 +707,7 @@ void signature_display(const char *title, alpm_sigresult_t *result) status = _("Signature error"); break; } - switch(result->validity[i]) { + switch(result->validity) { case ALPM_SIGVALIDITY_FULL: validity = _("full trust"); break; @@ -721,7 +722,7 @@ void signature_display(const char *title, alpm_sigresult_t *result) validity = _("unknown trust"); break; } - name = result->uid[i] ? result->uid[i] : _("{Key Unknown}"); + name = result->key.uid ? result->key.uid : result->key.fingerprint; snprintf(sigline, PATH_MAX, _("%s, %s from \"%s\""), status, validity, name); indentprint(sigline, len); diff --git a/src/pacman/util.h b/src/pacman/util.h index ee3dbd1..2411e65 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -57,7 +57,7 @@ double humanize_size(off_t bytes, const char target_unit, int long_labels, const int table_display(const char *title, const alpm_list_t *header, const alpm_list_t *rows); void list_display(const char *title, const alpm_list_t *list); void list_display_linebreak(const char *title, const alpm_list_t *list); -void signature_display(const char *title, alpm_sigresult_t *result); +void signature_display(const char *title, alpm_siglist_t *siglist); void display_targets(const alpm_list_t *pkgs, int install); int str_cmp(const void *s1, const void *s2); void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg); -- 1.7.6
This one wasn't all that necessary as we only used it in one place in the function, which can be checked easily enough at the call site. Signed-off-by: Dan McGee <dan@archlinux.org> --- lib/libalpm/be_package.c | 3 ++- lib/libalpm/be_sync.c | 3 ++- lib/libalpm/signing.c | 7 +------ lib/libalpm/signing.h | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index 8028754..deec0c4 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -349,7 +349,8 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle, const char *pkgfile, if(level & ALPM_SIG_PACKAGE && _alpm_check_pgp_helper(handle, pkgfile, base64_sig, level & ALPM_SIG_PACKAGE_OPTIONAL, level & ALPM_SIG_PACKAGE_MARGINAL_OK, - level & ALPM_SIG_PACKAGE_UNKNOWN_OK, ALPM_ERR_PKG_INVALID_SIG)) { + level & ALPM_SIG_PACKAGE_UNKNOWN_OK)) { + handle->pm_errno = ALPM_ERR_PKG_INVALID_SIG; _alpm_pkg_free(newpkg); return NULL; } diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 6e64e5f..d7c0a74 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -102,7 +102,8 @@ static int sync_db_validate(alpm_db_t *db) if(level & ALPM_SIG_DATABASE) { if(_alpm_check_pgp_helper(db->handle, dbpath, NULL, level & ALPM_SIG_DATABASE_OPTIONAL, level & ALPM_SIG_DATABASE_MARGINAL_OK, - level & ALPM_SIG_DATABASE_UNKNOWN_OK, ALPM_ERR_DB_INVALID_SIG)) { + level & ALPM_SIG_DATABASE_UNKNOWN_OK)) { + db->handle->pm_errno = ALPM_ERR_DB_INVALID_SIG; return 1; } } diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index 8af8a99..2ca7cce 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -438,8 +438,7 @@ char *_alpm_sigpath(alpm_handle_t *handle, const char *path) } int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, - const char *base64_sig, int optional, int marginal, int unknown, - enum _alpm_errno_t invalid_err) + const char *base64_sig, int optional, int marginal, int unknown) { alpm_siglist_t siglist; int ret; @@ -497,10 +496,6 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, break; } } - - if(ret) { - handle->pm_errno = invalid_err; - } } alpm_siglist_cleanup(&siglist); diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h index 6cb1656..8e47b2c 100644 --- a/lib/libalpm/signing.h +++ b/lib/libalpm/signing.h @@ -25,8 +25,7 @@ char *_alpm_sigpath(alpm_handle_t *handle, const char *path); int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path, const char *base64_sig, alpm_siglist_t *result); int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, - const char *base64_sig, int optional, int marginal, int unknown, - enum _alpm_errno_t invalid_err); + const char *base64_sig, int optional, int marginal, int unknown); #endif /* _ALPM_SIGNING_H */ -- 1.7.6
This allows the backend to prompt, as we do elsewhere, if we encounter an unknown key among those signatures we are attempting to verify. Add some search and import gpgme helper methods that do the heavy lifting, then add case code for the KEY_UNKNOWN case. Signed-off-by: Dan McGee <dan@archlinux.org> --- Note that this will prompt and import if Y is selected, but trust levels aren't being touched yet, so it still may show you the misleading invalid PGP signature error message and abort the transaction. However, if you do a before/after using pacman-key, you will see the new key is present. lib/libalpm/alpm.h | 1 + lib/libalpm/signing.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++-- src/pacman/callback.c | 9 ++++ 3 files changed, 117 insertions(+), 4 deletions(-) diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index c94cdf7..57f95d9 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -940,6 +940,7 @@ typedef enum _alpm_transconv_t { ALPM_TRANS_CONV_LOCAL_NEWER = (1 << 4), ALPM_TRANS_CONV_REMOVE_PKGS = (1 << 5), ALPM_TRANS_CONV_SELECT_PROVIDER = (1 << 6), + ALPM_TRANS_CONV_IMPORT_KEY = (1 << 7) } alpm_transconv_t; /** Transaction Progress */ diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c index 2ca7cce..67a2280 100644 --- a/lib/libalpm/signing.c +++ b/lib/libalpm/signing.c @@ -36,6 +36,7 @@ #include "log.h" #include "alpm.h" #include "handle.h" +#include "trans.h" #if HAVE_LIBGPGME #define CHECK_ERR(void) do { \ @@ -408,13 +409,83 @@ error: } return ret; } -#else + +static int key_search(alpm_handle_t *handle, const char *fpr, + alpm_pgpkey_t *pgpkey) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_keylist_mode_t mode; + gpgme_key_t key; + + memset(&ctx, 0, sizeof(ctx)); + err = gpgme_new(&ctx); + CHECK_ERR(); + + mode = gpgme_get_keylist_mode(ctx); + /* using LOCAL and EXTERN together doesn't work for GPG 1.X. Ugh. */ + mode &= ~GPGME_KEYLIST_MODE_LOCAL; + mode |= GPGME_KEYLIST_MODE_EXTERN; + err = gpgme_set_keylist_mode(ctx, mode); + CHECK_ERR(); + + _alpm_log(handle, ALPM_LOG_DEBUG, "looking up key %s\n", fpr); + + err = gpgme_get_key(ctx, fpr, &key, 0); + _alpm_log(handle, ALPM_LOG_DEBUG, "bogus logger\n"); + if(gpg_err_code(err) == GPG_ERR_EOF) { + _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); + } + _alpm_log(handle, ALPM_LOG_DEBUG, + "gpg error: %s\n", gpgme_strerror(err)); + CHECK_ERR(); + + /* should only get here if key actually exists */ + pgpkey->data = key; + if(key->subkeys->fpr) { + pgpkey->fingerprint = key->subkeys->fpr; + } else if(key->subkeys->keyid) { + pgpkey->fingerprint = key->subkeys->keyid; + } + pgpkey->uid = key->uids->uid; + pgpkey->name = key->uids->name; + pgpkey->email = key->uids->email; + pgpkey->created = key->subkeys->timestamp; + pgpkey->expires = key->subkeys->expires; + +error: + gpgme_release(ctx); + return gpg_err_code(err) == GPG_ERR_NO_ERROR; +} + +static int key_import(alpm_handle_t *handle, alpm_pgpkey_t *key) +{ + gpgme_error_t err; + gpgme_ctx_t ctx; + gpgme_key_t keys[2]; + + memset(&ctx, 0, sizeof(ctx)); + err = gpgme_new(&ctx); + CHECK_ERR(); + + + keys[0] = key->data; + keys[1] = NULL; + err = gpgme_op_import_keys(ctx, keys); + CHECK_ERR(); + +error: + gpgme_release(ctx); + return gpg_err_code(err) != GPG_ERR_NO_ERROR; +} + +#else /* HAVE_LIBGPGME */ int _alpm_gpgme_checksig(alpm_handle_t UNUSED *handle, const char UNUSED *path, const char UNUSED *base64_sig, alpm_sigresult_t UNUSED *result) { return -1; } -#endif +#endif /* HAVE_LIBGPGME */ /** * Form a signature path given a file path. @@ -441,7 +512,7 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, const char *base64_sig, int optional, int marginal, int unknown) { alpm_siglist_t siglist; - int ret; + int ret, rerun = 0; memset(&siglist, 0, sizeof(alpm_siglist_t)); @@ -488,8 +559,34 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, break; } break; - case ALPM_SIGSTATUS_SIG_EXPIRED: case ALPM_SIGSTATUS_KEY_UNKNOWN: + { + alpm_pgpkey_t fetch_key; + const char *fpr = siglist.results[num].key.fingerprint; + + memset(&fetch_key, 0, sizeof(fetch_key)); + + if(key_search(handle, fpr, &fetch_key)) { + int doimport = 0; + _alpm_log(handle, ALPM_LOG_DEBUG, + "unknown key, found %s on keyserver\n", fetch_key.uid); + QUESTION(handle->trans, ALPM_TRANS_CONV_IMPORT_KEY, + &fetch_key, NULL, NULL, &doimport); + if(doimport && !key_import(handle, &fetch_key)) { + rerun = 1; + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, + "signature is not valid, key not imported\n"); + ret = -1; + } + } else { + _alpm_log(handle, ALPM_LOG_DEBUG, + "signature is not valid, key unknown\n"); + ret = -1; + } + break; + } + case ALPM_SIGSTATUS_SIG_EXPIRED: case ALPM_SIGSTATUS_INVALID: _alpm_log(handle, ALPM_LOG_DEBUG, "signature is not valid\n"); ret = -1; @@ -499,6 +596,12 @@ int _alpm_check_pgp_helper(alpm_handle_t *handle, const char *path, } alpm_siglist_cleanup(&siglist); + + if(rerun) { + return _alpm_check_pgp_helper(handle, path, base64_sig, + optional, marginal, unknown); + } + return ret; } diff --git a/src/pacman/callback.c b/src/pacman/callback.c index 5ee4e5a..5859788 100644 --- a/src/pacman/callback.c +++ b/src/pacman/callback.c @@ -336,6 +336,15 @@ void cb_trans_conv(alpm_transconv_t event, void *data1, void *data2, (char *)data1, alpm_strerror(*(enum _alpm_errno_t *)data2)); break; + case ALPM_TRANS_CONV_IMPORT_KEY: + { + alpm_pgpkey_t *key = data1; + char created[12]; + strftime(created, 12, "%Y-%m-%d", localtime(&(key->created))); + *response = yesno(_(":: Import PGP key %s, \"%s\", created %s?"), + key->fingerprint, key->uid, created); + } + break; } if(config->noask) { if(config->ask & event) { -- 1.7.6
--- Thoughts? And why isn't this called --recv-keys like gpg? scripts/pacman-key.sh.in | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in index 74ecfcf..819ec69 100644 --- a/scripts/pacman-key.sh.in +++ b/scripts/pacman-key.sh.in @@ -60,7 +60,7 @@ usage() { echo "$(gettext " -f, --finger [<keyid(s)>] List fingerprint for specified or all keyids")" echo "$(gettext " -h, --help Show this help message and exit")" echo "$(gettext " -l, --list-keys [<keyid(s)>] List the specified or all keys")" - echo "$(gettext " -r, --receive <keyserver> <keyid(s)> Fetch the specified keyids")" + echo "$(gettext " -r, --receive <keyid(s)> Fetch the specified keyids")" echo "$(gettext " -u, --updatedb Update the trustdb of pacman")" echo "$(gettext " -v, --verify <signature> Verify the file specified by the signature")" echo "$(gettext " -V, --version Show program version")" @@ -265,7 +265,7 @@ receive_keys() { error "$(gettext "You need to specify the keyserver and at least one key identifier")" exit 1 fi - "${GPG_PACMAN[@]}" --keyserver "$KEYSERVER" --recv-keys "${KEYIDS[@]}" + "${GPG_PACMAN[@]}" --recv-keys "${KEYIDS[@]}" } edit_keys() { @@ -348,7 +348,7 @@ while true; do --init) INIT=1 ;; -l|--list-keys) LISTKEYS=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;; --list-sigs) LISTSIGS=1; [[ -n $2 && ${2:0:1} != "-" ]] && shift && KEYIDS=($1) ;; - -r|--receive) RECEIVE=1; shift; TMP=($1); KEYSERVER=${TMP[0]}; KEYIDS=(${TMP[@]:1}); unset TMP;; + -r|--receive) RECEIVE=1; shift; KEYIDS=($1);; --reload) RELOAD=1 ;; -u|--updatedb) UPDATEDB=1 ;; -v|--verify) VERIFY=1; shift; SIGNATURE=$1 ;; -- 1.7.6
On Thu, Aug 25, 2011 at 2:11 AM, Dan McGee <dan@archlinux.org> wrote:
---
Thoughts? And why isn't this called --recv-keys like gpg?
But how would you choose from where to receive the keys? --receive-keys is not exactly equivalent to to --recv-keys from gpg because the former maps to --keyserver and --recv-keys in gpg. It would save us a few keystrokes, as --keyserver is not useful for any other option (we don't send keys from pacman's keyring to any gpg keyserver). -- A: Because it obfuscates the reading. Q: Why is top posting so bad? ------------------------------------------- Denis A. Altoe Falqueto Linux user #524555 -------------------------------------------
On Thu, Aug 25, 2011 at 8:31 AM, Denis A. Altoé Falqueto <denisfalqueto@gmail.com> wrote:
On Thu, Aug 25, 2011 at 2:11 AM, Dan McGee <dan@archlinux.org> wrote:
---
Thoughts? And why isn't this called --recv-keys like gpg?
But how would you choose from where to receive the keys? --receive-keys is not exactly equivalent to to --recv-keys from gpg because the former maps to --keyserver and --recv-keys in gpg. It would save us a few keystrokes, as --keyserver is not useful for any other option (we don't send keys from pacman's keyring to any gpg keyserver).
We're going to need a gpg.conf, and we're going to have to require a "keyserver =" line in it for other things, I suppose I should have mentioned (the whole import keys bit). So this point becomes mute. -Dan
On 25/08/11 23:43, Dan McGee wrote:
On Thu, Aug 25, 2011 at 8:31 AM, Denis A. Altoé Falqueto <denisfalqueto@gmail.com> wrote:
On Thu, Aug 25, 2011 at 2:11 AM, Dan McGee<dan@archlinux.org> wrote:
---
Thoughts? And why isn't this called --recv-keys like gpg?
But how would you choose from where to receive the keys? --receive-keys is not exactly equivalent to to --recv-keys from gpg because the former maps to --keyserver and --recv-keys in gpg. It would save us a few keystrokes, as --keyserver is not useful for any other option (we don't send keys from pacman's keyring to any gpg keyserver).
We're going to need a gpg.conf, and we're going to have to require a "keyserver =" line in it for other things, I suppose I should have mentioned (the whole import keys bit). So this point becomes mute.
I think we still need the ability to manually specify the keyserver. The mirroring across keyservers is not necessarily the best, so you may need to specify one that works. Allan
participants (4)
-
Allan McRae
-
Dan McGee
-
Dan McGee
-
Denis A. Altoé Falqueto