Files
UXP-Fixed/security/manager/ssl/tests/mochitest/browser/browser_certViewer.js
T
2018-02-02 04:16:08 -05:00

225 lines
8.6 KiB
JavaScript

/* 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");
}