FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > ArchLinux > ArchLinux Pacman Development

 
 
LinkBack Thread Tools
 
Old 09-20-2011, 10:26 PM
Dan McGee
 
Default Implement PGP key search and import

Add two new static methods, key_search() and key_import(), to our
growing list of signing code.

If we come across a key we do not have, attempt to look it up remotely
and ask the user if they wish to import said key. If they do, flag the
validation process as a potential 'retry', meaning it might succeed the
next time it is ran.

These depend on you having a 'keyserver hkp://foo.example.com' line in
your gpg.conf file in your gnupg home directory to function.

Signed-off-by: Dan McGee <dan@archlinux.org>
---
lib/libalpm/signing.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 92 insertions(+), 5 deletions(-)

diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c
index e1b6452..4554d13 100644
--- a/lib/libalpm/signing.c
+++ b/lib/libalpm/signing.c
@@ -160,6 +160,74 @@ error:
RET_ERR(handle, ALPM_ERR_GPGME, 1);
}

+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
", fpr);
+
+ err = gpgme_get_key(ctx, fpr, &key, 0);
+ if(gpg_err_code(err) == GPG_ERR_EOF) {
+ _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key
");
+ } else if(gpg_err_code(err) != GPG_ERR_NO_ERROR) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "gpg error: %s
", 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;
+}
+
/**
* Decode a loaded signature in base64 form.
* @param base64_data the signature to attempt to decode
@@ -521,6 +589,7 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
for(i = 0; i < siglist->count; i++) {
alpm_sigresult_t *result = siglist->results + i;
const char *name = result->key.uid ? result->key.uid : result->key.fingerprint;
+ int answer;
switch(result->status) {
case ALPM_SIGSTATUS_VALID:
case ALPM_SIGSTATUS_KEY_EXPIRED:
@@ -532,6 +601,7 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
_alpm_log(handle, ALPM_LOG_ERROR,
_("%s: signature from "%s" is marginal trust
"),
identifier, name);
+ /* QUESTION(handle, ALPM_QUESTION_EDIT_KEY_TRUST, &result->key, NULL, NULL, &answer); */
}
break;
case ALPM_SIGVALIDITY_UNKNOWN:
@@ -539,6 +609,7 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
_alpm_log(handle, ALPM_LOG_ERROR,
_("%s: signature from "%s" is unknown trust
"),
identifier, name);
+ /* QUESTION(handle, ALPM_QUESTION_EDIT_KEY_TRUST, &result->key, NULL, NULL, &answer); */
}
break;
case ALPM_SIGVALIDITY_NEVER:
@@ -549,15 +620,31 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char *identifier,
}
break;
case ALPM_SIGSTATUS_KEY_UNKNOWN:
- /* TODO import key here */
_alpm_log(handle, ALPM_LOG_ERROR,
- _("%s: key "%s" is unknown
"),
- identifier, name);
+ _("%s: key "%s" is unknown
"), identifier, name);
+ {
+ alpm_pgpkey_t fetch_key;
+ memset(&fetch_key, 0, sizeof(fetch_key));
+
+ if(key_search(handle, result->key.fingerprint, &fetch_key)) {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "unknown key, found %s on keyserver
", fetch_key.uid);
+ QUESTION(handle, ALPM_QUESTION_IMPORT_KEY,
+ &fetch_key, NULL, NULL, &answer);
+ if(answer && !key_import(handle, &fetch_key)) {
+ retry = 1;
+ }
+ } else {
+ _alpm_log(handle, ALPM_LOG_DEBUG,
+ "key could not be looked up remotely
");
+ }
+ gpgme_key_unref(fetch_key.data);
+ break;
+ }
break;
case ALPM_SIGSTATUS_SIG_EXPIRED:
_alpm_log(handle, ALPM_LOG_ERROR,
- _("%s: signature from "%s" is expired
"),
- identifier, name);
+ _("%s: signature from "%s" is expired
"), identifier, name);
break;
case ALPM_SIGSTATUS_INVALID:
_alpm_log(handle, ALPM_LOG_ERROR,
--
1.7.6.3
 

Thread Tools




All times are GMT. The time now is 06:27 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org