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

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

mercurial