summaryrefslogtreecommitdiffstats
path: root/security/manager/pki/resources/content/clientauthask.js
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/pki/resources/content/clientauthask.js')
-rw-r--r--security/manager/pki/resources/content/clientauthask.js162
1 files changed, 162 insertions, 0 deletions
diff --git a/security/manager/pki/resources/content/clientauthask.js b/security/manager/pki/resources/content/clientauthask.js
new file mode 100644
index 0000000000..e9df667dbe
--- /dev/null
+++ b/security/manager/pki/resources/content/clientauthask.js
@@ -0,0 +1,162 @@
+/* -*- 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";
+
+const { parse, pemToDER } = ChromeUtils.importESModule(
+ "chrome://global/content/certviewer/certDecoder.mjs"
+);
+
+/**
+ * @file Implements the functionality of clientauthask.xhtml: a dialog that allows
+ * a user pick a client certificate for TLS client authentication.
+ * @param {object} window.arguments.0
+ * An Object with the properties:
+ * {String} hostname
+ * The hostname of the server requesting client authentication.
+ * {Array<nsIX509Cert>} certArray
+ * Array of certificates the user can choose from
+ * {Object} retVal
+ * Object to set the return values of calling the dialog on.
+ * See ClientAuthAskReturnValues.
+ */
+
+/**
+ * @typedef ClientAuthAskReturnValues
+ * @type {object}
+ * @property {nsIX509Cert} cert
+ * The certificate, if chosen. null otherwise.
+ * @property {boolean} rememberDecision
+ * Set to true if the user wanted their cert selection to be
+ * remembered, false otherwise.
+ */
+
+/**
+ * The array of certs the user can choose from.
+ *
+ * @type {Array<nsIX509Cert>}
+ */
+var certArray;
+
+/**
+ * The checkbox storing whether the user wants to remember the selected cert.
+ *
+ * @type {HTMLInputElement} Element checkbox, has to have |checked| property.
+ */
+var rememberBox;
+
+async function onLoad() {
+ let rememberSetting = Services.prefs.getBoolPref(
+ "security.remember_cert_checkbox_default_setting"
+ );
+ rememberBox = document.getElementById("rememberBox");
+ rememberBox.checked = rememberSetting;
+
+ certArray = window.arguments[0].certArray;
+
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthSiteIdentification"),
+ "client-auth-site-identification",
+ { hostname: window.arguments[0].hostname }
+ );
+
+ let selectElement = document.getElementById("nicknames");
+ for (let i = 0; i < certArray.length; i++) {
+ let menuItemNode = document.createXULElement("menuitem");
+ let cert = certArray[i];
+ let nickAndSerial = `${cert.displayName} [${cert.serialNumber}]`;
+ menuItemNode.setAttribute("value", i);
+ menuItemNode.setAttribute("label", nickAndSerial); // This is displayed.
+ selectElement.menupopup.appendChild(menuItemNode);
+ if (i == 0) {
+ selectElement.selectedItem = menuItemNode;
+ }
+ }
+
+ await setDetails();
+ document.addEventListener("dialogaccept", doOK);
+ document.addEventListener("dialogcancel", doCancel);
+
+ Services.obs.notifyObservers(
+ document.getElementById("certAuthAsk"),
+ "cert-dialog-loaded"
+ );
+}
+
+/**
+ * Populates the details section with information concerning the selected cert.
+ */
+async function setDetails() {
+ let index = parseInt(document.getElementById("nicknames").value);
+ let cert = certArray[index];
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsIssuedTo"),
+ "client-auth-cert-details-issued-to",
+ { issuedTo: cert.subjectName }
+ );
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsSerialNumber"),
+ "client-auth-cert-details-serial-number",
+ { serialNumber: cert.serialNumber }
+ );
+ const formatter = new Intl.DateTimeFormat(undefined, {
+ dateStyle: "medium",
+ timeStyle: "long",
+ });
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsValidityPeriod"),
+ "client-auth-cert-details-validity-period",
+ {
+ notBefore: formatter.format(new Date(cert.validity.notBefore / 1000)),
+ notAfter: formatter.format(new Date(cert.validity.notAfter / 1000)),
+ }
+ );
+ let parsedCert = await parse(pemToDER(cert.getBase64DERString()));
+ let keyUsages = parsedCert.ext.keyUsages;
+ if (keyUsages && keyUsages.purposes.length) {
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsKeyUsages"),
+ "client-auth-cert-details-key-usages",
+ { keyUsages: keyUsages.purposes.join(", ") }
+ );
+ }
+ let emailAddresses = cert.getEmailAddresses();
+ if (emailAddresses.length) {
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsEmailAddresses"),
+ "client-auth-cert-details-email-addresses",
+ { emailAddresses: emailAddresses.join(", ") }
+ );
+ }
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsIssuedBy"),
+ "client-auth-cert-details-issued-by",
+ { issuedBy: cert.issuerName }
+ );
+ document.l10n.setAttributes(
+ document.getElementById("clientAuthCertDetailsStoredOn"),
+ "client-auth-cert-details-stored-on",
+ { storedOn: cert.tokenName }
+ );
+}
+
+async function onCertSelected() {
+ await setDetails();
+}
+
+function doOK() {
+ let { retVals } = window.arguments[0];
+ let index = parseInt(document.getElementById("nicknames").value);
+ let cert = certArray[index];
+ retVals.cert = cert;
+ retVals.rememberDecision = rememberBox.checked;
+}
+
+function doCancel() {
+ let { retVals } = window.arguments[0];
+ retVals.cert = null;
+ retVals.rememberDecision = rememberBox.checked;
+}