[PATCH 5/5] Improve the console output for extract-keys and speed up import.

Werner Koch wk at gnupg.org
Mon Dec 3 07:41:56 UTC 2018


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.
---
 crypt-gpgme.c | 113 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 file 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))
             {
-- 
2.11.0




More information about the Mutt-dev mailing list