Add tests for S/MIME
Categories
(MailNews Core :: Security: S/MIME, defect)
Tracking
(Not tracked)
People
(Reporter: jcranmer, Assigned: KaiE)
References
Details
Attachments
(3 files, 17 obsolete files)
|
202.02 KB,
patch
|
jorgk-bmo
:
review+
|
Details | Diff | Splinter Review |
|
10.00 KB,
patch
|
KaiE
:
review+
|
Details | Diff | Splinter Review |
|
7.70 KB,
patch
|
KaiE
:
review+
|
Details | Diff | Splinter Review |
| Reporter | ||
Comment 1•11 years ago
|
||
| Reporter | ||
Comment 2•11 years ago
|
||
| Reporter | ||
Comment 3•8 years ago
|
||
| Reporter | ||
Comment 4•8 years ago
|
||
Comment 5•8 years ago
|
||
Comment 6•8 years ago
|
||
Comment 7•8 years ago
|
||
Comment 8•7 years ago
|
||
Updated•7 years ago
|
| Assignee | ||
Comment 9•7 years ago
|
||
Joshua, thanks for doing this groundwork. Do you remember which parts you considered to be still missing?
I think we shouldn't use openssl, if possible. As Jorg noted, it might not be available on all systems, especially not on Windows. And I think we don't need it.
NSS has tools for certificate generation and for CMS message generation, which are used by the NSS test suite. A Firefox build already produces the certutil and pk12util toolss, available in obj/dist/bin. S/MIME is base64-encoded CMS messages combined with headers and MIME. NSS has a cmsutil tool. To get from CMS to S/MIME, you just base64 encode and add the MIME wrappers. Using NSS tools means no external dependencies.
Let's start with dynamic certificate generation as part of the build, by default. If that needs to be optimized for execution time, by checking in pre-generated certs, let's handle that later. (Potentially NSS could distribute a few test certificates, e.g. valid for 3 years. Given that applications are supposed to frequently pick up newer versions of NSS, that might be sufficient for refreshing.)
We don't need many certificates, and the time necessary for that should be acceptable. Note that NSS already has a large test suite, which tests all the crypto details, and it also tests CMS message generation and verification. We can rely on that and focus on S/MIME message integration, and for that, avoiding the slower and larger keysizes should be OK.
We need a CA, an intermediate CA, and certs for maybe 4 email addresses, alice, bob, david, eve, that's what the NSS CMS tests do.
We should create the kind of messages that were mentioned in the initial comment. Also, we should have a few nested messages. For example, an unsigned message from Alice to Eve, which attaches/forwards a signed message from Bob. The message seen by Eve shouldn't show a signature. This test ensures that nested CMS status isn't propagated to the wrong display level.
I see the patch creates messages, stores them into a folder, and loads messages, then queries user interface elements to check the S/MIME status of the UI. Is that correct? Does that mean we don't require mozmill for testing the UI?
| Reporter | ||
Comment 10•7 years ago
|
||
My original work on this patch followed what mozilla-central's certificate tests were doing at the time (I haven't kept up to see if they're still doing this). That involved creating the certificates and some of the encrypted blobs at build time using some python-heavy code to do the generation. I actually reused as much of the infrastructure as I could, going so far as to drop in some of the other py-asn1 modules for the relevant CMS blobs. (I really, really hate ASN.1, have I mentioned that?)
Certificate generation isn't the hard part; I literally reused the GenerateCertificate blobs from mozilla-central. Generating the pkcs12 key file was more annoying; I resorted to OpenSSL there mostly because I couldn't get a working output file using the ASN.1 generation stuff. The hard part is actually generating the S/MIME messages themselves: the way the python system for generating keys/certificates works is to actually make manual calls to the encryption routines to generate the data. (The RNG is seeded, IIRC, to make bit-identical results). But there's nothing in the mozpython distribution to do the necessary symmetric encryption legwork.
The way I envisioned the framework working is that there is a build script that takes a fully-decrypted email variant and replaces the bodies of custom MIME parts with CMS blobs. That's pysmime.py, absent some missing functionality and the fact that it currently uses the OpenSSL for generation.
As for missing functionality:
- There's no way to select between multipart/signed and application/pkcs7-mime in message generation. Testing both is definitely essential for correctness.
- There's no mechanism to indicate a certs-only attachment. Definitely lower priority, though.
- There's also no mechanism for forcing a particular encryption method, hashing method, or signing time. This is also lower priority, and only really necessary if we're going to be doing more custom policy decisions than we do at present.
- This patch doesn't implement any tests of S/MIME composition, only decoding. I don't think it's missing much pieces for that, though.
Looking back at my original comments for tests, I see some other things that ought to be tested in the long run:
- EAI/IDN handling. I actually have no idea what the expected practice for certificates in this space is.
- Mozmill plumbing tests to make sure we're actually displaying security status, or propagating the status in compose.
- Mozmill tests for configuring use of certificates. I think we've had some bad regressions in this space.
We don't need to use mozmill for tests that are merely checking "did we encrypt the message correctly" or "do we compute the right security status for this message"; the xpcshell tests can easily reuse the same API we use to indicate it to the message view. And, personally, I much prefer xpcshell over mozmill for testing.
| Assignee | ||
Comment 11•7 years ago
|
||
Regression bug 1528615 demonstrates that this work should get a high priority.
Because I had an immediate need for testcases, I've extended the NSS script to create certificates and messages.
I'd like to attach some work-in-progress, which can be used for interactive testing, while we don't have it automated yet.
| Assignee | ||
Comment 12•7 years ago
|
||
Download, extract into the "Mail/Local Folders" subdirectory of a Thundebird profile.
| Assignee | ||
Comment 13•7 years ago
|
||
Database with certificates for the messages in the previous mailbox attachment. Extract into a test profile folder, overwriting the existing files.
| Assignee | ||
Comment 14•7 years ago
|
||
Patch against NSS used to generate the certificates and test messages.
(As part as running the NSS S/MIME tests, which aren't really S/MIME tests, but rather CMS tests (S/MIME without MIME).)
| Assignee | ||
Comment 15•7 years ago
|
||
In order to perform manual testing, do the following steps:
- download both attachment 9044666 [details] and attachment 9044667 [details]
- create a test thunderbird profile, quit thunderbird
- extract the db.tar.gz archive into the main thunderbird profile
(the one that contains files like prefs.js and cert9.db) - extract the smime-mailbox.tar.gz archive into the "Mail/Local Folders" subdirectory
- start thunderbird
- go to local folders, click the folder named "smime-mailbox"
- click on each of the messages (slowly):
- messages that start with a subject BAD should get a
broken signature icon (letter with large red X) - for all other messages,
ensure there is NO letter with a large red X.
If the subject mentions "signed", you should get a letter with a small red seal inside it.
If the subject mentions "envoloped", you should see a padlock
- messages that start with a subject BAD should get a
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Comment 16•7 years ago
|
||
This is Joshua's patch merged to current trunk, plus adjustments that were necessary. A lot has changed during the past years...
work-in-progress
| Assignee | ||
Comment 17•7 years ago
|
||
FYI, Firefox tests use pre-generated certificates that must be refreshed and committed yearly. They just recently tripped over that (no reminder...) in bug 1525191.
It seems reasonable to use the pre-generate approach for TB, too (but have a reminder, to do it before they expire).
I'd like to avoid the openssl dependency. The NSS test suite already creates certificates of many flavors, and it already creates test CMS messages, to ensure this functionality isn't regressing.
It's a small amount of work on top of that, to also generate what we require for TB. We could change NSS to place a folder with the data that TB requires in a separate folder. Then, once a year, someone would run the NSS test suite, copy over that folder into the TB tree, commit, done.
Comment 18•7 years ago
|
||
Yes, updating once a year is quite reasonable.
Not sure what reminder you had in mind, but I think the tests should check current date, and if it's over a hard coded end date, error out giving the prompt to update the certs and how.
| Assignee | ||
Comment 19•7 years ago
|
||
| Assignee | ||
Comment 20•7 years ago
|
||
This archive contains the test data that was produced as described in the README file, by the enhanced script from bug 1529950.
I think it's better to not attach it as a patch. To use it:
cd mailnews/test/data
tar xzf /tmp/mailnews-test-data-smime.tar.gz
| Assignee | ||
Comment 21•7 years ago
|
||
v6 contained a block that's already on trunk. v7 fixes that.
| Reporter | ||
Comment 22•7 years ago
|
||
(In reply to Kai Engert (:kaie:) from comment #17)
I'd like to avoid the openssl dependency. The NSS test suite already creates certificates of many flavors, and it already creates test CMS messages, to ensure this functionality isn't regressing.
The only reason I had openssl was because we weren't building the NSS tools when building TB. You've apparently fixed that now, so there should be no reason to use openssl.
| Assignee | ||
Comment 23•7 years ago
|
||
| Assignee | ||
Comment 24•7 years ago
|
||
Joshua, I'd like to credit you for the majority of the patch, which I reused, and which only required minor tweaks.
This is the subset of the v7 patch that's mostly from you.
Because it works, r+ from me.
| Assignee | ||
Comment 25•7 years ago
|
||
This part still contains snippets from Joshua (mostly smimeHeaderSink), but I rewrote most parts.
Joshua, would you like to review it?
I faced the challenge that the functions need to be async, because I needed to use "await". And I must wait until the message has really been copied to the inbox, prior to executing the test.
Also, if everything runs in parallel, the copying of multiple messages to the inbox might result in a non-predictable order of messages.
Also, I must ensure that smimeHeaderSink isn't being used in parallel, so another need to serialize.
My best idea was to use a chain of promises.
(There was also some c++ code, too, I've moved that to bug 1530099.)
| Assignee | ||
Updated•7 years ago
|
| Reporter | ||
Comment 26•7 years ago
|
||
| Reporter | ||
Updated•7 years ago
|
Comment 27•7 years ago
|
||
Comment 28•7 years ago
|
||
| Assignee | ||
Comment 29•7 years ago
|
||
(In reply to Joshua Cranmer [:jcranmer] from comment #26)
I do think the test suite could be more comprehensive,
True. Let's start with this initial set, which also focuses on the code required for testing. We can add more test cases in follow-up bugs.
and the generation of
the test emails a little more automatic, but I don't think those are reasons
to hold this work up.
Once we have cmsutil being built as part of TB (close to being done), we can use it together with the checked in certificates to create more emails in follow-up bugs.
::: mailnews/mime/test/unit/test_smime_decrypt.js
There's a lot of trailing whitespace in this file that should get cleaned up.
done
- { filename: 'alice.env.eml',
- { filename: 'alice.dsig.SHA1.multipart.bad.eml',
Some guide to what these email names mean would be helpful.
done, added comments
| Assignee | ||
Comment 30•7 years ago
|
||
(In reply to Magnus Melin [:mkmelin] from comment #27)
- var msgWindow = Cc["@mozilla.org/messenger/msgwindow;1"]
nit: make this too a |let|
done
Double star for documentation comments
done
+var EXPORTED_SYMBOLS = [
- 'SmimeUtils'
please prefer double quotes
done
Also, since this file is a module, name it .jsm
done
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://testing-common/mailnews/MockFactory.js");Does this still work? SHouldn't it be ChromeUtils.import?
Changed to var {} = ChromeUtils.import
+var Cc = Components.classes;
+var Ci = Components.interfaces;Cc and Ci should be globally available nowadays. Use them above. Y
removed
+var SmimeUtils = {
- ensureNSS: function () {
nit, no space after "function": function()
changed in all places
| Assignee | ||
Comment 31•7 years ago
|
||
(In reply to Magnus Melin [:mkmelin] from comment #28)
+var gMessageGenerator = new MessageGenerator();
not used
removed
2 space indention please
done
nit:
if (msg.enc && msg.sig) {
numExpected++
}
ok
- let r = smimeHeaderSink._results
nit: missing trailing ;
done.
+var messages = [
- { filename: 'alice.env.eml',
prefer double quotes
done
- for (let i = 0; i < iMax; ++i) {
i++ is more kosher
I'm changing it, but I'm used to ++i, because it's more efficient in C++:
https://stackoverflow.com/questions/24901/is-there-a-performance-difference-between-i-and-i-in-c
i++ means: "Take the value of i as an expression, then increment it, and the result is the new expression."
++i means: "Increment it, and use the new value as an expression."
There's also some talk about it in JS:
https://stackoverflow.com/questions/1546981/post-increment-vs-pre-increment-javascript-optimization
- if (i == (iMax -1)) {
nextResolver = gCleanupWaiter;here too some mixed indention. 2 space please
done
+HOST=localhost DOMSUF=localdomain ./all.sh
what does this do? I don't see HOST being used later
An internal requirement of the existing NSS test suite that we're reusing here.
It passes the variables to the all.sh script only.
They are required inside the NSS test suite.
The full NSS test suite executes servers and clients, and for that it needs to know the hostname, and also use that hostname inside the certificates it creates. The NSS test suite attempts to automatically detect that from the system's settings, but that often doesn't work, because frequently system's use a hostname that isn't registered in DNS. The hostname localhost.localdomain works everywhere, even on systems that aren't registered in DNS. That's why we commonly set these variables when executing the NSS test suite.
| Assignee | ||
Comment 32•7 years ago
|
||
+Copy all files from the ./tb subdirectory to the TB tree, e.g.
+cp -v ./tb/* $HOME/your-mozilla-tree/comm/mailnews/test/data/smime/Perhaps you could insclude a schell script for this and refer to that in the
README.
That's a very good idea!
And I realize that we don't need to clone nspr/nss from the server.
I'll add a generate.sh script. With that approach, I think your script optimizations aren't necessary.
The script will create a subdirectory for building, will copy nspr/nss from the parent mozilla tree, build, run the test, copy all the files, and remove the build tree.
| Assignee | ||
Comment 33•7 years ago
|
||
You can clean this entire bit up with
async function check_smime_message() {
for (let message of messages)
await check_smime(messages[i]);
}
I think that wouldn't work, because, this implementation was using a cascade. All async tests were started immediately, but the chain of promises assured that e.g. test 2 was delayed until after test 1 was done, and test 3 was delayed until test 2 was done, etc. That's why the waiting needed to be done at the beginning of each test, for the promise of the previous test. I needed to ensure that tests don't run in parallel.
But I realized this cascade isn't necessary, and found a simpler solution.
I reimplemented it to use just two promises:
- one function copies everything, and uses a promise to signal copying is done
- the test function waits for copying to be done, then loops over all the tests, then signals that testing is done
- the cleanup waits for the signal that testing is done
| Assignee | ||
Comment 34•7 years ago
|
||
Addressed the minor cleanup requests.
| Assignee | ||
Comment 35•7 years ago
|
||
| Assignee | ||
Comment 36•7 years ago
|
||
| Assignee | ||
Comment 37•7 years ago
|
||
Magnus, you had given feedback+ on the previous patch (attachment 9046125 [details] [diff] [review]). This version implements the requested changes, and it simplifies the async logic.
| Assignee | ||
Comment 38•7 years ago
|
||
Raw test data files, as a patch.
| Assignee | ||
Comment 39•7 years ago
|
||
same code as before, but properly formatted patch
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Comment 40•7 years ago
|
||
Comment 41•7 years ago
|
||
Comment 42•7 years ago
|
||
Can you also in the README write down the date for when first expiration is expected.
| Assignee | ||
Comment 43•7 years ago
|
||
(In reply to Magnus Melin [:mkmelin] from comment #42)
Can you also in the README write down the date for when first expiration is expected.
I'm worried that will get out of sync on next update. It might be better to automatically produce that information, and list it in a separate file.
I should be able to enhance the generate.sh script to list that information.
| Assignee | ||
Comment 44•7 years ago
|
||
(In reply to Magnus Melin [:mkmelin] from comment #41)
On a higher level it strikes me, what should we do to test messages that are
not in the expected format. I mean, messages that we can't generate but that
are found in the wild....
If we're talking about valid messages, this basic set of messages already contains both variations for signed messages. Although Thunderbird only produces one variation, NSS can be used to produce both variations.
| Assignee | ||
Comment 45•7 years ago
|
||
(In reply to Magnus Melin [:mkmelin] from comment #41)
You seem to have lost the instructions on where to get the nss build through
hg
Not sure what you're referring to. We no longer have to clone from hg, because the Mozilla tree contains all the NSS files that we need, and we simply make a local copy operation to get them.
The script automates building and generating all files, and copying them to the right place.
+echo "Done. Will remove the NSS build/test tree in 20 seconds."
+sleep 20
+rm -rf nssbuildmight not want to remove it (in case of errors, or in case someone needs to
go back and fiddle with something)
After the script has been executed, the new files obviously must be committed.
If we don't clean up, the person doing the refresh might accidentally commit a very large set of new files.
| Assignee | ||
Comment 46•7 years ago
|
||
| Assignee | ||
Comment 47•7 years ago
|
||
Added a file level comment to Joshua's code.
| Assignee | ||
Comment 48•7 years ago
|
||
Comment 49•7 years ago
|
||
Set checkin-needed and let the friendly sheriff know what you want landed. Or land them yourself with a pretty commit message, that is with - and . ;-) - We can discuss on IRC. Is there a try run that makes sure everything works?
| Assignee | ||
Updated•7 years ago
|
| Assignee | ||
Comment 50•7 years ago
|
||
| Assignee | ||
Comment 51•7 years ago
|
||
try build here:
https://treeherder.mozilla.org/#/jobs?repo=try-comm-central&revision=265a77f6352f17080bb4495447b52c28b9a58551
jcranmer-v11 fixes the ES lint issues, as can be seen here:
https://treeherder.mozilla.org/#/jobs?repo=try-comm-central&revision=37f362a0c11137c9b76b2bab4e5d9e1ea8b05a16
Comment 52•7 years ago
|
||
Comment 53•7 years ago
|
||
Pushed by kaie@kuix.de:
https://hg.mozilla.org/comm-central/rev/5ebc05985626
test data files (certificates and S/MIME messages). r=jorgk
https://hg.mozilla.org/comm-central/rev/9778f8499a7d
utility code for S/MIME testing. r=kaie
https://hg.mozilla.org/comm-central/rev/5d7419c95b2b
add S/MIME tests, and a helper script to create test certificates. r=mkmelin
Updated•7 years ago
|
| Assignee | ||
Comment 54•7 years ago
|
||
Description
•