Bug 1335475 - Deny plugins from non-HTTP/HTTPS origins. r?qdot r?ksteuber draft
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 03 Mar 2017 16:23:30 -0500
changeset 493398 14a0b8902e9754fb03026f9faaeaaacd03d74e23
parent 490961 a8f45b2afbf3bc116fc9c52d4631e426fb3d5733
child 547847 e831c5235d9016f0009f6274a02df211cea1bb2d
push id47747
push userbsmedberg@mozilla.com
push dateFri, 03 Mar 2017 21:24:04 +0000
reviewersqdot, ksteuber
bugs1335475
milestone54.0a1
Bug 1335475 - Deny plugins from non-HTTP/HTTPS origins. r?qdot r?ksteuber MozReview-Commit-ID: 3kPeycfMWVw
dom/base/nsDocument.cpp
dom/plugins/test/mochitest/browser.ini
dom/plugins/test/mochitest/browser_bug1335475.js
dom/plugins/test/mochitest/plugin_test.html
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -13031,33 +13031,47 @@ ArrayContainsTable(const nsTArray<nsCStr
  * For more information, see
  * toolkit/components/url-classifier/flash-block-lists.rst
  */
 FlashClassification
 nsDocument::PrincipalFlashClassification(bool aIsTopLevel)
 {
   nsresult rv;
 
-  // If flash blocking is disabled, it is equivalent to all sites being
-  // whitelisted.
-  if (!Preferences::GetBool("plugins.flashBlock.enabled")) {
-    return FlashClassification::Allowed;
-  }
-
   nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
   if (principal->GetIsNullPrincipal()) {
     return FlashClassification::Denied;
   }
 
   nsCOMPtr<nsIURI> classificationURI;
   rv = principal->GetURI(getter_AddRefs(classificationURI));
   if (NS_FAILED(rv) || !classificationURI) {
     return FlashClassification::Denied;
   }
 
+  if (Preferences::GetBool("plugins.http_https_only", true)) {
+    // Only allow plugins for documents from an HTTP/HTTPS origin. This should
+    // allow dependent data: URIs to load plugins, but not:
+    // * chrome documents
+    // * "bare" data: loads
+    // * FTP/gopher/file
+    nsAutoCString scheme;
+    rv = classificationURI->GetScheme(scheme);
+    if (NS_WARN_IF(NS_FAILED(rv)) ||
+        !(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
+      return FlashClassification::Denied;
+    }
+  }
+
+  // If flash blocking is disabled, it is equivalent to all sites being
+  // whitelisted.
+  if (!Preferences::GetBool("plugins.flashBlock.enabled")) {
+    return FlashClassification::Allowed;
+  }
+
   nsAutoCString allowTables, allowExceptionsTables,
                 denyTables, denyExceptionsTables,
                 subDocDenyTables, subDocDenyExceptionsTables,
                 tables;
   Preferences::GetCString("urlclassifier.flashAllowTable", &allowTables);
   MaybeAddTableToTableList(allowTables, tables);
   Preferences::GetCString("urlclassifier.flashAllowExceptTable",
                           &allowExceptionsTables);
--- a/dom/plugins/test/mochitest/browser.ini
+++ b/dom/plugins/test/mochitest/browser.ini
@@ -8,8 +8,9 @@ support-files =
 [browser_bug1163570.js]
 skip-if = true # Bug 1249878
 [browser_bug1196539.js]
 skip-if = (!e10s || os != "win")
 [browser_tabswitchbetweenplugins.js]
 skip-if = (!e10s || os != "win")
 [browser_pluginscroll.js]
 skip-if = (true || !e10s || os != "win") # Bug 1213631
+[browser_bug1335475.js]
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/browser_bug1335475.js
@@ -0,0 +1,64 @@
+var rootDir = getRootDirectory(gTestPath);
+const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
+
+add_task(function*() {
+  is(navigator.plugins.length, 0,
+     "plugins should not be available to chrome-privilege pages");
+  ok(!("application/x-shockwave-flash" in navigator.mimeTypes),
+     "plugins should not be available to chrome-privilege pages");
+
+  yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function*(browser) {
+    // about:blank triggered from a toplevel load should not inherit permissions
+    yield ContentTask.spawn(browser, null, function*() {
+      is(content.window.navigator.plugins.length, 0,
+         "plugins should not be available to null-principal about:blank");
+      ok(!("application/x-shockwave-flash" in content.window.navigator.mimeTypes),
+         "plugins should not be available to null-principal about:blank");
+    });
+
+    let promise = BrowserTestUtils.browserLoaded(browser);
+    browser.loadURI(gTestRoot + "plugin_test.html");
+    yield promise;
+
+    yield ContentTask.spawn(browser, null, function*() {
+      ok(content.window.navigator.plugins.length > 0,
+         "plugins should be available to HTTP-loaded pages");
+      ok("application/x-shockwave-flash" in content.window.navigator.mimeTypes,
+         "plugins should be available to HTTP-loaded pages");
+
+      let subwindow = content.document.getElementById("subf").contentWindow;
+
+      ok("application/x-shockwave-flash" in subwindow.navigator.mimeTypes,
+         "plugins should be available to an about:blank subframe loaded from a site");
+    });
+
+    // navigate from the HTTP page to an about:blank page which ought to
+    // inherit permissions
+    promise = BrowserTestUtils.browserLoaded(browser);
+    yield ContentTask.spawn(browser, null, function*() {
+      content.document.getElementById("aboutlink").click();
+    });
+    yield promise;
+
+    yield ContentTask.spawn(browser, null, function*() {
+      is(content.window.location.href, "about:blank", "sanity-check about:blank load");
+      ok("application/x-shockwave-flash" in content.window.navigator.mimeTypes,
+         "plugins should be available when a site triggers an about:blank load");
+    });
+
+    // navigate to the file: URI, which shouldn't allow plugins. This might
+    // be wrapped in jar:, but that shouldn't matter for this test
+    promise = BrowserTestUtils.browserLoaded(browser);
+    let converteduri = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry).convertChromeURL(Services.io.newURI(rootDir + "plugin_test.html"));
+    browser.loadURI(converteduri.spec);
+    yield promise;
+
+    yield ContentTask.spawn(browser, null, function*() {
+      ok(!("application/x-shockwave-flash" in content.window.navigator.mimeTypes),
+         "plugins should not be available to file: URI content");
+    });
+  });
+
+  // As much as it would be nice, this doesn't actually check ftp:// because
+  // we don't have a synthetic server.
+});
--- a/dom/plugins/test/mochitest/plugin_test.html
+++ b/dom/plugins/test/mochitest/plugin_test.html
@@ -2,10 +2,15 @@
 <html>
 <head>
 <meta charset="utf-8">
 </head>
 <body>
   <embed id="testplugin" type="application/x-test" drawmode="solid" color="ff00ff00" wmode="window"
          style="position:absolute; top:50px; left:50px; width:500px; height:250px">
 <div style="display:block; height:3000px;"></div>
+
+<iframe id="subf" src="about:blank" width="300" height="300"></iframe>
+
+<a href="about:blank" id="aboutlink">Navigate to about:blank</a>
+
 </body>
 </html>