summaryrefslogtreecommitdiffstats
path: root/security/manager/pki/resources/content/device_manager.js
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/pki/resources/content/device_manager.js')
-rw-r--r--security/manager/pki/resources/content/device_manager.js433
1 files changed, 433 insertions, 0 deletions
diff --git a/security/manager/pki/resources/content/device_manager.js b/security/manager/pki/resources/content/device_manager.js
new file mode 100644
index 0000000000..deb58d2ff3
--- /dev/null
+++ b/security/manager/pki/resources/content/device_manager.js
@@ -0,0 +1,433 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+var secmoddb;
+var skip_enable_buttons = false;
+
+/* Do the initial load of all PKCS# modules and list them. */
+function LoadModules() {
+ secmoddb = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
+ Ci.nsIPKCS11ModuleDB
+ );
+ RefreshDeviceList();
+}
+
+async function doPrompt(l10n_id) {
+ let [msg] = await document.l10n.formatValues([{ id: l10n_id }]);
+ Services.prompt.alert(window, null, msg);
+}
+
+async function doConfirm(l10n_id) {
+ let [msg] = await document.l10n.formatValues([{ id: l10n_id }]);
+ return Services.prompt.confirm(window, null, msg);
+}
+
+function RefreshDeviceList() {
+ for (let module of secmoddb.listModules()) {
+ let slots = module.listSlots();
+ AddModule(module, slots);
+ }
+
+ // Set the text on the FIPS button.
+ SetFIPSButton();
+}
+
+function SetFIPSButton() {
+ var fipsButton = document.getElementById("fipsbutton");
+ if (secmoddb.isFIPSEnabled) {
+ document.l10n.setAttributes(fipsButton, "devmgr-button-disable-fips");
+ } else {
+ document.l10n.setAttributes(fipsButton, "devmgr-button-enable-fips");
+ }
+
+ var can_toggle = secmoddb.canToggleFIPS;
+ if (can_toggle) {
+ fipsButton.removeAttribute("disabled");
+ } else {
+ fipsButton.setAttribute("disabled", "true");
+ }
+}
+
+/* Add a module to the tree. slots is the array of slots in the module,
+ * to be represented as children.
+ */
+function AddModule(module, slots) {
+ var tree = document.getElementById("device_list");
+ var item = document.createXULElement("treeitem");
+ var row = document.createXULElement("treerow");
+ var cell = document.createXULElement("treecell");
+ cell.setAttribute("label", module.name);
+ row.appendChild(cell);
+ item.appendChild(row);
+ var parent = document.createXULElement("treechildren");
+ for (let slot of slots) {
+ var child_item = document.createXULElement("treeitem");
+ var child_row = document.createXULElement("treerow");
+ var child_cell = document.createXULElement("treecell");
+ child_cell.setAttribute("label", slot.name);
+ child_row.appendChild(child_cell);
+ child_item.appendChild(child_row);
+ child_item.setAttribute("pk11kind", "slot");
+ // 'slot' is an attribute on any HTML element, hence 'slotObject' instead.
+ child_item.slotObject = slot;
+ parent.appendChild(child_item);
+ }
+ item.appendChild(parent);
+ item.setAttribute("pk11kind", "module");
+ item.module = module;
+ item.setAttribute("open", "true");
+ item.setAttribute("container", "true");
+ tree.appendChild(item);
+}
+
+var selected_slot;
+var selected_module;
+
+/* get the slot selected by the user (can only be one-at-a-time) */
+function getSelectedItem() {
+ let tree = document.getElementById("device_tree");
+ if (tree.currentIndex < 0) {
+ return;
+ }
+ let item = tree.view.getItemAtIndex(tree.currentIndex);
+ selected_slot = null;
+ selected_module = null;
+ if (item) {
+ let kind = item.getAttribute("pk11kind");
+ if (kind == "slot") {
+ selected_slot = item.slotObject;
+ } else {
+ // (kind == "module")
+ selected_module = item.module;
+ }
+ }
+}
+
+function enableButtons() {
+ if (skip_enable_buttons) {
+ return;
+ }
+
+ var login_toggle = "true";
+ var logout_toggle = "true";
+ var pw_toggle = "true";
+ var unload_toggle = "true";
+ getSelectedItem();
+ if (selected_module) {
+ unload_toggle = "false";
+ showModuleInfo();
+ } else if (selected_slot) {
+ // here's the workaround - login functions are all with token,
+ // so grab the token type
+ var selected_token = selected_slot.getToken();
+ if (selected_token != null) {
+ if (selected_token.needsLogin() || !selected_token.needsUserInit) {
+ pw_toggle = "false";
+ 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")
+ .setAttribute("disabled", pw_toggle);
+ document
+ .getElementById("unload_button")
+ .setAttribute("disabled", unload_toggle);
+}
+
+// clear the display of information for the slot
+function ClearInfoList() {
+ let infoList = document.getElementById("info_list");
+ while (infoList.hasChildNodes()) {
+ infoList.firstChild.remove();
+ }
+}
+
+function ClearDeviceList() {
+ ClearInfoList();
+
+ skip_enable_buttons = true;
+ var tree = document.getElementById("device_tree");
+ tree.view.selection.clearSelection();
+ skip_enable_buttons = false;
+
+ // Remove the existing listed modules so that a refresh doesn't display the
+ // module that just changed.
+ let deviceList = document.getElementById("device_list");
+ while (deviceList.hasChildNodes()) {
+ deviceList.firstChild.remove();
+ }
+}
+
+// show a list of info about a slot
+function showSlotInfo() {
+ var present = true;
+ ClearInfoList();
+ switch (selected_slot.status) {
+ case Ci.nsIPKCS11Slot.SLOT_DISABLED:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-disabled" },
+ "tok_status"
+ );
+ present = false;
+ break;
+ case Ci.nsIPKCS11Slot.SLOT_NOT_PRESENT:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-not-present" },
+ "tok_status"
+ );
+ present = false;
+ break;
+ case Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-uninitialized" },
+ "tok_status"
+ );
+ break;
+ case Ci.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-not-logged-in" },
+ "tok_status"
+ );
+ break;
+ case Ci.nsIPKCS11Slot.SLOT_LOGGED_IN:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-logged-in" },
+ "tok_status"
+ );
+ break;
+ case Ci.nsIPKCS11Slot.SLOT_READY:
+ AddInfoRow(
+ "devinfo-status",
+ { l10nID: "devinfo-status-ready" },
+ "tok_status"
+ );
+ break;
+ default:
+ return;
+ }
+ AddInfoRow("devinfo-desc", { label: selected_slot.desc }, "slot_desc");
+ AddInfoRow("devinfo-man-id", { label: selected_slot.manID }, "slot_manID");
+ AddInfoRow(
+ "devinfo-hwversion",
+ { label: selected_slot.HWVersion },
+ "slot_hwv"
+ );
+ AddInfoRow(
+ "devinfo-fwversion",
+ { label: selected_slot.FWVersion },
+ "slot_fwv"
+ );
+ if (present) {
+ showTokenInfo();
+ }
+}
+
+function showModuleInfo() {
+ ClearInfoList();
+ AddInfoRow("devinfo-modname", { label: selected_module.name }, "module_name");
+ AddInfoRow(
+ "devinfo-modpath",
+ { label: selected_module.libName },
+ "module_path"
+ );
+}
+
+// add a row to the info list, as [col1 col2] (ex.: ["status" "logged in"])
+function AddInfoRow(l10nID, col2, cell_id) {
+ var tree = document.getElementById("info_list");
+ var item = document.createXULElement("treeitem");
+ var row = document.createXULElement("treerow");
+ var cell1 = document.createXULElement("treecell");
+ document.l10n.setAttributes(cell1, l10nID);
+ cell1.setAttribute("crop", "never");
+ row.appendChild(cell1);
+ var cell2 = document.createXULElement("treecell");
+ if (col2.l10nID) {
+ document.l10n.setAttributes(cell2, col2.l10nID);
+ } else {
+ cell2.setAttribute("label", col2.label);
+ }
+ cell2.setAttribute("crop", "never");
+ cell2.setAttribute("id", cell_id);
+ row.appendChild(cell2);
+ item.appendChild(row);
+ tree.appendChild(item);
+}
+
+// log in to a slot
+function doLogin() {
+ getSelectedItem();
+ // here's the workaround - login functions are with token
+ var selected_token = selected_slot.getToken();
+ try {
+ selected_token.login(false);
+ var tok_status = document.getElementById("tok_status");
+ if (selected_token.isLoggedIn()) {
+ document.l10n.setAttributes(tok_status, "devinfo-status-logged-in");
+ } else {
+ document.l10n.setAttributes(tok_status, "devinfo-status-not-logged-in");
+ }
+ } catch (e) {
+ doPrompt("login-failed");
+ }
+ enableButtons();
+}
+
+// log out of a slot
+function doLogout() {
+ getSelectedItem();
+ // here's the workaround - login functions are with token
+ var selected_token = selected_slot.getToken();
+ try {
+ selected_token.logoutAndDropAuthenticatedResources();
+ var tok_status = document.getElementById("tok_status");
+ if (selected_token.isLoggedIn()) {
+ document.l10n.setAttributes(tok_status, "devinfo-status-logged-in");
+ } else {
+ document.l10n.setAttributes(tok_status, "devinfo-status-not-logged-in");
+ }
+ } catch (e) {}
+ enableButtons();
+}
+
+// load a new device
+function doLoad() {
+ window.browsingContext.topChromeWindow.open(
+ "load_device.xhtml",
+ "loaddevice",
+ "chrome,centerscreen,modal"
+ );
+ ClearDeviceList();
+ RefreshDeviceList();
+}
+
+async function deleteSelected() {
+ getSelectedItem();
+ if (selected_module && (await doConfirm("del-module-warning"))) {
+ try {
+ secmoddb.deleteModule(selected_module.name);
+ } catch (e) {
+ doPrompt("del-module-error");
+ return false;
+ }
+ selected_module = null;
+ return true;
+ }
+ return false;
+}
+
+async function doUnload() {
+ if (await deleteSelected()) {
+ ClearDeviceList();
+ RefreshDeviceList();
+ }
+}
+
+function changePassword() {
+ getSelectedItem();
+ let params = Cc["@mozilla.org/embedcomp/dialogparam;1"].createInstance(
+ Ci.nsIDialogParamBlock
+ );
+ let objects = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+ objects.appendElement(selected_slot.getToken());
+ params.objects = objects;
+ window.browsingContext.topChromeWindow.openDialog(
+ "changepassword.xhtml",
+ "",
+ "chrome,centerscreen,modal",
+ params
+ );
+ showSlotInfo();
+ enableButtons();
+}
+
+// ------------------------------------- Old code
+
+function showTokenInfo() {
+ var selected_token = selected_slot.getToken();
+ AddInfoRow("devinfo-label", { label: selected_token.tokenName }, "tok_label");
+ AddInfoRow(
+ "devinfo-man-id",
+ { label: selected_token.tokenManID },
+ "tok_manID"
+ );
+ AddInfoRow(
+ "devinfo-serialnum",
+ { label: selected_token.tokenSerialNumber },
+ "tok_sNum"
+ );
+ AddInfoRow(
+ "devinfo-hwversion",
+ { label: selected_token.tokenHWVersion },
+ "tok_hwv"
+ );
+ AddInfoRow(
+ "devinfo-fwversion",
+ { label: selected_token.tokenFWVersion },
+ "tok_fwv"
+ );
+}
+
+function toggleFIPS() {
+ if (!secmoddb.isFIPSEnabled) {
+ // A restriction of FIPS mode is, the password must be set
+ // In FIPS mode the password must be non-empty.
+ // This is different from what we allow in NON-Fips mode.
+
+ var tokendb = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
+ Ci.nsIPK11TokenDB
+ );
+ var internal_token = tokendb.getInternalKeyToken(); // nsIPK11Token
+ if (!internal_token.hasPassword) {
+ // Token has either no or an empty password.
+ doPrompt("fips-nonempty-primary-password-required");
+ return;
+ }
+ }
+
+ try {
+ secmoddb.toggleFIPSMode();
+ } catch (e) {
+ doPrompt("unable-to-toggle-fips");
+ return;
+ }
+
+ // Remove the existing listed modules so that a refresh doesn't display the
+ // module that just changed.
+ ClearDeviceList();
+
+ RefreshDeviceList();
+}