mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-31 19:47:32 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
55
security/manager/pki/resources/content/CAOverlay.xul
Normal file
55
security/manager/pki/resources/content/CAOverlay.xul
Normal 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>
|
||||
64
security/manager/pki/resources/content/MineOverlay.xul
Normal file
64
security/manager/pki/resources/content/MineOverlay.xul
Normal 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>
|
||||
47
security/manager/pki/resources/content/OrphanOverlay.xul
Normal file
47
security/manager/pki/resources/content/OrphanOverlay.xul
Normal 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>
|
||||
54
security/manager/pki/resources/content/OthersOverlay.xul
Normal file
54
security/manager/pki/resources/content/OthersOverlay.xul
Normal 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>
|
||||
57
security/manager/pki/resources/content/WebSitesOverlay.xul
Normal file
57
security/manager/pki/resources/content/WebSitesOverlay.xul
Normal 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>
|
||||
44
security/manager/pki/resources/content/certDump.xul
Normal file
44
security/manager/pki/resources/content/certDump.xul
Normal 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>
|
||||
542
security/manager/pki/resources/content/certManager.js
Normal file
542
security/manager/pki/resources/content/certManager.js
Normal 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();
|
||||
}
|
||||
51
security/manager/pki/resources/content/certManager.xul
Normal file
51
security/manager/pki/resources/content/certManager.xul
Normal 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>
|
||||
354
security/manager/pki/resources/content/certViewer.js
Normal file
354
security/manager/pki/resources/content/certViewer.js
Normal 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;
|
||||
}
|
||||
40
security/manager/pki/resources/content/certViewer.xul
Normal file
40
security/manager/pki/resources/content/certViewer.xul
Normal 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>
|
||||
270
security/manager/pki/resources/content/changepassword.js
Normal file
270
security/manager/pki/resources/content/changepassword.js
Normal 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);
|
||||
}
|
||||
78
security/manager/pki/resources/content/changepassword.xul
Normal file
78
security/manager/pki/resources/content/changepassword.xul
Normal 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>
|
||||
44
security/manager/pki/resources/content/choosetoken.js
Normal file
44
security/manager/pki/resources/content/choosetoken.js
Normal 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;
|
||||
}
|
||||
34
security/manager/pki/resources/content/choosetoken.xul
Normal file
34
security/manager/pki/resources/content/choosetoken.xul
Normal 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>
|
||||
158
security/manager/pki/resources/content/clientauthask.js
Normal file
158
security/manager/pki/resources/content/clientauthask.js
Normal 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;
|
||||
}
|
||||
49
security/manager/pki/resources/content/clientauthask.xul
Normal file
49
security/manager/pki/resources/content/clientauthask.xul
Normal 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>
|
||||
39
security/manager/pki/resources/content/createCertInfo.js
Normal file
39
security/manager/pki/resources/content/createCertInfo.js
Normal 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);
|
||||
}
|
||||
30
security/manager/pki/resources/content/createCertInfo.xul
Normal file
30
security/manager/pki/resources/content/createCertInfo.xul
Normal 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>
|
||||
134
security/manager/pki/resources/content/deletecert.js
Normal file
134
security/manager/pki/resources/content/deletecert.js
Normal 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;
|
||||
}
|
||||
28
security/manager/pki/resources/content/deletecert.xul
Normal file
28
security/manager/pki/resources/content/deletecert.xul
Normal 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>
|
||||
509
security/manager/pki/resources/content/device_manager.js
Normal file
509
security/manager/pki/resources/content/device_manager.js
Normal 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();
|
||||
}
|
||||
90
security/manager/pki/resources/content/device_manager.xul
Normal file
90
security/manager/pki/resources/content/device_manager.xul
Normal 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>
|
||||
92
security/manager/pki/resources/content/downloadcert.js
Normal file
92
security/manager/pki/resources/content/downloadcert.js
Normal 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;
|
||||
}
|
||||
69
security/manager/pki/resources/content/downloadcert.xul
Normal file
69
security/manager/pki/resources/content/downloadcert.xul
Normal 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>
|
||||
58
security/manager/pki/resources/content/editcacert.js
Normal file
58
security/manager/pki/resources/content/editcacert.js
Normal 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;
|
||||
}
|
||||
36
security/manager/pki/resources/content/editcacert.xul
Normal file
36
security/manager/pki/resources/content/editcacert.xul
Normal 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>
|
||||
368
security/manager/pki/resources/content/exceptionDialog.js
Normal file
368
security/manager/pki/resources/content/exceptionDialog.js
Normal 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);
|
||||
}
|
||||
89
security/manager/pki/resources/content/exceptionDialog.xul
Normal file
89
security/manager/pki/resources/content/exceptionDialog.xul
Normal 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>
|
||||
42
security/manager/pki/resources/content/load_device.xul
Normal file
42
security/manager/pki/resources/content/load_device.xul
Normal 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>
|
||||
191
security/manager/pki/resources/content/pippki.js
Normal file
191
security/manager/pki/resources/content/pippki.js
Normal 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]));
|
||||
}
|
||||
}
|
||||
42
security/manager/pki/resources/content/protectedAuth.js
Normal file
42
security/manager/pki/resources/content/protectedAuth.js
Normal 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");
|
||||
}
|
||||
33
security/manager/pki/resources/content/protectedAuth.xul
Normal file
33
security/manager/pki/resources/content/protectedAuth.xul
Normal 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>
|
||||
47
security/manager/pki/resources/content/resetpassword.js
Normal file
47
security/manager/pki/resources/content/resetpassword.js
Normal 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;
|
||||
}
|
||||
|
||||
35
security/manager/pki/resources/content/resetpassword.xul
Normal file
35
security/manager/pki/resources/content/resetpassword.xul
Normal 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>
|
||||
128
security/manager/pki/resources/content/setp12password.js
Normal file
128
security/manager/pki/resources/content/setp12password.js
Normal 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);
|
||||
}
|
||||
51
security/manager/pki/resources/content/setp12password.xul
Normal file
51
security/manager/pki/resources/content/setp12password.xul
Normal 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>
|
||||
104
security/manager/pki/resources/content/viewCertDetails.xul
Normal file
104
security/manager/pki/resources/content/viewCertDetails.xul
Normal 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>
|
||||
43
security/manager/pki/resources/jar.mn
Normal file
43
security/manager/pki/resources/jar.mn
Normal 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)
|
||||
7
security/manager/pki/resources/moz.build
Normal file
7
security/manager/pki/resources/moz.build
Normal 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']
|
||||
Loading…
Add table
Add a link
Reference in a new issue