netwerk/test/unit/test_signature_extraction.js

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* Any copyright is dedicated to the Public Domain.
michael@0 4 * http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 5
michael@0 6 /**
michael@0 7 * This file tests signature extraction using Windows Authenticode APIs of
michael@0 8 * downloaded files.
michael@0 9 */
michael@0 10
michael@0 11 ////////////////////////////////////////////////////////////////////////////////
michael@0 12 //// Globals
michael@0 13
michael@0 14 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 15
michael@0 16 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
michael@0 17 "resource://gre/modules/FileUtils.jsm");
michael@0 18 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
michael@0 19 "resource://gre/modules/NetUtil.jsm");
michael@0 20 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
michael@0 21 "resource://gre/modules/Promise.jsm");
michael@0 22 XPCOMUtils.defineLazyModuleGetter(this, "Task",
michael@0 23 "resource://gre/modules/Task.jsm");
michael@0 24
michael@0 25 const BackgroundFileSaverOutputStream = Components.Constructor(
michael@0 26 "@mozilla.org/network/background-file-saver;1?mode=outputstream",
michael@0 27 "nsIBackgroundFileSaver");
michael@0 28
michael@0 29 const StringInputStream = Components.Constructor(
michael@0 30 "@mozilla.org/io/string-input-stream;1",
michael@0 31 "nsIStringInputStream",
michael@0 32 "setData");
michael@0 33
michael@0 34 const TEST_FILE_NAME_1 = "test-backgroundfilesaver-1.txt";
michael@0 35
michael@0 36 /**
michael@0 37 * Returns a reference to a temporary file. If the file is then created, it
michael@0 38 * will be removed when tests in this file finish.
michael@0 39 */
michael@0 40 function getTempFile(aLeafName) {
michael@0 41 let file = FileUtils.getFile("TmpD", [aLeafName]);
michael@0 42 do_register_cleanup(function GTF_cleanup() {
michael@0 43 if (file.exists()) {
michael@0 44 file.remove(false);
michael@0 45 }
michael@0 46 });
michael@0 47 return file;
michael@0 48 }
michael@0 49
michael@0 50 /**
michael@0 51 * Waits for the given saver object to complete.
michael@0 52 *
michael@0 53 * @param aSaver
michael@0 54 * The saver, with the output stream or a stream listener implementation.
michael@0 55 * @param aOnTargetChangeFn
michael@0 56 * Optional callback invoked with the target file name when it changes.
michael@0 57 *
michael@0 58 * @return {Promise}
michael@0 59 * @resolves When onSaveComplete is called with a success code.
michael@0 60 * @rejects With an exception, if onSaveComplete is called with a failure code.
michael@0 61 */
michael@0 62 function promiseSaverComplete(aSaver, aOnTargetChangeFn) {
michael@0 63 let deferred = Promise.defer();
michael@0 64 aSaver.observer = {
michael@0 65 onTargetChange: function BFSO_onSaveComplete(aSaver, aTarget)
michael@0 66 {
michael@0 67 if (aOnTargetChangeFn) {
michael@0 68 aOnTargetChangeFn(aTarget);
michael@0 69 }
michael@0 70 },
michael@0 71 onSaveComplete: function BFSO_onSaveComplete(aSaver, aStatus)
michael@0 72 {
michael@0 73 if (Components.isSuccessCode(aStatus)) {
michael@0 74 deferred.resolve();
michael@0 75 } else {
michael@0 76 deferred.reject(new Components.Exception("Saver failed.", aStatus));
michael@0 77 }
michael@0 78 },
michael@0 79 };
michael@0 80 return deferred.promise;
michael@0 81 }
michael@0 82
michael@0 83 /**
michael@0 84 * Feeds a string to a BackgroundFileSaverOutputStream.
michael@0 85 *
michael@0 86 * @param aSourceString
michael@0 87 * The source data to copy.
michael@0 88 * @param aSaverOutputStream
michael@0 89 * The BackgroundFileSaverOutputStream to feed.
michael@0 90 * @param aCloseWhenDone
michael@0 91 * If true, the output stream will be closed when the copy finishes.
michael@0 92 *
michael@0 93 * @return {Promise}
michael@0 94 * @resolves When the copy completes with a success code.
michael@0 95 * @rejects With an exception, if the copy fails.
michael@0 96 */
michael@0 97 function promiseCopyToSaver(aSourceString, aSaverOutputStream, aCloseWhenDone) {
michael@0 98 let deferred = Promise.defer();
michael@0 99 let inputStream = new StringInputStream(aSourceString, aSourceString.length);
michael@0 100 let copier = Cc["@mozilla.org/network/async-stream-copier;1"]
michael@0 101 .createInstance(Ci.nsIAsyncStreamCopier);
michael@0 102 copier.init(inputStream, aSaverOutputStream, null, false, true, 0x8000, true,
michael@0 103 aCloseWhenDone);
michael@0 104 copier.asyncCopy({
michael@0 105 onStartRequest: function () { },
michael@0 106 onStopRequest: function (aRequest, aContext, aStatusCode)
michael@0 107 {
michael@0 108 if (Components.isSuccessCode(aStatusCode)) {
michael@0 109 deferred.resolve();
michael@0 110 } else {
michael@0 111 deferred.reject(new Components.Exception(aResult));
michael@0 112 }
michael@0 113 },
michael@0 114 }, null);
michael@0 115 return deferred.promise;
michael@0 116 }
michael@0 117
michael@0 118 let gStillRunning = true;
michael@0 119
michael@0 120 ////////////////////////////////////////////////////////////////////////////////
michael@0 121 //// Tests
michael@0 122
michael@0 123 function run_test()
michael@0 124 {
michael@0 125 run_next_test();
michael@0 126 }
michael@0 127
michael@0 128 add_task(function test_setup()
michael@0 129 {
michael@0 130 // Wait 10 minutes, that is half of the external xpcshell timeout.
michael@0 131 do_timeout(10 * 60 * 1000, function() {
michael@0 132 if (gStillRunning) {
michael@0 133 do_throw("Test timed out.");
michael@0 134 }
michael@0 135 })
michael@0 136 });
michael@0 137
michael@0 138 function readFileToString(aFilename) {
michael@0 139 let f = do_get_file(aFilename);
michael@0 140 let stream = Cc["@mozilla.org/network/file-input-stream;1"]
michael@0 141 .createInstance(Ci.nsIFileInputStream);
michael@0 142 stream.init(f, -1, 0, 0);
michael@0 143 let buf = NetUtil.readInputStreamToString(stream, stream.available());
michael@0 144 return buf;
michael@0 145 }
michael@0 146
michael@0 147 add_task(function test_signature()
michael@0 148 {
michael@0 149 // Check that we get a signature if the saver is finished on Windows.
michael@0 150 let destFile = getTempFile(TEST_FILE_NAME_1);
michael@0 151
michael@0 152 let data = readFileToString("data/signed_win.exe");
michael@0 153 let saver = new BackgroundFileSaverOutputStream();
michael@0 154 let completionPromise = promiseSaverComplete(saver);
michael@0 155
michael@0 156 try {
michael@0 157 let signatureInfo = saver.signatureInfo;
michael@0 158 do_throw("Can't get signature before saver is complete.");
michael@0 159 } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
michael@0 160
michael@0 161 saver.enableSignatureInfo();
michael@0 162 saver.setTarget(destFile, false);
michael@0 163 yield promiseCopyToSaver(data, saver, true);
michael@0 164
michael@0 165 saver.finish(Cr.NS_OK);
michael@0 166 yield completionPromise;
michael@0 167
michael@0 168 // There's only one nsIX509CertList in the signature array.
michael@0 169 do_check_eq(1, saver.signatureInfo.length);
michael@0 170 let certLists = saver.signatureInfo.enumerate();
michael@0 171 do_check_true(certLists.hasMoreElements());
michael@0 172 let certList = certLists.getNext().QueryInterface(Ci.nsIX509CertList);
michael@0 173 do_check_false(certLists.hasMoreElements());
michael@0 174
michael@0 175 // Check that it has 3 certs.
michael@0 176 let certs = certList.getEnumerator();
michael@0 177 do_check_true(certs.hasMoreElements());
michael@0 178 let signer = certs.getNext().QueryInterface(Ci.nsIX509Cert);
michael@0 179 do_check_true(certs.hasMoreElements());
michael@0 180 let issuer = certs.getNext().QueryInterface(Ci.nsIX509Cert);
michael@0 181 do_check_true(certs.hasMoreElements());
michael@0 182 let root = certs.getNext().QueryInterface(Ci.nsIX509Cert);
michael@0 183 do_check_false(certs.hasMoreElements());
michael@0 184
michael@0 185 // Check that the certs have expected strings attached.
michael@0 186 let organization = "Microsoft Corporation";
michael@0 187 do_check_eq("Microsoft Corporation", signer.commonName);
michael@0 188 do_check_eq(organization, signer.organization);
michael@0 189 do_check_eq("Copyright (c) 2002 Microsoft Corp.", signer.organizationalUnit);
michael@0 190
michael@0 191 do_check_eq("Microsoft Code Signing PCA", issuer.commonName);
michael@0 192 do_check_eq(organization, issuer.organization);
michael@0 193 do_check_eq("Copyright (c) 2000 Microsoft Corp.", issuer.organizationalUnit);
michael@0 194
michael@0 195 do_check_eq("Microsoft Root Authority", root.commonName);
michael@0 196 do_check_false(root.organization);
michael@0 197 do_check_eq("Copyright (c) 1997 Microsoft Corp.", root.organizationalUnit);
michael@0 198
michael@0 199 // Clean up.
michael@0 200 destFile.remove(false);
michael@0 201 });
michael@0 202
michael@0 203 add_task(function test_teardown()
michael@0 204 {
michael@0 205 gStillRunning = false;
michael@0 206 });

mercurial