From 0f6b89bd267e566a82d12931d8788c42e815d828 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Thu, 27 Dec 2018 12:05:43 -0800 Subject: [PATCH] Add $crypt_protected_headers_save 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 --- commands.c | 8 ++++++++ copy.c | 26 +++++++++++++++++++++++++- copy.h | 3 ++- email/envelope.h | 1 + globals.h | 1 + init.h | 24 ++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 2 deletions(-) diff --git a/commands.c b/commands.c index 94c5e00fe..c76aa1418 100644 --- a/commands.c +++ b/commands.c @@ -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 6370a44a6..4beed6546 100644 --- 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 fd4cca895..596d97ef6 100644 --- 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); diff --git a/email/envelope.h b/email/envelope.h index 04bfbe108..c9aa60a7a 100644 --- a/email/envelope.h +++ b/email/envelope.h @@ -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 diff --git a/globals.h b/globals.h index 8d27f1b55..ca75c431c 100644 --- 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 bcfa8a3ee..f33fd1abf 100644 --- 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 -- 2.40.0