]> granicus.if.org Git - mutt/commitdiff
Handle autocrypt message decryption.
authorKevin McCarthy <kevin@8t8.us>
Fri, 26 Jul 2019 20:55:46 +0000 (13:55 -0700)
committerKevin McCarthy <kevin@8t8.us>
Sat, 3 Aug 2019 21:08:09 +0000 (14:08 -0700)
Try autocrypt first for crypt_pgp_decrypt_mime() and
pgp_gpgme_encrypted_handler().

Propagate the autocrypt bit if successful.  This is used when replying
to an autocrypt message, to force a reply using autocrypt.

crypt-gpgme.c
crypt.c
cryptglue.c
handler.c
mutt.h

index 83f6ae6ac1fb778931b601afb5af1dd758af51d9..418bc180215740bebd5bdfe19d2fc2f5c57582b7 100644 (file)
@@ -1947,10 +1947,10 @@ static BODY *decrypt_part (BODY *a, STATE *s, FILE *fpout, int is_smime,
                            int *r_is_signed)
 {
   struct stat info;
-  BODY *tattach;
+  BODY *tattach = NULL;
   int err = 0;
-  gpgme_ctx_t ctx;
-  gpgme_data_t ciphertext, plaintext;
+  gpgme_ctx_t ctx = NULL;
+  gpgme_data_t ciphertext = NULL, plaintext = NULL;
   int maybe_signed = 0;
   int anywarn = 0;
   int sig_stat = 0;
@@ -1964,7 +1964,7 @@ restart:
   /* Make a data object from the body, create context etc. */
   ciphertext = file_to_data_object (s->fpin, a->offset, a->length);
   if (!ciphertext)
-    return NULL;
+    goto cleanup;
   plaintext = create_gpgme_data ();
 
   /* Do the decryption or the verification in case of the S/MIME hack. */
@@ -1986,8 +1986,13 @@ restart:
   else
     err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
   gpgme_data_release (ciphertext);
+  ciphertext = NULL;
   if (err)
     {
+      /* Abort right away and silently.  Autocrypt will retry on the
+       * normal keyring. */
+      if (option (OPTAUTOCRYPTGPGME))
+        goto cleanup;
       if (is_smime && !maybe_signed
           && gpg_err_code (err) == GPG_ERR_NO_DATA)
         {
@@ -2003,9 +2008,11 @@ restart:
             {
               maybe_signed = 1;
               gpgme_data_release (plaintext);
+              plaintext = NULL;
               /* We release the context because recent versions of gpgme+gpgsm
                * appear to end the session after an error */
               gpgme_release (ctx);
+              ctx = NULL;
               goto restart;
             }
         }
@@ -2019,9 +2026,7 @@ restart:
                     gpgme_strerror (err));
           state_attach_puts (buf, s);
         }
-      gpgme_data_release (plaintext);
-      gpgme_release (ctx);
-      return NULL;
+      goto cleanup;
   }
   mutt_need_hard_redraw ();
 
@@ -2029,11 +2034,10 @@ restart:
      otherwise read_mime_header has a hard time parsing the message.  */
   if (data_object_to_stream (plaintext, fpout))
     {
-      gpgme_data_release (plaintext);
-      gpgme_release (ctx);
-      return NULL;
+      goto cleanup;
     }
   gpgme_data_release (plaintext);
+  plaintext = NULL;
 
   a->is_signed_data = 0;
   if (sig_stat)
@@ -2063,7 +2067,8 @@ restart:
         state_attach_puts (_("[-- End signature "
                              "information --]\n\n"), s);
     }
-  gpgme_release (ctx); ctx = NULL;
+  gpgme_release (ctx);
+  ctx = NULL;
 
   fflush (fpout);
   rewind (fpout);
@@ -2082,6 +2087,11 @@ restart:
       mutt_parse_part (fpout, tattach);
     }
 
+cleanup:
+  gpgme_data_release (ciphertext);
+  gpgme_data_release (plaintext);
+  gpgme_release (ctx);
+
   return tattach;
 }
 
@@ -2158,10 +2168,16 @@ int pgp_gpgme_decrypt_mime (FILE *fpin, FILE **fpout, BODY *b, BODY **cur)
   unlink (tempfile);
 
   if ((*cur = decrypt_part (b, &s, *fpout, 0, &is_signed)) == NULL)
+  {
     rv = -1;
-  rewind (*fpout);
-  if (is_signed > 0)
-    first_part->goodsig = 1;
+    safe_fclose (fpout);
+  }
+  else
+  {
+    rewind (*fpout);
+    if (is_signed > 0)
+      first_part->goodsig = 1;
+  }
 
 bail:
   if (need_decode)
@@ -3030,8 +3046,11 @@ int pgp_gpgme_encrypted_handler (BODY *a, STATE *s)
     }
   else
     {
-      mutt_error _("Could not decrypt PGP message");
-      mutt_sleep (2);
+      if (!option (OPTAUTOCRYPTGPGME))
+        {
+          mutt_error _("Could not decrypt PGP message");
+          mutt_sleep (2);
+        }
       rc = -1;
     }
 
diff --git a/crypt.c b/crypt.c
index 84d8bd0e2b9d39def210c2922144ca30e51d0c0f..1d5f9c5f7202998ca7b757eb3b9d7f98e0a9edcb 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -609,6 +609,10 @@ int crypt_query (BODY *m)
 
     if (t && m->goodsig)
       t |= GOODSIGN;
+#ifdef USE_AUTOCRYPT
+    if (t && m->is_autocrypt)
+      t |= AUTOCRYPT;
+#endif
   }
 
   if (m->type == TYPEMULTIPART || m->type == TYPEMESSAGE)
index ce822173b88c962eb3ff10a0f65878adc85c814b..b154e8dc4c3f98554b9e9eab21a121463e5791f4 100644 (file)
@@ -161,6 +161,19 @@ int crypt_pgp_valid_passphrase (void)
 /* Decrypt a PGP/MIME message. */
 int crypt_pgp_decrypt_mime (FILE *a, FILE **b, BODY *c, BODY **d)
 {
+#ifdef USE_AUTOCRYPT
+  int result;
+
+  set_option (OPTAUTOCRYPTGPGME);
+  result = pgp_gpgme_decrypt_mime (a, b, c, d);
+  unset_option (OPTAUTOCRYPTGPGME);
+  if (result == 0)
+  {
+    c->is_autocrypt = 1;
+    return result;
+  }
+#endif
+
   if (CRYPT_MOD_CALL_CHECK (PGP, decrypt_mime))
     return (CRYPT_MOD_CALL (PGP, decrypt_mime)) (a, b, c, d);
 
@@ -179,6 +192,19 @@ int crypt_pgp_application_pgp_handler (BODY *m, STATE *s)
 /* MIME handler for an PGP/MIME encrypted message. */
 int crypt_pgp_encrypted_handler (BODY *a, STATE *s)
 {
+#ifdef USE_AUTOCRYPT
+  int result;
+
+  set_option (OPTAUTOCRYPTGPGME);
+  result = pgp_gpgme_encrypted_handler (a, s);
+  unset_option (OPTAUTOCRYPTGPGME);
+  if (result == 0)
+  {
+    a->is_autocrypt = 1;
+    return result;
+  }
+#endif
+
   if (CRYPT_MOD_CALL_CHECK (PGP, encrypted_handler))
     return (CRYPT_MOD_CALL (PGP, encrypted_handler)) (a, s);
 
index 5c6397fcbca05876a9932802a72948a16b2da988..990b3df6c716a361274c3290274440931d941753 100644 (file)
--- a/handler.c
+++ b/handler.c
@@ -1718,6 +1718,9 @@ static int valid_pgp_encrypted_handler (BODY *b, STATE *s)
   else
     rc = crypt_pgp_encrypted_handler (octetstream, s);
   b->goodsig |= octetstream->goodsig;
+#ifdef USE_AUTOCRYPT
+  b->is_autocrypt |= octetstream->is_autocrypt;
+#endif
 
   /* Relocate protected headers onto the multipart/encrypted part */
   if (!rc && octetstream->mime_headers)
@@ -1744,6 +1747,9 @@ static int malformed_pgp_encrypted_handler (BODY *b, STATE *s)
   /* exchange encodes the octet-stream, so re-run it through the decoder */
   rc = run_decode_and_handler (octetstream, s, crypt_pgp_encrypted_handler, 0);
   b->goodsig |= octetstream->goodsig;
+#ifdef USE_AUTOCRYPT
+  b->is_autocrypt |= octetstream->is_autocrypt;
+#endif
 
   /* Relocate protected headers onto the multipart/encrypted part */
   if (!rc && octetstream->mime_headers)
diff --git a/mutt.h b/mutt.h
index ba0df11e0fe79f59b19a717cc9b32071b1b4db7f..9d02a1d258e766fb17c330b8a6ab31ef361869f9 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -812,6 +812,10 @@ typedef struct body
   unsigned int goodsig : 1;    /* good cryptographic signature */
   unsigned int warnsig : 1;     /* maybe good signature */
   unsigned int badsig : 1;     /* bad cryptographic signature (needed to check encrypted s/mime-signatures) */
+#ifdef USE_AUTOCRYPT
+  unsigned int is_autocrypt : 1;  /* used to flag autocrypt-decrypted messages
+                                   * for replying */
+#endif
 
   unsigned int collapsed : 1;  /* used by recvattach */
   unsigned int attach_qualifies : 1;