summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/ssl/tests/mochitest/browser/browser_certViewer.js')
-rw-r--r--security/manager/ssl/tests/mochitest/browser/browser_certViewer.js224
1 files changed, 224 insertions, 0 deletions
diff --git a/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js b/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
new file mode 100644
index 000000000..d75f9f207
--- /dev/null
+++ b/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
@@ -0,0 +1,224 @@
+/* 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";
+
+// Repeatedly opens the certificate viewer dialog with various certificates and
+// determines that the viewer correctly identifies either what usages those
+// certificates are valid for or what errors prevented the certificates from
+// being verified.
+
+var { OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
+
+add_task(function* testCAandTitle() {
+ let cert = yield readCertificate("ca.pem", "CTu,CTu,CTu");
+ let win = yield displayCertificate(cert);
+ checkUsages(win, ["SSL Certificate Authority"]);
+
+ // There's no real need to test the title for every cert, so we just test it
+ // once here.
+ Assert.equal(win.document.title, "Certificate Viewer: \u201Cca\u201D",
+ "Actual and expected title should match");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testSSLEndEntity() {
+ let cert = yield readCertificate("ssl-ee.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkUsages(win, ["SSL Server Certificate", "SSL Client Certificate"]);
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testEmailEndEntity() {
+ let cert = yield readCertificate("email-ee.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate"]);
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testCodeSignEndEntity() {
+ let cert = yield readCertificate("code-ee.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkUsages(win, ["Object Signer"]);
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testExpired() {
+ let cert = yield readCertificate("expired-ca.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win, "Could not verify this certificate because it has expired.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testIssuerExpired() {
+ let cert = yield readCertificate("ee-from-expired-ca.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win,
+ "Could not verify this certificate because the CA certificate " +
+ "is invalid.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testUnknownIssuer() {
+ let cert = yield readCertificate("unknown-issuer.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win,
+ "Could not verify this certificate because the issuer is " +
+ "unknown.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testInsecureAlgo() {
+ let cert = yield readCertificate("md5-ee.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win,
+ "Could not verify this certificate because it was signed using " +
+ "a signature algorithm that was disabled because that algorithm " +
+ "is not secure.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testUntrusted() {
+ let cert = yield readCertificate("untrusted-ca.pem", "p,p,p");
+ let win = yield displayCertificate(cert);
+ checkError(win,
+ "Could not verify this certificate because it is not trusted.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testUntrustedIssuer() {
+ let cert = yield readCertificate("ee-from-untrusted-ca.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win,
+ "Could not verify this certificate because the issuer is not " +
+ "trusted.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testRevoked() {
+ // Note that there's currently no way to un-do this. This should only be a
+ // problem if another test re-uses a certificate with this same key (perhaps
+ // likely) and subject (less likely).
+ let certBlocklist = Cc["@mozilla.org/security/certblocklist;1"]
+ .getService(Ci.nsICertBlocklist);
+ certBlocklist.revokeCertBySubjectAndPubKey(
+ "MBIxEDAOBgNVBAMMB3Jldm9rZWQ=", // CN=revoked
+ "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8="); // hash of the shared key
+ let cert = yield readCertificate("revoked.pem", ",,");
+ let win = yield displayCertificate(cert);
+ // As of bug 1312827, OneCRL only applies to TLS web server certificates, so
+ // this certificate will actually verify successfully for every end-entity
+ // usage except TLS web server.
+ checkUsages(win, ["Email Recipient Certificate", "Email Signer Certificate",
+ "Object Signer", "SSL Client Certificate"]);
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+add_task(function* testInvalid() {
+ // This certificate has a keyUsage extension asserting cRLSign and
+ // keyCertSign, but it doesn't have a basicConstraints extension. This
+ // shouldn't be valid for any usage. Sadly, we give a pretty lame error
+ // message in this case.
+ let cert = yield readCertificate("invalid.pem", ",,");
+ let win = yield displayCertificate(cert);
+ checkError(win, "Could not verify this certificate for unknown reasons.");
+ yield BrowserTestUtils.closeWindow(win);
+});
+
+/**
+ * Given a certificate, returns a promise that will resolve when the certificate
+ * viewer has opened is displaying that certificate, and has finished
+ * determining its valid usages.
+ *
+ * @param {nsIX509Cert} certificate
+ * The certificate to view and determine usages for.
+ * @return {Promise}
+ * A promise that will resolve with a handle on the opened certificate
+ * viewer window when the usages have been determined.
+ */
+function displayCertificate(certificate) {
+ let win = window.openDialog("chrome://pippki/content/certViewer.xul", "",
+ "", certificate);
+ return TestUtils.topicObserved("ViewCertDetails:CertUsagesDone",
+ (subject, data) => subject == win)
+ .then(([subject, data]) => subject, error => { throw error; });
+}
+
+/**
+ * Given a certificate viewer window, finds the usages the certificate is valid
+ * for.
+ *
+ * @param {window} win
+ * The certificate viewer window.
+ * @return {String[]}
+ * An array of strings describing the usages the certificate is valid
+ * for.
+ */
+function getUsages(win) {
+ let determinedUsages = [];
+ let verifyInfoBox = win.document.getElementById("verify_info_box");
+ Array.from(verifyInfoBox.children).forEach(child => {
+ if (child.getAttribute("hidden") != "true" &&
+ child.getAttribute("id") != "verified") {
+ determinedUsages.push(child.getAttribute("value"));
+ }
+ });
+ return determinedUsages.sort();
+}
+
+/**
+ * Given a certificate viewer window, returns the error string describing a
+ * failure encountered when determining the certificate's usages. It will be
+ * "This certificate has been verified for the following uses:" when the
+ * certificate has successfully verified for at least one usage.
+ *
+ * @param {window} win
+ * The certificate viewer window.
+ * @return {String}
+ * A string describing the error encountered, or the success message if
+ * the certificate is valid for at least one usage.
+ */
+function getError(win) {
+ return win.document.getElementById("verified").textContent;
+}
+
+/**
+ * Given a certificate viewer window and an array of expected usage
+ * descriptions, verifies that the window is actually showing that the
+ * certificate has validated for those usages.
+ *
+ * @param {window} win
+ * The certificate viewer window.
+ * @param {String[]} usages
+ * An array of expected usage descriptions.
+ */
+function checkUsages(win, usages) {
+ Assert.equal(getError(win),
+ "This certificate has been verified for the following uses:",
+ "should have successful verification message");
+ let determinedUsages = getUsages(win);
+ usages.sort();
+ Assert.equal(determinedUsages.length, usages.length,
+ "number of usages as determined by cert viewer should be equal");
+ while (usages.length > 0) {
+ Assert.equal(determinedUsages.pop(), usages.pop(),
+ "usages as determined by cert viewer should be equal");
+ }
+}
+
+/**
+ * Given a certificate viewer window and an expected error, verifies that the
+ * window is actually showing that error.
+ *
+ * @param {window} win
+ * The certificate viewer window.
+ * @param {String} error
+ * The expected error message.
+ */
+function checkError(win, error) {
+ let determinedUsages = getUsages(win);
+ Assert.equal(determinedUsages.length, 0,
+ "should not have any successful usages in error case");
+ Assert.equal(getError(win), error,
+ "determined error should be the same as expected error");
+}