1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/tests/unit/test_cert_overrides.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,262 @@ 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 +// Tests the certificate overrides we allow. 1.11 +// add_cert_override_test will queue a test that does the following: 1.12 +// 1. Attempt to connect to the given host. This should fail with the 1.13 +// given error and override bits. 1.14 +// 2. Add an override for that host/port/certificate/override bits. 1.15 +// 3. Connect again. This should succeed. 1.16 + 1.17 +do_get_profile(); 1.18 +let certOverrideService = Cc["@mozilla.org/security/certoverride;1"] 1.19 + .getService(Ci.nsICertOverrideService); 1.20 + 1.21 +function add_cert_override(aHost, aExpectedBits, aSecurityInfo) { 1.22 + let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider) 1.23 + .SSLStatus; 1.24 + let bits = 1.25 + (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) | 1.26 + (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) | 1.27 + (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0); 1.28 + do_check_eq(bits, aExpectedBits); 1.29 + let cert = sslstatus.serverCert; 1.30 + certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits, 1.31 + true); 1.32 +} 1.33 + 1.34 +function add_cert_override_test(aHost, aExpectedBits, aExpectedError) { 1.35 + add_connection_test(aHost, aExpectedError, null, 1.36 + add_cert_override.bind(this, aHost, aExpectedBits)); 1.37 + add_connection_test(aHost, Cr.NS_OK); 1.38 +} 1.39 + 1.40 +function add_non_overridable_test(aHost, aExpectedError) { 1.41 + add_connection_test( 1.42 + aHost, getXPCOMStatusFromNSS(aExpectedError), null, 1.43 + function (securityInfo) { 1.44 + // bug 754369 - no SSLStatus probably means this is a non-overridable 1.45 + // error, which is what we're testing (although it would be best to test 1.46 + // this directly). 1.47 + securityInfo.QueryInterface(Ci.nsISSLStatusProvider); 1.48 + do_check_eq(securityInfo.SSLStatus, null); 1.49 + }); 1.50 +} 1.51 + 1.52 +function check_telemetry() { 1.53 + let histogram = Cc["@mozilla.org/base/telemetry;1"] 1.54 + .getService(Ci.nsITelemetry) 1.55 + .getHistogramById("SSL_CERT_ERROR_OVERRIDES") 1.56 + .snapshot(); 1.57 + do_check_eq(histogram.counts[ 0], 0); 1.58 + do_check_eq(histogram.counts[ 2], 8 + 1); // SEC_ERROR_UNKNOWN_ISSUER 1.59 + do_check_eq(histogram.counts[ 3], 2); // SEC_ERROR_CA_CERT_INVALID 1.60 + do_check_eq(histogram.counts[ 4], 0 + 5); // SEC_ERROR_UNTRUSTED_ISSUER 1.61 + do_check_eq(histogram.counts[ 5], 0 + 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE 1.62 + do_check_eq(histogram.counts[ 6], 0 + 1); // SEC_ERROR_UNTRUSTED_CERT 1.63 + do_check_eq(histogram.counts[ 7], 0 + 1); // SEC_ERROR_INADEQUATE_KEY_USAGE 1.64 + do_check_eq(histogram.counts[ 8], 2 + 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED 1.65 + do_check_eq(histogram.counts[ 9], 4 + 4); // SSL_ERROR_BAD_CERT_DOMAIN 1.66 + do_check_eq(histogram.counts[10], 5 + 5); // SEC_ERROR_EXPIRED_CERTIFICATE 1.67 + run_next_test(); 1.68 +} 1.69 + 1.70 +function run_test() { 1.71 + add_tls_server_setup("BadCertServer"); 1.72 + 1.73 + let fakeOCSPResponder = new HttpServer(); 1.74 + fakeOCSPResponder.registerPrefixHandler("/", function (request, response) { 1.75 + response.setStatusLine(request.httpVersion, 500, "Internal Server Error"); 1.76 + }); 1.77 + fakeOCSPResponder.start(8080); 1.78 + 1.79 + add_tests_in_mode(true); 1.80 + add_tests_in_mode(false); 1.81 + 1.82 + add_test(function () { 1.83 + fakeOCSPResponder.stop(check_telemetry); 1.84 + }); 1.85 + 1.86 + run_next_test(); 1.87 +} 1.88 + 1.89 +function add_tests_in_mode(useMozillaPKIX) { 1.90 + add_test(function () { 1.91 + Services.prefs.setBoolPref("security.use_mozillapkix_verification", 1.92 + useMozillaPKIX); 1.93 + run_next_test(); 1.94 + }); 1.95 + 1.96 + add_simple_tests(useMozillaPKIX); 1.97 + add_combo_tests(useMozillaPKIX); 1.98 + add_distrust_tests(useMozillaPKIX); 1.99 + 1.100 + add_test(function () { 1.101 + certOverrideService.clearValidityOverride("all:temporary-certificates", 0); 1.102 + run_next_test(); 1.103 + }); 1.104 +} 1.105 + 1.106 +function add_simple_tests(useMozillaPKIX) { 1.107 + add_cert_override_test("expired.example.com", 1.108 + Ci.nsICertOverrideService.ERROR_TIME, 1.109 + getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_CERTIFICATE)); 1.110 + if (useMozillaPKIX) { 1.111 + add_cert_override_test("selfsigned.example.com", 1.112 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.113 + getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER)); 1.114 + } else { 1.115 + add_cert_override_test("selfsigned.example.com", 1.116 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.117 + getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID)); 1.118 + } 1.119 + add_cert_override_test("unknownissuer.example.com", 1.120 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.121 + getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER)); 1.122 + add_cert_override_test("expiredissuer.example.com", 1.123 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.124 + getXPCOMStatusFromNSS( 1.125 + useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER 1.126 + : SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE)); 1.127 + add_cert_override_test("md5signature.example.com", 1.128 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.129 + getXPCOMStatusFromNSS( 1.130 + SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)); 1.131 + add_cert_override_test("mismatch.example.com", 1.132 + Ci.nsICertOverrideService.ERROR_MISMATCH, 1.133 + getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN)); 1.134 + 1.135 + // A Microsoft IIS utility generates self-signed certificates with 1.136 + // properties similar to the one this "host" will present (see 1.137 + // tlsserver/generate_certs.sh). 1.138 + // One of the errors classic verification collects is that this 1.139 + // certificate has an inadequate key usage to sign a certificate 1.140 + // (i.e. itself). As a result, to be able to override this, 1.141 + // SEC_ERROR_INADEQUATE_KEY_USAGE must be overridable (although, 1.142 + // confusingly, this isn't the main error reported). 1.143 + // mozilla::pkix just says this certificate's issuer is unknown. 1.144 + if (useMozillaPKIX) { 1.145 + add_cert_override_test("selfsigned-inadequateEKU.example.com", 1.146 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.147 + getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER)); 1.148 + } else { 1.149 + add_cert_override_test("selfsigned-inadequateEKU.example.com", 1.150 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.151 + getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID)); 1.152 + } 1.153 + 1.154 + // SEC_ERROR_INADEQUATE_KEY_USAGE is overridable in general for 1.155 + // classic verification, but not for mozilla::pkix verification. 1.156 + if (useMozillaPKIX) { 1.157 + add_non_overridable_test("inadequatekeyusage.example.com", 1.158 + SEC_ERROR_INADEQUATE_KEY_USAGE); 1.159 + } else { 1.160 + add_cert_override_test("inadequatekeyusage.example.com", 1.161 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.162 + getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE)); 1.163 + } 1.164 + 1.165 + // Bug 990603: Apache documentation has recommended generating a self-signed 1.166 + // test certificate with basic constraints: CA:true. For compatibility, this 1.167 + // is a scenario in which an override is allowed. 1.168 + add_cert_override_test("self-signed-end-entity-with-cA-true.example.com", 1.169 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.170 + getXPCOMStatusFromNSS( 1.171 + useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER 1.172 + : SEC_ERROR_UNTRUSTED_ISSUER)); 1.173 +} 1.174 + 1.175 +function add_combo_tests(useMozillaPKIX) { 1.176 + // Note that "untrusted" here really is "unknown issuer" in the 1.177 + // mozilla::pkix case. 1.178 + 1.179 + add_cert_override_test("mismatch-expired.example.com", 1.180 + Ci.nsICertOverrideService.ERROR_MISMATCH | 1.181 + Ci.nsICertOverrideService.ERROR_TIME, 1.182 + getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN)); 1.183 + add_cert_override_test("mismatch-untrusted.example.com", 1.184 + Ci.nsICertOverrideService.ERROR_MISMATCH | 1.185 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, 1.186 + getXPCOMStatusFromNSS( 1.187 + useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER 1.188 + : SEC_ERROR_UNTRUSTED_ISSUER)); 1.189 + add_cert_override_test("untrusted-expired.example.com", 1.190 + Ci.nsICertOverrideService.ERROR_UNTRUSTED | 1.191 + Ci.nsICertOverrideService.ERROR_TIME, 1.192 + getXPCOMStatusFromNSS( 1.193 + useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER 1.194 + : SEC_ERROR_UNTRUSTED_ISSUER)); 1.195 + add_cert_override_test("mismatch-untrusted-expired.example.com", 1.196 + Ci.nsICertOverrideService.ERROR_MISMATCH | 1.197 + Ci.nsICertOverrideService.ERROR_UNTRUSTED | 1.198 + Ci.nsICertOverrideService.ERROR_TIME, 1.199 + getXPCOMStatusFromNSS( 1.200 + useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER 1.201 + : SEC_ERROR_UNTRUSTED_ISSUER)); 1.202 + 1.203 + add_cert_override_test("md5signature-expired.example.com", 1.204 + Ci.nsICertOverrideService.ERROR_UNTRUSTED | 1.205 + Ci.nsICertOverrideService.ERROR_TIME, 1.206 + getXPCOMStatusFromNSS( 1.207 + SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)); 1.208 +} 1.209 + 1.210 +function add_distrust_tests(useMozillaPKIX) { 1.211 + // Before we specifically distrust this certificate, it should be trusted. 1.212 + add_connection_test("untrusted.example.com", Cr.NS_OK); 1.213 + 1.214 + // XXX(Bug 975777): Active distrust is an overridable error when NSS-based 1.215 + // verification is used. 1.216 + add_distrust_override_test("tlsserver/default-ee.der", 1.217 + "untrusted.example.com", 1.218 + getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT), 1.219 + useMozillaPKIX 1.220 + ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT) 1.221 + : Cr.NS_OK); 1.222 + 1.223 + // XXX(Bug 975777): Active distrust is an overridable error when NSS-based 1.224 + // verification is used. 1.225 + add_distrust_override_test("tlsserver/other-test-ca.der", 1.226 + "untrustedissuer.example.com", 1.227 + getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER), 1.228 + useMozillaPKIX 1.229 + ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER) 1.230 + : Cr.NS_OK); 1.231 +} 1.232 + 1.233 +function add_distrust_override_test(certFileName, hostName, 1.234 + expectedResultBefore, expectedResultAfter) { 1.235 + let certToDistrust = constructCertFromFile(certFileName); 1.236 + 1.237 + add_test(function () { 1.238 + // Add an entry to the NSS certDB that says to distrust the cert 1.239 + setCertTrust(certToDistrust, "pu,,"); 1.240 + clearSessionCache(); 1.241 + run_next_test(); 1.242 + }); 1.243 + add_connection_test(hostName, expectedResultBefore, null, 1.244 + function (securityInfo) { 1.245 + securityInfo.QueryInterface(Ci.nsISSLStatusProvider); 1.246 + // XXX(Bug 754369): SSLStatus isn't available for 1.247 + // non-overridable errors. 1.248 + if (securityInfo.SSLStatus) { 1.249 + certOverrideService.rememberValidityOverride( 1.250 + hostName, 8443, securityInfo.SSLStatus.serverCert, 1.251 + Ci.nsICertOverrideService.ERROR_UNTRUSTED, true); 1.252 + } else { 1.253 + // A missing SSLStatus probably means (due to bug 1.254 + // 754369) that the error was non-overridable, which 1.255 + // is what we're trying to test, though we'd rather 1.256 + // not test it this way. 1.257 + do_check_neq(expectedResultAfter, Cr.NS_OK); 1.258 + } 1.259 + clearSessionCache(); 1.260 + }); 1.261 + add_connection_test(hostName, expectedResultAfter, null, 1.262 + function () { 1.263 + setCertTrust(certToDistrust, "u,,"); 1.264 + }); 1.265 +}