# HG changeset patch # User Magnus Melin # Date 1529260250 -10800 # Node ID b474dfcfa256b5f5800083d592a8307b430d1303 # Parent 42e58a91a47e4237f226ae27650d70b9c85c6c99 Bug 1464056 - Don't decrypt S/MIME sub parts. Only allow decryption at top level. r=jorgk DONTBUILD diff --git a/mailnews/mailnews.js b/mailnews/mailnews.js --- a/mailnews/mailnews.js +++ b/mailnews/mailnews.js @@ -139,16 +139,17 @@ pref("mail.quoteasblock", pref("mail.strictly_mime", false); pref("mail.strictly_mime_headers", true); // 0/1 (name param is encoded in a legacy way), 2(RFC 2231 only) // 0 the name param is never separated to multiple lines. pref("mail.strictly_mime.parm_folding", 1); pref("mail.label_ascii_only_mail_as_us_ascii", false); pref("mail.file_attach_binary", false); pref("mail.show_headers", 1); // some +pref("mail.decrypt_children", false); // Protect against efail. pref("mail.pane_config.dynamic", 0); pref("mail.addr_book.mapit_url.format", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.1.name", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.1.format", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.2.name", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.2.format", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.3.name", "chrome://messenger-region/locale/region.properties"); pref("mail.addr_book.mapit_url.3.format", "chrome://messenger-region/locale/region.properties"); diff --git a/mailnews/mime/src/mimecryp.cpp b/mailnews/mime/src/mimecryp.cpp --- a/mailnews/mime/src/mimecryp.cpp +++ b/mailnews/mime/src/mimecryp.cpp @@ -413,17 +413,17 @@ MimeEncrypted_emit_buffered_child(MimeOb object, we only emit the HTML once (since the normal way of encrypting and signing is to nest the signature inside the crypto envelope.) */ if (enc->crypto_closure && obj->options && obj->options->headers != MimeHeadersCitation && obj->options->write_html_p && obj->options->output_fn) - // && !mime_crypto_object_p(enc->hdrs, true)) // XXX fix later XXX // + // && !mime_crypto_object_p(enc->hdrs, true, obj->options)) // XXX fix later XXX // { char *html; #if 0 // XXX Fix this later XXX // char *html = (((MimeEncryptedClass *) obj->clazz)->crypto_generate_html (enc->crypto_closure)); if (!html) return -1; /* MK_OUT_OF_MEMORY? */ status = MimeObject_write(obj, html, strlen(html), false); diff --git a/mailnews/mime/src/mimei.cpp b/mailnews/mime/src/mimei.cpp --- a/mailnews/mime/src/mimei.cpp +++ b/mailnews/mime/src/mimei.cpp @@ -63,21 +63,24 @@ #include "nsXPCOMCID.h" #include "nsISimpleMimeConverter.h" #include "nsSimpleMimeConverterStub.h" #include "nsTArray.h" #include "nsMimeStringResources.h" #include "nsMimeTypes.h" #include "nsMsgUtils.h" #include "nsIPrefBranch.h" +#include "mozilla/Preferences.h" #include "imgLoader.h" #include "nsIMsgMailNewsUrl.h" #include "nsIMsgHdr.h" +using namespace mozilla; + // forward declaration void getMsgHdrForCurrentURL(MimeDisplayOptions *opts, nsIMsgDBHdr ** aMsgHdr); #define IMAP_EXTERNAL_CONTENT_HEADER "X-Mozilla-IMAP-Part" #define EXTERNAL_ATTACHMENT_URL_HEADER "X-Mozilla-External-Attachment-URL" /* ========================================================================== Allocation and destruction @@ -708,17 +711,28 @@ mime_find_class (const char *content_typ clazz = (MimeObjectClass *)&mimeInlineImageClass; else clazz = (MimeObjectClass *)&mimeExternalObjectClass; } #ifdef ENABLE_SMIME else if (!PL_strcasecmp(content_type, APPLICATION_XPKCS7_MIME) || !PL_strcasecmp(content_type, APPLICATION_PKCS7_MIME)) { - char *ct = (hdrs ? MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE, + + if (!Preferences::GetBool("mail.decrypt_children", false) && + opts->is_child) { + // We do not allow encrypted parts except as top level. + // Allowing them would leak the plain text in case the part is + // cleverly hidden and the decrypted content gets included in + // replies and forwards. + clazz = (MimeObjectClass *)&mimeExternalObjectClass; + return clazz; + } + + char *ct = (hdrs ? MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE, false, false) : nullptr); char *st = (ct ? MimeHeaders_get_parameter(ct, "smime-type", NULL, NULL) : nullptr); /* by default, assume that it is an encrypted message */ clazz = (MimeObjectClass *)&mimeEncryptedCMSClass; @@ -1163,17 +1177,17 @@ mime_external_attachment_url(MimeObject } #ifdef ENABLE_SMIME /* Asks whether the given object is one of the cryptographically signed or encrypted objects that we know about. (MimeMessageClass uses this to decide if the headers need to be presented differently.) */ bool -mime_crypto_object_p(MimeHeaders *hdrs, bool clearsigned_counts) +mime_crypto_object_p(MimeHeaders *hdrs, bool clearsigned_counts, MimeDisplayOptions *opts) { char *ct; MimeObjectClass *clazz; if (!hdrs) return false; ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, true, false); if (!ct) return false; @@ -1182,17 +1196,17 @@ mime_crypto_object_p(MimeHeaders *hdrs, if (PL_strcasecmp(ct, MULTIPART_SIGNED) && PL_strncasecmp(ct, "application/", 12)) { PR_Free(ct); return false; } /* It's a candidate for being a crypto object. Let's find out for sure... */ - clazz = mime_find_class (ct, hdrs, 0, true); + clazz = mime_find_class(ct, hdrs, opts, true); PR_Free(ct); if (clazz == ((MimeObjectClass *)&mimeEncryptedCMSClass)) return true; else if (clearsigned_counts && clazz == ((MimeObjectClass *)&mimeMultipartSignedCMSClass)) return true; else diff --git a/mailnews/mime/src/mimei.h b/mailnews/mime/src/mimei.h --- a/mailnews/mime/src/mimei.h +++ b/mailnews/mime/src/mimei.h @@ -318,17 +318,17 @@ extern char *mime_find_content_type_of_p extern int mime_parse_url_options(const char *url, MimeDisplayOptions *); #ifdef ENABLE_SMIME /* Asks whether the given object is one of the cryptographically signed or encrypted objects that we know about. (MimeMessageClass uses this to decide if the headers need to be presented differently.) */ -extern bool mime_crypto_object_p(MimeHeaders *, bool clearsigned_counts); +extern bool mime_crypto_object_p(MimeHeaders *, bool clearsigned_counts, MimeDisplayOptions *); /* Tells whether the given MimeObject is a message which has been encrypted or signed. (Helper for MIME_GetMessageCryptoState()). */ extern void mime_get_crypto_state (MimeObject *obj, bool *signed_p, bool *encrypted_p, bool *signed_ok, bool *encrypted_ok); diff --git a/mailnews/mime/src/mimemsg.cpp b/mailnews/mime/src/mimemsg.cpp --- a/mailnews/mime/src/mimemsg.cpp +++ b/mailnews/mime/src/mimemsg.cpp @@ -307,17 +307,17 @@ MimeMessage_close_headers (MimeObject *o #ifdef MIME_DRAFTS if (outer_p && obj->options && (obj->options->decompose_file_p || obj->options->caller_need_root_headers) && obj->options->decompose_headers_info_fn) { #ifdef ENABLE_SMIME - if (obj->options->decrypt_p && !mime_crypto_object_p (msg->hdrs, false)) + if (obj->options->decrypt_p && !mime_crypto_object_p(msg->hdrs, false, obj->options)) obj->options->decrypt_p = false; #endif /* ENABLE_SMIME */ if (!obj->options->caller_need_root_headers || (obj == obj->options->state->root)) status = obj->options->decompose_headers_info_fn ( obj->options->stream_closure, msg->hdrs ); } #endif /* MIME_DRAFTS */ @@ -406,17 +406,17 @@ MimeMessage_close_headers (MimeObject *o /* If this message has a body which is encrypted and we're going to decrypt it (whithout converting it to HTML, since decrypt_p and write_html_p are never true at the same time) */ if (obj->output_p && obj->options && obj->options->decrypt_p #ifdef ENABLE_SMIME - && !mime_crypto_object_p (msg->hdrs, false) + && !mime_crypto_object_p(msg->hdrs, false, obj->options) #endif /* ENABLE_SMIME */ ) { /* The body of this message is not an encrypted object, so we need to turn off the decrypt_p flag (to prevent us from s#$%ing the body of the internal object up into one.) In this case, our output will end up being identical to our input. */ diff --git a/mailnews/mime/src/mimemult.cpp b/mailnews/mime/src/mimemult.cpp --- a/mailnews/mime/src/mimemult.cpp +++ b/mailnews/mime/src/mimemult.cpp @@ -425,16 +425,19 @@ MimeMultipart_create_child(MimeObject *o char *ct = (mult->hdrs ? MimeHeaders_get (mult->hdrs, HEADER_CONTENT_TYPE, true, false) : 0); const char *dct = (((MimeMultipartClass *) obj->clazz)->default_part_type); MimeObject *body = NULL; mult->state = MimeMultipartPartFirstLine; + if (obj->options) + obj->options->is_child = true; + /* Don't pass in NULL as the content-type (this means that the auto-uudecode-hack won't ever be done for subparts of a multipart, but only for untyped children of message/rfc822. */ body = mime_create(((ct && *ct) ? ct : (dct ? dct: TEXT_PLAIN)), mult->hdrs, obj->options); PR_FREEIF(ct); if (!body) return MIME_OUT_OF_MEMORY; diff --git a/mailnews/mime/src/modlmime.h b/mailnews/mime/src/modlmime.h --- a/mailnews/mime/src/modlmime.h +++ b/mailnews/mime/src/modlmime.h @@ -172,16 +172,19 @@ public: eradicated -- this is only meaningful when write_html_p is false; we set this when attaching a message for forwarding, since forwarding someone else a message that wasn't xlated for them doesn't work. We have to dexlate it before sending it. */ + /* Whether this MIME part is a child of another part (and not top level). */ + bool is_child = false; + uint32_t whattodo ; /* from the prefs, we'll get if the user wants to do glyph or structure substitutions and set this member variable. */ char *default_charset; /* If this is non-NULL, then it is the charset to assume when no other one is specified via a `charset' parameter. */ bool override_charset; /* If this is true, then we will assume that all data is in the default_charset, regardless