From a0553fe67c17a1e15aae47b65a7d79c4d0c91cc8 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Sun, 16 Dec 2018 13:15:05 -0800 Subject: [PATCH] Add config and data structure for protected header write support Add config vars $crypt_protected_headers_write (unset by default), and $crypt_protected_headers_subject. Store the protected headers during mime_protect(). Co-authored-by: Richard Russon --- globals.h | 2 ++ init.h | 30 ++++++++++++++++++++++++++++++ ncrypt/crypt.c | 27 ++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/globals.h b/globals.h index 7ba9f9bd7..8d27f1b55 100644 --- a/globals.h +++ b/globals.h @@ -104,6 +104,7 @@ WHERE char *Attribution; ///< Config: Message to start a reply WHERE char *AttributionLocale; ///< Config: Locale for dates in the attribution message WHERE char *AttachFormat; ///< Config: printf-like format string for the attachment menu WHERE char *ConfigCharset; ///< Config: Character set that the config files are in +WHERE char *CryptProtectedHeadersSubject; ///< Config: Use this as the subject for encrypted emails WHERE char *DateFormat; ///< Config: strftime format string for the `%d` expando WHERE char *DsnNotify; ///< Config: Request notification for message delivery or delay WHERE char *DsnReturn; ///< Config: What to send as a notification of message delivery or delay @@ -272,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 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 WHERE bool PgpLongIds; ///< Config: Display long PGP key IDs to the user diff --git a/init.h b/init.h index f3b361dca..bcfa8a3ee 100644 --- a/init.h +++ b/init.h @@ -669,10 +669,40 @@ struct ConfigDef MuttVars[] = { ** Protected headers are stored inside the encrypted or signed part of an ** an email, to prevent disclosure or tampering. ** For more information see https://github.com/autocrypt/memoryhole. + ** Currently Mutt only supports the Subject header. + ** .pp + ** Encrypted messages using protected headers often substitute the exposed + ** Subject header with a dummy value (see $$crypt_protected_headers_subject). + ** Mutt will update its concept of the correct subject \fBafter\fP the + ** message is opened, i.e. via the \fC\fP function. + ** If you reply to a message before opening it, Mutt will end up using + ** the dummy Subject header, so be sure to open such a message first. + ** (Crypto only) + */ + { "crypt_protected_headers_write", DT_BOOL, R_NONE, &CryptProtectedHeadersWrite, false }, + /* + ** .pp + ** When set, Mutt will generate protected headers ("Memory Hole") for + ** signed and encrypted emails. + ** + ** Protected headers are stored inside the encrypted or signed part of an + ** an email, to prevent disclosure or tampering. + ** For more information see https://github.com/autocrypt/memoryhole. ** ** Currently Mutt only supports the Subject header. ** (Crypto only) */ + { "crypt_protected_headers_subject", DT_STRING, R_NONE, &CryptProtectedHeadersSubject, IP "Encrypted subject" }, + /* + ** .pp + ** When $$crypt_protected_headers_write is set, and the message is marked + ** for encryption, this will be substituted into the Subject field in the + ** message headers. + ** + ** To prevent a subject from being substituted, unset this variable, or set it + ** to the empty string. + ** (Crypto only) + */ { "crypt_replyencrypt", DT_BOOL, R_NONE, &CryptReplyencrypt, true }, /* ** .pp diff --git a/ncrypt/crypt.c b/ncrypt/crypt.c index 02b0c23d7..417501700 100644 --- a/ncrypt/crypt.c +++ b/ncrypt/crypt.c @@ -265,13 +265,25 @@ int mutt_protect(struct Email *msg, char *keylist) mutt_addr_free(&from); } + if (CryptProtectedHeadersWrite) + { + struct Envelope *protected_headers = mutt_env_new(); + mutt_str_replace(&protected_headers->subject, msg->env->subject); + /* Note: if other headers get added, such as to, cc, then a call to + * mutt_env_to_intl() will need to be added here too. */ + mutt_prepare_envelope(protected_headers, 0); + + mutt_env_free(&msg->content->mime_headers); + msg->content->mime_headers = protected_headers; + } + if (msg->security & SIGN) { if (((WithCrypto & APPLICATION_SMIME) != 0) && (msg->security & APPLICATION_SMIME)) { tmp_pbody = crypt_smime_sign_message(msg->content); if (!tmp_pbody) - return -1; + goto bail; pbody = tmp_pbody; tmp_smime_pbody = tmp_pbody; } @@ -281,7 +293,7 @@ int mutt_protect(struct Email *msg, char *keylist) { tmp_pbody = crypt_pgp_sign_message(msg->content); if (!tmp_pbody) - return -1; + goto bail; flags &= ~SIGN; pbody = tmp_pbody; @@ -303,7 +315,7 @@ int mutt_protect(struct Email *msg, char *keylist) if (!tmp_pbody) { /* signed ? free it! */ - return -1; + goto bail; } /* free tmp_body if messages was signed AND encrypted ... */ if (tmp_smime_pbody != msg->content && tmp_smime_pbody != tmp_pbody) @@ -331,7 +343,7 @@ int mutt_protect(struct Email *msg, char *keylist) mutt_body_free(&tmp_pgp_pbody->next); } - return -1; + goto bail; } /* destroy temporary signature envelope when doing retainable @@ -347,9 +359,14 @@ int mutt_protect(struct Email *msg, char *keylist) } if (pbody) + { msg->content = pbody; + return 0; + } - return 0; +bail: + mutt_env_free(&msg->content->mime_headers); + return -1; } /** -- 2.50.0