1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,192 @@ 1.4 +// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 +// This Source Code Form is subject to the terms of the Mozilla Public 1.6 +// License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.8 +"use strict"; 1.9 + 1.10 +// In which we connect to a number of domains (as faked by a server running 1.11 +// locally) with and without OCSP stapling enabled to determine that good 1.12 +// things happen and bad things don't. 1.13 + 1.14 +let gExpectOCSPRequest; 1.15 + 1.16 +function add_ocsp_test(aHost, aExpectedResult, aStaplingEnabled) { 1.17 + add_connection_test(aHost, aExpectedResult, 1.18 + function() { 1.19 + gExpectOCSPRequest = !aStaplingEnabled; 1.20 + clearOCSPCache(); 1.21 + clearSessionCache(); 1.22 + Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", 1.23 + aStaplingEnabled); 1.24 + }); 1.25 +} 1.26 + 1.27 +function add_tests_in_mode(useMozillaPKIX, certDB, otherTestCA) { 1.28 + add_test(function () { 1.29 + Services.prefs.setBoolPref("security.use_mozillapkix_verification", 1.30 + useMozillaPKIX); 1.31 + run_next_test(); 1.32 + }); 1.33 + 1.34 + // In the absence of OCSP stapling, these should actually all work. 1.35 + add_ocsp_test("ocsp-stapling-good.example.com", Cr.NS_OK, false); 1.36 + add_ocsp_test("ocsp-stapling-revoked.example.com", Cr.NS_OK, false); 1.37 + add_ocsp_test("ocsp-stapling-good-other-ca.example.com", Cr.NS_OK, false); 1.38 + add_ocsp_test("ocsp-stapling-malformed.example.com", Cr.NS_OK, false); 1.39 + add_ocsp_test("ocsp-stapling-srverr.example.com", Cr.NS_OK, false); 1.40 + add_ocsp_test("ocsp-stapling-trylater.example.com", Cr.NS_OK, false); 1.41 + add_ocsp_test("ocsp-stapling-needssig.example.com", Cr.NS_OK, false); 1.42 + add_ocsp_test("ocsp-stapling-unauthorized.example.com", Cr.NS_OK, false); 1.43 + add_ocsp_test("ocsp-stapling-unknown.example.com", Cr.NS_OK, false); 1.44 + add_ocsp_test("ocsp-stapling-good-other.example.com", Cr.NS_OK, false); 1.45 + add_ocsp_test("ocsp-stapling-none.example.com", Cr.NS_OK, false); 1.46 + add_ocsp_test("ocsp-stapling-expired.example.com", Cr.NS_OK, false); 1.47 + add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com", Cr.NS_OK, false); 1.48 + add_ocsp_test("ocsp-stapling-skip-responseBytes.example.com", Cr.NS_OK, false); 1.49 + add_ocsp_test("ocsp-stapling-critical-extension.example.com", Cr.NS_OK, false); 1.50 + add_ocsp_test("ocsp-stapling-noncritical-extension.example.com", Cr.NS_OK, false); 1.51 + add_ocsp_test("ocsp-stapling-empty-extensions.example.com", Cr.NS_OK, false); 1.52 + 1.53 + // Now test OCSP stapling 1.54 + // The following error codes are defined in security/nss/lib/util/SECerrs.h 1.55 + 1.56 + add_ocsp_test("ocsp-stapling-good.example.com", Cr.NS_OK, true); 1.57 + 1.58 + add_ocsp_test("ocsp-stapling-revoked.example.com", 1.59 + getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE), true); 1.60 + 1.61 + // SEC_ERROR_OCSP_INVALID_SIGNING_CERT vs SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE 1.62 + // depends on whether the CA that signed the response is a trusted CA 1.63 + // (but only with the classic implementation - mozilla::pkix always 1.64 + // results in the error SEC_ERROR_OCSP_INVALID_SIGNING_CERT). 1.65 + 1.66 + // This stapled response is from a CA that is untrusted and did not issue 1.67 + // the server's certificate. 1.68 + add_test(function() { 1.69 + certDB.setCertTrust(otherTestCA, Ci.nsIX509Cert.CA_CERT, 1.70 + Ci.nsIX509CertDB.UNTRUSTED); 1.71 + run_next_test(); 1.72 + }); 1.73 + add_ocsp_test("ocsp-stapling-good-other-ca.example.com", 1.74 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.75 + 1.76 + // The stapled response is from a CA that is trusted but did not issue the 1.77 + // server's certificate. 1.78 + add_test(function() { 1.79 + certDB.setCertTrust(otherTestCA, Ci.nsIX509Cert.CA_CERT, 1.80 + Ci.nsIX509CertDB.TRUSTED_SSL); 1.81 + run_next_test(); 1.82 + }); 1.83 + // TODO(bug 979055): When using ByName instead of ByKey, the error here is 1.84 + // SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE. We should be testing both cases. 1.85 + add_ocsp_test("ocsp-stapling-good-other-ca.example.com", 1.86 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), 1.87 + true); 1.88 + 1.89 + // TODO: Test the case where the signing cert can't be found at all, which 1.90 + // will result in SEC_ERROR_BAD_DATABASE in the NSS classic case. 1.91 + 1.92 + add_ocsp_test("ocsp-stapling-malformed.example.com", 1.93 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_REQUEST), true); 1.94 + add_ocsp_test("ocsp-stapling-srverr.example.com", 1.95 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_SERVER_ERROR), true); 1.96 + add_ocsp_test("ocsp-stapling-trylater.example.com", 1.97 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_TRY_SERVER_LATER), true); 1.98 + add_ocsp_test("ocsp-stapling-needssig.example.com", 1.99 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG), true); 1.100 + add_ocsp_test("ocsp-stapling-unauthorized.example.com", 1.101 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST), 1.102 + true); 1.103 + add_ocsp_test("ocsp-stapling-unknown.example.com", 1.104 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT), true); 1.105 + add_ocsp_test("ocsp-stapling-good-other.example.com", 1.106 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT), true); 1.107 + // If the server doesn't staple an OCSP response, we continue as normal 1.108 + // (this means that even though stapling is enabled, we expect an OCSP 1.109 + // request). 1.110 + add_connection_test("ocsp-stapling-none.example.com", Cr.NS_OK, 1.111 + function() { 1.112 + gExpectOCSPRequest = true; 1.113 + clearOCSPCache(); 1.114 + clearSessionCache(); 1.115 + Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true); 1.116 + } 1.117 + ); 1.118 + add_ocsp_test("ocsp-stapling-empty.example.com", 1.119 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_RESPONSE), true); 1.120 + 1.121 + // TODO(bug 979070): NSS can't handle this yet. 1.122 + if (useMozillaPKIX) { 1.123 + add_ocsp_test("ocsp-stapling-skip-responseBytes.example.com", 1.124 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_MALFORMED_RESPONSE), true); 1.125 + } 1.126 + 1.127 + add_ocsp_test("ocsp-stapling-critical-extension.example.com", 1.128 + useMozillaPKIX 1.129 + ? getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION) 1.130 + : Cr.NS_OK, // TODO(bug 987426): NSS doesn't handle unknown critical extensions 1.131 + true); 1.132 + add_ocsp_test("ocsp-stapling-noncritical-extension.example.com", Cr.NS_OK, true); 1.133 + // TODO(bug 997994): Disallow empty Extensions in responses 1.134 + add_ocsp_test("ocsp-stapling-empty-extensions.example.com", Cr.NS_OK, true); 1.135 + 1.136 + add_ocsp_test("ocsp-stapling-delegated-included.example.com", Cr.NS_OK, true); 1.137 + add_ocsp_test("ocsp-stapling-delegated-included-last.example.com", Cr.NS_OK, true); 1.138 + add_ocsp_test("ocsp-stapling-delegated-missing.example.com", 1.139 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.140 + add_ocsp_test("ocsp-stapling-delegated-missing-multiple.example.com", 1.141 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.142 + add_ocsp_test("ocsp-stapling-delegated-no-extKeyUsage.example.com", 1.143 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.144 + add_ocsp_test("ocsp-stapling-delegated-from-intermediate.example.com", 1.145 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.146 + add_ocsp_test("ocsp-stapling-delegated-keyUsage-crlSigning.example.com", 1.147 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.148 + add_ocsp_test("ocsp-stapling-delegated-wrong-extKeyUsage.example.com", 1.149 + getXPCOMStatusFromNSS(SEC_ERROR_OCSP_INVALID_SIGNING_CERT), true); 1.150 + 1.151 + // ocsp-stapling-expired.example.com and 1.152 + // ocsp-stapling-expired-fresh-ca.example.com are handled in 1.153 + // test_ocsp_stapling_expired.js 1.154 +} 1.155 + 1.156 +function check_ocsp_stapling_telemetry() { 1.157 + let histogram = Cc["@mozilla.org/base/telemetry;1"] 1.158 + .getService(Ci.nsITelemetry) 1.159 + .getHistogramById("SSL_OCSP_STAPLING") 1.160 + .snapshot(); 1.161 + do_check_eq(histogram.counts[0], 2 * 0); // histogram bucket 0 is unused 1.162 + do_check_eq(histogram.counts[1], 5 + 6); // 5 or 6 connections with a good response (bug 987426) 1.163 + do_check_eq(histogram.counts[2], 2 * 18); // 18 connections with no stapled resp. 1.164 + do_check_eq(histogram.counts[3], 2 * 0); // 0 connections with an expired response 1.165 + do_check_eq(histogram.counts[4], 19 + 17); // 19 or 17 connections with bad responses (bug 979070, bug 987426) 1.166 + run_next_test(); 1.167 +} 1.168 + 1.169 +function run_test() { 1.170 + do_get_profile(); 1.171 + 1.172 + let certDB = Cc["@mozilla.org/security/x509certdb;1"] 1.173 + .getService(Ci.nsIX509CertDB); 1.174 + let otherTestCAFile = do_get_file("tlsserver/other-test-ca.der", false); 1.175 + let otherTestCADER = readFile(otherTestCAFile); 1.176 + let otherTestCA = certDB.constructX509(otherTestCADER, otherTestCADER.length); 1.177 + 1.178 + let fakeOCSPResponder = new HttpServer(); 1.179 + fakeOCSPResponder.registerPrefixHandler("/", function (request, response) { 1.180 + response.setStatusLine(request.httpVersion, 500, "Internal Server Error"); 1.181 + do_check_true(gExpectOCSPRequest); 1.182 + }); 1.183 + fakeOCSPResponder.start(8080); 1.184 + 1.185 + add_tls_server_setup("OCSPStaplingServer"); 1.186 + 1.187 + add_tests_in_mode(true, certDB, otherTestCA); 1.188 + add_tests_in_mode(false, certDB, otherTestCA); 1.189 + 1.190 + add_test(function () { 1.191 + fakeOCSPResponder.stop(check_ocsp_stapling_telemetry); 1.192 + }); 1.193 + 1.194 + run_next_test(); 1.195 +}