Bug 1854592 - Introduce a pref to optionally accept S/MIME message signatures that use SHA-1. r=mkmelin
Differential Revision: https://phabricator.services.mozilla.com/D191203 --HG-- rename : mailnews/mime/test/unit/test_smime_decrypt.js => mailnews/mime/test/unit/test_smime_decrypt_allow_sha1.js extra : amend_source : 05c7fdea97d37d9cdc64e46b533cb9dbc8ba9de8
This commit is contained in:
Родитель
af4a75d890
Коммит
7ede5c31ed
|
@ -94,6 +94,8 @@ pref("mail.openpgp.remind_encryption_possible", true);
|
|||
// sent with S/MIME encryption (without further user actions/decisions).
|
||||
pref("mail.smime.remind_encryption_possible", true);
|
||||
|
||||
pref("mail.smime.accept_insecure_sha1_message_signatures", false);
|
||||
|
||||
// When sending, encrypt to this additional key. Not available in release channel builds.
|
||||
pref("mail.openpgp.debug.extra_encryption_key", "");
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "secerr.h"
|
||||
#include "smime.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::psm;
|
||||
|
@ -50,8 +51,8 @@ nsresult nsCMSMessage::Init() {
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCMSMessage::VerifySignature() {
|
||||
return CommonVerifySignature({}, 0);
|
||||
NS_IMETHODIMP nsCMSMessage::VerifySignature(int32_t verifyFlags) {
|
||||
return CommonVerifySignature(verifyFlags, {}, 0);
|
||||
}
|
||||
|
||||
NSSCMSSignerInfo* nsCMSMessage::GetTopLevelSignerInfo() {
|
||||
|
@ -147,11 +148,12 @@ NS_IMETHODIMP nsCMSMessage::GetEncryptionCert(nsIX509Cert**) {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCMSMessage::VerifyDetachedSignature(const nsTArray<uint8_t>& aDigestData,
|
||||
nsCMSMessage::VerifyDetachedSignature(int32_t verifyFlags,
|
||||
const nsTArray<uint8_t>& aDigestData,
|
||||
int16_t aDigestType) {
|
||||
if (aDigestData.IsEmpty()) return NS_ERROR_FAILURE;
|
||||
|
||||
return CommonVerifySignature(aDigestData, aDigestType);
|
||||
return CommonVerifySignature(verifyFlags, aDigestData, aDigestType);
|
||||
}
|
||||
|
||||
// This is an exact copy of NSS_CMSArray_Count from NSS' cmsarray.c,
|
||||
|
@ -391,7 +393,8 @@ loser:
|
|||
}
|
||||
|
||||
nsresult nsCMSMessage::CommonVerifySignature(
|
||||
const nsTArray<uint8_t>& aDigestData, int16_t aDigestType) {
|
||||
int32_t verifyFlags, const nsTArray<uint8_t>& aDigestData,
|
||||
int16_t aDigestType) {
|
||||
MOZ_LOG(gCMSLog, LogLevel::Debug,
|
||||
("nsCMSMessage::CommonVerifySignature, content level count %d",
|
||||
NSS_CMSMessage_ContentLevelCount(m_cmsMsg)));
|
||||
|
@ -506,6 +509,15 @@ nsresult nsCMSMessage::CommonVerifySignature(
|
|||
case SEC_OID_SHA512:
|
||||
break;
|
||||
|
||||
case SEC_OID_SHA1:
|
||||
if (verifyFlags & nsICMSVerifyFlags::VERIFY_ALLOW_WEAK_SHA1) {
|
||||
break;
|
||||
}
|
||||
// else fall through to failure
|
||||
#if defined(__clang__)
|
||||
[[clang::fallthrough]];
|
||||
#endif
|
||||
|
||||
default:
|
||||
MOZ_LOG(
|
||||
gCMSLog, LogLevel::Debug,
|
||||
|
@ -583,28 +595,30 @@ loser:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP nsCMSMessage::AsyncVerifySignature(
|
||||
nsISMimeVerificationListener* aListener) {
|
||||
return CommonAsyncVerifySignature(aListener, {}, 0);
|
||||
int32_t verifyFlags, nsISMimeVerificationListener* aListener) {
|
||||
return CommonAsyncVerifySignature(verifyFlags, aListener, {}, 0);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCMSMessage::AsyncVerifyDetachedSignature(
|
||||
nsISMimeVerificationListener* aListener,
|
||||
int32_t verifyFlags, nsISMimeVerificationListener* aListener,
|
||||
const nsTArray<uint8_t>& aDigestData, int16_t aDigestType) {
|
||||
if (aDigestData.IsEmpty()) return NS_ERROR_FAILURE;
|
||||
|
||||
return CommonAsyncVerifySignature(aListener, aDigestData, aDigestType);
|
||||
return CommonAsyncVerifySignature(verifyFlags, aListener, aDigestData,
|
||||
aDigestType);
|
||||
}
|
||||
|
||||
class SMimeVerificationTask final : public CryptoTask {
|
||||
public:
|
||||
SMimeVerificationTask(nsICMSMessage* aMessage,
|
||||
SMimeVerificationTask(nsICMSMessage* aMessage, int32_t verifyFlags,
|
||||
nsISMimeVerificationListener* aListener,
|
||||
const nsTArray<uint8_t>& aDigestData,
|
||||
int16_t aDigestType)
|
||||
: mMessage(aMessage),
|
||||
mListener(aListener),
|
||||
mDigestData(aDigestData.Clone()),
|
||||
mDigestType(aDigestType) {
|
||||
mDigestType(aDigestType),
|
||||
mVerifyFlags(verifyFlags) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
|
@ -618,9 +632,10 @@ class SMimeVerificationTask final : public CryptoTask {
|
|||
mozilla::StaticMutexAutoLock lock(sMutex);
|
||||
nsresult rv;
|
||||
if (mDigestData.IsEmpty()) {
|
||||
rv = mMessage->VerifySignature();
|
||||
rv = mMessage->VerifySignature(mVerifyFlags);
|
||||
} else {
|
||||
rv = mMessage->VerifyDetachedSignature(mDigestData, mDigestType);
|
||||
rv = mMessage->VerifyDetachedSignature(mVerifyFlags, mDigestData,
|
||||
mDigestType);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -634,6 +649,7 @@ class SMimeVerificationTask final : public CryptoTask {
|
|||
nsCOMPtr<nsISMimeVerificationListener> mListener;
|
||||
nsTArray<uint8_t> mDigestData;
|
||||
int16_t mDigestType;
|
||||
int32_t mVerifyFlags;
|
||||
|
||||
static mozilla::StaticMutex sMutex;
|
||||
};
|
||||
|
@ -641,10 +657,10 @@ class SMimeVerificationTask final : public CryptoTask {
|
|||
mozilla::StaticMutex SMimeVerificationTask::sMutex;
|
||||
|
||||
nsresult nsCMSMessage::CommonAsyncVerifySignature(
|
||||
nsISMimeVerificationListener* aListener,
|
||||
int32_t verifyFlags, nsISMimeVerificationListener* aListener,
|
||||
const nsTArray<uint8_t>& aDigestData, int16_t aDigestType) {
|
||||
RefPtr<CryptoTask> task =
|
||||
new SMimeVerificationTask(this, aListener, aDigestData, aDigestType);
|
||||
RefPtr<CryptoTask> task = new SMimeVerificationTask(
|
||||
this, verifyFlags, aListener, aDigestData, aDigestType);
|
||||
return task->Dispatch();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,10 +40,12 @@ class nsCMSMessage : public nsICMSMessage {
|
|||
nsCOMPtr<nsIInterfaceRequestor> m_ctx;
|
||||
NSSCMSMessage* m_cmsMsg;
|
||||
NSSCMSSignerInfo* GetTopLevelSignerInfo();
|
||||
nsresult CommonVerifySignature(const nsTArray<uint8_t>& aDigestData,
|
||||
nsresult CommonVerifySignature(int32_t verifyFlags,
|
||||
const nsTArray<uint8_t>& aDigestData,
|
||||
int16_t aDigestType);
|
||||
|
||||
nsresult CommonAsyncVerifySignature(nsISMimeVerificationListener* aListener,
|
||||
nsresult CommonAsyncVerifySignature(int32_t verifyFlags,
|
||||
nsISMimeVerificationListener* aListener,
|
||||
const nsTArray<uint8_t>& aDigestData,
|
||||
int16_t aDigestType);
|
||||
bool IsAllowedHash(const int16_t aCryptoHashInt);
|
||||
|
|
|
@ -19,6 +19,13 @@ interface nsISMimeVerificationListener;
|
|||
|
||||
interface nsIX509Cert;
|
||||
|
||||
[uuid(cd76ec81-02f0-41a3-8852-c0acce0bab53)]
|
||||
interface nsICMSVerifyFlags : nsISupports
|
||||
{
|
||||
const long NONE = 0;
|
||||
const long VERIFY_ALLOW_WEAK_SHA1 = 1 << 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* nsICMSMessage
|
||||
* Interface to a CMS Message
|
||||
|
@ -32,8 +39,17 @@ interface nsICMSMessage : nsISupports
|
|||
void getSignerEmailAddress(out string aEmail);
|
||||
void getSignerCert(out nsIX509Cert scert);
|
||||
void getEncryptionCert(out nsIX509Cert ecert);
|
||||
void verifySignature();
|
||||
void verifyDetachedSignature(in Array<octet> aDigestData,
|
||||
|
||||
/**
|
||||
* @param verifyFlags - Optional flags from nsICMSVerifyFlags.
|
||||
*/
|
||||
void verifySignature(in long verifyFlags);
|
||||
|
||||
/**
|
||||
* @param verifyFlags - Optional flags from nsICMSVerifyFlags.
|
||||
*/
|
||||
void verifyDetachedSignature(in long verifyFlags,
|
||||
in Array<octet> aDigestData,
|
||||
in int16_t aDigestType);
|
||||
void CreateEncrypted(in Array<nsIX509Cert> aRecipientCerts);
|
||||
|
||||
|
@ -47,7 +63,8 @@ interface nsICMSMessage : nsISupports
|
|||
* availability of results will be notified using a
|
||||
* call to nsISMimeVerificationListener.
|
||||
*/
|
||||
void asyncVerifySignature(in nsISMimeVerificationListener listener);
|
||||
void asyncVerifySignature(in long verifyFlags,
|
||||
in nsISMimeVerificationListener listener);
|
||||
|
||||
/**
|
||||
* Async version of nsICMSMessage::VerifyDetachedSignature.
|
||||
|
@ -57,7 +74,8 @@ interface nsICMSMessage : nsISupports
|
|||
*
|
||||
* Set aDigestType to one of the values from nsICryptoHash.
|
||||
*/
|
||||
void asyncVerifyDetachedSignature(in nsISMimeVerificationListener listener,
|
||||
void asyncVerifyDetachedSignature(in long verifyFlags,
|
||||
in nsISMimeVerificationListener listener,
|
||||
in Array<octet> aDigestData,
|
||||
in int16_t aDigestType);
|
||||
};
|
||||
|
|
|
@ -596,10 +596,18 @@ void MimeCMSRequestAsyncSignatureVerification(
|
|||
new nsSMimeVerificationListener(
|
||||
aFromAddr, aFromName, aSenderAddr, aSenderName, aHeaderSink,
|
||||
aMimeNestingLevel, aMsgNeckoURL, aOriginMimePartNumber);
|
||||
|
||||
long verifyFlags = 0;
|
||||
if (mozilla::Preferences::GetBool(
|
||||
"mail.smime.accept_insecure_sha1_message_signatures", false)) {
|
||||
verifyFlags |= nsICMSVerifyFlags::VERIFY_ALLOW_WEAK_SHA1;
|
||||
}
|
||||
|
||||
if (aDigestData.IsEmpty())
|
||||
aCMSMsg->AsyncVerifySignature(listener);
|
||||
aCMSMsg->AsyncVerifySignature(verifyFlags, listener);
|
||||
else
|
||||
aCMSMsg->AsyncVerifyDetachedSignature(listener, aDigestData, aDigestType);
|
||||
aCMSMsg->AsyncVerifyDetachedSignature(verifyFlags, listener, aDigestData,
|
||||
aDigestType);
|
||||
}
|
||||
|
||||
static int MimeCMS_eof(void* crypto_closure, bool abort_p) {
|
||||
|
|
|
@ -205,9 +205,18 @@ static void* MimeMultCMS_init(MimeObject* obj) {
|
|||
return 0; /* #### bogus message? out of memory? */
|
||||
}
|
||||
|
||||
if (!PL_strcasecmp(micalg, PARAM_MICALG_SHA256) ||
|
||||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_2) ||
|
||||
!PL_strcasecmp(micalg, PARAM_MICALG_SHA256_3))
|
||||
bool allowSha1 = mozilla::Preferences::GetBool(
|
||||
"mail.smime.accept_insecure_sha1_message_signatures", false);
|
||||
|
||||
if (allowSha1 && (!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) ||
|
||||
|
|
|
@ -0,0 +1,717 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This file is mostly a copy of test_smime_decrypt.js
|
||||
* with the difference that pref
|
||||
* mail.smime.accept_insecure_sha1_message_signatures is set to true,
|
||||
* and tests using sha-1 are expected to pass.
|
||||
*
|
||||
* This file must not run in parallel with other s/mime tests.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests to ensure signed and/or encrypted S/MIME messages are
|
||||
* processed correctly, and the signature status is treated as good
|
||||
* or bad as expected.
|
||||
*/
|
||||
|
||||
var { MessageInjection } = ChromeUtils.import(
|
||||
"resource://testing-common/mailnews/MessageInjection.jsm"
|
||||
);
|
||||
var { PromiseTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/mailnews/PromiseTestUtils.jsm"
|
||||
);
|
||||
var { PromiseUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/PromiseUtils.sys.mjs"
|
||||
);
|
||||
var { SmimeUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/mailnews/smimeUtils.jsm"
|
||||
);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(
|
||||
"mail.smime.accept_insecure_sha1_message_signatures"
|
||||
);
|
||||
});
|
||||
|
||||
add_setup(function () {
|
||||
Services.prefs.setBoolPref(
|
||||
"mail.smime.accept_insecure_sha1_message_signatures",
|
||||
true
|
||||
);
|
||||
|
||||
let messageInjection = new MessageInjection({ mode: "local" });
|
||||
gInbox = messageInjection.getInboxFolder();
|
||||
SmimeUtils.ensureNSS();
|
||||
|
||||
SmimeUtils.loadPEMCertificate(
|
||||
do_get_file(smimeDataDirectory + "TestCA.pem"),
|
||||
Ci.nsIX509Cert.CA_CERT
|
||||
);
|
||||
SmimeUtils.loadCertificateAndKey(
|
||||
do_get_file(smimeDataDirectory + "Alice.p12"),
|
||||
"nss"
|
||||
);
|
||||
SmimeUtils.loadCertificateAndKey(
|
||||
do_get_file(smimeDataDirectory + "Bob.p12"),
|
||||
"nss"
|
||||
);
|
||||
SmimeUtils.loadCertificateAndKey(
|
||||
do_get_file(smimeDataDirectory + "Dave.p12"),
|
||||
"nss"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function verifyTestCertsStillValid() {
|
||||
// implementation of nsIDoneFindCertForEmailCallback
|
||||
var doneFindCertForEmailCallback = {
|
||||
findCertDone(email, cert) {
|
||||
Assert.notEqual(cert, null);
|
||||
if (!cert) {
|
||||
Assert.ok(
|
||||
false,
|
||||
"The S/MIME test certificates are invalid today.\n" +
|
||||
"Please look at the expiration date in file comm/mailnews/test/data/smime/expiration.txt\n" +
|
||||
"If that date is in the past, new certificates need to be generated and committed.\n" +
|
||||
"Follow the instructions in comm/mailnews/test/data/smime/README.md\n" +
|
||||
"If that date is in the future, the test failure is unrelated to expiration and indicates " +
|
||||
"an error in certificate validation."
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIDoneFindCertForEmailCallback"]),
|
||||
};
|
||||
|
||||
let composeSecure = Cc[
|
||||
"@mozilla.org/messengercompose/composesecure;1"
|
||||
].createInstance(Ci.nsIMsgComposeSecure);
|
||||
composeSecure.asyncFindCertByEmailAddr(
|
||||
"Alice@example.com",
|
||||
doneFindCertForEmailCallback
|
||||
);
|
||||
});
|
||||
|
||||
var gInbox;
|
||||
|
||||
var smimeDataDirectory = "../../../data/smime/";
|
||||
|
||||
let smimeHeaderSink = {
|
||||
expectResults(maxLen) {
|
||||
// dump("Restarting for next test\n");
|
||||
this._deferred = PromiseUtils.defer();
|
||||
this._expectedEvents = maxLen;
|
||||
this.countReceived = 0;
|
||||
this._results = [];
|
||||
this.haveSignedBad = false;
|
||||
this.haveEncryptionBad = false;
|
||||
this.resultSig = null;
|
||||
this.resultEnc = null;
|
||||
this.resultSigFirst = undefined;
|
||||
return this._deferred.promise;
|
||||
},
|
||||
signedStatus(aNestingLevel, aSignedStatus, aSignerCert) {
|
||||
console.log("signedStatus " + aSignedStatus + " level " + aNestingLevel);
|
||||
// dump("Signed message\n");
|
||||
Assert.equal(aNestingLevel, 1);
|
||||
if (!this.haveSignedBad) {
|
||||
// override with newer allowed
|
||||
this.resultSig = {
|
||||
type: "signed",
|
||||
status: aSignedStatus,
|
||||
certificate: aSignerCert,
|
||||
};
|
||||
if (aSignedStatus != 0) {
|
||||
this.haveSignedBad = true;
|
||||
}
|
||||
if (this.resultSigFirst == undefined) {
|
||||
this.resultSigFirst = true;
|
||||
}
|
||||
}
|
||||
this.countReceived++;
|
||||
this.checkFinished();
|
||||
},
|
||||
encryptionStatus(aNestingLevel, aEncryptedStatus, aRecipientCert) {
|
||||
console.log(
|
||||
"encryptionStatus " + aEncryptedStatus + " level " + aNestingLevel
|
||||
);
|
||||
// dump("Encrypted message\n");
|
||||
Assert.equal(aNestingLevel, 1);
|
||||
if (!this.haveEncryptionBad) {
|
||||
// override with newer allowed
|
||||
this.resultEnc = {
|
||||
type: "encrypted",
|
||||
status: aEncryptedStatus,
|
||||
certificate: aRecipientCert,
|
||||
};
|
||||
if (aEncryptedStatus != 0) {
|
||||
this.haveEncryptionBad = true;
|
||||
}
|
||||
if (this.resultSigFirst == undefined) {
|
||||
this.resultSigFirst = false;
|
||||
}
|
||||
}
|
||||
this.countReceived++;
|
||||
this.checkFinished();
|
||||
},
|
||||
checkFinished() {
|
||||
if (this.countReceived == this._expectedEvents) {
|
||||
if (this.resultSigFirst) {
|
||||
this._results.push(this.resultSig);
|
||||
if (this.resultEnc != null) {
|
||||
this._results.push(this.resultEnc);
|
||||
}
|
||||
} else {
|
||||
this._results.push(this.resultEnc);
|
||||
if (this.resultSig != null) {
|
||||
this._results.push(this.resultSig);
|
||||
}
|
||||
}
|
||||
this._deferred.resolve(this._results);
|
||||
}
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIMsgSMIMEHeaderSink"]),
|
||||
};
|
||||
|
||||
/**
|
||||
* Note on FILENAMES taken from the NSS test suite:
|
||||
* - env: CMS enveloped (encrypted)
|
||||
* - dsig: CMS detached signature (with multipart MIME)
|
||||
* - sig: CMS opaque signature (content embedded inside signature)
|
||||
* - bad: message text does not match signature
|
||||
* - mismatch: embedded content is different
|
||||
*
|
||||
* Control variables used for checking results:
|
||||
* - env: If true, we expect a report to encryptionStatus() that message
|
||||
* is encrypted.
|
||||
* - sig: If true, we expect a report to signedStatus() that message
|
||||
* is signed.
|
||||
* - sig_good: If true, we expect that the reported signature has a
|
||||
* good status.
|
||||
* If false, we expect a report of bad status.
|
||||
* Because of the sequential processing caused by nested
|
||||
* messages, additional calls to signedStatus() might
|
||||
* override an earlier decision.
|
||||
* (An earlier bad status report cannot be overridden by a
|
||||
* later report of a good status.)
|
||||
* - extra: If set to a number > 0, we expect that nested processing of
|
||||
* MIME parts will trigger the given number of additional
|
||||
* status calls.
|
||||
* (default is 0.)
|
||||
* - dave: If true, we expect that the outermost message was done by
|
||||
* Dave's certificate.
|
||||
* (default is false, which means we expect Alice's cert.)
|
||||
*/
|
||||
|
||||
var gMessages = [
|
||||
{
|
||||
filename: "alice.env.eml",
|
||||
enc: true,
|
||||
sig: false,
|
||||
sig_good: false,
|
||||
check_text: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA1.multipart.bad.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA1.multipart.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
check_text: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA1.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
check_text: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA1.multipart.mismatch-econtent.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA256.multipart.bad.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA256.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA256.multipart.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA256.multipart.mismatch-econtent.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA384.multipart.bad.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA384.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA384.multipart.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA384.multipart.mismatch-econtent.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA512.multipart.bad.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA512.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA512.multipart.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.dsig.SHA512.multipart.mismatch-econtent.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
check_text: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA1.opaque.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
check_text: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA256.opaque.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA384.opaque.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
{
|
||||
filename: "alice.sig.SHA512.opaque.env.eml",
|
||||
enc: true,
|
||||
sig: true,
|
||||
sig_good: true,
|
||||
},
|
||||
|
||||
// encrypt-then-sign
|
||||
{
|
||||
filename: "alice.env.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA1.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA256.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA384.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA512.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
extra: 1,
|
||||
},
|
||||
|
||||
// encrypt-then-sign, then sign again
|
||||
{
|
||||
filename: "alice.env.sig.SHA1.opaque.dave.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA1.multipart.dave.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA256.opaque.dave.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA256.multipart.dave.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA384.opaque.dave.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA384.multipart.dave.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.sig.SHA512.opaque.dave.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.env.dsig.SHA512.multipart.dave.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
|
||||
// sign, then sign again
|
||||
{
|
||||
filename: "alice.plain.sig.SHA1.opaque.dave.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.dsig.SHA1.multipart.dave.sig.SHA1.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA256.opaque.dave.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.dsig.SHA256.multipart.dave.sig.SHA256.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA384.opaque.dave.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.dsig.SHA384.multipart.dave.sig.SHA384.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA512.opaque.dave.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.dsig.SHA512.multipart.dave.sig.SHA512.opaque.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
|
||||
{
|
||||
filename: "alice.plain.sig.SHA1.opaque.dave.dsig.SHA1.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.dsig.SHA1.multipart.dave.dsig.SHA1.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA256.opaque.dave.dsig.SHA256.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename:
|
||||
"alice.plain.dsig.SHA256.multipart.dave.dsig.SHA256.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA384.opaque.dave.dsig.SHA384.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename:
|
||||
"alice.plain.dsig.SHA384.multipart.dave.dsig.SHA384.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename: "alice.plain.sig.SHA512.opaque.dave.dsig.SHA512.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
{
|
||||
filename:
|
||||
"alice.plain.dsig.SHA512.multipart.dave.dsig.SHA512.multipart.eml",
|
||||
enc: false,
|
||||
sig: true,
|
||||
sig_good: false,
|
||||
dave: 1,
|
||||
extra: 1,
|
||||
},
|
||||
];
|
||||
|
||||
let gCopyWaiter = PromiseUtils.defer();
|
||||
|
||||
add_task(async function copy_messages() {
|
||||
for (let msg of gMessages) {
|
||||
let promiseCopyListener = new PromiseTestUtils.PromiseCopyListener();
|
||||
|
||||
MailServices.copy.copyFileMessage(
|
||||
do_get_file(smimeDataDirectory + msg.filename),
|
||||
gInbox,
|
||||
null,
|
||||
true,
|
||||
0,
|
||||
"",
|
||||
promiseCopyListener,
|
||||
null
|
||||
);
|
||||
|
||||
await promiseCopyListener.promise;
|
||||
promiseCopyListener = null;
|
||||
}
|
||||
gCopyWaiter.resolve();
|
||||
});
|
||||
|
||||
add_task(async function check_smime_message() {
|
||||
await gCopyWaiter.promise;
|
||||
|
||||
let hdrIndex = 0;
|
||||
|
||||
for (let msg of gMessages) {
|
||||
console.log("checking " + msg.filename);
|
||||
|
||||
let numExpected = 1;
|
||||
if (msg.enc && msg.sig) {
|
||||
numExpected++;
|
||||
}
|
||||
|
||||
let eventsExpected = numExpected;
|
||||
if ("extra" in msg) {
|
||||
eventsExpected += msg.extra;
|
||||
}
|
||||
|
||||
let hdr = mailTestUtils.getMsgHdrN(gInbox, hdrIndex);
|
||||
let uri = hdr.folder.getUriForMsg(hdr);
|
||||
let sinkPromise = smimeHeaderSink.expectResults(eventsExpected);
|
||||
|
||||
let conversion = apply_mime_conversion(uri, smimeHeaderSink);
|
||||
await conversion.promise;
|
||||
|
||||
let contents = conversion._data;
|
||||
// dump("contents: " + contents + "\n");
|
||||
|
||||
if (!msg.sig || msg.sig_good || "check_text" in msg) {
|
||||
let expected = "This is a test message from Alice to Bob.";
|
||||
Assert.ok(contents.includes(expected));
|
||||
}
|
||||
// Check that we're also using the display output.
|
||||
Assert.ok(contents.includes("<html>"));
|
||||
|
||||
await sinkPromise;
|
||||
|
||||
let r = smimeHeaderSink._results;
|
||||
Assert.equal(r.length, numExpected);
|
||||
|
||||
let sigIndex = 0;
|
||||
|
||||
if (msg.enc) {
|
||||
Assert.equal(r[0].type, "encrypted");
|
||||
Assert.equal(r[0].status, 0);
|
||||
Assert.equal(r[0].certificate, null);
|
||||
sigIndex = 1;
|
||||
}
|
||||
if (msg.sig) {
|
||||
Assert.equal(r[sigIndex].type, "signed");
|
||||
let cert = r[sigIndex].certificate;
|
||||
if (msg.sig_good) {
|
||||
Assert.notEqual(cert, null);
|
||||
}
|
||||
if (cert) {
|
||||
if ("dave" in msg) {
|
||||
Assert.equal(cert.emailAddress, "dave@example.com");
|
||||
} else {
|
||||
Assert.equal(cert.emailAddress, "alice@example.com");
|
||||
}
|
||||
}
|
||||
if (msg.sig_good) {
|
||||
Assert.equal(r[sigIndex].status, 0);
|
||||
} else {
|
||||
Assert.notEqual(r[sigIndex].status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
hdrIndex++;
|
||||
}
|
||||
});
|
|
@ -26,6 +26,10 @@ support-files =
|
|||
[test_parser.js]
|
||||
[test_rfc822_body.js]
|
||||
[test_smime_decrypt.js]
|
||||
|
||||
[test_smime_decrypt_allow_sha1.js]
|
||||
run-sequentially = Because it set's a pref that must not be active for other tests.
|
||||
|
||||
[test_smime_perm_decrypt.js]
|
||||
[test_structured_headers.js]
|
||||
[test_text_attachment.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче