Bug 1190020 - P2. Testcase to ensure digest is not truncated. r=francois
authorDimi Lee <dlee@mozilla.com>
Tue, 23 Oct 2018 20:03:44 +0000
changeset 491011 b872e2aa271c063a31219ee93455541198b99cbc
parent 491010 ffb7704a1bf8af534306427755e18cfe4db8da62
child 491012 94f5958dbd0ff027a4b4fa65bcc2c956ba8c0d47
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersfrancois
bugs1190020
milestone65.0a1
Bug 1190020 - P2. Testcase to ensure digest is not truncated. r=francois This test will trigger a remote lookup. Verify the protocol buffer sent by download protection service matches the hard-coded protocol buffer. This protcol buffer contains following information: 1. source URI 2. referrer URI 3. redirect UiRI 4. sha256 hash with '\x00' in the middle of the data 5. suggested file name Differential Revision: https://phabricator.services.mozilla.com/D9138
toolkit/components/reputationservice/test/unit/test_app_rep.js
--- a/toolkit/components/reputationservice/test/unit/test_app_rep.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep.js
@@ -6,24 +6,29 @@
 
 ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const gAppRep = Cc["@mozilla.org/reputationservice/application-reputation-service;1"].
                   getService(Ci.nsIApplicationReputationService);
 var gHttpServ = null;
 var gTables = {};
+var gExpectedRemote = false;
+var gExpectedRemoteRequestBody = "";
 
 var ALLOW_LIST = 0;
 var BLOCK_LIST = 1;
 var NO_LIST = 2;
 
 var whitelistedURI = createURI("http://foo:bar@whitelisted.com/index.htm#junk");
 var exampleURI = createURI("http://user:password@example.com/i.html?foo=bar");
+var exampleReferrerURI = createURI("http://user:password@example.referrer.com/i.html?foo=bar");
+var exampleRedirectURI = createURI("http://user:password@example.redirect.com/i.html?foo=bar");
 var blocklistedURI = createURI("http://baz:qux@blocklisted.com?xyzzy");
+
 var binaryFile = "binaryFile.exe";
 var nonBinaryFile = "nonBinaryFile.txt";
 
 const appRepURLPref = "browser.safebrowsing.downloads.remote.url";
 
 function readFileToString(aFilename) {
   let f = do_get_file(aFilename);
   let stream = Cc["@mozilla.org/network/file-input-stream;1"]
@@ -83,17 +88,23 @@ add_task(async function test_setup() {
   registerCleanupFunction(function() {
     Services.prefs.clearUserPref("urlclassifier.downloadBlockTable");
     Services.prefs.clearUserPref("urlclassifier.downloadAllowTable");
   });
 
   gHttpServ = new HttpServer();
   gHttpServ.registerDirectory("/", do_get_cwd());
   gHttpServ.registerPathHandler("/download", function(request, response) {
-    do_throw("This test should never make a remote lookup");
+    if (gExpectedRemote) {
+      let body = NetUtil.readInputStreamToString(request.bodyInputStream,
+                                                 request.bodyInputStream.available());
+      Assert.equal(gExpectedRemoteRequestBody, body);
+    } else {
+      do_throw("This test should never make a remote lookup");
+    }
   });
   gHttpServ.start(4444);
 
   registerCleanupFunction(function() {
     return (async function() {
       await new Promise(resolve => {
         gHttpServ.stop(resolve);
       });
@@ -434,8 +445,51 @@ add_test(function test_whitelisted_redir
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
     check_telemetry(counts.shouldBlock, listCounts);
     run_next_test();
   });
 });
+
+add_test(function test_remote_lookup_protocolbuf() {
+  // This long hard-coded string is the contents of the request generated by
+  // the Application Reputation component, converted to the binary protobuf format.
+  // If this test is changed, or we add anything to the remote lookup requests
+  // in ApplicationReputation.cpp, then we'll need to update this hard-coded string.
+  gExpectedRemote = true;
+  gExpectedRemoteRequestBody = "\x0A\x19\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x12\x22\x0A\x20\x61\x62\x63\x00\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x18\x0C\x22\x41\x0A\x19\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x10\x00\x22\x22\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x72\x65\x66\x65\x72\x72\x65\x72\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x22\x26\x0A\x22\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x72\x65\x64\x69\x72\x65\x63\x74\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x10\x01\x30\x01\x4A\x0E\x62\x69\x6E\x61\x72\x79\x46\x69\x6C\x65\x2E\x65\x78\x65\x50\x00\x5A\x05\x65\x6E\x2D\x55\x53";
+  Services.prefs.setCharPref(appRepURLPref,
+                             "http://localhost:4444/download");
+  let secman = Services.scriptSecurityManager;
+  let counts = get_telemetry_counts();
+  let listCounts = counts.listCounts;
+  listCounts[NO_LIST] += 3;
+
+  // Redirects
+  let redirects = Cc["@mozilla.org/array;1"]
+                     .createInstance(Ci.nsIMutableArray);
+  let redirect1 = {
+    QueryInterface: ChromeUtils.generateQI([Ci.nsIRedirectHistoryEntry]),
+    principal: secman.createCodebasePrincipal(exampleRedirectURI, {}),
+  };
+  redirects.appendElement(redirect1);
+
+  // Insert null(\x00) in the middle of the hash to test we won't truncate it.
+  let sha256Hash = "abc\x00" + "de".repeat(14);
+
+  gAppRep.queryReputation({
+    sourceURI: exampleURI,
+    referrerURI: exampleReferrerURI,
+    suggestedFileName: binaryFile,
+    sha256Hash,
+    redirects,
+    fileSize: 12,
+  }, function onComplete(aShouldBlock, aStatus) {
+    Assert.equal(Cr.NS_OK, aStatus);
+    Assert.ok(!aShouldBlock);
+    check_telemetry(counts.shouldBlock, listCounts);
+
+    gExpectedRemote = false;
+    run_next_test();
+  });
+});