]> granicus.if.org Git - neomutt/commitdiff
Add $crypt_protected_headers_save
authorKevin McCarthy <kevin@8t8.us>
Thu, 27 Dec 2018 20:05:43 +0000 (12:05 -0800)
committerRichard Russon <rich@flatcap.org>
Mon, 7 Jan 2019 15:09:42 +0000 (15:09 +0000)
Setting this option will save the protected header back into the
clear-text message headers.  This improves
usability (searching/limiting/replying) when reopening a mailbox
without header cache.  However, it is a security trade-off, so
defaults off and strongly warns about what it is doing in the documentation.

Co-authored-by: Richard Russon <rich@flatcap.org>
commands.c
copy.c
copy.h
email/envelope.h
globals.h
init.h

index 94c5e00fee2a44edfe401b72f12800031e8af3a2..c76aa14189ce5bdf71df9d925990f5ae5beb85c5 100644 (file)
@@ -155,6 +155,14 @@ static void update_protected_headers(struct Email *cur)
       mutt_hash_insert(Context->mailbox->subj_hash, cur->env->real_subj, cur);
 
     mx_save_hcache(Context->mailbox, cur);
+
+    /* Also persist back to the message headers if this is set */
+    if (CryptProtectedHeadersSave)
+    {
+      cur->env->changed |= MUTT_ENV_CHANGED_SUBJECT;
+      cur->changed = 1;
+      Context->mailbox->changed = 1;
+    }
   }
 }
 
diff --git a/copy.c b/copy.c
index 6370a44a6aed453e9d7367939a84283ea596b067..4beed654697aa8670970d5833a2e2ab959addd72 100644 (file)
--- a/copy.c
+++ b/copy.c
@@ -140,6 +140,8 @@ int mutt_copy_hdr(FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end,
           continue;
         if (flags & CH_UPDATE_LABEL && mutt_str_startswith(buf, "X-Label:", CASE_IGNORE))
           continue;
+        if ((flags & CH_UPDATE_SUBJECT) && mutt_str_startswith(buf, "Subject:", CASE_IGNORE))
+          continue;
 
         ignore = false;
       }
@@ -267,6 +269,10 @@ int mutt_copy_hdr(FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end,
         continue;
       if ((flags & CH_UPDATE_IRT) && mutt_str_startswith(buf, "In-Reply-To:", CASE_IGNORE))
         continue;
+      if ((flags & CH_UPDATE_LABEL) && mutt_str_startswith(buf, "X-Label:", CASE_IGNORE))
+        continue;
+      if ((flags & CH_UPDATE_SUBJECT) && mutt_str_startswith(buf, "Subject:", CASE_IGNORE))
+        continue;
 
       /* Find x -- the array entry where this header is to be saved */
       if (flags & CH_REORDER)
@@ -412,7 +418,8 @@ int mutt_copy_header(FILE *in, struct Email *e, FILE *out, int flags, const char
   {
     flags |= ((e->env->changed & MUTT_ENV_CHANGED_IRT) ? CH_UPDATE_IRT : 0) |
              ((e->env->changed & MUTT_ENV_CHANGED_REFS) ? CH_UPDATE_REFS : 0) |
-             ((e->env->changed & MUTT_ENV_CHANGED_XLABEL) ? CH_UPDATE_LABEL : 0);
+             ((e->env->changed & MUTT_ENV_CHANGED_XLABEL) ? CH_UPDATE_LABEL : 0) |
+             ((e->env->changed & MUTT_ENV_CHANGED_SUBJECT) ? CH_UPDATE_SUBJECT : 0);
   }
 
   if (mutt_copy_hdr(in, out, e->offset, e->content->offset, flags, prefix) == -1)
@@ -525,6 +532,23 @@ int mutt_copy_header(FILE *in, struct Email *e, FILE *out, int flags, const char
       FREE(&temp_hdr);
   }
 
+  if ((flags & CH_UPDATE_SUBJECT) && e->env->subject)
+  {
+    temp_hdr = e->env->subject;
+    /* env->subject is directly referenced in Context->subj_hash, so we
+     * have to be careful not to encode (and thus free) that memory. */
+    if (!(flags & CH_DECODE))
+    {
+      temp_hdr = mutt_str_strdup(temp_hdr);
+      rfc2047_encode(&temp_hdr, NULL, sizeof("Subject:"), SendCharset);
+    }
+    if (mutt_write_one_header(out, "Subject", temp_hdr, flags & CH_PREFIX ? prefix : 0,
+                              mutt_window_wrap_cols(MuttIndexWindow, Wrap), flags) == -1)
+      return -1;
+    if (!(flags & CH_DECODE))
+      FREE(&temp_hdr);
+  }
+
   if ((flags & CH_NONEWLINE) == 0)
   {
     if (flags & CH_PREFIX)
diff --git a/copy.h b/copy.h
index fd4cca89589e84a51c4a40e58c6ece7adf91ce97..596d97ef6b4d0f423be42e8327fa42f9b52800f8 100644 (file)
--- a/copy.h
+++ b/copy.h
@@ -64,7 +64,8 @@ struct Mailbox;
 #define CH_UPDATE_REFS    (1 << 17) /**< update References: */
 #define CH_DISPLAY        (1 << 18) /**< display result to user */
 #define CH_UPDATE_LABEL   (1 << 19) /**< update X-Label: from hdr->env->x_label? */
-#define CH_VIRTUAL        (1 << 20) /**< write virtual header lines too */
+#define CH_UPDATE_SUBJECT (1 << 20) /**< update Subject: protected header update */
+#define CH_VIRTUAL        (1 << 21) /**< write virtual header lines too */
 
 int mutt_copy_hdr(FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end,
                   int flags, const char *prefix);
index 04bfbe108defe820715754c7652a2a3dae0f96ec..c9aa60a7a525f0add5e39a43355ca01c4d3b50ba 100644 (file)
@@ -29,6 +29,7 @@
 #define MUTT_ENV_CHANGED_IRT     (1<<0)  ///< In-Reply-To changed to link/break threads
 #define MUTT_ENV_CHANGED_REFS    (1<<1)  ///< References changed to break thread
 #define MUTT_ENV_CHANGED_XLABEL  (1<<2)  ///< X-Label edited
+#define MUTT_ENV_CHANGED_SUBJECT (1<<3)  ///< Protected header update
 
 /**
  * struct Envelope - The header of an email
index 8d27f1b55d0865b9e0a827e442b6d1718a614cc9..ca75c431cc63da63bccf92684e650615ed87e944 100644 (file)
--- a/globals.h
+++ b/globals.h
@@ -273,6 +273,7 @@ WHERE bool CryptUsePka;                    ///< Config: Use GPGME to use PKA (lo
 WHERE bool CryptConfirmhook;               ///< Config: Prompt the user to confirm keys before use
 WHERE bool CryptOpportunisticEncrypt;      ///< Config: Enable encryption when the recipient's key is available
 WHERE bool CryptProtectedHeadersRead;      ///< Config: Display protected headers (Memory Hole) in the pager
+WHERE bool CryptProtectedHeadersSave;      ///< Config: Save the cleartext Subject with the headers
 WHERE bool CryptProtectedHeadersWrite;     ///< Config: Generate protected header (Memory Hole) for signed and encrypted emails
 WHERE bool SmimeIsDefault;                 ///< Config: Use SMIME rather than PGP by default
 WHERE bool PgpIgnoreSubkeys;               ///< Config: Only use the principal PGP key
diff --git a/init.h b/init.h
index bcfa8a3ee124694a00f41b34c2bfa2dd481113d3..f33fd1abf982ebf8b480169b930ce15e6a7dc998 100644 (file)
--- a/init.h
+++ b/init.h
@@ -679,6 +679,30 @@ struct ConfigDef MuttVars[] = {
   ** the dummy Subject header, so be sure to open such a message first.
   ** (Crypto only)
   */
+  { "crypt_protected_headers_save", DT_BOOL, R_NONE, &CryptProtectedHeadersSave, false },
+  /*
+  ** .pp
+  ** When $$crypt_protected_headers_read is set, and a message with a
+  ** protected Subject is opened, Mutt will save the updated Subject
+  ** into the header cache by default.  This allows searching/limiting
+  ** based on the protected Subject header if the mailbox is
+  ** re-opened, without having to re-open the message each time.
+  ** However, for mbox/mh mailbox types, or if header caching is not
+  ** set up, you would need to re-open the message each time the
+  ** mailbox was reopened before you could see or search/limit on the
+  ** protected subject again.
+  ** .pp
+  ** When this variable is set, Mutt additionally saves the protected
+  ** Subject back \fBin the clear-text message headers\fP.  This
+  ** provides better usability, but with the tradeoff of reduced
+  ** security.  The protected Subject header, which may have
+  ** previously been encrypted, is now stored in clear-text in the
+  ** message headers.  Copying the message elsewhere, via Mutt or
+  ** external tools, could expose this previously encrypted data.
+  ** Please make sure you understand the consequences of this before
+  ** you enable this variable.
+  ** (Crypto only)
+  */
   { "crypt_protected_headers_write", DT_BOOL, R_NONE, &CryptProtectedHeadersWrite, false },
   /*
   ** .pp