Bug 1429148 - Policy: Don't let a Master Password to be set. r=keeler
authorFelipe Gomes <felipc@gmail.com>
Tue, 20 Feb 2018 20:46:11 -0300
changeset 404697 c9dc10752a478322dc99201b0b215c7fd1d7a44b
parent 404696 ffe15fb2541cc5999f6fcee6c13e6075e4f0feb7
child 404698 d418ce8a05644edb16f317c13fc1c8cd2b6c3c2f
child 404740 4da181c6e0538ece8e10a052f2ff18d914432124
push id59940
push userfelipc@gmail.com
push dateWed, 21 Feb 2018 18:26:26 +0000
treeherderautoland@c9dc10752a47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1429148
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1429148 - Policy: Don't let a Master Password to be set. r=keeler MozReview-Commit-ID: 8Adqg0KU7cZ
browser/components/enterprisepolicies/Policies.jsm
browser/components/enterprisepolicies/helpers/sample.json
browser/components/enterprisepolicies/schemas/policies-schema.json
browser/components/enterprisepolicies/tests/browser/browser.ini
browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js
browser/components/preferences/in-content/privacy.js
security/manager/pki/resources/content/device_manager.js
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -106,16 +106,24 @@ this.Policies = {
   "block_set_desktop_background": {
     onBeforeUIStartup(manager, param) {
       if (param) {
         manager.disallowFeature("setDesktopBackground", true);
       }
     }
   },
 
+  "CreateMasterPassword": {
+    onBeforeUIStartup(manager, param) {
+      if (!param) {
+        manager.disallowFeature("createMasterPassword");
+      }
+    }
+  },
+
   "DisableFirefoxScreenshots": {
     onBeforeAddons(manager, param) {
       if (param) {
         setAndLockPref("extensions.screenshots.disabled", true);
       }
     }
   },
 
--- a/browser/components/enterprisepolicies/helpers/sample.json
+++ b/browser/components/enterprisepolicies/helpers/sample.json
@@ -8,11 +8,12 @@
         "https://www.example.com"
       ],
 
       "block": [
         "https://www.example.org"
       ]
     },
 
-    "block_about_profiles": true
+    "block_about_profiles": true,
+    "CreateMasterPassword": false
   }
 }
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -62,16 +62,24 @@
     "block_set_desktop_background": {
       "description": "Prevents usage of the \"Set Image as Desktop Background\" feature.",
       "first_available": "60.0",
 
       "type": "boolean",
       "enum": [true]
     },
 
+    "CreateMasterPassword": {
+      "description": "If false, removes access to create a master password.",
+      "first_available": "60.0",
+
+      "type": "boolean",
+      "enum": [false]
+    },
+
     "DisableFirefoxScreenshots": {
       "description": "Prevents usage of the Firefox Screenshots feature.",
       "first_available": "60.0",
 
       "type": "boolean",
       "enum": [true]
     },
 
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -14,14 +14,15 @@ support-files =
 [browser_policy_app_update.js]
 [browser_policy_block_about_addons.js]
 [browser_policy_block_about_config.js]
 [browser_policy_block_about_profiles.js]
 [browser_policy_block_about_support.js]
 [browser_policy_block_set_desktop_background.js]
 [browser_policy_default_browser_check.js]
 [browser_policy_disable_fxscreenshots.js]
+[browser_policy_disable_masterpassword.js]
 [browser_policy_display_bookmarks.js]
 [browser_policy_disable_formhistory.js]
 [browser_policy_display_menu.js]
 [browser_policy_disable_shield.js]
 [browser_policy_remember_passwords.js]
 
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js
@@ -0,0 +1,79 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const MASTER_PASSWORD = "omgsecret!";
+const mpToken = Cc["@mozilla.org/security/pk11tokendb;1"]
+                  .getService(Ci.nsIPK11TokenDB)
+                  .getInternalKeyToken();
+
+async function checkDeviceManager({buttonIsDisabled}) {
+  let deviceManagerWindow = window.openDialog("chrome://pippki/content/device_manager.xul", "", "");
+  await new Promise(resolve => {
+    deviceManagerWindow.addEventListener("load", resolve, {once: true});
+  });
+
+  let tree = deviceManagerWindow.document.getElementById("device_tree");
+  ok(tree, "The device tree exists");
+
+  // Find and select the item related to the internal key token
+  for (let i = 0; i < tree.view.rowCount; i++) {
+    tree.view.selection.select(i);
+
+    try {
+      let selected_token = deviceManagerWindow.selected_slot.getToken();
+      if (selected_token.isInternalKeyToken) {
+        break;
+      }
+    } catch (e) {}
+  }
+
+  // Check to see if the button was updated correctly
+  let changePwButton = deviceManagerWindow.document.getElementById("change_pw_button");
+  is(changePwButton.getAttribute("disabled") == "true", buttonIsDisabled,
+     "Change Password button is in the correct state: " + buttonIsDisabled);
+
+  await BrowserTestUtils.closeWindow(deviceManagerWindow);
+}
+
+async function checkAboutPreferences({checkboxIsDisabled}) {
+  await BrowserTestUtils.withNewTab("about:preferences#privacy", async browser => {
+  // eslint-disable-next-line mozilla/no-cpows-in-tests
+  is(browser.contentDocument.getElementById("useMasterPassword").disabled, checkboxIsDisabled,
+    "Master Password checkbox is in the correct state: " + checkboxIsDisabled);
+});
+
+}
+
+add_task(async function test_policy_disable_masterpassword() {
+  ok(!mpToken.hasPassword, "Starting the test with no password");
+
+  // No password and no policy: access to setting a master password
+  // should be enabled.
+  await checkDeviceManager({buttonIsDisabled: false});
+  await checkAboutPreferences({checkboxIsDisabled: false});
+
+  await setupPolicyEngineWithJson({
+    "policies": {
+      "CreateMasterPassword": false
+    }
+  });
+
+  // With the `CreateMasterPassword: false` policy active, the
+  // UI entry points for creating a Master Password should be disabled.
+  await checkDeviceManager({buttonIsDisabled: true});
+  await checkAboutPreferences({checkboxIsDisabled: true});
+
+  mpToken.changePassword("", MASTER_PASSWORD);
+  ok(mpToken.hasPassword, "Master password was set");
+
+  // If a Master Password is already set, there's no point in disabling
+  // the
+  await checkDeviceManager({buttonIsDisabled: false});
+  await checkAboutPreferences({checkboxIsDisabled: false});
+
+  // Clean up
+  mpToken.changePassword(MASTER_PASSWORD, "");
+  ok(!mpToken.hasPassword, "Master password was cleaned up");
+});
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -1119,16 +1119,17 @@ var gPrivacyPane = {
   _initMasterPasswordUI() {
     var noMP = !LoginHelper.isMasterPasswordSet();
 
     var button = document.getElementById("changeMasterPassword");
     button.disabled = noMP;
 
     var checkbox = document.getElementById("useMasterPassword");
     checkbox.checked = !noMP;
+    checkbox.disabled = noMP && !Services.policies.isAllowed("createMasterPassword");
   },
 
   /**
    * Enables/disables the master password button depending on the state of the
    * "use master password" checkbox, and prompts for master password removal if
    * one is set.
    */
   updateMasterPasswordButton() {
--- a/security/manager/pki/resources/content/device_manager.js
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -157,16 +157,22 @@ function enableButtons() {
         if (selected_token.needsLogin()) {
           if (selected_token.isLoggedIn()) {
             logout_toggle = "false";
           } else {
             login_toggle = "false";
           }
         }
       }
+
+      if (!Services.policies.isAllowed("createMasterPassword") &&
+          selected_token.isInternalKeyToken &&
+          !selected_token.hasPassword) {
+        pw_toggle = "true";
+      }
     }
     showSlotInfo();
   }
   document.getElementById("login_button")
           .setAttribute("disabled", login_toggle);
   document.getElementById("logout_button")
           .setAttribute("disabled", logout_toggle);
   document.getElementById("change_pw_button")