import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="CAOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="CACerts">
<description>&certmgr.cas;</description>
<separator class="thin"/>
<tree id="ca-tree" flex="1" enableColumnDrag="true"
onselect="ca_enableButtons()">
<treecols>
<treecol id="certcol" label="&certmgr.certname;" primary="true"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="tokencol" label="&certmgr.tokenname;"
persist="hidden width ordinal" flex="1"/>
</treecols>
<treechildren ondblclick="viewCerts();"/>
</tree>
<separator class="thin"/>
<hbox>
<button id="ca_viewButton"
label="&certmgr.view2.label;"
accesskey="&certmgr.view2.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="ca_editButton"
label="&certmgr.edit3.label;"
accesskey="&certmgr.edit3.accesskey;"
disabled="true" oncommand="editCerts();"/>
<button id="ca_addButton"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore2.accesskey;"
oncommand="addCACerts();"/>
<button id="ca_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="ca_deleteButton"
label="&certmgr.delete_builtin.label;"
accesskey="&certmgr.delete_builtin.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,64 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="MineOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="myCerts">
<description>&certmgr.mine;</description>
<separator class="thin"/>
<tree id="user-tree" flex="1" enableColumnDrag="true"
onselect="mine_enableButtons()">
<treecols>
<treecol id="certcol" label="&certmgr.certname;" primary="true"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="tokencol" label="&certmgr.tokenname;"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="serialnumcol" label="&certmgr.serial;"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="issuedcol" label="&certmgr.begins;"
hidden="true" persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="expiredcol" label="&certmgr.expires;"
persist="hidden width ordinal" flex="1"/>
</treecols>
<treechildren ondblclick="viewCerts();"/>
</tree>
<separator class="thin"/>
<hbox>
<button id="mine_viewButton" class="normal"
label="&certmgr.view2.label;"
accesskey="&certmgr.view2.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="mine_backupButton" class="normal"
label="&certmgr.backup2.label;"
accesskey="&certmgr.backup2.accesskey;"
disabled="true" oncommand="backupCerts();"/>
<button id="mine_backupAllButton" class="normal"
label="&certmgr.backupall2.label;"
accesskey="&certmgr.backupall2.accesskey;"
oncommand="backupAllCerts();"/>
<button id="mine_restoreButton" class="normal"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore2.accesskey;"
oncommand="restoreCerts();"/>
<button id="mine_deleteButton" class="normal"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete2.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="OrphanOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="OrphanCerts">
<description>&certmgr.orphans;</description>
<separator class="thin"/>
<tree id="orphan-tree" flex="1" enableColumnDrag="true"
onselect="orphan_enableButtons()">
<treecols>
<treecol id="certcol" label="&certmgr.certname;" primary="true"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="tokencol" label="&certmgr.tokenname;"
persist="hidden width ordinal" flex="1"/>
</treecols>
<treechildren ondblclick="viewCerts();"/>
</tree>
<separator class="thin"/>
<hbox>
<button id="orphan_viewButton" class="normal"
label="&certmgr.view2.label;"
accesskey="&certmgr.view2.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="orphan_exportButton" class="normal"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="orphan_deleteButton" class="normal"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete2.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,54 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="OthersOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="othersCerts">
<description>&certmgr.others;</description>
<separator class="thin"/>
<tree id="email-tree" flex="1"
onselect="email_enableButtons()">
<treecols>
<treecol id="certcol" label="&certmgr.certname;" primary="true"
flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="emailcol" label="&certmgr.email;"
flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="expiredcol" label="&certmgr.expires;"
flex="1"/>
</treecols>
<treechildren flex="1" ondblclick="viewCerts();"/>
</tree>
<separator class="thin"/>
<hbox>
<button id="email_viewButton"
label="&certmgr.view2.label;"
accesskey="&certmgr.view2.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="email_addButton"
label="&certmgr.restore2.label;"
accesskey="&certmgr.restore2.accesskey;"
oncommand="addEmailCert();"/>
<button id="email_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="email_deleteButton"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete2.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,57 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="WebSitesOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="webCerts">
<description>&certmgr.websites2;</description>
<separator class="thin"/>
<tree id="server-tree" flex="1" enableColumnDrag="true"
onselect="websites_enableButtons()">
<treecols>
<treecol id="certcol" label="&certmgr.certname;" primary="true"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="sitecol" label="&certmgr.certserver;"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="lifetimecol" label="&certmgr.override_lifetime;"
persist="hidden width ordinal" flex="1"/>
<splitter class="tree-splitter"/>
<treecol id="expiredcol" label="&certmgr.expires;"
persist="hidden width ordinal" flex="1"/>
</treecols>
<treechildren ondblclick="viewCerts();"/>
</tree>
<separator class="thin"/>
<hbox>
<button id="websites_viewButton"
label="&certmgr.view2.label;"
accesskey="&certmgr.view2.accesskey;"
disabled="true" oncommand="viewCerts();"/>
<button id="websites_exportButton"
label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
disabled="true" oncommand="exportCerts();"/>
<button id="websites_deleteButton"
label="&certmgr.delete2.label;"
accesskey="&certmgr.delete2.accesskey;"
disabled="true" oncommand="deleteCerts();"/>
<button id="websites_exceptionButton"
label="&certmgr.addException.label;"
accesskey="&certmgr.addException.accesskey;"
oncommand="addException();"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,44 @@
<?xml version="1.0"?>
<!-- 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/. -->
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="certDumpOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox class="box-padded" id="certPrettyPrint" flex="1">
<label class="header" value="&certmgr.hierarchy.label;"
control="treesetDump" accesskey="&certmgr.hierarchy.accesskey2;"/>
<tree id="treesetDump" onselect="updateCertDump();" flex="1"
hidecolumnpicker="true" style="height: 8em;">
<treecols>
<treecol id="dumpCol" flex="1" primary="true" hideheader="true"/>
</treecols>
</tree>
<label class="header" value="&certmgr.details.label;"
control="prettyDumpTree" accesskey="&certmgr.details.accesskey;"/>
<tree id="prettyDumpTree" style="height: 15em" treelines="true" flex="1"
onselect="displaySelected();" hidecolumnpicker="true">
<treecols>
<treecol flex="1" id="certDataCol" primary="true" hideheader="true"/>
</treecols>
<treechildren/>
</tree>
<label class="header" value="&certmgr.fields.label;"
control="certDumpVal" accesskey="&certmgr.fields.accesskey;"/>
<textbox id="certDumpVal" multiline="true" flex="1"
readonly="true" style="height: 11em; font-family: -moz-fixed;"/>
<separator class="thin"/>
<hbox>
<button id="export_cert" class="normal" label="&certmgr.export.label;"
accesskey="&certmgr.export.accesskey;"
oncommand="exportToFile(window, getCurrentCert());"/>
</hbox>
</vbox>
</overlay>

View file

@ -0,0 +1,542 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const nsIFilePicker = Components.interfaces.nsIFilePicker;
const nsFilePicker = "@mozilla.org/filepicker;1";
const nsIX509CertDB = Components.interfaces.nsIX509CertDB;
const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
const nsIX509Cert = Components.interfaces.nsIX509Cert;
const nsICertTree = Components.interfaces.nsICertTree;
const nsCertTree = "@mozilla.org/security/nsCertTree;1";
const gCertFileTypes = "*.p7b; *.crt; *.cert; *.cer; *.pem; *.der";
var { NetUtil } = Components.utils.import("resource://gre/modules/NetUtil.jsm", {});
var { Services } = Components.utils.import("resource://gre/modules/Services.jsm", {});
var key;
/**
* List of certs currently selected in the active tab.
* @type nsIX509Cert[]
*/
var selected_certs = [];
var selected_tree_items = [];
var selected_index = [];
var certdb;
/**
* Cert tree for the "Authorities" tab.
* @type nsICertTree
*/
var caTreeView;
/**
* Cert tree for the "Servers" tab.
* @type nsICertTree
*/
var serverTreeView;
/**
* Cert tree for the "People" tab.
* @type nsICertTree
*/
var emailTreeView;
/**
* Cert tree for the "Your Certificates" tab.
* @type nsICertTree
*/
var userTreeView;
/**
* Cert tree for the "Other" tab.
* @type nsICertTree
*/
var orphanTreeView;
var smartCardObserver = {
observe: function() {
onSmartCardChange();
}
};
function DeregisterSmartCardObservers()
{
Services.obs.removeObserver(smartCardObserver, "smartcard-insert");
Services.obs.removeObserver(smartCardObserver, "smartcard-remove");
}
function LoadCerts()
{
Services.obs.addObserver(smartCardObserver, "smartcard-insert", false);
Services.obs.addObserver(smartCardObserver, "smartcard-remove", false);
certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
var certcache = certdb.getCerts();
caTreeView = Components.classes[nsCertTree]
.createInstance(nsICertTree);
caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
document.getElementById('ca-tree').view = caTreeView;
serverTreeView = Components.classes[nsCertTree]
.createInstance(nsICertTree);
serverTreeView.loadCertsFromCache(certcache, nsIX509Cert.SERVER_CERT);
document.getElementById('server-tree').view = serverTreeView;
emailTreeView = Components.classes[nsCertTree]
.createInstance(nsICertTree);
emailTreeView.loadCertsFromCache(certcache, nsIX509Cert.EMAIL_CERT);
document.getElementById('email-tree').view = emailTreeView;
userTreeView = Components.classes[nsCertTree]
.createInstance(nsICertTree);
userTreeView.loadCertsFromCache(certcache, nsIX509Cert.USER_CERT);
document.getElementById('user-tree').view = userTreeView;
orphanTreeView = Components.classes[nsCertTree]
.createInstance(nsICertTree);
orphanTreeView.loadCertsFromCache(certcache, nsIX509Cert.UNKNOWN_CERT);
document.getElementById('orphan-tree').view = orphanTreeView;
enableBackupAllButton();
}
function enableBackupAllButton()
{
let backupAllButton = document.getElementById("mine_backupAllButton");
backupAllButton.disabled = userTreeView.rowCount < 1;
}
function getSelectedCerts()
{
var ca_tab = document.getElementById("ca_tab");
var mine_tab = document.getElementById("mine_tab");
var others_tab = document.getElementById("others_tab");
var websites_tab = document.getElementById("websites_tab");
var orphan_tab = document.getElementById("orphan_tab");
var items = null;
if (ca_tab.selected) {
items = caTreeView.selection;
} else if (mine_tab.selected) {
items = userTreeView.selection;
} else if (others_tab.selected) {
items = emailTreeView.selection;
} else if (websites_tab.selected) {
items = serverTreeView.selection;
} else if (orphan_tab.selected) {
items = orphanTreeView.selection;
}
selected_certs = [];
var cert = null;
var nr = 0;
if (items != null) nr = items.getRangeCount();
if (nr > 0) {
for (let i = 0; i < nr; i++) {
var o1 = {};
var o2 = {};
items.getRangeAt(i, o1, o2);
var min = o1.value;
var max = o2.value;
for (let j = min; j <= max; j++) {
if (ca_tab.selected) {
cert = caTreeView.getCert(j);
} else if (mine_tab.selected) {
cert = userTreeView.getCert(j);
} else if (others_tab.selected) {
cert = emailTreeView.getCert(j);
} else if (websites_tab.selected) {
cert = serverTreeView.getCert(j);
} else if (orphan_tab.selected) {
cert = orphanTreeView.getCert(j);
}
if (cert) {
var sc = selected_certs.length;
selected_certs[sc] = cert;
selected_index[sc] = j;
}
}
}
}
}
function getSelectedTreeItems()
{
var ca_tab = document.getElementById("ca_tab");
var mine_tab = document.getElementById("mine_tab");
var others_tab = document.getElementById("others_tab");
var websites_tab = document.getElementById("websites_tab");
var orphan_tab = document.getElementById("orphan_tab");
var items = null;
if (ca_tab.selected) {
items = caTreeView.selection;
} else if (mine_tab.selected) {
items = userTreeView.selection;
} else if (others_tab.selected) {
items = emailTreeView.selection;
} else if (websites_tab.selected) {
items = serverTreeView.selection;
} else if (orphan_tab.selected) {
items = orphanTreeView.selection;
}
selected_certs = [];
selected_tree_items = [];
selected_index = [];
var tree_item = null;
var nr = 0;
if (items != null) nr = items.getRangeCount();
if (nr > 0) {
for (let i = 0; i < nr; i++) {
var o1 = {};
var o2 = {};
items.getRangeAt(i, o1, o2);
var min = o1.value;
var max = o2.value;
for (let j = min; j <= max; j++) {
if (ca_tab.selected) {
tree_item = caTreeView.getTreeItem(j);
} else if (mine_tab.selected) {
tree_item = userTreeView.getTreeItem(j);
} else if (others_tab.selected) {
tree_item = emailTreeView.getTreeItem(j);
} else if (websites_tab.selected) {
tree_item = serverTreeView.getTreeItem(j);
} else if (orphan_tab.selected) {
tree_item = orphanTreeView.getTreeItem(j);
}
if (tree_item) {
var sc = selected_tree_items.length;
selected_tree_items[sc] = tree_item;
selected_index[sc] = j;
}
}
}
}
}
/**
* Returns true if nothing in the given cert tree is selected or if the
* selection includes a container. Returns false otherwise.
*
* @param {nsICertTree} certTree
* @returns {Boolean}
*/
function nothingOrContainerSelected(certTree)
{
var certTreeSelection = certTree.selection;
var numSelectionRanges = certTreeSelection.getRangeCount();
if (numSelectionRanges == 0) {
return true;
}
for (var i = 0; i < numSelectionRanges; i++) {
var o1 = {};
var o2 = {};
certTreeSelection.getRangeAt(i, o1, o2);
var minIndex = o1.value;
var maxIndex = o2.value;
for (var j = minIndex; j <= maxIndex; j++) {
if (certTree.isContainer(j)) {
return true;
}
}
}
return false;
}
/**
* Enables or disables buttons corresponding to a cert tree depending on what
* is selected in the cert tree.
*
* @param {nsICertTree} certTree
* @param {Array} idList A list of string identifiers for button elements to
* enable or disable.
*/
function enableButtonsForCertTree(certTree, idList)
{
let disableButtons = nothingOrContainerSelected(certTree);
for (let id of idList) {
document.getElementById(id).setAttribute("disabled", disableButtons);
}
}
function ca_enableButtons()
{
let idList = [
"ca_viewButton",
"ca_editButton",
"ca_exportButton",
"ca_deleteButton",
];
enableButtonsForCertTree(caTreeView, idList);
}
function mine_enableButtons()
{
let idList = [
"mine_viewButton",
"mine_backupButton",
"mine_deleteButton",
];
enableButtonsForCertTree(userTreeView, idList);
}
function websites_enableButtons()
{
let idList = [
"websites_viewButton",
"websites_exportButton",
"websites_deleteButton",
];
enableButtonsForCertTree(serverTreeView, idList);
}
function email_enableButtons()
{
let idList = [
"email_viewButton",
"email_exportButton",
"email_deleteButton",
];
enableButtonsForCertTree(emailTreeView, idList);
}
function orphan_enableButtons()
{
let idList = [
"orphan_viewButton",
"orphan_exportButton",
"orphan_deleteButton",
];
enableButtonsForCertTree(orphanTreeView, idList);
}
function backupCerts()
{
getSelectedCerts();
var numcerts = selected_certs.length;
if (numcerts == 0) {
return;
}
var bundle = document.getElementById("pippki_bundle");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.getString("chooseP12BackupFileDialog"),
nsIFilePicker.modeSave);
fp.appendFilter(bundle.getString("file_browse_PKCS12_spec"),
"*.p12");
fp.appendFilters(nsIFilePicker.filterAll);
var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
certdb.exportPKCS12File(null, fp.file, selected_certs.length,
selected_certs);
}
}
function backupAllCerts()
{
// Select all rows, then call doBackup()
var items = userTreeView.selection.selectAll();
backupCerts();
}
function editCerts()
{
getSelectedCerts();
for (let cert of selected_certs) {
window.openDialog("chrome://pippki/content/editcacert.xul", "",
"chrome,centerscreen,modal", cert);
}
}
function restoreCerts()
{
var bundle = document.getElementById("pippki_bundle");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.getString("chooseP12RestoreFileDialog2"),
nsIFilePicker.modeOpen);
fp.appendFilter(bundle.getString("file_browse_PKCS12_spec"),
"*.p12; *.pfx");
fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
gCertFileTypes);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
// If this is an X509 user certificate, import it as one.
var isX509FileType = false;
var fileTypesList = gCertFileTypes.slice(1).split('; *');
for (var type of fileTypesList) {
if (fp.file.path.endsWith(type)) {
isX509FileType = true;
break;
}
}
if (isX509FileType) {
let fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
fstream.init(fp.file, -1, 0, 0);
let dataString = NetUtil.readInputStreamToString(fstream, fstream.available());
let dataArray = [];
for (let i = 0; i < dataString.length; i++) {
dataArray.push(dataString.charCodeAt(i));
}
fstream.close();
let prompter = Services.ww.getNewPrompter(window);
let interfaceRequestor = {
getInterface: function() {
return prompter;
}
};
certdb.importUserCertificate(dataArray, dataArray.length, interfaceRequestor);
} else {
// Otherwise, assume it's a PKCS12 file and import it that way.
certdb.importPKCS12File(null, fp.file);
}
var certcache = certdb.getCerts();
userTreeView.loadCertsFromCache(certcache, nsIX509Cert.USER_CERT);
userTreeView.selection.clearSelection();
caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
caTreeView.selection.clearSelection();
enableBackupAllButton();
}
}
function exportCerts()
{
getSelectedCerts();
for (let cert of selected_certs) {
exportToFile(window, cert);
}
}
/**
* Deletes the selected certs in the active tab.
*/
function deleteCerts() {
getSelectedTreeItems();
let numcerts = selected_tree_items.length;
if (numcerts == 0) {
return;
}
const treeViewMap = {
"mine_tab": userTreeView,
"websites_tab": serverTreeView,
"ca_tab": caTreeView,
"others_tab": emailTreeView,
"orphan_tab": orphanTreeView,
};
let selTab = document.getElementById("certMgrTabbox").selectedItem;
let selTabID = selTab.getAttribute("id");
if (!(selTabID in treeViewMap)) {
return;
}
let retVals = {
deleteConfirmed: false,
};
window.openDialog("chrome://pippki/content/deletecert.xul", "",
"chrome,centerscreen,modal", selTabID, selected_tree_items,
retVals);
if (retVals.deleteConfirmed) {
let treeView = treeViewMap[selTabID];
for (let t = numcerts - 1; t >= 0; t--) {
treeView.deleteEntryObject(selected_index[t]);
}
selected_tree_items = [];
selected_index = [];
treeView.selection.clearSelection();
if (selTabID == "mine_tab") {
enableBackupAllButton();
}
}
}
function viewCerts()
{
getSelectedCerts();
for (let cert of selected_certs) {
viewCertHelper(window, cert);
}
}
function addCACerts()
{
var bundle = document.getElementById("pippki_bundle");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.getString("importCACertsPrompt"),
nsIFilePicker.modeOpen);
fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
gCertFileTypes);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
certdb.importCertsFromFile(fp.file, nsIX509Cert.CA_CERT);
caTreeView.loadCerts(nsIX509Cert.CA_CERT);
caTreeView.selection.clearSelection();
}
}
function onSmartCardChange()
{
var certcache = certdb.getCerts();
// We've change the state of the smart cards inserted or removed
// that means the available certs may have changed. Update the display
userTreeView.loadCertsFromCache(certcache, nsIX509Cert.USER_CERT);
userTreeView.selection.clearSelection();
caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
caTreeView.selection.clearSelection();
serverTreeView.loadCertsFromCache(certcache, nsIX509Cert.SERVER_CERT);
serverTreeView.selection.clearSelection();
emailTreeView.loadCertsFromCache(certcache, nsIX509Cert.EMAIL_CERT);
emailTreeView.selection.clearSelection();
orphanTreeView.loadCertsFromCache(certcache, nsIX509Cert.UNKNOWN_CERT);
orphanTreeView.selection.clearSelection();
}
function addEmailCert()
{
var bundle = document.getElementById("pippki_bundle");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
bundle.getString("importEmailCertPrompt"),
nsIFilePicker.modeOpen);
fp.appendFilter(bundle.getString("file_browse_Certificate_spec"),
gCertFileTypes);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
certdb.importCertsFromFile(fp.file, nsIX509Cert.EMAIL_CERT);
var certcache = certdb.getCerts();
emailTreeView.loadCertsFromCache(certcache, nsIX509Cert.EMAIL_CERT);
emailTreeView.selection.clearSelection();
caTreeView.loadCertsFromCache(certcache, nsIX509Cert.CA_CERT);
caTreeView.selection.clearSelection();
}
}
function addException()
{
window.openDialog('chrome://pippki/content/exceptionDialog.xul', "",
'chrome,centerscreen,modal');
var certcache = certdb.getCerts();
serverTreeView.loadCertsFromCache(certcache, nsIX509Cert.SERVER_CERT);
serverTreeView.selection.clearSelection();
orphanTreeView.loadCertsFromCache(certcache, nsIX509Cert.UNKNOWN_CERT);
orphanTreeView.selection.clearSelection();
}

View file

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xul-overlay href="chrome://pippki/content/MineOverlay.xul"?>
<?xul-overlay href="chrome://pippki/content/OthersOverlay.xul"?>
<?xul-overlay href="chrome://pippki/content/WebSitesOverlay.xul"?>
<?xul-overlay href="chrome://pippki/content/CAOverlay.xul"?>
<?xul-overlay href="chrome://pippki/content/OrphanOverlay.xul"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
<dialog id="certmanager"
windowtype="mozilla:certmanager"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&certmgr.title;"
onload="LoadCerts();"
onunload="DeregisterSmartCardObservers();"
buttons="accept"
style="width: 63em; height: 32em;"
persist="screenX screenY width height">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript" src="chrome://pippki/content/certManager.js"/>
<vbox flex="1">
<tabbox id="certmanagertabs" flex="1" style="margin:5px" persist="selectedIndex">
<tabs id="certMgrTabbox">
<tab id="mine_tab" label="&certmgr.tab.mine;"/>
<tab id="others_tab" label="&certmgr.tab.others2;"/>
<tab id="websites_tab" label="&certmgr.tab.websites3;"/>
<tab id="ca_tab" label="&certmgr.tab.ca;" selected="true"/>
<tab id="orphan_tab" label="&certmgr.tab.orphan2;"/>
</tabs>
<tabpanels flex="1">
<vbox id="myCerts" flex="1"/>
<vbox id="othersCerts" flex="1"/>
<vbox id="webCerts" flex="1"/>
<vbox id="CACerts" flex="1"/>
<vbox id="OrphanCerts" flex="1"/>
</tabpanels>
</tabbox>
</vbox>
</dialog>

View file

@ -0,0 +1,354 @@
/* 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";
/**
* @file Implements functionality for certViewer.xul and its tabs certDump.xul
* and viewCertDetails.xul: a dialog that allows various attributes of a
* certificate to be viewed.
* @argument {nsISupports} window.arguments[0]
* The cert to view, queryable to nsIX509Cert.
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
const nsIX509Cert = Ci.nsIX509Cert;
const nsX509CertDB = "@mozilla.org/security/x509certdb;1";
const nsIX509CertDB = Ci.nsIX509CertDB;
const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
const nsIPK11TokenDB = Ci.nsIPK11TokenDB;
const nsIASN1Object = Ci.nsIASN1Object;
const nsIASN1Sequence = Ci.nsIASN1Sequence;
const nsIASN1PrintableItem = Ci.nsIASN1PrintableItem;
const nsIASN1Tree = Ci.nsIASN1Tree;
const nsASN1Tree = "@mozilla.org/security/nsASN1Tree;1";
var bundle;
function doPrompt(msg)
{
let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
prompts.alert(window, null, msg);
}
/**
* Fills out the "Certificate Hierarchy" tree of the cert viewer "Details" tab.
*
* @param {tree} node
* Parent tree node to append to.
* @param {nsIArray<nsIX509Cert>} chain
* Chain where cert element n is issued by cert element n + 1.
*/
function AddCertChain(node, chain)
{
var child = document.getElementById(node);
var currCert;
var displayVal;
for (let i = chain.length - 1; i >= 0; i--) {
currCert = chain.queryElementAt(i, nsIX509Cert);
if (currCert.commonName) {
displayVal = currCert.commonName;
} else {
displayVal = currCert.windowTitle;
}
let addTwistie = i != 0;
child = addChildrenToTree(child, displayVal, currCert.dbKey, addTwistie);
}
}
/**
* Adds a "verified usage" of a cert to the "General" tab of the cert viewer.
*
* @param {String} usage
* Verified usage to add.
*/
function AddUsage(usage)
{
let verifyInfoBox = document.getElementById("verify_info_box");
let text = document.createElement("textbox");
text.setAttribute("value", usage);
text.setAttribute("style", "margin: 2px 5px");
text.setAttribute("readonly", "true");
text.setAttribute("class", "scrollfield");
verifyInfoBox.appendChild(text);
}
function setWindowName()
{
bundle = document.getElementById("pippki_bundle");
let cert = window.arguments[0].QueryInterface(Ci.nsIX509Cert);
document.title = bundle.getFormattedString("certViewerTitle",
[cert.windowTitle]);
//
// Set the cert attributes for viewing
//
// The chain of trust
AddCertChain("treesetDump", cert.getChain());
DisplayGeneralDataFromCert(cert);
BuildPrettyPrint(cert);
asyncDetermineUsages(cert);
}
// Certificate usages we care about in the certificate viewer.
const certificateUsageSSLClient = 0x0001;
const certificateUsageSSLServer = 0x0002;
const certificateUsageSSLCA = 0x0008;
const certificateUsageEmailSigner = 0x0010;
const certificateUsageEmailRecipient = 0x0020;
const certificateUsageObjectSigner = 0x0040;
// A map from the name of a certificate usage to the value of the usage.
// Useful for printing debugging information and for enumerating all supported
// usages.
const certificateUsages = {
certificateUsageSSLClient,
certificateUsageSSLServer,
certificateUsageSSLCA,
certificateUsageEmailSigner,
certificateUsageEmailRecipient,
certificateUsageObjectSigner,
};
// Map of certificate usage name to localization identifier.
const certificateUsageToStringBundleName = {
certificateUsageSSLClient: "VerifySSLClient",
certificateUsageSSLServer: "VerifySSLServer",
certificateUsageSSLCA: "VerifySSLCA",
certificateUsageEmailSigner: "VerifyEmailSigner",
certificateUsageEmailRecipient: "VerifyEmailRecip",
certificateUsageObjectSigner: "VerifyObjSign",
};
const PRErrorCodeSuccess = 0;
const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
const SEC_ERROR_EXPIRED_CERTIFICATE = SEC_ERROR_BASE + 11;
const SEC_ERROR_REVOKED_CERTIFICATE = SEC_ERROR_BASE + 12;
const SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13;
const SEC_ERROR_UNTRUSTED_ISSUER = SEC_ERROR_BASE + 20;
const SEC_ERROR_UNTRUSTED_CERT = SEC_ERROR_BASE + 21;
const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = SEC_ERROR_BASE + 30;
const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = SEC_ERROR_BASE + 176;
/**
* Kicks off asynchronous verifications of the given certificate to determine
* what usages it is currently valid for. Updates the usage display area when
* complete.
*
* @param {nsIX509Cert} cert
* The certificate to determine valid usages for.
*/
function asyncDetermineUsages(cert) {
let promises = [];
let now = Date.now() / 1000;
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
Object.keys(certificateUsages).forEach(usageString => {
promises.push(new Promise((resolve, reject) => {
let usage = certificateUsages[usageString];
certdb.asyncVerifyCertAtTime(cert, usage, 0, null, now,
(aPRErrorCode, aVerifiedChain, aHasEVPolicy) => {
resolve({ usageString: usageString, errorCode: aPRErrorCode });
});
}));
});
Promise.all(promises).then(displayUsages);
}
/**
* Updates the usage display area given the results from asyncDetermineUsages.
*
* @param {Array} results
* An array of objects with the properties "usageString" and "errorCode".
* usageString is a string that is a key in the certificateUsages map.
* errorCode is either an NSPR error code or PRErrorCodeSuccess (which is
* a pseudo-NSPR error code with the value 0 that indicates success).
*/
function displayUsages(results) {
document.getElementById("verify_pending").setAttribute("hidden", "true");
let verified = document.getElementById("verified");
let someSuccess = results.some(result =>
result.errorCode == PRErrorCodeSuccess
);
if (someSuccess) {
let verifystr = bundle.getString("certVerified");
verified.textContent = verifystr;
let pipnssBundle = Services.strings.createBundle(
"chrome://pipnss/locale/pipnss.properties");
results.forEach(result => {
if (result.errorCode != PRErrorCodeSuccess) {
return;
}
let bundleName = certificateUsageToStringBundleName[result.usageString];
let usage = pipnssBundle.GetStringFromName(bundleName);
AddUsage(usage);
});
} else {
const errorRankings = [
{ error: SEC_ERROR_REVOKED_CERTIFICATE,
bundleString: "certNotVerified_CertRevoked" },
{ error: SEC_ERROR_UNTRUSTED_CERT,
bundleString: "certNotVerified_CertNotTrusted" },
{ error: SEC_ERROR_UNTRUSTED_ISSUER,
bundleString: "certNotVerified_IssuerNotTrusted" },
{ error: SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED,
bundleString: "certNotVerified_AlgorithmDisabled" },
{ error: SEC_ERROR_EXPIRED_CERTIFICATE,
bundleString: "certNotVerified_CertExpired" },
{ error: SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE,
bundleString: "certNotVerified_CAInvalid" },
{ error: SEC_ERROR_UNKNOWN_ISSUER,
bundleString: "certNotVerified_IssuerUnknown" },
];
let verifystr;
for (let errorRanking of errorRankings) {
let errorPresent = results.some(result =>
result.errorCode == errorRanking.error
);
if (errorPresent) {
verifystr = bundle.getString(errorRanking.bundleString);
break;
}
}
if (!verifystr) {
verifystr = bundle.getString("certNotVerified_Unknown");
}
verified.textContent = verifystr;
}
// Notify that we are done determining the certificate's valid usages (this
// should be treated as an implementation detail that enables tests to run
// efficiently - other code in the browser probably shouldn't rely on this).
Services.obs.notifyObservers(window, "ViewCertDetails:CertUsagesDone", null);
}
function addChildrenToTree(parentTree, label, value, addTwistie)
{
let treeChild1 = document.createElement("treechildren");
let treeElement = addTreeItemToTreeChild(treeChild1, label, value,
addTwistie);
parentTree.appendChild(treeChild1);
return treeElement;
}
function addTreeItemToTreeChild(treeChild, label, value, addTwistie)
{
let treeElem1 = document.createElement("treeitem");
if (addTwistie) {
treeElem1.setAttribute("container", "true");
treeElem1.setAttribute("open", "true");
}
let treeRow = document.createElement("treerow");
let treeCell = document.createElement("treecell");
treeCell.setAttribute("label", label);
if (value) {
treeCell.setAttribute("display", value);
}
treeRow.appendChild(treeCell);
treeElem1.appendChild(treeRow);
treeChild.appendChild(treeElem1);
return treeElem1;
}
function displaySelected() {
var asn1Tree = document.getElementById('prettyDumpTree')
.view.QueryInterface(nsIASN1Tree);
var items = asn1Tree.selection;
var certDumpVal = document.getElementById('certDumpVal');
if (items.currentIndex != -1) {
var value = asn1Tree.getDisplayData(items.currentIndex);
certDumpVal.value = value;
} else {
certDumpVal.value = "";
}
}
function BuildPrettyPrint(cert)
{
var certDumpTree = Components.classes[nsASN1Tree].
createInstance(nsIASN1Tree);
certDumpTree.loadASN1Structure(cert.ASN1Structure);
document.getElementById('prettyDumpTree').view = certDumpTree;
}
function addAttributeFromCert(nodeName, value)
{
var node = document.getElementById(nodeName);
if (!value) {
value = bundle.getString('notPresent');
}
node.setAttribute('value', value);
}
/**
* Displays information about a cert in the "General" tab of the cert viewer.
*
* @param {nsIX509Cert} cert
* Cert to display information about.
*/
function DisplayGeneralDataFromCert(cert)
{
addAttributeFromCert("commonname", cert.commonName);
addAttributeFromCert("organization", cert.organization);
addAttributeFromCert("orgunit", cert.organizationalUnit);
addAttributeFromCert("serialnumber", cert.serialNumber);
addAttributeFromCert("sha256fingerprint", cert.sha256Fingerprint);
addAttributeFromCert("sha1fingerprint", cert.sha1Fingerprint);
addAttributeFromCert("validitystart", cert.validity.notBeforeLocalDay);
addAttributeFromCert("validityend", cert.validity.notAfterLocalDay);
addAttributeFromCert("issuercommonname", cert.issuerCommonName);
addAttributeFromCert("issuerorganization", cert.issuerOrganization);
addAttributeFromCert("issuerorgunit", cert.issuerOrganizationUnit);
}
function updateCertDump()
{
var asn1Tree = document.getElementById('prettyDumpTree')
.view.QueryInterface(nsIASN1Tree);
var tree = document.getElementById('treesetDump');
if (tree.currentIndex < 0) {
doPrompt("No items are selected."); //This should never happen.
} else {
var item = tree.contentView.getItemAtIndex(tree.currentIndex);
var dbKey = item.firstChild.firstChild.getAttribute('display');
// Get the cert from the cert database
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
var cert = certdb.findCertByDBKey(dbKey);
asn1Tree.loadASN1Structure(cert.ASN1Structure);
}
displaySelected();
}
function getCurrentCert()
{
var realIndex;
var tree = document.getElementById('treesetDump');
if (tree.view.selection.isSelected(tree.currentIndex)
&& document.getElementById('prettyprint_tab').selected) {
/* if the user manually selected a cert on the Details tab,
then take that one */
realIndex = tree.currentIndex;
} else {
/* otherwise, take the one at the bottom of the chain
(i.e. the one of the end-entity, unless we're displaying
CA certs) */
realIndex = tree.view.rowCount - 1;
}
if (realIndex >= 0) {
var item = tree.contentView.getItemAtIndex(realIndex);
var dbKey = item.firstChild.firstChild.getAttribute('display');
var certdb = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
var cert = certdb.findCertByDBKey(dbKey);
return cert;
}
/* shouldn't really happen */
return null;
}

View file

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
<?xul-overlay href="chrome://pippki/content/viewCertDetails.xul"?>
<?xul-overlay href="chrome://pippki/content/certDump.xul"?>
<dialog id="certDetails"
title="&certmgr.certdetail.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept"
buttonlabelaccept="&certmgr.close.label;"
buttonaccesskeyaccept="&certmgr.close.accesskey;"
onload="setWindowName();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript"
src="chrome://pippki/content/certViewer.js"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<tabbox flex="1">
<tabs>
<tab id="general_tab" label="&certmgr.detail.general_tab.title;"
accesskey="&certmgr.detail.general_tab.accesskey;"/>
<tab id="prettyprint_tab" label="&certmgr.detail.prettyprint_tab.title;"
accesskey="&certmgr.detail.prettyprint_tab.accesskey;"/>
</tabs>
<tabpanels flex="1">
<vbox id="general_info"/>
<vbox id="certPrettyPrint"/>
</tabpanels>
</tabbox>
</dialog>

View file

@ -0,0 +1,270 @@
/* 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 nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1";
const nsIPKCS11ModuleDB = Components.interfaces.nsIPKCS11ModuleDB;
const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
const nsIPK11Token = Components.interfaces.nsIPK11Token;
var params;
var tokenName = "";
var pw1;
function doPrompt(msg)
{
let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
prompts.alert(window, null, msg);
}
function onLoad()
{
document.documentElement.getButton("accept").disabled = true;
pw1 = document.getElementById("pw1");
try {
params = window.arguments[0].QueryInterface(nsIDialogParamBlock);
tokenName = params.GetString(1);
} catch (e) {
// this should not happen.
// previously we had self.name, but self.name was a bad idea
// as window name must be a subset of ascii, and the code was
// previously trying to assign unicode to the window's name.
// I checked all the places where we get a password prompt and
// all of them pass an argument as part of this patch.
tokenName = "";
}
if (tokenName == "") {
let tokenDB = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
let tokenList = tokenDB.listTokens();
let i = 0;
let menu = document.getElementById("tokenMenu");
while (tokenList.hasMoreElements()) {
let token = tokenList.getNext().QueryInterface(nsIPK11Token);
if (token.needsLogin() || !(token.needsUserInit)) {
let menuItemNode = document.createElement("menuitem");
menuItemNode.setAttribute("value", token.tokenName);
menuItemNode.setAttribute("label", token.tokenName);
menu.firstChild.appendChild(menuItemNode);
if (i == 0) {
menu.selectedItem = menuItemNode;
tokenName = token.tokenName;
}
i++;
}
}
} else {
var sel = document.getElementById("tokenMenu");
sel.setAttribute("hidden", "true");
var tag = document.getElementById("tokenName");
tag.setAttribute("value", tokenName);
}
process();
}
function onMenuChange()
{
//get the selected token
var list = document.getElementById("tokenMenu");
tokenName = list.value;
process();
}
function process()
{
var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
var bundle = document.getElementById("pippki_bundle");
// If the token is unitialized, don't use the old password box.
// Otherwise, do.
var slot = secmoddb.findSlotByName(tokenName);
if (slot) {
var oldpwbox = document.getElementById("oldpw");
var msgBox = document.getElementById("message");
var status = slot.status;
if (status == nsIPKCS11Slot.SLOT_UNINITIALIZED
|| status == nsIPKCS11Slot.SLOT_READY) {
oldpwbox.setAttribute("hidden", "true");
msgBox.setAttribute("value", bundle.getString("password_not_set"));
msgBox.setAttribute("hidden", "false");
if (status == nsIPKCS11Slot.SLOT_READY) {
oldpwbox.setAttribute("inited", "empty");
} else {
oldpwbox.setAttribute("inited", "true");
}
// Select first password field
document.getElementById('pw1').focus();
} else {
// Select old password field
oldpwbox.setAttribute("hidden", "false");
msgBox.setAttribute("hidden", "true");
oldpwbox.setAttribute("inited", "false");
oldpwbox.focus();
}
}
if (params) {
// Return value 0 means "canceled"
params.SetInt(1, 0);
}
checkPasswords();
}
function setPassword()
{
var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
var token = pk11db.findTokenByName(tokenName);
var oldpwbox = document.getElementById("oldpw");
var initpw = oldpwbox.getAttribute("inited");
var bundle = document.getElementById("pippki_bundle");
var success = false;
if (initpw == "false" || initpw == "empty") {
try {
var oldpw = "";
var passok = 0;
if (initpw == "empty") {
passok = 1;
} else {
oldpw = oldpwbox.value;
passok = token.checkPassword(oldpw);
}
if (passok) {
if (initpw == "empty" && pw1.value == "") {
// checkPasswords() should have prevented this path from being reached.
} else {
if (pw1.value == "") {
var secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
if (secmoddb.isFIPSEnabled) {
// empty passwords are not allowed in FIPS mode
doPrompt(bundle.getString("pw_change2empty_in_fips_mode"));
passok = 0;
}
}
if (passok) {
token.changePassword(oldpw, pw1.value);
if (pw1.value == "") {
doPrompt(bundle.getString("pw_erased_ok")
+ " "
+ bundle.getString("pw_empty_warning"));
} else {
doPrompt(bundle.getString("pw_change_ok"));
}
success = true;
}
}
} else {
oldpwbox.focus();
oldpwbox.setAttribute("value", "");
doPrompt(bundle.getString("incorrect_pw"));
}
} catch (e) {
doPrompt(bundle.getString("failed_pw_change"));
}
} else {
token.initPassword(pw1.value);
if (pw1.value == "") {
doPrompt(bundle.getString("pw_not_wanted") + " " +
bundle.getString("pw_empty_warning"));
}
success = true;
}
if (success && params) {
// Return value 1 means "successfully executed ok"
params.SetInt(1, 1);
}
// Terminate dialog
return success;
}
function setPasswordStrength()
{
// We weigh the quality of the password by checking the number of:
// - Characters
// - Numbers
// - Non-alphanumeric chars
// - Upper and lower case characters
let pw = document.getElementById("pw1").value;
let pwlength = pw.length;
if (pwlength > 5) {
pwlength = 5;
}
let numnumeric = pw.replace(/[0-9]/g, "");
let numeric = pw.length - numnumeric.length;
if (numeric > 3) {
numeric = 3;
}
let symbols = pw.replace(/\W/g, "");
let numsymbols = pw.length - symbols.length;
if (numsymbols > 3) {
numsymbols = 3;
}
let numupper = pw.replace(/[A-Z]/g, "");
let upper = pw.length - numupper.length;
if (upper > 3) {
upper = 3;
}
let pwstrength = (pwlength * 10) - 20 + (numeric * 10) + (numsymbols * 15) +
(upper * 10);
// Clamp strength to [0, 100].
if (pwstrength < 0) {
pwstrength = 0;
}
if (pwstrength > 100) {
pwstrength = 100;
}
let meter = document.getElementById("pwmeter");
meter.setAttribute("value", pwstrength);
return;
}
function checkPasswords()
{
let pw1 = document.getElementById("pw1").value;
let pw2 = document.getElementById("pw2").value;
var oldpwbox = document.getElementById("oldpw");
if (oldpwbox) {
var initpw = oldpwbox.getAttribute("inited");
if (initpw == "empty" && pw1 == "") {
// The token has already been initialized, therefore this dialog
// was called with the intention to change the password.
// The token currently uses an empty password.
// We will not allow changing the password from empty to empty.
document.documentElement.getButton("accept").disabled = true;
return;
}
}
document.documentElement.getButton("accept").disabled = (pw1 != pw2);
}

View file

@ -0,0 +1,78 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/pippki.dtd">
<dialog id="set_password" title="&setPassword.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel"
ondialogaccept="return setPassword();"
onload="onLoad();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript"
src="chrome://pippki/content/changepassword.js"/>
<hbox align="center">
<label value="&setPassword.tokenName.label;: "/>
<label id="tokenName" />
<menulist id="tokenMenu" oncommand="onMenuChange()">
<menupopup/>
</menulist>
</hbox>
<!--
<menulist id="signerList" disabled="true">
<menupopup>
<menuitem id="token-menu" label="Built-in private key database"/>
<menuitem label="Bob Lord's iButton"/>
</menupopup>
</menulist>
-->
<separator/>
<groupbox>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<label value="&setPassword.oldPassword.label;"/>
<textbox id="oldpw" type="password"/>
<!-- This textbox is inserted as a workaround to the fact that making the 'type'
& 'disabled' property of the 'oldpw' textbox toggle between ['password' &
'false'] and ['text' & 'true'] - as would be necessary if the menu has more
than one tokens, some initialized and some not - does not work properly. So,
either the textbox 'oldpw' or the textbox 'message' would be displayed,
depending on the state of the token selected
-->
<textbox id="message" disabled="true" />
</row>
<row>
<label value="&setPassword.newPassword.label;"/>
<textbox id="pw1" type="password"
oninput="setPasswordStrength(); checkPasswords();"/>
</row>
<row>
<label value="&setPassword.reenterPassword.label;"/>
<textbox id="pw2" type="password" oninput="checkPasswords();"/>
</row>
</rows>
</grid>
</groupbox>
<groupbox>
<caption label="&setPassword.meter.label;"/>
<progressmeter id="pwmeter" mode="determined"
value="0"/>
</groupbox>
</dialog>

View file

@ -0,0 +1,44 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
*
* 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/. */
/* import-globals-from pippki.js */
"use strict";
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var dialogParams;
function onLoad()
{
dialogParams = window.arguments[0].QueryInterface(nsIDialogParamBlock);
let selectElement = document.getElementById("tokens");
let count = dialogParams.GetInt(0);
for (let i = 0; i < count; i++) {
let menuItemNode = document.createElement("menuitem");
let token = dialogParams.GetString(i);
menuItemNode.setAttribute("value", token);
menuItemNode.setAttribute("label", token);
selectElement.firstChild.appendChild(menuItemNode);
if (i == 0) {
selectElement.selectedItem = menuItemNode;
}
}
}
function doOK()
{
let tokenList = document.getElementById("tokens");
// Signal that the user accepted.
dialogParams.SetInt(0, 1);
// Signal the name of the token the user chose.
dialogParams.SetString(0, tokenList.value);
return true;
}
function doCancel()
{
dialogParams.SetInt(0, 0); // Signal that the user cancelled.
return true;
}

View file

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog [
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<dialog id="ssl_warning" title="&chooseToken.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 40em;"
buttons="accept,cancel"
ondialogaccept="return doOK();"
ondialogcancel="return doCancel();"
onload="onLoad();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript" src="chrome://pippki/content/choosetoken.js"/>
<groupbox>
<description>&chooseToken.message1;</description>
<menulist id="tokens">
<menupopup/>
</menulist>
</groupbox>
</dialog>

View file

@ -0,0 +1,158 @@
/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
*
* 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/. */
/* import-globals-from pippki.js */
"use strict";
/**
* @file Implements the functionality of clientauthask.xul: a dialog that allows
* a user pick a client certificate for TLS client authentication.
* @argument {String} window.arguments[0]
* The hostname of the server requesting client authentication.
* @argument {String} window.arguments[1]
* The Organization of the server cert.
* @argument {String} window.arguments[2]
* The Organization of the issuer of the server cert.
* @argument {Number} window.arguments[3]
* The port of the server.
* @argument {nsISupports} window.arguments[4]
* List of certificates the user can choose from, queryable to
* nsIArray<nsIX509Cert>.
* @argument {nsISupports} window.arguments[5]
* Object to set the return values of calling the dialog on, queryable
* to the underlying type of ClientAuthAskReturnValues.
*/
/**
* @typedef ClientAuthAskReturnValues
* @type nsIWritablePropertyBag2
* @property {Boolean} certChosen
* Set to true if the user chose a cert and accepted the dialog, false
* otherwise.
* @property {Boolean} rememberSelection
* Set to true if the user wanted their cert selection to be
* remembered, false otherwise.
* @property {Number} selectedIndex
* The index the chosen cert is at for the given cert list. Undefined
* value if |certChosen| is not true.
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
/**
* The pippki <stringbundle> element.
* @type <stringbundle>
*/
var bundle;
/**
* The array of certs the user can choose from.
* @type nsIArray<nsIX509Cert>
*/
var certArray;
/**
* The checkbox storing whether the user wants to remember the selected cert.
* @type nsIDOMXULCheckboxElement
*/
var rememberBox;
function onLoad() {
bundle = document.getElementById("pippki_bundle");
let rememberSetting =
Services.prefs.getBoolPref("security.remember_cert_checkbox_default_setting");
rememberBox = document.getElementById("rememberBox");
rememberBox.label = bundle.getString("clientAuthRemember");
rememberBox.checked = rememberSetting;
let hostname = window.arguments[0];
let org = window.arguments[1];
let issuerOrg = window.arguments[2];
let port = window.arguments[3];
let formattedOrg = bundle.getFormattedString("clientAuthMessage1", [org]);
let formattedIssuerOrg = bundle.getFormattedString("clientAuthMessage2",
[issuerOrg]);
let formattedHostnameAndPort =
bundle.getFormattedString("clientAuthHostnameAndPort",
[hostname, port.toString()]);
setText("hostname", formattedHostnameAndPort);
setText("organization", formattedOrg);
setText("issuer", formattedIssuerOrg);
let selectElement = document.getElementById("nicknames");
certArray = window.arguments[4].QueryInterface(Ci.nsIArray);
for (let i = 0; i < certArray.length; i++) {
let menuItemNode = document.createElement("menuitem");
let cert = certArray.queryElementAt(i, Ci.nsIX509Cert);
let nickAndSerial =
bundle.getFormattedString("clientAuthNickAndSerial",
[cert.nickname, cert.serialNumber]);
menuItemNode.setAttribute("value", i);
menuItemNode.setAttribute("label", nickAndSerial); // This is displayed.
selectElement.firstChild.appendChild(menuItemNode);
if (i == 0) {
selectElement.selectedItem = menuItemNode;
}
}
setDetails();
Services.obs.notifyObservers(document.getElementById("certAuthAsk"),
"cert-dialog-loaded", null);
}
/**
* Populates the details section with information concerning the selected cert.
*/
function setDetails() {
let index = parseInt(document.getElementById("nicknames").value);
let cert = certArray.queryElementAt(index, Ci.nsIX509Cert);
let detailLines = [
bundle.getFormattedString("clientAuthIssuedTo", [cert.subjectName]),
bundle.getFormattedString("clientAuthSerial", [cert.serialNumber]),
bundle.getFormattedString("clientAuthValidityPeriod",
[cert.validity.notBeforeLocalTime,
cert.validity.notAfterLocalTime]),
];
let keyUsages = cert.keyUsages;
if (keyUsages) {
detailLines.push(bundle.getFormattedString("clientAuthKeyUsages",
[keyUsages]));
}
let emailAddresses = cert.getEmailAddresses({});
if (emailAddresses.length > 0) {
let joinedAddresses = emailAddresses.join(", ");
detailLines.push(bundle.getFormattedString("clientAuthEmailAddresses",
[joinedAddresses]));
}
detailLines.push(bundle.getFormattedString("clientAuthIssuedBy",
[cert.issuerName]));
detailLines.push(bundle.getFormattedString("clientAuthStoredOn",
[cert.tokenName]));
document.getElementById("details").value = detailLines.join("\n");
}
function onCertSelected() {
setDetails();
}
function doOK() {
let retVals = window.arguments[5].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("certChosen", true);
let index = parseInt(document.getElementById("nicknames").value);
retVals.setPropertyAsUint32("selectedIndex", index);
retVals.setPropertyAsBool("rememberSelection", rememberBox.checked);
return true;
}
function doCancel() {
let retVals = window.arguments[5].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("certChosen", false);
retVals.setPropertyAsBool("rememberSelection", rememberBox.checked);
return true;
}

View file

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog [
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<dialog id="certAuthAsk" title="&clientAuthAsk.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel"
ondialogaccept="return doOK();"
ondialogcancel="return doCancel();"
onload="onLoad();">
<stringbundleset id="stringbundleset">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
</stringbundleset>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript" src="chrome://pippki/content/clientauthask.js"/>
<groupbox>
<description style="font-weight: bold;">&clientAuthAsk.message1;</description>
<description id="hostname"/>
<description id="organization"/>
<description id="issuer"/>
</groupbox>
<groupbox>
<description style="font-weight: bold;">&clientAuthAsk.message2;</description>
<broadcaster id="certSelected" oncommand="onCertSelected();"/>
<!-- The items in this menulist must never be sorted,
but remain in the order filled by the application
-->
<menulist id="nicknames" observes="certSelected">
<menupopup/>
</menulist>
<description>&clientAuthAsk.message3;</description>
<textbox readonly="true" id="details" multiline="true"
style="height: 11em;"/>
<checkbox id="rememberBox" checked="true"/>
</groupbox>
</dialog>

View file

@ -0,0 +1,39 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
*
* 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/. */
/* import-globals-from pippki.js */
"use strict";
var keygenThread;
function onLoad()
{
keygenThread = window.arguments[0].QueryInterface(Components.interfaces.nsIKeygenThread);
if (!keygenThread) {
window.close();
return;
}
window.setCursor("wait");
var obs = {
observe: function keygenListenerObserve(subject, topic, data) {
if (topic == "keygen-finished") {
window.close();
}
}
};
keygenThread.startKeyGeneration(obs);
}
function onClose()
{
window.setCursor("auto");
var alreadyClosed = {};
keygenThread.userCanceled(alreadyClosed);
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://pippki/locale/pippki.dtd">
<window
id="domainMismatch" title="&createCertInfo.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
onclose="onClose();"
>
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="pippki.js" />
<script type="application/javascript" src="createCertInfo.js" />
<vbox style="margin: 5px; max-width: 50em;">
<description>&createCertInfo.msg1;</description>
<separator/>
<description style="font-weight: bold; text-align: center;">&createCertInfo.msg2;</description>
<separator/>
</vbox>
</window>

View file

@ -0,0 +1,134 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
/**
* @file Implements the functionality of deletecert.xul: a dialog that allows a
* user to confirm whether to delete certain certificates.
* @argument {String} window.arguments[0]
* One of the tab IDs listed in certManager.xul.
* @argument {nsICertTreeItem[]} window.arguments[1]
* An array of cert tree items representing the certs to delete.
* @argument {DeleteCertReturnValues} window.arguments[2]
* Object holding the return values of calling the dialog.
*/
/**
* @typedef DeleteCertReturnValues
* @type Object
* @property {Boolean} deleteConfirmed
* Set to true if the user confirmed deletion of the given certs,
* false otherwise.
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
/**
* Returns the most appropriate string to represent the given nsICertTreeItem.
* @param {nsICertTreeItem} certTreeItem
* The item to represent.
* @returns {String}
* A representative string.
*/
function certTreeItemToString(certTreeItem) {
let cert = certTreeItem.cert;
if (!cert) {
return certTreeItem.hostPort;
}
const attributes = [
cert.commonName,
cert.organizationalUnit,
cert.organization,
cert.subjectName,
];
for (let attribute of attributes) {
if (attribute) {
return attribute;
}
}
let bundle = document.getElementById("pippki_bundle");
return bundle.getFormattedString("certWithSerial", [cert.serialNumber]);
}
/**
* onload() handler.
*/
function onLoad() {
let typeFlag = window.arguments[0];
let bundle = document.getElementById("pippki_bundle");
let title;
let confirm;
let impact;
switch (typeFlag) {
case "mine_tab":
title = bundle.getString("deleteUserCertTitle");
confirm = bundle.getString("deleteUserCertConfirm");
impact = bundle.getString("deleteUserCertImpact");
break;
case "websites_tab":
title = bundle.getString("deleteSslCertTitle3");
confirm = bundle.getString("deleteSslCertConfirm3");
impact = bundle.getString("deleteSslCertImpact3");
break;
case "ca_tab":
title = bundle.getString("deleteCaCertTitle2");
confirm = bundle.getString("deleteCaCertConfirm2");
impact = bundle.getString("deleteCaCertImpactX2");
break;
case "others_tab":
title = bundle.getString("deleteEmailCertTitle");
confirm = bundle.getString("deleteEmailCertConfirm");
impact = bundle.getString("deleteEmailCertImpactDesc");
break;
case "orphan_tab":
title = bundle.getString("deleteOrphanCertTitle");
confirm = bundle.getString("deleteOrphanCertConfirm");
impact = "";
break;
default:
return;
}
document.title = title;
setText("confirm", confirm);
let box = document.getElementById("certlist");
let certTreeItems = window.arguments[1];
for (let certTreeItem of certTreeItems) {
let listItem = document.createElement("richlistitem");
let label = document.createElement("label");
label.setAttribute("value", certTreeItemToString(certTreeItem));
listItem.appendChild(label);
box.appendChild(listItem);
}
setText("impact", impact);
}
/**
* ondialogaccept() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogAccept() {
let retVals = window.arguments[2];
retVals.deleteConfirmed = true;
return true;
}
/**
* ondialogcancel() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogCancel() {
let retVals = window.arguments[2];
retVals.deleteConfirmed = false;
return true;
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
<dialog id="deleteCertificate"
title="&certmgr.deletecert.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
buttons="accept,cancel"
ondialogaccept="return onDialogAccept();"
ondialogcancel="return onDialogCancel();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/deletecert.js"/>
<script type="application/javascript" src="pippki.js" />
<description id="confirm" style="width: 400px;"/>
<richlistbox id="certlist" class="box-padded" flex="1"
style="min-height: 8em; height: 8em; min-width: 35em;"/>
<description id="impact" style="width: 400px;"/>
</dialog>

View file

@ -0,0 +1,509 @@
/* 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 nsIFilePicker = Components.interfaces.nsIFilePicker;
const nsFilePicker = "@mozilla.org/filepicker;1";
const nsIPKCS11Slot = Components.interfaces.nsIPKCS11Slot;
const nsIPKCS11Module = Components.interfaces.nsIPKCS11Module;
const nsPKCS11ModuleDB = "@mozilla.org/security/pkcs11moduledb;1";
const nsIPKCS11ModuleDB = Components.interfaces.nsIPKCS11ModuleDB;
const nsIPK11Token = Components.interfaces.nsIPK11Token;
const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
const nsDialogParamBlock = "@mozilla.org/embedcomp/dialogparam;1";
const nsIPKCS11 = Components.interfaces.nsIPKCS11;
const nsPKCS11ContractID = "@mozilla.org/security/pkcs11;1";
var { Services } = Components.utils.import("resource://gre/modules/Services.jsm", {});
var bundle;
var secmoddb;
var skip_enable_buttons = false;
var smartCardObserver = {
observe: function() {
onSmartCardChange();
}
};
function DeregisterSmartCardObservers()
{
Services.obs.removeObserver(smartCardObserver, "smartcard-insert");
Services.obs.removeObserver(smartCardObserver, "smartcard-remove");
}
/* Do the initial load of all PKCS# modules and list them. */
function LoadModules()
{
bundle = document.getElementById("pippki_bundle");
secmoddb = Components.classes[nsPKCS11ModuleDB].getService(nsIPKCS11ModuleDB);
Services.obs.addObserver(smartCardObserver, "smartcard-insert", false);
Services.obs.addObserver(smartCardObserver, "smartcard-remove", false);
RefreshDeviceList();
}
function getPKCS11()
{
return Components.classes[nsPKCS11ContractID].getService(nsIPKCS11);
}
function getNSSString(name)
{
return document.getElementById("pipnss_bundle").getString(name);
}
function doPrompt(msg)
{
let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
prompts.alert(window, null, msg);
}
function doConfirm(msg)
{
let prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
return prompts.confirm(window, null, msg);
}
function RefreshDeviceList()
{
let modules = secmoddb.listModules();
while (modules.hasMoreElements()) {
let module = modules.getNext().QueryInterface(nsIPKCS11Module);
let slotnames = [];
let slots = module.listSlots();
while (slots.hasMoreElements()) {
let slot = slots.getNext().QueryInterface(nsIPKCS11Slot);
// Token names are preferred because NSS prefers lookup by token name.
slotnames.push(slot.tokenName ? slot.tokenName : slot.name);
}
AddModule(module.name, slotnames);
}
// Set the text on the FIPS button.
SetFIPSButton();
}
function SetFIPSButton()
{
var fipsButton = document.getElementById("fipsbutton");
var label;
if (secmoddb.isFIPSEnabled) {
label = bundle.getString("disable_fips");
} else {
label = bundle.getString("enable_fips");
}
fipsButton.setAttribute("label", label);
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.createElement("treeitem");
var row = document.createElement("treerow");
var cell = document.createElement("treecell");
cell.setAttribute("label", module);
row.appendChild(cell);
item.appendChild(row);
var parent = document.createElement("treechildren");
for (let slot of slots) {
var child_item = document.createElement("treeitem");
var child_row = document.createElement("treerow");
var child_cell = document.createElement("treecell");
child_cell.setAttribute("label", slot);
child_row.appendChild(child_cell);
child_item.appendChild(child_row);
child_item.setAttribute("pk11kind", "slot");
parent.appendChild(child_item);
}
item.appendChild(parent);
item.setAttribute("pk11kind", "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()
{
var tree = document.getElementById('device_tree');
if (tree.currentIndex < 0) return;
var item = tree.contentView.getItemAtIndex(tree.currentIndex);
selected_slot = null;
selected_module = null;
if (item) {
var kind = item.getAttribute("pk11kind");
var module_name;
if (kind == "slot") {
// get the module cell for this slot cell
var cell = item.parentNode.parentNode.firstChild.firstChild;
module_name = cell.getAttribute("label");
var module = secmoddb.findModuleByName(module_name);
// get the cell for the selected row (the slot to display)
cell = item.firstChild.firstChild;
var slot_name = cell.getAttribute("label");
selected_slot = module.findSlotByName(slot_name);
} else { // (kind == "module")
// get the cell for the selected row (the module to display)
cell = item.firstChild.firstChild;
module_name = cell.getAttribute("label");
selected_module = secmoddb.findModuleByName(module_name);
}
}
}
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";
}
}
}
}
showSlotInfo();
}
var thebutton = document.getElementById('login_button');
thebutton.setAttribute("disabled", login_toggle);
thebutton = document.getElementById('logout_button');
thebutton.setAttribute("disabled", logout_toggle);
thebutton = document.getElementById('change_pw_button');
thebutton.setAttribute("disabled", pw_toggle);
thebutton = document.getElementById('unload_button');
thebutton.setAttribute("disabled", unload_toggle);
// not implemented
//thebutton = document.getElementById('change_slotname_button');
//thebutton.setAttribute("disabled", toggle);
}
// clear the display of information for the slot
function ClearInfoList()
{
let infoList = document.getElementById("info_list");
while (infoList.hasChildNodes()) {
infoList.removeChild(infoList.firstChild);
}
}
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.removeChild(deviceList.firstChild);
}
}
// show a list of info about a slot
function showSlotInfo()
{
var present = true;
ClearInfoList();
switch (selected_slot.status) {
case nsIPKCS11Slot.SLOT_DISABLED:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_disabled"),
"tok_status");
present = false;
break;
case nsIPKCS11Slot.SLOT_NOT_PRESENT:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_notpresent"),
"tok_status");
present = false;
break;
case nsIPKCS11Slot.SLOT_UNINITIALIZED:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_uninitialized"),
"tok_status");
break;
case nsIPKCS11Slot.SLOT_NOT_LOGGED_IN:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_notloggedin"),
"tok_status");
break;
case nsIPKCS11Slot.SLOT_LOGGED_IN:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_loggedin"),
"tok_status");
break;
case nsIPKCS11Slot.SLOT_READY:
AddInfoRow(bundle.getString("devinfo_status"),
bundle.getString("devinfo_stat_ready"),
"tok_status");
break;
}
AddInfoRow(bundle.getString("devinfo_desc"),
selected_slot.desc, "slot_desc");
AddInfoRow(bundle.getString("devinfo_manID"),
selected_slot.manID, "slot_manID");
AddInfoRow(bundle.getString("devinfo_hwversion"),
selected_slot.HWVersion, "slot_hwv");
AddInfoRow(bundle.getString("devinfo_fwversion"),
selected_slot.FWVersion, "slot_fwv");
if (present) {
showTokenInfo();
}
}
function showModuleInfo()
{
ClearInfoList();
AddInfoRow(bundle.getString("devinfo_modname"),
selected_module.name, "module_name");
AddInfoRow(bundle.getString("devinfo_modpath"),
selected_module.libName, "module_path");
}
// add a row to the info list, as [col1 col2] (ex.: ["status" "logged in"])
function AddInfoRow(col1, col2, cell_id)
{
var tree = document.getElementById("info_list");
var item = document.createElement("treeitem");
var row = document.createElement("treerow");
var cell1 = document.createElement("treecell");
cell1.setAttribute("label", col1);
cell1.setAttribute("crop", "never");
row.appendChild(cell1);
var cell2 = document.createElement("treecell");
cell2.setAttribute("label", col2);
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()) {
tok_status.setAttribute("label",
bundle.getString("devinfo_stat_loggedin"));
} else {
tok_status.setAttribute("label",
bundle.getString("devinfo_stat_notloggedin"));
}
} catch (e) {
doPrompt(bundle.getString("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()) {
tok_status.setAttribute("label",
bundle.getString("devinfo_stat_loggedin"));
} else {
tok_status.setAttribute("label",
bundle.getString("devinfo_stat_notloggedin"));
}
} catch (e) {
}
enableButtons();
}
// load a new device
function doLoad()
{
window.open("load_device.xul", "loaddevice", "chrome,centerscreen,modal");
ClearDeviceList();
RefreshDeviceList();
}
function deleteSelected()
{
getSelectedItem();
if (selected_module &&
doConfirm(getNSSString("DelModuleWarning"))) {
try {
getPKCS11().deleteModule(selected_module.name);
}
catch (e) {
doPrompt(getNSSString("DelModuleError"));
return false;
}
selected_module = null;
return true;
}
return false;
}
function doUnload()
{
if (deleteSelected()) {
ClearDeviceList();
RefreshDeviceList();
}
}
// handle card insertion and removal
function onSmartCardChange()
{
var tree = document.getElementById('device_tree');
var index = tree.currentIndex;
tree.currentIndex = 0;
ClearDeviceList();
RefreshDeviceList();
tree.currentIndex = index;
enableButtons();
}
function changePassword()
{
getSelectedItem();
let params = Components.classes[nsDialogParamBlock]
.createInstance(nsIDialogParamBlock);
params.SetString(1, selected_slot.tokenName);
window.openDialog("changepassword.xul", "", "chrome,centerscreen,modal",
params);
showSlotInfo();
enableButtons();
}
// browse fs for PKCS#11 device
function doBrowseFiles()
{
var srbundle = document.getElementById("pippki_bundle");
var fp = Components.classes[nsFilePicker].createInstance(nsIFilePicker);
fp.init(window,
srbundle.getString("loadPK11TokenDialog"),
nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() == nsIFilePicker.returnOK) {
var pathbox = document.getElementById("device_path");
pathbox.setAttribute("value", fp.file.path);
}
}
function doLoadDevice()
{
var name_box = document.getElementById("device_name");
var path_box = document.getElementById("device_path");
try {
getPKCS11().addModule(name_box.value, path_box.value, 0, 0);
} catch (e) {
if (e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
doPrompt(getNSSString("AddModuleDup"));
} else {
doPrompt(getNSSString("AddModuleFailure"));
}
return false;
}
return true;
}
// ------------------------------------- Old code
function showTokenInfo()
{
//ClearInfoList();
var selected_token = selected_slot.getToken();
AddInfoRow(bundle.getString("devinfo_label"),
selected_token.tokenLabel, "tok_label");
AddInfoRow(bundle.getString("devinfo_manID"),
selected_token.tokenManID, "tok_manID");
AddInfoRow(bundle.getString("devinfo_serialnum"),
selected_token.tokenSerialNumber, "tok_sNum");
AddInfoRow(bundle.getString("devinfo_hwversion"),
selected_token.tokenHWVersion, "tok_hwv");
AddInfoRow(bundle.getString("devinfo_fwversion"),
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 = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
var internal_token = tokendb.getInternalKeyToken(); // nsIPK11Token
var slot = secmoddb.findSlotByName(internal_token.tokenName);
switch (slot.status) {
case nsIPKCS11Slot.SLOT_UNINITIALIZED:
case nsIPKCS11Slot.SLOT_READY:
// Token has either no or an empty password.
doPrompt(bundle.getString("fips_nonempty_password_required"));
return;
}
}
try {
secmoddb.toggleFIPSMode();
}
catch (e) {
doPrompt(bundle.getString("unable_to_toggle_fips"));
return;
}
// Remove the existing listed modules so that a refresh doesn't display the
// module that just changed.
ClearDeviceList();
RefreshDeviceList();
}

View file

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog [
<!ENTITY % deviceManangerDTD SYSTEM "chrome://pippki/locale/deviceManager.dtd">
%deviceManangerDTD;
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<dialog id="devicemanager"
windowtype="mozilla:devicemanager"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&devmgr.title;"
style="&devmgr.style2;"
persist="screenX screenY width height"
onload="LoadModules();"
onunload="DeregisterSmartCardObservers();"
buttons="accept">
<stringbundleset id="stringbundleset">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<stringbundle id="pipnss_bundle" src="chrome://pipnss/locale/pipnss.properties"/>
</stringbundleset>
<script type="application/javascript" src="chrome://pippki/content/device_manager.js"/>
<grid flex="1" style="margin:5px">
<columns>
<column flex="1"/>
<column flex="3"/>
<column/>
</columns>
<rows>
<row flex="1">
<vbox> <!-- List of devices -->
<tree id="device_tree" seltype="single"
onselect="enableButtons();" hidecolumnpicker="true"
flex="1" style="min-width: 15em">
<treecols>
<treecol id="deviceCol" flex="1" primary="true" label="&devmgr.devlist.label;"/>
</treecols>
<treechildren id="device_list"/>
</tree>
</vbox> <!-- / List of devices -->
<vbox> <!-- Device status -->
<tree id="info_tree" seltype="single" hidecolumnpicker="true"
flex="1" style="min-width: 10em">
<treecols>
<treecol id="title1Col" flex="5" primary="true" label="&devmgr.details.title;"/>
<treecol id="title2Col" flex="7" label="&devmgr.details.title2;"/>
</treecols>
<treechildren id="info_list"/>
</tree>
</vbox> <!-- / Device status -->
<vbox> <!-- Buttons for manipulating devices -->
<button id="login_button"
label="&devmgr.button.login.label;"
accesskey="&devmgr.button.login.accesskey;"
oncommand="doLogin();" disabled="true"/>
<button id="logout_button"
label="&devmgr.button.logout.label;"
accesskey="&devmgr.button.logout.accesskey;"
oncommand="doLogout();" disabled="true"/>
<button id="change_pw_button"
label="&devmgr.button.changepw.label;"
accesskey="&devmgr.button.changepw.accesskey;"
oncommand="changePassword();" disabled="true"/>
<button id="load_button"
label="&devmgr.button.load.label;"
accesskey="&devmgr.button.load.accesskey;"
oncommand="doLoad();"/>
<button id="unload_button"
label="&devmgr.button.unload.label;"
accesskey="&devmgr.button.unload.accesskey;"
oncommand="doUnload();" disabled="true"/>
<button id="fipsbutton"
label=""
accesskey="&devmgr.button.fips.accesskey;"
oncommand="toggleFIPS();"/>
</vbox> <!-- / Buttons for manipulating devices -->
</row>
</rows>
</grid>
</dialog>

View file

@ -0,0 +1,92 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
/**
* @file Implements the functionality of downloadcert.xul: a dialog that allows
* a user to confirm whether to import a certificate, and if so what trust
* to give it.
* @argument {nsISupports} window.arguments[0]
* Certificate to confirm import of, queryable to nsIX509Cert.
* @argument {nsISupports} window.arguments[1]
* Object to set the return values of calling the dialog on, queryable
* to the underlying type of DownloadCertReturnValues.
*/
/**
* @typedef DownloadCertReturnValues
* @type nsIWritablePropertyBag2
* @property {Boolean} importConfirmed
* Set to true if the user confirmed import of the cert and accepted
* the dialog, false otherwise.
* @property {Boolean} trustForSSL
* Set to true if the cert should be trusted for SSL, false otherwise.
* Undefined value if |importConfirmed| is not true.
* @property {Boolean} trustForEmail
* Set to true if the cert should be trusted for e-mail, false
* otherwise. Undefined value if |importConfirmed| is not true.
* @property {Boolean} trustForObjSign
* Set to true if the cert should be trusted for object signing, false
* otherwise. Undefined value if |importConfirmed| is not true.
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
/**
* The cert to potentially import.
* @type nsIX509Cert
*/
var gCert;
/**
* onload() handler.
*/
function onLoad() {
gCert = window.arguments[0].QueryInterface(Ci.nsIX509Cert);
let bundle = document.getElementById("pippki_bundle");
let caName = gCert.commonName;
if (caName.length == 0) {
caName = bundle.getString("unnamedCA");
}
setText("trustHeader", bundle.getFormattedString("newCAMessage1", [caName]));
}
/**
* Handler for the "View Cert" button.
*/
function viewCert() {
viewCertHelper(window, gCert);
}
/**
* ondialogaccept() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogAccept() {
let checkSSL = document.getElementById("trustSSL");
let checkEmail = document.getElementById("trustEmail");
let checkObjSign = document.getElementById("trustObjSign");
let retVals = window.arguments[1].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("importConfirmed", true);
retVals.setPropertyAsBool("trustForSSL", checkSSL.checked);
retVals.setPropertyAsBool("trustForEmail", checkEmail.checked);
retVals.setPropertyAsBool("trustForObjSign", checkObjSign.checked);
return true;
}
/**
* ondialogcancel() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogCancel() {
let retVals = window.arguments[1].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("importConfirmed", false);
return true;
}

View file

@ -0,0 +1,69 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/pippki.dtd">
<dialog id="download_cert"
title="&downloadCert.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 46em;"
buttons="accept,cancel"
ondialogaccept="return onDialogAccept();"
ondialogcancel="return onDialogCancel();"
onload="onLoad();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/downloadcert.js"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<!-- Let 'em know what they're doing -->
<vbox>
<description>&downloadCert.message1;</description>
</vbox>
<separator/>
<!-- checkboxes for trust bits
- "do you want to?"
- * trust for SSL
- * trust for email
- * trust for object signing
-->
<vbox>
<description id="trustHeader"/>
<checkbox label="&downloadCert.trustSSL;"
id="trustSSL"/>
<checkbox label="&downloadCert.trustEmail;"
id="trustEmail"/>
<checkbox label="&downloadCert.trustObjSign;"
id="trustObjSign"/>
</vbox>
<separator/>
<vbox>
<description>&downloadCert.message3;</description>
<separator/>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<button id="viewC-button"
label="&downloadCert.viewCert.label;"
oncommand="viewCert();"/>
<description style="margin: 4px;">&downloadCert.viewCert.text;</description>
</row>
</rows>
</grid>
</vbox>
</dialog>

View file

@ -0,0 +1,58 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
var gCertDB = Cc["@mozilla.org/security/x509certdb;1"]
.getService(Ci.nsIX509CertDB);
/**
* Cert to edit the trust of.
* @type nsIX509Cert
*/
var gCert;
/**
* onload() handler.
*/
function onLoad() {
gCert = window.arguments[0];
let bundle = document.getElementById("pippki_bundle");
setText("certmsg",
bundle.getFormattedString("editTrustCA", [gCert.commonName]));
let sslCheckbox = document.getElementById("trustSSL");
sslCheckbox.checked = gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_SSL);
let emailCheckbox = document.getElementById("trustEmail");
emailCheckbox.checked = gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_EMAIL);
let objSignCheckbox = document.getElementById("trustObjSign");
objSignCheckbox.checked =
gCertDB.isCertTrusted(gCert, Ci.nsIX509Cert.CA_CERT,
Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
}
/**
* ondialogaccept() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogAccept() {
let sslCheckbox = document.getElementById("trustSSL");
let emailCheckbox = document.getElementById("trustEmail");
let objSignCheckbox = document.getElementById("trustObjSign");
let trustSSL = sslCheckbox.checked ? Ci.nsIX509CertDB.TRUSTED_SSL : 0;
let trustEmail = emailCheckbox.checked ? Ci.nsIX509CertDB.TRUSTED_EMAIL : 0;
let trustObjSign = objSignCheckbox.checked ? Ci.nsIX509CertDB.TRUSTED_OBJSIGN
: 0;
gCertDB.setCertTrust(gCert, Ci.nsIX509Cert.CA_CERT,
trustSSL | trustEmail | trustObjSign);
return true;
}

View file

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
<dialog id="editCaCert"
title="&certmgr.editcacert.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel"
ondialogaccept="return onDialogAccept();"
onload="onLoad();"
>
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript"
src="chrome://pippki/content/editcacert.js"/>
<description id="certmsg"/>
<separator/>
<description>&certmgr.editcert.edittrust;</description>
<vbox align="start">
<checkbox label="&certmgr.editcert.trustssl;"
id="trustSSL"/>
<checkbox label="&certmgr.editcert.trustemail;"
id="trustEmail"/>
<checkbox label="&certmgr.editcert.trustobjsign;"
id="trustObjSign"/>
</vbox>
</dialog>

View file

@ -0,0 +1,368 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
var gDialog;
var gBundleBrand;
var gPKIBundle;
var gSSLStatus;
var gCert;
var gChecking;
var gBroken;
var gNeedReset;
var gSecHistogram;
var gNsISecTel;
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
function badCertListener() {}
badCertListener.prototype = {
getInterface: function (aIID) {
return this.QueryInterface(aIID);
},
QueryInterface: function(aIID) {
if (aIID.equals(Components.interfaces.nsIBadCertListener2) ||
aIID.equals(Components.interfaces.nsIInterfaceRequestor) ||
aIID.equals(Components.interfaces.nsISupports)) {
return this;
}
throw new Error(Components.results.NS_ERROR_NO_INTERFACE);
},
handle_test_result: function () {
if (gSSLStatus) {
gCert = gSSLStatus.QueryInterface(Components.interfaces.nsISSLStatus).serverCert;
}
},
notifyCertProblem: function MSR_notifyCertProblem(socketInfo, sslStatus, targetHost) {
gBroken = true;
gSSLStatus = sslStatus;
this.handle_test_result();
return true; // suppress error UI
}
};
function initExceptionDialog() {
gNeedReset = false;
gDialog = document.documentElement;
gBundleBrand = document.getElementById("brand_bundle");
gPKIBundle = document.getElementById("pippki_bundle");
gSecHistogram = Components.classes["@mozilla.org/base/telemetry;1"].
getService(Components.interfaces.nsITelemetry).
getHistogramById("SECURITY_UI");
gNsISecTel = Components.interfaces.nsISecurityUITelemetry;
var brandName = gBundleBrand.getString("brandShortName");
setText("warningText", gPKIBundle.getFormattedString("addExceptionBrandedWarning2", [brandName]));
gDialog.getButton("extra1").disabled = true;
var args = window.arguments;
if (args && args[0]) {
if (args[0].location) {
// We were pre-seeded with a location.
document.getElementById("locationTextBox").value = args[0].location;
document.getElementById('checkCertButton').disabled = false;
if (args[0].sslStatus) {
gSSLStatus = args[0].sslStatus;
gCert = gSSLStatus.serverCert;
gBroken = true;
updateCertStatus();
} else if (args[0].prefetchCert) {
// We can optionally pre-fetch the certificate too. Don't do this
// synchronously, since it would prevent the window from appearing
// until the fetch is completed, which could be multiple seconds.
// Instead, let's use a timer to spawn the actual fetch, but update
// the dialog to "checking..." state right away, so that the UI
// is appropriately responsive. Bug 453855
document.getElementById("checkCertButton").disabled = true;
gChecking = true;
updateCertStatus();
window.setTimeout(checkCert, 0);
}
}
// Set out parameter to false by default
args[0].exceptionAdded = false;
}
}
/**
* Attempt to download the certificate for the location specified, and populate
* the Certificate Status section with the result.
*/
function checkCert() {
gCert = null;
gSSLStatus = null;
gChecking = true;
gBroken = false;
updateCertStatus();
var uri = getURI();
var req = new XMLHttpRequest();
try {
if (uri) {
req.open('GET', uri.prePath, false);
req.channel.notificationCallbacks = new badCertListener();
req.send(null);
}
} catch (e) {
// We *expect* exceptions if there are problems with the certificate
// presented by the site. Log it, just in case, but we can proceed here,
// with appropriate sanity checks
Components.utils.reportError("Attempted to connect to a site with a bad certificate in the add exception dialog. " +
"This results in a (mostly harmless) exception being thrown. " +
"Logged for information purposes only: " + e);
} finally {
gChecking = false;
}
if (req.channel && req.channel.securityInfo) {
const Ci = Components.interfaces;
gSSLStatus = req.channel.securityInfo
.QueryInterface(Ci.nsISSLStatusProvider).SSLStatus;
gCert = gSSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
}
updateCertStatus();
}
/**
* Build and return a URI, based on the information supplied in the
* Certificate Location fields
*/
function getURI() {
// Use fixup service instead of just ioservice's newURI since it's quite
// likely that the host will be supplied without a protocol prefix, resulting
// in malformed uri exceptions being thrown.
let fus = Components.classes["@mozilla.org/docshell/urifixup;1"]
.getService(Components.interfaces.nsIURIFixup);
let locationTextBox = document.getElementById("locationTextBox");
let uri = fus.createFixupURI(locationTextBox.value, 0);
if (!uri) {
return null;
}
if (uri.scheme == "http") {
uri.scheme = "https";
}
if (uri.port == -1) {
uri.port = 443;
}
return uri;
}
function resetDialog() {
document.getElementById("viewCertButton").disabled = true;
document.getElementById("permanent").disabled = true;
gDialog.getButton("extra1").disabled = true;
setText("headerDescription", "");
setText("statusDescription", "");
setText("statusLongDescription", "");
setText("status2Description", "");
setText("status2LongDescription", "");
setText("status3Description", "");
setText("status3LongDescription", "");
}
/**
* Called by input textboxes to manage UI state
*/
function handleTextChange() {
var checkCertButton = document.getElementById('checkCertButton');
checkCertButton.disabled = !(document.getElementById("locationTextBox").value);
if (gNeedReset) {
gNeedReset = false;
resetDialog();
}
}
function updateCertStatus() {
var shortDesc, longDesc;
var shortDesc2, longDesc2;
var shortDesc3, longDesc3;
var use2 = false;
var use3 = false;
let bucketId = gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_BASE;
if (gCert) {
if (gBroken) {
var mms = "addExceptionDomainMismatchShort";
var mml = "addExceptionDomainMismatchLong2";
var exs = "addExceptionExpiredShort";
var exl = "addExceptionExpiredLong2";
var uts = "addExceptionUnverifiedOrBadSignatureShort";
var utl = "addExceptionUnverifiedOrBadSignatureLong2";
var use1 = false;
if (gSSLStatus.isDomainMismatch) {
bucketId += gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_FLAG_DOMAIN;
use1 = true;
shortDesc = mms;
longDesc = mml;
}
if (gSSLStatus.isNotValidAtThisTime) {
bucketId += gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_FLAG_TIME;
if (!use1) {
use1 = true;
shortDesc = exs;
longDesc = exl;
}
else {
use2 = true;
shortDesc2 = exs;
longDesc2 = exl;
}
}
if (gSSLStatus.isUntrusted) {
bucketId += gNsISecTel.WARNING_BAD_CERT_TOP_ADD_EXCEPTION_FLAG_UNTRUSTED;
if (!use1) {
use1 = true;
shortDesc = uts;
longDesc = utl;
} else if (!use2) {
use2 = true;
shortDesc2 = uts;
longDesc2 = utl;
} else {
use3 = true;
shortDesc3 = uts;
longDesc3 = utl;
}
}
gSecHistogram.add(bucketId);
// In these cases, we do want to enable the "Add Exception" button
gDialog.getButton("extra1").disabled = false;
// If the Private Browsing service is available and the mode is active,
// don't store permanent exceptions, since they would persist after
// private browsing mode was disabled.
var inPrivateBrowsing = inPrivateBrowsingMode();
var pe = document.getElementById("permanent");
pe.disabled = inPrivateBrowsing;
pe.checked = !inPrivateBrowsing;
setText("headerDescription", gPKIBundle.getString("addExceptionInvalidHeader"));
}
else {
shortDesc = "addExceptionValidShort";
longDesc = "addExceptionValidLong";
gDialog.getButton("extra1").disabled = true;
document.getElementById("permanent").disabled = true;
}
// We're done checking the certificate, so allow the user to check it again.
document.getElementById("checkCertButton").disabled = false;
document.getElementById("viewCertButton").disabled = false;
// Notify observers about the availability of the certificate
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(null, "cert-exception-ui-ready", null);
}
else if (gChecking) {
shortDesc = "addExceptionCheckingShort";
longDesc = "addExceptionCheckingLong2";
// We're checking the certificate, so we disable the Get Certificate
// button to make sure that the user can't interrupt the process and
// trigger another certificate fetch.
document.getElementById("checkCertButton").disabled = true;
document.getElementById("viewCertButton").disabled = true;
gDialog.getButton("extra1").disabled = true;
document.getElementById("permanent").disabled = true;
}
else {
shortDesc = "addExceptionNoCertShort";
longDesc = "addExceptionNoCertLong2";
// We're done checking the certificate, so allow the user to check it again.
document.getElementById("checkCertButton").disabled = false;
document.getElementById("viewCertButton").disabled = true;
gDialog.getButton("extra1").disabled = true;
document.getElementById("permanent").disabled = true;
}
setText("statusDescription", gPKIBundle.getString(shortDesc));
setText("statusLongDescription", gPKIBundle.getString(longDesc));
if (use2) {
setText("status2Description", gPKIBundle.getString(shortDesc2));
setText("status2LongDescription", gPKIBundle.getString(longDesc2));
}
if (use3) {
setText("status3Description", gPKIBundle.getString(shortDesc3));
setText("status3LongDescription", gPKIBundle.getString(longDesc3));
}
gNeedReset = true;
}
/**
* Handle user request to display certificate details
*/
function viewCertButtonClick() {
gSecHistogram.add(gNsISecTel.WARNING_BAD_CERT_TOP_CLICK_VIEW_CERT);
if (gCert) {
viewCertHelper(this, gCert);
}
}
/**
* Handle user request to add an exception for the specified cert
*/
function addException() {
if (!gCert || !gSSLStatus) {
return;
}
var overrideService = Components.classes["@mozilla.org/security/certoverride;1"]
.getService(Components.interfaces.nsICertOverrideService);
var flags = 0;
let confirmBucketId = gNsISecTel.WARNING_BAD_CERT_TOP_CONFIRM_ADD_EXCEPTION_BASE;
if (gSSLStatus.isUntrusted) {
flags |= overrideService.ERROR_UNTRUSTED;
confirmBucketId += gNsISecTel.WARNING_BAD_CERT_TOP_CONFIRM_ADD_EXCEPTION_FLAG_UNTRUSTED;
}
if (gSSLStatus.isDomainMismatch) {
flags |= overrideService.ERROR_MISMATCH;
confirmBucketId += gNsISecTel.WARNING_BAD_CERT_TOP_CONFIRM_ADD_EXCEPTION_FLAG_DOMAIN;
}
if (gSSLStatus.isNotValidAtThisTime) {
flags |= overrideService.ERROR_TIME;
confirmBucketId += gNsISecTel.WARNING_BAD_CERT_TOP_CONFIRM_ADD_EXCEPTION_FLAG_TIME;
}
var permanentCheckbox = document.getElementById("permanent");
var shouldStorePermanently = permanentCheckbox.checked && !inPrivateBrowsingMode();
if (!permanentCheckbox.checked) {
gSecHistogram.add(gNsISecTel.WARNING_BAD_CERT_TOP_DONT_REMEMBER_EXCEPTION);
}
gSecHistogram.add(confirmBucketId);
var uri = getURI();
overrideService.rememberValidityOverride(
uri.asciiHost, uri.port,
gCert,
flags,
!shouldStorePermanently);
let args = window.arguments;
if (args && args[0]) {
args[0].exceptionAdded = true;
}
gDialog.acceptDialog();
}
/**
* Returns true if this dialog is in private browsing mode.
*/
function inPrivateBrowsingMode() {
return PrivateBrowsingUtils.isWindowPrivate(window);
}

View file

@ -0,0 +1,89 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/certManager.dtd">
<dialog id="exceptiondialog"
windowtype="mozilla:exceptiondialog"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&exceptionMgr.title;"
buttons="cancel,extra1,extra2"
buttonlabelextra1="&exceptionMgr.exceptionButton.label;"
buttonaccesskeyextra1="&exceptionMgr.exceptionButton.accesskey;"
style="width: 46em; min-height: 38em;"
onload="initExceptionDialog();"
ondialogextra1="addException();"
ondialogextra2="checkCert();"
persist="screenX screenY width height"
defaultButton="extra2">
<stringbundleset id="stringbundleset">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<stringbundle id="brand_bundle" src="chrome://branding/locale/brand.properties"/>
</stringbundleset>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript" src="chrome://pippki/content/exceptionDialog.js"/>
<hbox>
<vbox>
#ifdef MOZ_WIDGET_GTK
<image src="moz-icon://stock/gtk-dialog-warning?size=dialog"/>
#else
<image src="chrome://global/skin/icons/warning-large.png"/>
#endif
<spacer flex="1"/>
</vbox>
<vbox flex="1">
<!-- Note that because of the styling, there must be no whitespace within
the description tags -->
<description id="warningText"
style="white-space: pre-wrap"/>
<description id="warningSupplemental"
style="font-weight: bold; white-space: pre-wrap;"
>&exceptionMgr.supplementalWarning;</description>
</vbox>
</hbox>
<groupbox id="locationGroupBox">
<caption label="&exceptionMgr.certlocation.caption2;"/>
<hbox align="center">
<label control="locationTextBox" value="&exceptionMgr.certlocation.url;"/>
<textbox id="locationTextBox" flex="1" oninput="handleTextChange();"
value="https://" class="uri-element"/>
<button id="checkCertButton" disabled="true" dlgtype="extra2"
accesskey="&exceptionMgr.certlocation.accesskey;"
label="&exceptionMgr.certlocation.download;"/>
</hbox>
</groupbox>
<groupbox id="certStatusGroupBox" flex="1">
<caption label="&exceptionMgr.certstatus.caption;"/>
<hbox>
<description id="headerDescription" style="white-space: pre-wrap;"
flex="1"/>
<vbox>
<button id="viewCertButton" label="&exceptionMgr.certstatus.viewCert;"
accesskey="&exceptionMgr.certstatus.accesskey;"
disabled="true" oncommand="viewCertButtonClick();"/>
</vbox>
</hbox>
<description id="statusDescription"
style="font-weight: bold; padding-bottom: 1em;"/>
<description id="statusLongDescription" style="white-space: pre-wrap;"/>
<description id="status2Description"
style="font-weight: bold; padding-bottom: 1em;"/>
<description id="status2LongDescription" style="white-space: pre-wrap;"/>
<description id="status3Description"
style="font-weight: bold; padding-bottom: 1em;"/>
<description id="status3LongDescription" style="white-space: pre-wrap;"/>
<spacer flex="1"/>
<checkbox id="permanent" disabled="true"
label="&exceptionMgr.permanent.label;"
accesskey="&exceptionMgr.permanent.accesskey;"/>
</groupbox>
</dialog>

View file

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog [
<!ENTITY % deviceManangerDTD SYSTEM "chrome://pippki/locale/deviceManager.dtd">
%deviceManangerDTD;
<!ENTITY % pippkiDTD SYSTEM "chrome://pippki/locale/pippki.dtd" >
%pippkiDTD;
]>
<dialog id="loaddevice"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&loaddevice.title;"
buttons="accept,cancel"
ondialogaccept="return doLoadDevice();">
<stringbundleset id="stringbundleset">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<stringbundle id="pipnss_bundle" src="chrome://pipnss/locale/pipnss.properties"/>
</stringbundleset>
<script type="application/javascript" src="chrome://pippki/content/device_manager.js"/>
<description>&loaddevice.info;</description>
<hbox align="center">
<label value="&loaddevice.modname;" accesskey="&loaddevice.modname.accesskey;"
control="device_name"/>
<textbox id="device_name" flex="1" value="&loaddevice.modname.default;"/>
</hbox>
<hbox align="center">
<label value="&loaddevice.filename;" accesskey="&loaddevice.filename.accesskey;"
control="device_path"/>
<textbox id="device_path" flex="1"/>
<button label="&loaddevice.browse;" flex="1"
accesskey="&loaddevice.browse.accesskey;" oncommand="doBrowseFiles();"/>
</hbox>
</dialog>

View file

@ -0,0 +1,191 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
*
* 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";
/*
* These are helper functions to be included
* pippki UI js files.
*/
function setText(id, value) {
let element = document.getElementById(id);
if (!element) {
return;
}
if (element.hasChildNodes()) {
element.removeChild(element.firstChild);
}
element.appendChild(document.createTextNode(value));
}
const nsICertificateDialogs = Components.interfaces.nsICertificateDialogs;
const nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1";
function viewCertHelper(parent, cert) {
if (!cert) {
return;
}
var cd = Components.classes[nsCertificateDialogs].getService(nsICertificateDialogs);
cd.viewCert(parent, cert);
}
function getDERString(cert)
{
var length = {};
var derArray = cert.getRawDER(length);
var derString = '';
for (var i = 0; i < derArray.length; i++) {
derString += String.fromCharCode(derArray[i]);
}
return derString;
}
function getPKCS7String(cert, chainMode)
{
var length = {};
var pkcs7Array = cert.exportAsCMS(chainMode, length);
var pkcs7String = '';
for (var i = 0; i < pkcs7Array.length; i++) {
pkcs7String += String.fromCharCode(pkcs7Array[i]);
}
return pkcs7String;
}
function getPEMString(cert)
{
var derb64 = btoa(getDERString(cert));
// Wrap the Base64 string into lines of 64 characters with CRLF line breaks
// (as specified in RFC 1421).
var wrapped = derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
return "-----BEGIN CERTIFICATE-----\r\n"
+ wrapped
+ "\r\n-----END CERTIFICATE-----\r\n";
}
function alertPromptService(title, message)
{
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService);
ps.alert(window, title, message);
}
const DEFAULT_CERT_EXTENSION = "crt";
/**
* Generates a filename for a cert suitable to set as the |defaultString|
* attribute on an nsIFilePicker.
*
* @param {nsIX509Cert} cert
* The cert to generate a filename for.
* @returns {String}
* Generated filename.
*/
function certToFilename(cert) {
let filename = cert.commonName;
if (!filename) {
filename = cert.windowTitle;
}
// Remove unneeded and/or unsafe characters.
filename = filename.replace(/\s/g, "")
.replace(/\./g, "")
.replace(/\\/g, "")
.replace(/\//g, "");
// nsIFilePicker.defaultExtension is more of a suggestion to some
// implementations, so we include the extension in the file name as well. This
// is what the documentation for nsIFilePicker.defaultString says we should do
// anyways.
return `${filename}.${DEFAULT_CERT_EXTENSION}`;
}
function exportToFile(parent, cert)
{
var bundle = document.getElementById("pippki_bundle");
if (!cert) {
return;
}
var nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].
createInstance(nsIFilePicker);
fp.init(parent, bundle.getString("SaveCertAs"),
nsIFilePicker.modeSave);
fp.defaultString = certToFilename(cert);
fp.defaultExtension = DEFAULT_CERT_EXTENSION;
fp.appendFilter(bundle.getString("CertFormatBase64"), "*.crt; *.pem");
fp.appendFilter(bundle.getString("CertFormatBase64Chain"), "*.crt; *.pem");
fp.appendFilter(bundle.getString("CertFormatDER"), "*.der");
fp.appendFilter(bundle.getString("CertFormatPKCS7"), "*.p7c");
fp.appendFilter(bundle.getString("CertFormatPKCS7Chain"), "*.p7c");
fp.appendFilters(nsIFilePicker.filterAll);
var res = fp.show();
if (res != nsIFilePicker.returnOK && res != nsIFilePicker.returnReplace) {
return;
}
var content = '';
switch (fp.filterIndex) {
case 1:
content = getPEMString(cert);
var chain = cert.getChain();
for (let i = 1; i < chain.length; i++) {
content += getPEMString(chain.queryElementAt(i, Components.interfaces.nsIX509Cert));
}
break;
case 2:
content = getDERString(cert);
break;
case 3:
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertOnly);
break;
case 4:
content = getPKCS7String(cert, Components.interfaces.nsIX509Cert.CMS_CHAIN_MODE_CertChainWithRoot);
break;
case 0:
default:
content = getPEMString(cert);
break;
}
var msg;
var written = 0;
try {
var file = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(fp.file.path);
var fos = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
// flags: PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
fos.init(file, 0x02 | 0x08 | 0x20, 0o0644, 0);
written = fos.write(content, content.length);
fos.close();
} catch (e) {
switch (e.result) {
case Components.results.NS_ERROR_FILE_ACCESS_DENIED:
msg = bundle.getString("writeFileAccessDenied");
break;
case Components.results.NS_ERROR_FILE_IS_LOCKED:
msg = bundle.getString("writeFileIsLocked");
break;
case Components.results.NS_ERROR_FILE_NO_DEVICE_SPACE:
case Components.results.NS_ERROR_FILE_DISK_FULL:
msg = bundle.getString("writeFileNoDeviceSpace");
break;
default:
msg = e.message;
break;
}
}
if (written != content.length) {
if (msg.length == 0) {
msg = bundle.getString("writeFileUnknownError");
}
alertPromptService(bundle.getString("writeFileFailure"),
bundle.getFormattedString("writeFileFailed",
[fp.file.path, msg]));
}
}

View file

@ -0,0 +1,42 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
function onLoad()
{
let protectedAuthThread =
window.arguments[0].QueryInterface(Components.interfaces.nsIProtectedAuthThread);
if (!protectedAuthThread) {
window.close();
return;
}
try {
let tokenName = protectedAuthThread.getTokenName();
let tag = document.getElementById("tokenName");
tag.setAttribute("value", tokenName);
window.setCursor("wait");
let obs = {
observe: function protectedAuthListenerObserve(subject, topic, data) {
if (topic == "operation-completed") {
window.close();
}
}
};
protectedAuthThread.login(obs);
} catch (exception) {
window.close();
}
}
function onClose()
{
window.setCursor("auto");
}

View file

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://pippki/locale/pippki.dtd">
<window
id="protectedAuth" title="&protectedAuth.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
onclose="onClose();"
>
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="pippki.js" />
<script type="application/javascript" src="protectedAuth.js" />
<script type="application/javascript" src="chrome://help/content/help.js" />
<vbox style="margin: 5px; max-width: 50em;">
<description>&protectedAuth.msg;</description>
<hbox>
<description>&protectedAuth.tokenName.label;</description>
<description id="tokenName"></description>
</hbox>
</vbox>
</window>

View file

@ -0,0 +1,47 @@
/* 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/. */
/* import-globals-from pippki.js */
"use strict";
const nsPK11TokenDB = "@mozilla.org/security/pk11tokendb;1";
const nsIPK11TokenDB = Components.interfaces.nsIPK11TokenDB;
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var tokenName;
function onLoad()
{
if ("arguments" in window) {
var params = window.arguments[0].QueryInterface(nsIDialogParamBlock);
tokenName = params.GetString(1);
} else {
tokenName = self.name;
}
}
function resetPassword()
{
var pk11db = Components.classes[nsPK11TokenDB].getService(nsIPK11TokenDB);
var token = pk11db.findTokenByName(tokenName);
token.reset();
try {
var loginManager = Components.classes["@mozilla.org/login-manager;1"].
getService(Components.interfaces.nsILoginManager);
loginManager.removeAllLogins();
} catch (e) {
}
var bundle = document.getElementById("pippki_bundle");
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService();
promptService = promptService.QueryInterface(Components.interfaces.nsIPromptService);
if (promptService && bundle) {
promptService.alert(window,
bundle.getString("resetPasswordConfirmationTitle"),
bundle.getString("resetPasswordConfirmationMessage"));
}
return true;
}

View file

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/pippki.dtd">
<dialog id="reset_password" title="&resetPassword.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel"
buttonlabelaccept="&resetPasswordButtonLabel;"
defaultButton="cancel"
ondialogaccept="return resetPassword();"
style="width: 40em;" onload="onLoad();">
<stringbundle id="pippki_bundle" src="chrome://pippki/locale/pippki.properties"/>
<script type="application/javascript" src="chrome://pippki/content/pippki.js"/>
<script type="application/javascript" src="chrome://pippki/content/resetpassword.js"/>
<hbox flex="1">
<vbox>
<image class="alert-icon" style="margin: 5px;"/>
</vbox>
<vbox style="margin: 5px;" flex="1">
<hbox flex="1">
<vbox flex="1">
<description>&resetPassword.text;</description>
</vbox>
</hbox>
</vbox>
</hbox>
</dialog>

View file

@ -0,0 +1,128 @@
/* 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";
/**
* @file Implements the functionality of setp12password.xul: a dialog that lets
* the user confirm the password to set on a PKCS #12 file.
* @argument {nsISupports} window.arguments[0]
* Object to set the return values of calling the dialog on, queryable
* to the underlying type of SetP12PasswordReturnValues.
*/
/**
* @typedef SetP12PasswordReturnValues
* @type nsIWritablePropertyBag2
* @property {Boolean} confirmedPassword
* Set to true if the user entered two matching passwords and
* confirmed the dialog.
* @property {String} password
* The password the user entered. Undefined value if
* |confirmedPassword| is not true.
*/
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
/**
* onload() handler.
*/
function onLoad() {
// Ensure the first password textbox has focus.
document.getElementById("pw1").focus();
}
/**
* ondialogaccept() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogAccept() {
let password = document.getElementById("pw1").value;
let retVals = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("confirmedPassword", true);
retVals.setPropertyAsAString("password", password);
return true;
}
/**
* ondialogcancel() handler.
*
* @returns {Boolean} true to make the dialog close, false otherwise.
*/
function onDialogCancel() {
let retVals = window.arguments[0].QueryInterface(Ci.nsIWritablePropertyBag2);
retVals.setPropertyAsBool("confirmedPassword", false);
return true;
}
/**
* Calculates the strength of the given password, suitable for use in updating
* a progress bar that represents said strength.
*
* The strength of the password is calculated by checking the number of:
* - Characters
* - Numbers
* - Non-alphanumeric chars
* - Upper case characters
*
* @param {String} password
* The password to calculate the strength of.
* @returns {Number}
* The strength of the password in the range [0, 100].
*/
function getPasswordStrength(password) {
let lengthStrength = password.length;
if (lengthStrength > 5) {
lengthStrength = 5;
}
let nonNumericChars = password.replace(/[0-9]/g, "");
let numericStrength = password.length - nonNumericChars.length;
if (numericStrength > 3) {
numericStrength = 3;
}
let nonSymbolChars = password.replace(/\W/g, "");
let symbolStrength = password.length - nonSymbolChars.length;
if (symbolStrength > 3) {
symbolStrength = 3;
}
let nonUpperAlphaChars = password.replace(/[A-Z]/g, "");
let upperAlphaStrength = password.length - nonUpperAlphaChars.length;
if (upperAlphaStrength > 3) {
upperAlphaStrength = 3;
}
let strength = (lengthStrength * 10) - 20 + (numericStrength * 10) +
(symbolStrength * 15) + (upperAlphaStrength * 10);
if (strength < 0) {
strength = 0;
}
if (strength > 100) {
strength = 100;
}
return strength;
}
/**
* oninput() handler for both password textboxes.
*
* @param {Boolean} recalculatePasswordStrength
* Whether to recalculate the strength of the first password.
*/
function onPasswordInput(recalculatePasswordStrength) {
let pw1 = document.getElementById("pw1").value;
if (recalculatePasswordStrength) {
document.getElementById("pwmeter").value = getPasswordStrength(pw1);
}
// Disable the accept button if the two passwords don't match, and enable it
// if the passwords do match.
let pw2 = document.getElementById("pw2").value;
document.documentElement.getButton("accept").disabled = (pw1 != pw2);
}

View file

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!-- 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/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://pippki/locale/pippki.dtd">
<dialog id="setp12password"
title="&pkcs12.setpassword.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 48em;"
buttons="accept,cancel"
ondialogaccept="return onDialogAccept();"
ondialogcancel="return onDialogCancel();"
onload="onLoad();">
<script type="application/javascript"
src="chrome://pippki/content/setp12password.js"/>
<description>&pkcs12.setpassword.message;</description>
<separator />
<grid>
<columns> <column/> <column/> </columns>
<rows>
<row>
<label value="&pkcs12.setpassword.label1;"/>
<textbox id="pw1" type="password" oninput="onPasswordInput(true);"/>
</row>
<row>
<label value="&pkcs12.setpassword.label2;"/>
<textbox id="pw2" type="password" oninput="onPasswordInput(false);"/>
</row>
</rows>
</grid>
<separator/>
<description>&pkcs12.setpassword.reminder;</description>
<separator/>
<label value="&setPassword.meter.label;"/>
<grid style="margin: 4px;">
<rows> <row/> </rows>
<columns>
<column style="margin: 5px;">
<progressmeter flex="1" id="pwmeter" mode="determined" value="0"
orient="horizontal"
style="width: 20em; foreground-color: red"/>
</column>
</columns>
</grid>
</dialog>

View file

@ -0,0 +1,104 @@
<?xml version="1.0"?>
<!-- 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/. -->
<!DOCTYPE overlay SYSTEM "chrome://pippki/locale/certManager.dtd">
<overlay id="certViewerOverlay"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cert="http://netscape.com/rdf-cert#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox class="box-padded" id="general_info">
<vbox id="verify_info_box">
<label id="verify_pending" value="&certmgr.pending.label;"/>
<label class="header" id="verified"/>
</vbox>
<separator class="groove"/>
<vbox flex="1">
<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row>
<label class="header" value="&certmgr.subjectinfo.label;"/>
<spacer/>
<spacer/>
</row>
<row>
<label value="&certmgr.certdetail.cn;"/>
<textbox id="commonname" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.certdetail.o;"/>
<textbox id="organization" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.certdetail.ou;"/>
<textbox id="orgunit" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.certdetail.serialnumber;"/>
<textbox id="serialnumber" class="plain" readonly="true"/>
</row>
<row>
<separator class="thin"/>
<spacer/>
</row>
<row>
<label class="header" value="&certmgr.issuerinfo.label;"/>
<spacer/>
</row>
<row>
<label value="&certmgr.certdetail.cn;"/>
<textbox id="issuercommonname" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.certdetail.o;"/>
<textbox id="issuerorganization" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.certdetail.ou;"/>
<textbox id="issuerorgunit" class="plain" readonly="true"/>
</row>
<row>
<separator class="thin"/>
<spacer/>
</row>
<row>
<label class ="header" value="&certmgr.periodofvalidity.label;"/>
<spacer/>
</row>
<row>
<label value="&certmgr.begins;"/>
<textbox id="validitystart" class="plain" readonly="true"/>
</row>
<row>
<label value="&certmgr.expires;"/>
<textbox id="validityend" class="plain" readonly="true"/>
</row>
<row>
<separator class="thin"/>
<spacer/>
</row>
<row>
<label class="header" value="&certmgr.fingerprints.label;"/>
<spacer/>
</row>
<row>
<label value="&certmgr.certdetail.sha256fingerprint;"/>
<hbox>
<textbox id="sha256fingerprint" class="plain" readonly="true" multiline="true"
style="height: 6ex; width: 48ch; font-family: monospace;"/>
</hbox>
</row>
<row>
<label value="&certmgr.certdetail.sha1fingerprint;"/>
<textbox id="sha1fingerprint" class="plain" readonly="true" style="min-width:34em;"/>
</row>
</rows>
</grid>
</vbox>
</vbox>
</overlay>

View file

@ -0,0 +1,43 @@
# 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/.
pippki.jar:
% content pippki %content/pippki/
content/pippki/CAOverlay.xul (content/CAOverlay.xul)
content/pippki/MineOverlay.xul (content/MineOverlay.xul)
content/pippki/OrphanOverlay.xul (content/OrphanOverlay.xul)
content/pippki/OthersOverlay.xul (content/OthersOverlay.xul)
content/pippki/WebSitesOverlay.xul (content/WebSitesOverlay.xul)
content/pippki/certDump.xul (content/certDump.xul)
content/pippki/certManager.js (content/certManager.js)
content/pippki/certManager.xul (content/certManager.xul)
content/pippki/certViewer.js (content/certViewer.js)
content/pippki/certViewer.xul (content/certViewer.xul)
content/pippki/changepassword.js (content/changepassword.js)
content/pippki/changepassword.xul (content/changepassword.xul)
content/pippki/choosetoken.js (content/choosetoken.js)
content/pippki/choosetoken.xul (content/choosetoken.xul)
content/pippki/clientauthask.js (content/clientauthask.js)
content/pippki/clientauthask.xul (content/clientauthask.xul)
content/pippki/createCertInfo.js (content/createCertInfo.js)
content/pippki/createCertInfo.xul (content/createCertInfo.xul)
content/pippki/deletecert.js (content/deletecert.js)
content/pippki/deletecert.xul (content/deletecert.xul)
content/pippki/device_manager.js (content/device_manager.js)
content/pippki/device_manager.xul (content/device_manager.xul)
content/pippki/downloadcert.js (content/downloadcert.js)
content/pippki/downloadcert.xul (content/downloadcert.xul)
content/pippki/editcacert.js (content/editcacert.js)
content/pippki/editcacert.xul (content/editcacert.xul)
content/pippki/exceptionDialog.js (content/exceptionDialog.js)
* content/pippki/exceptionDialog.xul (content/exceptionDialog.xul)
content/pippki/load_device.xul (content/load_device.xul)
content/pippki/pippki.js (content/pippki.js)
content/pippki/protectedAuth.js (content/protectedAuth.js)
content/pippki/protectedAuth.xul (content/protectedAuth.xul)
content/pippki/resetpassword.js (content/resetpassword.js)
content/pippki/resetpassword.xul (content/resetpassword.xul)
content/pippki/setp12password.js (content/setp12password.js)
content/pippki/setp12password.xul (content/setp12password.xul)
content/pippki/viewCertDetails.xul (content/viewCertDetails.xul)

View file

@ -0,0 +1,7 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
JAR_MANIFESTS += ['jar.mn']