Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: os == 'android' OR msix
- Manifest: security/manager/ssl/tests/unit/xpcshell-smartcards.toml
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
// Any copyright is dedicated to the Public Domain.
"use strict";
// Tests using a client authentication certificate via a PKCS#11 module.
// Ensure that the appropriate initialization has happened.
do_get_profile();
const gCertDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
var gPrompt = {
QueryInterface: ChromeUtils.generateQI(["nsIPrompt"]),
// This intentionally does not use arrow function syntax to avoid an issue
// where in the context of the arrow function, |this != gPrompt| due to
// how objects get wrapped when going across xpcom boundaries.
alert(_title, text) {
const EXPECTED_PROMPT_TEXT =
"Please authenticate to the token “Test PKCS11 Tokeñ 2 Label”. How to do so depends on the token (for example, using a fingerprint reader or entering a code with a keypad).";
equal(text, EXPECTED_PROMPT_TEXT, "expecting alert() to be called");
},
promptPassword() {
ok(false, "not expecting promptPassword() to be called");
},
};
const gPromptFactory = {
QueryInterface: ChromeUtils.generateQI(["nsIPromptFactory"]),
getPrompt: () => gPrompt,
};
MockRegistrar.register("@mozilla.org/prompter;1", gPromptFactory);
// Replace the UI dialog that prompts the user to pick a client certificate.
const gClientAuthDialogService = {
set certificateNameToUse(name) {
this._certificateNameToUse = name;
},
chooseCertificate(hostname, certArray, loadContext, caNames, callback) {
for (let cert of certArray) {
if (cert.subjectName == this._certificateNameToUse) {
callback.certificateChosen(cert, false);
return;
}
}
callback.certificateChosen(null, false);
},
QueryInterface: ChromeUtils.generateQI([Ci.nsIClientAuthDialogService]),
};
MockRegistrar.register(
"@mozilla.org/security/ClientAuthDialogService;1",
gClientAuthDialogService
);
function run_test() {
let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
libraryFile.append("pkcs11testmodule");
libraryFile.append(ctypes.libraryName("pkcs11testmodule"));
loadPKCS11Module(libraryFile, "PKCS11 Test Module", true);
Services.prefs.setCharPref(
"network.dns.localDomains",
"requireclientauth.example.com"
);
add_tls_server_setup("BadCertAndPinningServer", "bad_certs");
add_test(function set_up_rsa_client_certificate() {
gClientAuthDialogService.certificateNameToUse = "CN=client cert rsa";
run_next_test();
});
add_connection_test("requireclientauth.example.com", PRErrorCodeSuccess);
add_test(function set_up_ecdsa_client_certificate() {
gClientAuthDialogService.certificateNameToUse = "CN=client cert ecdsa";
run_next_test();
});
add_connection_test("requireclientauth.example.com", PRErrorCodeSuccess);
// The test module currently has a slot that uses a protected authentication
// path (i.e., when Firefox wants to authenticate to it, it opens a dialog
// that says "okay, authenticate to your token by using an external keypad or
// something" and waits for that to happen). For some reason, if this
// authentication happens as a result of the socket thread looking for client
// auth certificates, it results in an assertion failure ("Assertion
// failure: mSleep == AWAKE") in profiler_thread_sleep(). This probably has
// something to do with the fact that the socket thread is synchronously
// waiting on the main thread, which is spinning a nested event loop (which
// tends to cause problems like this).
// Since this is an uncommon configuration and since this issue hasn't been
// reproduced outside of this test infrastructure, this works around it for
// the time being by authenticating to all tokens on the main thread so that
// the socket thread doesn't have to.
gCertDB.getCerts();
run_next_test();
}