Bug 1128126 - Enforce safe schemes in isInstallAllowed. r=Mossop a=abillings
authorBlair McBride <bmcbride@mozilla.com>
Tue, 10 Feb 2015 15:47:50 +1300
changeset 249743 a57074c09df5e8d2f06dbb004715dd22fcd41593
parent 249742 ed925a89b63eba733345b039b909a738e346b1ee
child 249744 c49fbde40955ef9e048012a5684df7a17ba1b090
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop, abillings
bugs1128126
milestone37.0a2
Bug 1128126 - Enforce safe schemes in isInstallAllowed. r=Mossop a=abillings
browser/base/content/browser-addons.js
browser/base/content/test/general/browser_bug553455.js
browser/base/content/test/general/browser_bug592338.js
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js
toolkit/mozapps/extensions/test/xpinstall/head.js
--- a/browser/base/content/browser-addons.js
+++ b/browser/base/content/browser-addons.js
@@ -365,16 +365,20 @@ var LightWeightThemeWebInstaller = {
 
     this._manager.resetPreview();
   },
 
   _isAllowed: function (node) {
     var pm = Services.perms;
 
     var uri = node.ownerDocument.documentURIObject;
+
+    if (!uri.schemeIs("https"))
+      return false;
+
     return pm.testPermission(uri, "install") == pm.ALLOW_ACTION;
   },
 
   _getThemeFromNode: function (node) {
     return this._manager.parseTheme(node.getAttribute("data-browsertheme"),
                                     node.baseURI);
   }
 }
--- a/browser/base/content/test/general/browser_bug553455.js
+++ b/browser/base/content/test/general/browser_bug553455.js
@@ -835,16 +835,17 @@ var XPInstallObserver = {
 };
 
 function test() {
   requestLongerTimeout(4);
   waitForExplicitFinish();
 
   Services.prefs.setBoolPref("extensions.logging.enabled", true);
   Services.prefs.setBoolPref("extensions.strictCompatibility", true);
+  Services.prefs.setBoolPref("extensions.install.requireSecureOrigin", false);
 
   Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-failed", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-complete", false);
 
   registerCleanupFunction(function() {
     // Make sure no more test parts run in case we were timed out
@@ -854,16 +855,17 @@ function test() {
     AddonManager.getAllInstalls(function(aInstalls) {
       aInstalls.forEach(function(aInstall) {
         aInstall.cancel();
       });
     });
 
     Services.prefs.clearUserPref("extensions.logging.enabled");
     Services.prefs.clearUserPref("extensions.strictCompatibility");
+    Services.prefs.clearUserPref("extensions.install.requireSecureOrigin");
 
     Services.obs.removeObserver(XPInstallObserver, "addon-install-started");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-blocked");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-failed");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-complete");
   });
 
   runNextTest();
--- a/browser/base/content/test/general/browser_bug592338.js
+++ b/browser/base/content/test/general/browser_bug592338.js
@@ -11,23 +11,51 @@ var LightweightThemeManager = tempScope.
 function wait_for_notification(aCallback) {
   PopupNotifications.panel.addEventListener("popupshown", function() {
     PopupNotifications.panel.removeEventListener("popupshown", arguments.callee, false);
     aCallback(PopupNotifications.panel);
   }, false);
 }
 
 var TESTS = [
+function test_install_http() {
+  is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
+
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.org/"), "install", pm.ALLOW_ACTION);
+
+  gBrowser.selectedTab = gBrowser.addTab("http://example.org/browser/browser/base/content/test/general/bug592338.html");
+  gBrowser.selectedBrowser.addEventListener("pageshow", function() {
+    if (gBrowser.contentDocument.location.href == "about:blank")
+      return;
+
+    gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, false);
+
+    executeSoon(function() {
+      var link = gBrowser.contentDocument.getElementById("theme-install");
+      EventUtils.synthesizeMouse(link, 2, 2, {}, gBrowser.contentWindow);
+
+      is(LightweightThemeManager.currentTheme, null, "Should not have installed the test theme");
+
+      gBrowser.removeTab(gBrowser.selectedTab);
+
+      pm.remove("example.org", "install");
+
+      runNextTest();
+    });
+  }, false);
+},
+
 function test_install_lwtheme() {
   is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
 
   var pm = Services.perms;
   pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
-  gBrowser.selectedTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/general/bug592338.html");
+  gBrowser.selectedTab = gBrowser.addTab("https://example.com/browser/browser/base/content/test/general/bug592338.html");
   gBrowser.selectedBrowser.addEventListener("pageshow", function() {
     if (gBrowser.contentDocument.location.href == "about:blank")
       return;
 
     gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, false);
 
     executeSoon(function() {
       var link = gBrowser.contentDocument.getElementById("theme-install");
@@ -49,19 +77,19 @@ function test_lwtheme_switch_theme() {
   is(LightweightThemeManager.currentTheme, null, "Should be no lightweight theme selected");
 
   AddonManager.getAddonByID("theme-xpi@tests.mozilla.org", function(aAddon) {
     aAddon.userDisabled = false;
     ok(aAddon.isActive, "Theme should have immediately enabled");
     Services.prefs.setBoolPref("extensions.dss.enabled", false);
 
     var pm = Services.perms;
-    pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
+    pm.add(makeURI("https://example.com/"), "install", pm.ALLOW_ACTION);
 
-    gBrowser.selectedTab = gBrowser.addTab("http://example.com/browser/browser/base/content/test/general/bug592338.html");
+    gBrowser.selectedTab = gBrowser.addTab("https://example.com/browser/browser/base/content/test/general/bug592338.html");
     gBrowser.selectedBrowser.addEventListener("pageshow", function() {
       if (gBrowser.contentDocument.location.href == "about:blank")
         return;
 
       gBrowser.selectedBrowser.removeEventListener("pageshow", arguments.callee, false);
 
       executeSoon(function() {
         var link = gBrowser.contentDocument.getElementById("theme-install");
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -76,16 +76,17 @@ const PREF_EM_AUTO_DISABLED_SCOPES    = 
 const PREF_EM_SHOW_MISMATCH_UI        = "extensions.showMismatchUI";
 const PREF_XPI_ENABLED                = "xpinstall.enabled";
 const PREF_XPI_WHITELIST_REQUIRED     = "xpinstall.whitelist.required";
 const PREF_XPI_DIRECT_WHITELISTED     = "xpinstall.whitelist.directRequest";
 const PREF_XPI_FILE_WHITELISTED       = "xpinstall.whitelist.fileRequest";
 const PREF_XPI_PERMISSIONS_BRANCH     = "xpinstall.";
 const PREF_XPI_UNPACK                 = "extensions.alwaysUnpack";
 const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
+const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin";
 const PREF_INSTALL_DISTRO_ADDONS      = "extensions.installDistroAddons";
 const PREF_BRANCH_INSTALLED_ADDON     = "extensions.installedDistroAddon.";
 const PREF_SHOWN_SELECTION_UI         = "extensions.shownSelectionUI";
 const PREF_INTERPOSITION_ENABLED      = "extensions.interposition.enabled";
 
 const PREF_EM_MIN_COMPAT_APP_VERSION      = "extensions.minCompatibleAppVersion";
 const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
 
@@ -3730,16 +3731,21 @@ this.XPIProvider = {
     let permission = Services.perms.testPermission(aUri, XPI_PERMISSION);
     if (permission == Ci.nsIPermissionManager.DENY_ACTION)
       return false;
 
     let requireWhitelist = Preferences.get(PREF_XPI_WHITELIST_REQUIRED, true);
     if (requireWhitelist && (permission != Ci.nsIPermissionManager.ALLOW_ACTION))
       return false;
 
+    let requireSecureOrigin = Preferences.get(PREF_INSTALL_REQUIRESECUREORIGIN, true);
+    let safeSchemes = ["https", "chrome", "file"];
+    if (requireSecureOrigin && safeSchemes.indexOf(aUri.scheme) == -1)
+      return false;
+
     return true;
   },
 
   /**
    * Called to get an AddonInstall to download and install an add-on from a URL.
    *
    * @param  aUrl
    *         The URL to be installed
--- a/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
@@ -11,66 +11,72 @@ const XPI_MIMETYPE = "application/x-xpin
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
 
   Services.prefs.setCharPref("xpinstall.whitelist.add", "test1.com,test2.com");
   Services.prefs.setCharPref("xpinstall.whitelist.add.36", "test3.com,www.test4.com");
   Services.prefs.setCharPref("xpinstall.whitelist.add.test5", "test5.com");
 
-  Services.perms.add(NetUtil.newURI("http://www.test9.com"), "install",
+  Services.perms.add(NetUtil.newURI("https://www.test9.com"), "install",
                      AM_Ci.nsIPermissionManager.ALLOW_ACTION);
 
   startupManager();
 
+  do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+                                               NetUtil.newURI("http://test1.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                              NetUtil.newURI("http://test1.com")));
+                                              NetUtil.newURI("https://test1.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                               NetUtil.newURI("https://www.test2.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                               NetUtil.newURI("https://test3.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://test4.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                               NetUtil.newURI("https://www.test4.com")));
+  do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+                                               NetUtil.newURI("http://www.test5.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                              NetUtil.newURI("http://www.test5.com")));
+                                              NetUtil.newURI("https://www.test5.com")));
 
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("http://www.test6.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://test7.com")));
+                                               NetUtil.newURI("https://www.test6.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://www.test8.com")));
+                                               NetUtil.newURI("https://test7.com")));
+  do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+                                               NetUtil.newURI("https://www.test8.com")));
 
   // This should remain unaffected
-  do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                              NetUtil.newURI("http://www.test9.com")));
+  do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
+                                               NetUtil.newURI("http://www.test9.com")));
   do_check_true(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                               NetUtil.newURI("https://www.test9.com")));
 
   Services.perms.removeAll();
 
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://test1.com")));
+                                               NetUtil.newURI("https://test1.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://www.test2.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://test3.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://www.test4.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://www.test5.com")));
+                                               NetUtil.newURI("https://www.test5.com")));
 
   // Upgrade the application and verify that the permissions are still not there
   restartManager("2");
 
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://test1.com")));
+                                               NetUtil.newURI("https://test1.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://www.test2.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://test3.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
                                                NetUtil.newURI("https://www.test4.com")));
   do_check_false(AddonManager.isInstallAllowed(XPI_MIMETYPE,
-                                               NetUtil.newURI("http://www.test5.com")));
+                                               NetUtil.newURI("https://www.test5.com")));
 }
--- a/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/browser_concurrent_installs.js
@@ -67,22 +67,24 @@ function createTab(url) {
 
   return tab;
 }
 
 function test() {
   waitForExplicitFinish();
 
   Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
+  Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false);
   Services.wm.addListener(gAddonAndWindowListener);
   AddonManager.addInstallListener(gAddonAndWindowListener);
   registerCleanupFunction(function() {
     Services.wm.removeListener(gAddonAndWindowListener);
     AddonManager.removeInstallListener(gAddonAndWindowListener);
     Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
+    Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN);
 
     Services.perms.remove("example.com", "install");
     Services.perms.remove("example.org", "install");
 
     while (gConcurrentTabs.length) {
       gBrowser.removeTab(gConcurrentTabs.shift());
     }
   });
--- a/toolkit/mozapps/extensions/test/xpinstall/head.js
+++ b/toolkit/mozapps/extensions/test/xpinstall/head.js
@@ -2,16 +2,17 @@ const RELATIVE_DIR = "toolkit/mozapps/ex
 
 const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
 const TESTROOT2 = "http://example.org/browser/" + RELATIVE_DIR;
 const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
 const PROMPT_URL = "chrome://global/content/commonDialog.xul";
 const ADDONS_URL = "chrome://mozapps/content/extensions/extensions.xul";
 const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
 const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
+const PREF_INSTALL_REQUIRESECUREORIGIN = "extensions.install.requireSecureOrigin";
 const CHROME_NAME = "mochikit";
 
 function getChromeRoot(path) {
   if (path === undefined) {
     return "chrome://" + CHROME_NAME + "/content/browser/" + RELATIVE_DIR
   }
   return getRootDirectory(path);
 }
@@ -83,30 +84,33 @@ var Harness = {
   waitingForFinish: false,
 
   // Setup and tear down functions
   setup: function() {
     if (!this.waitingForFinish) {
       waitForExplicitFinish();
       this.waitingForFinish = true;
 
+      Services.prefs.setBoolPref(PREF_INSTALL_REQUIRESECUREORIGIN, false);
+
       Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
       Services.obs.addObserver(this, "addon-install-started", false);
       Services.obs.addObserver(this, "addon-install-disabled", false);
       Services.obs.addObserver(this, "addon-install-blocked", false);
       Services.obs.addObserver(this, "addon-install-failed", false);
       Services.obs.addObserver(this, "addon-install-complete", false);
 
       AddonManager.addInstallListener(this);
 
       Services.wm.addListener(this);
 
       var self = this;
       registerCleanupFunction(function() {
         Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
+        Services.prefs.clearUserPref(PREF_INSTALL_REQUIRESECUREORIGIN);
         Services.obs.removeObserver(self, "addon-install-started");
         Services.obs.removeObserver(self, "addon-install-disabled");
         Services.obs.removeObserver(self, "addon-install-blocked");
         Services.obs.removeObserver(self, "addon-install-failed");
         Services.obs.removeObserver(self, "addon-install-complete");
 
         AddonManager.removeInstallListener(self);