summaryrefslogtreecommitdiff
path: root/mailnews/mime/src/mimemcms.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mailnews/mime/src/mimemcms.cpp')
-rw-r--r--mailnews/mime/src/mimemcms.cpp177
1 files changed, 98 insertions, 79 deletions
diff --git a/mailnews/mime/src/mimemcms.cpp b/mailnews/mime/src/mimemcms.cpp
index 1a281b1620..96aa5481f2 100644
--- a/mailnews/mime/src/mimemcms.cpp
+++ b/mailnews/mime/src/mimemcms.cpp
@@ -38,6 +38,7 @@ static int MimeMultCMS_sig_eof (void *, bool);
static int MimeMultCMS_sig_init (void *, MimeObject *, MimeHeaders *);
static char * MimeMultCMS_generate (void *);
static void MimeMultCMS_free (void *);
+static void MimeMultCMS_suppressed_child(void *crypto_closure);
extern int SEC_ERROR_CERT_ADDR_MISMATCH;
@@ -56,6 +57,7 @@ MimeMultipartSignedCMSClassInitialize(MimeMultipartSignedCMSClass *clazz)
sclass->crypto_signature_hash = MimeMultCMS_sig_hash;
sclass->crypto_signature_eof = MimeMultCMS_sig_eof;
sclass->crypto_generate_html = MimeMultCMS_generate;
+ sclass->crypto_notify_suppressed_child = MimeMultCMS_suppressed_child;
sclass->crypto_free = MimeMultCMS_free;
PR_ASSERT(!oclass->class_initialized);
@@ -80,8 +82,6 @@ typedef struct MimeMultCMSdata
unsigned char* item_data;
uint32_t item_len;
MimeObject *self;
- bool parent_is_encrypted_p;
- bool parent_holds_stamp_p;
nsCOMPtr<nsIMsgSMIMEHeaderSink> smimeHeaderSink;
nsCString url;
@@ -90,11 +90,7 @@ typedef struct MimeMultCMSdata
sender_addr(nullptr),
decoding_failed(false),
item_data(nullptr),
- self(nullptr),
- parent_is_encrypted_p(false),
- parent_holds_stamp_p(false)
- {
- }
+ self(nullptr) {}
~MimeMultCMSdata()
{
@@ -113,7 +109,7 @@ typedef struct MimeMultCMSdata
/* #### MimeEncryptedCMS and MimeMultipartSignedCMS have a sleazy,
incestuous, dysfunctional relationship. */
-extern bool MimeEncryptedCMS_encrypted_p (MimeObject *obj);
+extern bool MimeAnyParentCMSSigned(MimeObject *obj);
extern void MimeCMSGetFromSender(MimeObject *obj,
nsCString &from_addr,
nsCString &from_name,
@@ -142,82 +138,11 @@ MimeMultCMS_init (MimeObject *obj)
int16_t hash_type;
nsresult rv;
- ct = MimeHeaders_get (hdrs, HEADER_CONTENT_TYPE, false, false);
- if (!ct) return 0; /* #### bogus message? out of memory? */
- micalg = MimeHeaders_get_parameter (ct, PARAM_MICALG, NULL, NULL);
- PR_Free(ct);
- ct = 0;
- if (!micalg) return 0; /* #### bogus message? out of memory? */
-
- if (!PL_strcasecmp(micalg, PARAM_MICALG_MD5) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_MD5_2))
- hash_type = nsICryptoHash::MD5;
- else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA1) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_5))
- hash_type = nsICryptoHash::SHA1;
- else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA256) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA256_2) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA256_3))
- hash_type = nsICryptoHash::SHA256;
- else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA384) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA384_2) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA384_3))
- hash_type = nsICryptoHash::SHA384;
- else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA512) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA512_2) ||
- !PL_strcasecmp(micalg, PARAM_MICALG_SHA512_3))
- hash_type = nsICryptoHash::SHA512;
- else if (!PL_strcasecmp(micalg, PARAM_MICALG_MD2))
- hash_type = nsICryptoHash::MD2;
- else
- hash_type = -1;
-
- PR_Free(micalg);
- micalg = 0;
-
- if (hash_type == -1) return 0; /* #### bogus message? */
-
data = new MimeMultCMSdata;
if (!data)
return 0;
data->self = obj;
- data->hash_type = hash_type;
-
- data->data_hash_context = do_CreateInstance("@mozilla.org/security/hash;1", &rv);
- if (NS_FAILED(rv))
- {
- delete data;
- return 0;
- }
-
- rv = data->data_hash_context->Init(data->hash_type);
- if (NS_FAILED(rv))
- {
- delete data;
- return 0;
- }
-
- PR_SetError(0,0);
-
- data->parent_holds_stamp_p =
- (obj->parent && mime_crypto_stamped_p(obj->parent));
-
- data->parent_is_encrypted_p =
- (obj->parent && MimeEncryptedCMS_encrypted_p (obj->parent));
-
- /* If the parent of this object is a crypto-blob, then it's the grandparent
- who would have written out the headers and prepared for a stamp...
- (This s##t s$%#s.)
- */
- if (data->parent_is_encrypted_p &&
- !data->parent_holds_stamp_p &&
- obj->parent && obj->parent->parent)
- data->parent_holds_stamp_p =
- mime_crypto_stamped_p (obj->parent->parent);
mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
if (msd)
@@ -266,6 +191,89 @@ MimeMultCMS_init (MimeObject *obj)
} // if channel
} // if msd
+ if (obj->parent && MimeAnyParentCMSSigned(obj)) {
+ // Parent is signed. We know this part is a signature, too, because
+ // multipart doesn't allow encryption.
+ // We don't support "inner sign" with outer sign, because the
+ // inner encrypted part could have been produced by an attacker who
+ // stripped away a part containing the signature (S/MIME doesn't
+ // have integrity protection).
+ // Also we don't want to support sign-then-sign, that's misleading,
+ // which part would be shown as having a signature?
+ // TODO: should we show all contents, without any signature info?
+
+ if (data->smimeHeaderSink) {
+ data->smimeHeaderSink->SignedStatus(
+ MIMEGetRelativeCryptoNestLevel(data->self),
+ nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
+ }
+ delete data;
+ PR_SetError(-1, 0);
+ return 0;
+ }
+
+ ct = MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE, false, false);
+ if (!ct) {
+ delete data;
+ return 0; /* #### bogus message? out of memory? */
+ }
+ micalg = MimeHeaders_get_parameter(ct, PARAM_MICALG, NULL, NULL);
+ PR_Free(ct);
+ ct = 0;
+ if (!micalg) {
+ delete data;
+ return 0; /* #### bogus message? out of memory? */
+ }
+
+ if (!PL_strcasecmp(micalg, PARAM_MICALG_MD5) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_MD5_2))
+ hash_type = nsICryptoHash::MD5;
+ else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA1) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_2) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_3) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_4) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA1_5))
+ hash_type = nsICryptoHash::SHA1;
+ else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA256) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA256_2) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA256_3))
+ hash_type = nsICryptoHash::SHA256;
+ else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA384) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA384_2) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA384_3))
+ hash_type = nsICryptoHash::SHA384;
+ else if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA512) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA512_2) ||
+ !PL_strcasecmp(micalg, PARAM_MICALG_SHA512_3))
+ hash_type = nsICryptoHash::SHA512;
+ else
+ hash_type = -1;
+
+ PR_Free(micalg);
+ micalg = 0;
+
+ if (hash_type == -1) {
+ delete data;
+ return 0; /* #### bogus message? */
+ }
+
+ data->hash_type = hash_type;
+
+ data->data_hash_context =
+ do_CreateInstance("@mozilla.org/security/hash;1", &rv);
+ if (NS_FAILED(rv)) {
+ delete data;
+ return 0;
+ }
+
+ rv = data->data_hash_context->Init(data->hash_type);
+ if (NS_FAILED(rv)) {
+ delete data;
+ return 0;
+ }
+
+ PR_SetError(0, 0);
+
return data;
}
@@ -400,6 +408,17 @@ MimeMultCMS_free (void *crypto_closure)
delete data;
}
+static void MimeMultCMS_suppressed_child(void *crypto_closure) {
+ // I'm a multipart/signed. If one of my cryptographic child elements
+ // was suppressed, then I want my signature to be shown as invalid.
+ MimeMultCMSdata *data = (MimeMultCMSdata *)crypto_closure;
+ if (data && data->smimeHeaderSink) {
+ data->smimeHeaderSink->SignedStatus(
+ MIMEGetRelativeCryptoNestLevel(data->self),
+ nsICMSMessageErrors::GENERAL_ERROR, nullptr, data->url);
+ }
+}
+
static char *
MimeMultCMS_generate (void *crypto_closure)
{