summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/tests/mochitest/browser/browser_clientAuth_ui.js
blob: 9bf961250ad091e46e615f2d0a730903e98130dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/
"use strict";

// Tests that the client authentication certificate chooser correctly displays
// provided information and correctly returns user input.

const TEST_HOSTNAME = "Test Hostname";
const TEST_ORG = "Test Org";
const TEST_ISSUER_ORG = "Test Issuer Org";
const TEST_PORT = 123;

var certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
  Ci.nsIX509CertDB
);
/**
 * Test certificate (i.e. build/pgo/certs/mochitest.client).
 *
 * @type {nsIX509Cert}
 */
var cert;

/**
 * Opens the client auth cert chooser dialog.
 *
 * @param {nsIX509Cert} cert The cert to pass to the dialog for display.
 * @returns {Promise}
 *          A promise that resolves when the dialog has finished loading, with
 *          an array consisting of:
 *            1. The window of the opened dialog.
 *            2. The return value nsIWritablePropertyBag2 passed to the dialog.
 */
function openClientAuthDialog(cert) {
  let certArray = [cert];
  let retVals = { cert: undefined, rememberDecision: undefined };
  let win = window.openDialog(
    "chrome://pippki/content/clientauthask.xhtml",
    "",
    "",
    { hostname: TEST_HOSTNAME, certArray, retVals }
  );
  return TestUtils.topicObserved("cert-dialog-loaded").then(() => {
    return { win, retVals };
  });
}

/**
 * Checks that the contents of the given cert chooser dialog match the details
 * of build/pgo/certs/mochitest.client.
 *
 * @param {window} win The cert chooser window.
 * @param {string} notBefore
 *        The formatted notBefore date of mochitest.client.
 * @param {string} notAfter
 *        The formatted notAfter date of mochitest.client.
 */
async function checkDialogContents(win, notBefore, notAfter) {
  await TestUtils.waitForCondition(() => {
    return win.document
      .getElementById("clientAuthSiteIdentification")
      .textContent.includes(`${TEST_HOSTNAME}`);
  });
  let nicknames = win.document.getElementById("nicknames");
  await TestUtils.waitForCondition(() => {
    return nicknames.label == "Mochitest client [03]";
  });
  await TestUtils.waitForCondition(() => {
    return nicknames.itemCount == 1;
  });
  let subject = win.document.getElementById("clientAuthCertDetailsIssuedTo");
  await TestUtils.waitForCondition(() => {
    return subject.textContent == "Issued to: CN=Mochitest client";
  });
  let serialNum = win.document.getElementById(
    "clientAuthCertDetailsSerialNumber"
  );
  await TestUtils.waitForCondition(() => {
    return serialNum.textContent == "Serial number: 03";
  });
  let validity = win.document.getElementById(
    "clientAuthCertDetailsValidityPeriod"
  );
  await TestUtils.waitForCondition(() => {
    return validity.textContent == `Valid from ${notBefore} to ${notAfter}`;
  });
  let issuer = win.document.getElementById("clientAuthCertDetailsIssuedBy");
  await TestUtils.waitForCondition(() => {
    return (
      issuer.textContent ==
      "Issued by: OU=Profile Guided Optimization,O=Mozilla Testing,CN=Temporary Certificate Authority"
    );
  });
  let tokenName = win.document.getElementById("clientAuthCertDetailsStoredOn");
  await TestUtils.waitForCondition(() => {
    return tokenName.textContent == "Stored on: Software Security Device";
  });
}

function findCertByCommonName(commonName) {
  for (let cert of certDB.getCerts()) {
    if (cert.commonName == commonName) {
      return cert;
    }
  }
  return null;
}

add_setup(async function () {
  cert = findCertByCommonName("Mochitest client");
  isnot(cert, null, "Should be able to find the test client cert");
});

// Test that the contents of the dialog correspond to the details of the
// provided cert.
add_task(async function testContents() {
  const formatter = new Intl.DateTimeFormat(undefined, {
    dateStyle: "medium",
    timeStyle: "long",
  });
  let { win } = await openClientAuthDialog(cert);
  await checkDialogContents(
    win,
    formatter.format(new Date(cert.validity.notBefore / 1000)),
    formatter.format(new Date(cert.validity.notAfter / 1000))
  );
  await BrowserTestUtils.closeWindow(win);
});

// Test that the right values are returned when the dialog is accepted.
add_task(async function testAcceptDialogReturnValues() {
  let { win, retVals } = await openClientAuthDialog(cert);
  win.document.getElementById("rememberBox").checked = true;
  info("Accepting dialog");
  win.document.getElementById("certAuthAsk").acceptDialog();
  await BrowserTestUtils.windowClosed(win);

  is(retVals.cert, cert, "cert should be returned as chosen cert");
  ok(
    retVals.rememberDecision,
    "Return value should signal 'Remember this decision' checkbox was checked"
  );
});

// Test that the right values are returned when the dialog is canceled.
add_task(async function testCancelDialogReturnValues() {
  let { win, retVals } = await openClientAuthDialog(cert);
  win.document.getElementById("rememberBox").checked = false;
  info("Canceling dialog");
  win.document.getElementById("certAuthAsk").cancelDialog();
  await BrowserTestUtils.windowClosed(win);

  ok(
    !retVals.cert,
    "Return value should signal user did not choose a certificate"
  );
  ok(
    !retVals.rememberDecision,
    "Return value should signal 'Remember this decision' checkbox was unchecked"
  );
});