From: Werner Koch Date: Mon, 3 Dec 2018 07:41:56 +0000 (+0100) Subject: Improve the console output for extract-keys and speed up import. X-Git-Tag: mutt-1-12-rel~194 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=382355a5ddc5fb86bde4e2a376b70c9b0864cc53;p=mutt 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. --- 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)) {