test_pkcs11_module_client_auth.js (3930B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ 2 // Any copyright is dedicated to the Public Domain. 3 // http://creativecommons.org/publicdomain/zero/1.0/ 4 "use strict"; 5 6 // Tests using a client authentication certificate via a PKCS#11 module. 7 8 // Ensure that the appropriate initialization has happened. 9 do_get_profile(); 10 11 const gCertDB = Cc["@mozilla.org/security/x509certdb;1"].getService( 12 Ci.nsIX509CertDB 13 ); 14 15 var gPrompt = { 16 QueryInterface: ChromeUtils.generateQI(["nsIPrompt"]), 17 18 // This intentionally does not use arrow function syntax to avoid an issue 19 // where in the context of the arrow function, |this != gPrompt| due to 20 // how objects get wrapped when going across xpcom boundaries. 21 alert(_title, text) { 22 const EXPECTED_PROMPT_TEXT = 23 "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)."; 24 equal(text, EXPECTED_PROMPT_TEXT, "expecting alert() to be called"); 25 }, 26 27 promptPassword() { 28 ok(false, "not expecting promptPassword() to be called"); 29 }, 30 }; 31 32 const gPromptFactory = { 33 QueryInterface: ChromeUtils.generateQI(["nsIPromptFactory"]), 34 getPrompt: () => gPrompt, 35 }; 36 37 MockRegistrar.register("@mozilla.org/prompter;1", gPromptFactory); 38 39 // Replace the UI dialog that prompts the user to pick a client certificate. 40 const gClientAuthDialogService = { 41 set certificateNameToUse(name) { 42 this._certificateNameToUse = name; 43 }, 44 45 chooseCertificate(hostname, certArray, loadContext, caNames, callback) { 46 for (let cert of certArray) { 47 if (cert.subjectName == this._certificateNameToUse) { 48 callback.certificateChosen(cert, false); 49 return; 50 } 51 } 52 callback.certificateChosen(null, false); 53 }, 54 55 QueryInterface: ChromeUtils.generateQI([Ci.nsIClientAuthDialogService]), 56 }; 57 58 MockRegistrar.register( 59 "@mozilla.org/security/ClientAuthDialogService;1", 60 gClientAuthDialogService 61 ); 62 63 function run_test() { 64 let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile); 65 libraryFile.append("pkcs11testmodule"); 66 libraryFile.append(ctypes.libraryName("pkcs11testmodule")); 67 loadPKCS11Module(libraryFile, "PKCS11 Test Module", true); 68 69 Services.prefs.setCharPref( 70 "network.dns.localDomains", 71 "requireclientauth.example.com" 72 ); 73 74 add_tls_server_setup("BadCertAndPinningServer", "bad_certs"); 75 add_test(function set_up_rsa_client_certificate() { 76 gClientAuthDialogService.certificateNameToUse = "CN=client cert rsa"; 77 run_next_test(); 78 }); 79 add_connection_test("requireclientauth.example.com", PRErrorCodeSuccess); 80 add_test(function set_up_ecdsa_client_certificate() { 81 gClientAuthDialogService.certificateNameToUse = "CN=client cert ecdsa"; 82 run_next_test(); 83 }); 84 add_connection_test("requireclientauth.example.com", PRErrorCodeSuccess); 85 86 // The test module currently has a slot that uses a protected authentication 87 // path (i.e., when Firefox wants to authenticate to it, it opens a dialog 88 // that says "okay, authenticate to your token by using an external keypad or 89 // something" and waits for that to happen). For some reason, if this 90 // authentication happens as a result of the socket thread looking for client 91 // auth certificates, it results in an assertion failure ("Assertion 92 // failure: mSleep == AWAKE") in profiler_thread_sleep(). This probably has 93 // something to do with the fact that the socket thread is synchronously 94 // waiting on the main thread, which is spinning a nested event loop (which 95 // tends to cause problems like this). 96 // Since this is an uncommon configuration and since this issue hasn't been 97 // reproduced outside of this test infrastructure, this works around it for 98 // the time being by authenticating to all tokens on the main thread so that 99 // the socket thread doesn't have to. 100 gCertDB.getCerts(); 101 102 run_next_test(); 103 }