summaryrefslogtreecommitdiffstats
path: root/security/manager/pki/resources/content/pippki.js
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/pki/resources/content/pippki.js')
-rw-r--r--security/manager/pki/resources/content/pippki.js191
1 files changed, 191 insertions, 0 deletions
diff --git a/security/manager/pki/resources/content/pippki.js b/security/manager/pki/resources/content/pippki.js
new file mode 100644
index 000000000..b660d2d93
--- /dev/null
+++ b/security/manager/pki/resources/content/pippki.js
@@ -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]));
+ }
+}