diff options
Diffstat (limited to 'security/manager/pki/resources/content/certManager.js')
-rw-r--r-- | security/manager/pki/resources/content/certManager.js | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/security/manager/pki/resources/content/certManager.js b/security/manager/pki/resources/content/certManager.js new file mode 100644 index 000000000..c52477442 --- /dev/null +++ b/security/manager/pki/resources/content/certManager.js @@ -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(); +} |