Source code

Revision control

Copy as Markdown

Other Tools

/* 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();
}