]> granicus.if.org Git - neomutt/commitdiff
Handle autocrypt message decryption
authorKevin McCarthy <kevin@8t8.us>
Fri, 26 Jul 2019 20:55:46 +0000 (13:55 -0700)
committerRichard Russon <rich@flatcap.org>
Mon, 19 Aug 2019 23:14:27 +0000 (00:14 +0100)
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.

Co-authored-by: Richard Russon <rich@flatcap.org>
email/body.h
handler.c
ncrypt/crypt.c
ncrypt/crypt_gpgme.c
ncrypt/cryptglue.c

index 6dfb1b7179f230044a92bdc9fd84128781ce191c..338251c9a02c90922c9f05030c4a871b59000c33 100644 (file)
@@ -81,6 +81,10 @@ struct Body
   bool goodsig : 1;               ///< Good cryptographic signature
   bool warnsig : 1;               ///< Maybe good signature
   bool 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
 
   bool collapsed : 1;             ///< Used by recvattach
   bool attach_qualifies : 1;      ///< This attachment should be counted
index 1f6e01b07423e227cda15eff75fabb5abd28e799..d86f5a51fc5107d29ebc5717374562f0c5c19df7 100644 (file)
--- a/handler.c
+++ b/handler.c
@@ -1457,6 +1457,9 @@ static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s)
   /* exchange encodes the octet-stream, so re-run it through the decoder */
   int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false);
   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)
index 9e367fc3d423708b3f70c53b2d3d7e72b8c8c284..40fa0472d8ff907e9cad9689bd002c5242aad2f1 100644 (file)
@@ -730,6 +730,10 @@ SecurityFlags crypt_query(struct Body *m)
 
     if (rc && m->goodsig)
       rc |= SEC_GOODSIGN;
+#ifdef USE_AUTOCRYPT
+    if (rc && m->is_autocrypt)
+      rc |= SEC_AUTOCRYPT;
+#endif
   }
 
   if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE))
index aab9ea3f7f8647662fa9e2f0dbb6acc8f3327064..2c3d43a93b9f3a4cdbd7d831e3f8e5523daf5080 100644 (file)
@@ -2155,8 +2155,8 @@ static struct Body *decrypt_part(struct Body *a, struct State *s, FILE *fp_out,
   struct stat info;
   struct 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;
   bool maybe_signed = false;
   bool anywarn = false;
   int sig_stat = 0;
@@ -2172,7 +2172,7 @@ restart:
   /* Make a data object from the body, create context etc. */
   ciphertext = file_to_data_object(s->fp_in, 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. */
@@ -2194,8 +2194,13 @@ restart:
   else
     err = gpgme_op_decrypt(ctx, ciphertext, plaintext);
   gpgme_data_release(ciphertext);
+  ciphertext = NULL;
   if (err != 0)
   {
+    /* Abort right away and silently.  Autocrypt will retry on the
+       * normal keyring. */
+    if (OptAutocryptGpgme)
+      goto cleanup;
     if (is_smime && !maybe_signed && (gpg_err_code(err) == GPG_ERR_NO_DATA))
     {
       /* Check whether this might be a signed message despite what the mime
@@ -2209,9 +2214,10 @@ restart:
       {
         maybe_signed = true;
         gpgme_data_release(plaintext);
+        plaintext = NULL;
         /* gpgsm ends the session after an error; restart it */
         gpgme_release(ctx);
-        ctx = create_gpgme_context(is_smime);
+        ctx = NULL;
         goto restart;
       }
     }
@@ -2224,9 +2230,7 @@ restart:
                _("[-- Error: decryption failed: %s --]\n\n"), gpgme_strerror(err));
       state_attach_puts(buf, s);
     }
-    gpgme_data_release(plaintext);
-    gpgme_release(ctx);
-    return NULL;
+    goto cleanup;
   }
   redraw_if_needed(ctx);
 
@@ -2234,11 +2238,10 @@ restart:
    * otherwise read_mime_header has a hard time parsing the message.  */
   if (data_object_to_stream(plaintext, fp_out))
   {
-    gpgme_data_release(plaintext);
-    gpgme_release(ctx);
-    return NULL;
+    goto cleanup;
   }
   gpgme_data_release(plaintext);
+  plaintext = NULL;
 
   a->is_signed_data = false;
   if (sig_stat)
@@ -2292,6 +2295,11 @@ restart:
     mutt_parse_part(fp_out, tattach);
   }
 
+cleanup:
+  gpgme_data_release(ciphertext);
+  gpgme_data_release(plaintext);
+  gpgme_release(ctx);
+
   return tattach;
 }
 
@@ -2366,10 +2374,16 @@ int pgp_gpgme_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Bo
 
   *cur = decrypt_part(b, &s, *fp_out, false, &is_signed);
   if (!*cur)
+  {
     rc = -1;
-  rewind(*fp_out);
-  if (is_signed > 0)
-    first_part->goodsig = true;
+    mutt_file_fclose(fp_out);
+  }
+  else
+  {
+    rewind(*fp_out);
+    if (is_signed > 0)
+      first_part->goodsig = true;
+  }
 
 bail:
   if (need_decode)
@@ -3225,7 +3239,10 @@ int pgp_gpgme_encrypted_handler(struct Body *a, struct State *s)
   }
   else
   {
-    mutt_error(_("Could not decrypt PGP message"));
+    if (!OptAutocryptGpgme)
+    {
+      mutt_error(_("Could not decrypt PGP message"));
+    }
     rc = -1;
   }
 
index c7e63eb25b8f0b95d44857026fa0bb4c3cdc8b53..27f002de6967a7aae9ae03c6c64f0fe29a40aa24 100644 (file)
@@ -197,6 +197,19 @@ bool crypt_pgp_valid_passphrase(void)
  */
 int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
 {
+#ifdef USE_AUTOCRYPT
+  int result;
+
+  OptAutocryptGpgme = true;
+  result = pgp_gpgme_decrypt_mime(fp_in, fp_out, b, cur);
+  OptAutocryptGpgme = false;
+  if (result == 0)
+  {
+    b->is_autocrypt = 1;
+    return result;
+  }
+#endif
+
   if (CRYPT_MOD_CALL_CHECK(PGP, decrypt_mime))
     return CRYPT_MOD_CALL(PGP, decrypt_mime)(fp_in, fp_out, b, cur);
 
@@ -223,6 +236,19 @@ int crypt_pgp_application_handler(struct Body *m, struct State *s)
  */
 int crypt_pgp_encrypted_handler(struct Body *a, struct State *s)
 {
+#ifdef USE_AUTOCRYPT
+  int result;
+
+  OptAutocryptGpgme = true;
+  result = pgp_gpgme_encrypted_handler(a, s);
+  OptAutocryptGpgme = false;
+  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);