diff options
author | Werner Koch <wk@gnupg.org> | 2018-12-03 08:41:56 +0100 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2018-12-04 20:03:11 -0800 |
commit | 382355a5ddc5fb86bde4e2a376b70c9b0864cc53 (patch) | |
tree | 2a8f66cc72ac1f2821dab0f2cba9133b3cef803c /crypt-gpgme.c | |
parent | 55c18b7e2fc2b7779beb6cb69d9524a402e9f2ef (diff) |
Improve the console output for extract-keys and speed up import.
The listing of imported keys to the console must have stopped working
on 2014-12-31 due to a fix for bug #3698, commit
bbc5acb6de0ca56d7e8366402d68a1a919ca9b23 which was needed due to a
not fully working stub code introduced in 2008 with commit
a4b3a60dd63bc7af7927025b2d1344530ca89aa9.
The latter commit also introduced a bug in the import code which
listed all keys in the keyring to a temporary file and copied that one
to stdout. The former commit avoided the output to stdout.
The fix here is to use pgp_gpgme_extract_keys only for extracting
information about the key and don't re-use the same code for importing
keys. We now import the keys directly in pgp_gpgme_invoke_import and
we print the fingerprint and status flags for all imported keys. That
information available from GPGME for ages (0.3.1 from 2003).
The user id is unfortunately not printed; that would require a lookup
of the newly imported key. Can be done with another patch.
Diffstat (limited to 'crypt-gpgme.c')
-rw-r--r-- | crypt-gpgme.c | 113 |
1 files changed, 85 insertions, 28 deletions
diff --git a/crypt-gpgme.c b/crypt-gpgme.c index 515d81b3..f727292b 100644 --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -2228,7 +2228,7 @@ int smime_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur) return *cur? 0:-1; } -static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun) +static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp) { /* Before gpgme 1.9.0 and gpg 2.1.14 there was no side-effect free * way to view key data in GPGME, so we import the key into a @@ -2257,7 +2257,7 @@ static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun) tmpctx = create_gpgme_context (0); - if (dryrun && legacy_api) + if (legacy_api) { snprintf (tmpdir, sizeof(tmpdir), "%s/mutt-gpgme-XXXXXX", Tempdir); if (!mkdtemp (tmpdir)) @@ -2284,15 +2284,6 @@ static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun) } } - if (!dryrun || legacy_api) - { - if ((err = gpgme_op_import (tmpctx, keydata)) != GPG_ERR_NO_ERROR) - { - dprint (1, (debugfile, "Error importing key\n")); - goto err_tmpdir; - } - } - mutt_mktemp (tmpfile, sizeof (tmpfile)); *fp = safe_fopen (tmpfile, "w+"); if (!*fp) @@ -2303,7 +2294,7 @@ static int pgp_gpgme_extract_keys (gpgme_data_t keydata, FILE** fp, int dryrun) unlink (tmpfile); #if GPGME_VERSION_NUMBER >= 0x010900 /* 1.9.0 */ - if (dryrun && !legacy_api) + if (!legacy_api) err = gpgme_op_keylist_from_data_start (tmpctx, keydata, 0); else #endif /* gpgme >= 1.9.0 */ @@ -2351,7 +2342,7 @@ err_fp: if (rc) safe_fclose (fp); err_tmpdir: - if (dryrun && legacy_api) + if (legacy_api) mutt_rmtree (tmpdir); err_ctx: gpgme_release (tmpctx); @@ -2359,6 +2350,7 @@ err_ctx: return rc; } + /* Check that 'b' is a complete line containing 'a' followed by either LF or CRLF. * * returns: @@ -2466,37 +2458,102 @@ int pgp_gpgme_check_traditional (FILE *fp, BODY *b, int just_one) void pgp_gpgme_invoke_import (const char *fname) { - gpgme_data_t keydata; + gpgme_ctx_t ctx; + gpgme_data_t keydata = NULL; gpgme_error_t err; - FILE* in; - FILE* out; + FILE *in = NULL; + gpgme_import_result_t impres; + gpgme_import_status_t st; + int any; + + ctx = create_gpgme_context (0); if (!(in = safe_fopen (fname, "r"))) - return; + { + mutt_perror (fname); + goto leave; + } + /* Note that the stream, "in", needs to be kept open while the keydata - * is used. - */ + * is used. */ if ((err = gpgme_data_new_from_stream (&keydata, in)) != GPG_ERR_NO_ERROR) { - safe_fclose (&in); mutt_error (_("error allocating data object: %s\n"), gpgme_strerror (err)); mutt_sleep (1); - return; + goto leave; } - if (pgp_gpgme_extract_keys (keydata, &out, 0)) + err = gpgme_op_import (ctx, keydata); + if (err) { - mutt_error (_("Error extracting key data!\n")); + mutt_error (_("error importing key: %s\n"), gpgme_strerror (err)); mutt_sleep (1); + goto leave; } - else + + /* Print infos about the imported keys to stdout. */ + impres = gpgme_op_import_result (ctx); + if (!impres) { - fseek (out, 0, SEEK_SET); - mutt_copy_stream (out, stdout); + fputs ("oops: no import result returned\n", stdout); + goto leave; } + + for (st = impres->imports; st; st = st->next) + { + if (st->result) + continue; + printf ("key %s imported (", NONULL (st->fpr)); + /* Note that we use the singular even if it is possible that + * several uids etc are new. This simply looks better. */ + any = 0; + if (st->status & GPGME_IMPORT_SECRET) + { + printf ("secret parts"); + any = 1; + } + if ((st->status & GPGME_IMPORT_NEW)) + { + printf ("%snew key", any? ", ":""); + any = 1; + } + if ((st->status & GPGME_IMPORT_UID)) + { + printf ("%snew uid", any? ", ":""); + any = 1; + } + if ((st->status & GPGME_IMPORT_SIG)) + { + printf ("%snew sig", any? ", ":""); + any = 1; + } + if ((st->status & GPGME_IMPORT_SUBKEY)) + { + printf ("%snew subkey", any? ", ":""); + any = 1; + } + printf ("%s)\n", any? "":"not changed"); + /* Fixme: Should we lookup each imported key and print more infos? */ + } + /* Now print keys which failed the import. Unfortunately in most + * cases gpg will bail out early and not tell gpgme about. */ + /* FIXME: We could instead use the new GPGME_AUDITLOG_DIAG to show + * the actual gpg diagnostics. But I fear that would clutter the + * output too much. Maybe a dedicated prompt or option to do this + * would be helpful. */ + for (st = impres->imports; st; st = st->next) + { + if (!st->result) + continue; + printf ("key %s import failed: %s\n", NONULL (st->fpr), + gpgme_strerror (st->result)); + } + fflush (stdout); + + leave: + gpgme_release (ctx); gpgme_data_release (keydata); safe_fclose (&in); - safe_fclose (&out); } @@ -2641,7 +2698,7 @@ int pgp_gpgme_application_handler (BODY *m, STATE *s) /* Invoke PGP if needed */ if (pgp_keyblock) { - pgp_gpgme_extract_keys (armored_data, &pgpout, 1); + pgp_gpgme_extract_keys (armored_data, &pgpout); } else if (!clearsign || (s->flags & MUTT_VERIFY)) { |