1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 const { XPCOMUtils } = ChromeUtils.importESModule(
7 "resource://gre/modules/XPCOMUtils.sys.mjs"
11 var skip_enable_buttons = false;
13 /* Do the initial load of all PKCS# modules and list them. */
14 function LoadModules() {
15 secmoddb = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
21 async function doPrompt(l10n_id) {
22 let [msg] = await document.l10n.formatValues([{ id: l10n_id }]);
23 Services.prompt.alert(window, null, msg);
26 async function doConfirm(l10n_id) {
27 let [msg] = await document.l10n.formatValues([{ id: l10n_id }]);
28 return Services.prompt.confirm(window, null, msg);
31 function RefreshDeviceList() {
32 for (let module of secmoddb.listModules()) {
33 let slots = module.listSlots();
34 AddModule(module, slots);
37 // Set the text on the FIPS button.
41 function SetFIPSButton() {
42 var fipsButton = document.getElementById("fipsbutton");
43 if (secmoddb.isFIPSEnabled) {
44 document.l10n.setAttributes(fipsButton, "devmgr-button-disable-fips");
46 document.l10n.setAttributes(fipsButton, "devmgr-button-enable-fips");
49 var can_toggle = secmoddb.canToggleFIPS;
51 fipsButton.removeAttribute("disabled");
53 fipsButton.setAttribute("disabled", "true");
57 /* Add a module to the tree. slots is the array of slots in the module,
58 * to be represented as children.
60 function AddModule(module, slots) {
61 var tree = document.getElementById("device_list");
62 var item = document.createXULElement("treeitem");
63 var row = document.createXULElement("treerow");
64 var cell = document.createXULElement("treecell");
65 cell.setAttribute("label", module.name);
66 row.appendChild(cell);
67 item.appendChild(row);
68 var parent = document.createXULElement("treechildren");
69 for (let slot of slots) {
70 var child_item = document.createXULElement("treeitem");
71 var child_row = document.createXULElement("treerow");
72 var child_cell = document.createXULElement("treecell");
73 child_cell.setAttribute("label", slot.name);
74 child_row.appendChild(child_cell);
75 child_item.appendChild(child_row);
76 child_item.setAttribute("pk11kind", "slot");
77 // 'slot' is an attribute on any HTML element, hence 'slotObject' instead.
78 child_item.slotObject = slot;
79 parent.appendChild(child_item);
81 item.appendChild(parent);
82 item.setAttribute("pk11kind", "module");
84 item.setAttribute("open", "true");
85 item.setAttribute("container", "true");
86 tree.appendChild(item);
92 /* get the slot selected by the user (can only be one-at-a-time) */
93 function getSelectedItem() {
94 let tree = document.getElementById("device_tree");
95 if (tree.currentIndex < 0) {
98 let item = tree.view.getItemAtIndex(tree.currentIndex);
100 selected_module = null;
102 let kind = item.getAttribute("pk11kind");
103 if (kind == "slot") {
104 selected_slot = item.slotObject;
106 // (kind == "module")
107 selected_module = item.module;
112 function enableButtons() {
113 if (skip_enable_buttons) {
117 var login_toggle = "true";
118 var logout_toggle = "true";
119 var pw_toggle = "true";
120 var unload_toggle = "true";
122 if (selected_module) {
123 unload_toggle = "false";
125 } else if (selected_slot) {
126 // here's the workaround - login functions are all with token,
127 // so grab the token type
128 var selected_token = selected_slot.getToken();
129 if (selected_token != null) {
130 if (selected_token.needsLogin() || !selected_token.needsUserInit) {
132 if (selected_token.needsLogin()) {
133 if (selected_token.isLoggedIn()) {
134 logout_toggle = "false";
136 login_toggle = "false";
142 !Services.policies.isAllowed("createMasterPassword") &&
143 selected_token.isInternalKeyToken &&
144 !selected_token.hasPassword
152 .getElementById("login_button")
153 .setAttribute("disabled", login_toggle);
155 .getElementById("logout_button")
156 .setAttribute("disabled", logout_toggle);
158 .getElementById("change_pw_button")
159 .setAttribute("disabled", pw_toggle);
161 .getElementById("unload_button")
162 .setAttribute("disabled", unload_toggle);
165 // clear the display of information for the slot
166 function ClearInfoList() {
167 let infoList = document.getElementById("info_list");
168 while (infoList.hasChildNodes()) {
169 infoList.firstChild.remove();
173 function ClearDeviceList() {
176 skip_enable_buttons = true;
177 var tree = document.getElementById("device_tree");
178 tree.view.selection.clearSelection();
179 skip_enable_buttons = false;
181 // Remove the existing listed modules so that a refresh doesn't display the
182 // module that just changed.
183 let deviceList = document.getElementById("device_list");
184 while (deviceList.hasChildNodes()) {
185 deviceList.firstChild.remove();
189 // show a list of info about a slot
190 function showSlotInfo() {
193 switch (selected_slot.status) {
194 case Ci.nsIPKCS11Slot.SLOT_DISABLED:
197 { l10nID: "devinfo-status-disabled" },
202 case Ci.nsIPKCS11Slot.SLOT_NOT_PRESENT:
205 { l10nID: "devinfo-status-not-present" },
210 case Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED:
213 { l10nID: "devinfo-status-uninitialized" },
217 case Ci.nsIPKCS11Slot.SLOT_NOT_LOGGED_IN:
220 { l10nID: "devinfo-status-not-logged-in" },
224 case Ci.nsIPKCS11Slot.SLOT_LOGGED_IN:
227 { l10nID: "devinfo-status-logged-in" },
231 case Ci.nsIPKCS11Slot.SLOT_READY:
234 { l10nID: "devinfo-status-ready" },
241 AddInfoRow("devinfo-desc", { label: selected_slot.desc }, "slot_desc");
242 AddInfoRow("devinfo-man-id", { label: selected_slot.manID }, "slot_manID");
245 { label: selected_slot.HWVersion },
250 { label: selected_slot.FWVersion },
258 function showModuleInfo() {
260 AddInfoRow("devinfo-modname", { label: selected_module.name }, "module_name");
263 { label: selected_module.libName },
268 // add a row to the info list, as [col1 col2] (ex.: ["status" "logged in"])
269 function AddInfoRow(l10nID, col2, cell_id) {
270 var tree = document.getElementById("info_list");
271 var item = document.createXULElement("treeitem");
272 var row = document.createXULElement("treerow");
273 var cell1 = document.createXULElement("treecell");
274 document.l10n.setAttributes(cell1, l10nID);
275 cell1.setAttribute("crop", "never");
276 row.appendChild(cell1);
277 var cell2 = document.createXULElement("treecell");
279 document.l10n.setAttributes(cell2, col2.l10nID);
281 cell2.setAttribute("label", col2.label);
283 cell2.setAttribute("crop", "never");
284 cell2.setAttribute("id", cell_id);
285 row.appendChild(cell2);
286 item.appendChild(row);
287 tree.appendChild(item);
293 // here's the workaround - login functions are with token
294 var selected_token = selected_slot.getToken();
296 selected_token.login(false);
297 var tok_status = document.getElementById("tok_status");
298 if (selected_token.isLoggedIn()) {
299 document.l10n.setAttributes(tok_status, "devinfo-status-logged-in");
301 document.l10n.setAttributes(tok_status, "devinfo-status-not-logged-in");
304 doPrompt("login-failed");
310 function doLogout() {
312 // here's the workaround - login functions are with token
313 var selected_token = selected_slot.getToken();
315 selected_token.logoutAndDropAuthenticatedResources();
316 var tok_status = document.getElementById("tok_status");
317 if (selected_token.isLoggedIn()) {
318 document.l10n.setAttributes(tok_status, "devinfo-status-logged-in");
320 document.l10n.setAttributes(tok_status, "devinfo-status-not-logged-in");
328 window.browsingContext.topChromeWindow.open(
331 "chrome,centerscreen,modal"
337 async function deleteSelected() {
339 if (selected_module && (await doConfirm("del-module-warning"))) {
341 secmoddb.deleteModule(selected_module.name);
343 doPrompt("del-module-error");
346 selected_module = null;
352 async function doUnload() {
353 if (await deleteSelected()) {
359 function changePassword() {
361 let params = Cc["@mozilla.org/embedcomp/dialogparam;1"].createInstance(
362 Ci.nsIDialogParamBlock
364 let objects = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
365 objects.appendElement(selected_slot.getToken());
366 params.objects = objects;
367 window.browsingContext.topChromeWindow.openDialog(
368 "changepassword.xhtml",
370 "chrome,centerscreen,modal",
377 // ------------------------------------- Old code
379 function showTokenInfo() {
380 var selected_token = selected_slot.getToken();
381 AddInfoRow("devinfo-label", { label: selected_token.tokenName }, "tok_label");
384 { label: selected_token.tokenManID },
389 { label: selected_token.tokenSerialNumber },
394 { label: selected_token.tokenHWVersion },
399 { label: selected_token.tokenFWVersion },
404 function toggleFIPS() {
405 if (!secmoddb.isFIPSEnabled) {
406 // A restriction of FIPS mode is, the password must be set
407 // In FIPS mode the password must be non-empty.
408 // This is different from what we allow in NON-Fips mode.
410 var tokendb = Cc["@mozilla.org/security/pk11tokendb;1"].getService(
413 var internal_token = tokendb.getInternalKeyToken(); // nsIPK11Token
414 if (!internal_token.hasPassword) {
415 // Token has either no or an empty password.
416 doPrompt("fips-nonempty-primary-password-required");
422 secmoddb.toggleFIPSMode();
424 doPrompt("unable-to-toggle-fips");
428 // Remove the existing listed modules so that a refresh doesn't display the
429 // module that just changed.