security/manager/ssl/tests/unit/test_cert_overrides.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 // This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 // License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 5 "use strict";
michael@0 6
michael@0 7 // Tests the certificate overrides we allow.
michael@0 8 // add_cert_override_test will queue a test that does the following:
michael@0 9 // 1. Attempt to connect to the given host. This should fail with the
michael@0 10 // given error and override bits.
michael@0 11 // 2. Add an override for that host/port/certificate/override bits.
michael@0 12 // 3. Connect again. This should succeed.
michael@0 13
michael@0 14 do_get_profile();
michael@0 15 let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
michael@0 16 .getService(Ci.nsICertOverrideService);
michael@0 17
michael@0 18 function add_cert_override(aHost, aExpectedBits, aSecurityInfo) {
michael@0 19 let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
michael@0 20 .SSLStatus;
michael@0 21 let bits =
michael@0 22 (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) |
michael@0 23 (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) |
michael@0 24 (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
michael@0 25 do_check_eq(bits, aExpectedBits);
michael@0 26 let cert = sslstatus.serverCert;
michael@0 27 certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits,
michael@0 28 true);
michael@0 29 }
michael@0 30
michael@0 31 function add_cert_override_test(aHost, aExpectedBits, aExpectedError) {
michael@0 32 add_connection_test(aHost, aExpectedError, null,
michael@0 33 add_cert_override.bind(this, aHost, aExpectedBits));
michael@0 34 add_connection_test(aHost, Cr.NS_OK);
michael@0 35 }
michael@0 36
michael@0 37 function add_non_overridable_test(aHost, aExpectedError) {
michael@0 38 add_connection_test(
michael@0 39 aHost, getXPCOMStatusFromNSS(aExpectedError), null,
michael@0 40 function (securityInfo) {
michael@0 41 // bug 754369 - no SSLStatus probably means this is a non-overridable
michael@0 42 // error, which is what we're testing (although it would be best to test
michael@0 43 // this directly).
michael@0 44 securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
michael@0 45 do_check_eq(securityInfo.SSLStatus, null);
michael@0 46 });
michael@0 47 }
michael@0 48
michael@0 49 function check_telemetry() {
michael@0 50 let histogram = Cc["@mozilla.org/base/telemetry;1"]
michael@0 51 .getService(Ci.nsITelemetry)
michael@0 52 .getHistogramById("SSL_CERT_ERROR_OVERRIDES")
michael@0 53 .snapshot();
michael@0 54 do_check_eq(histogram.counts[ 0], 0);
michael@0 55 do_check_eq(histogram.counts[ 2], 8 + 1); // SEC_ERROR_UNKNOWN_ISSUER
michael@0 56 do_check_eq(histogram.counts[ 3], 2); // SEC_ERROR_CA_CERT_INVALID
michael@0 57 do_check_eq(histogram.counts[ 4], 0 + 5); // SEC_ERROR_UNTRUSTED_ISSUER
michael@0 58 do_check_eq(histogram.counts[ 5], 0 + 1); // SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
michael@0 59 do_check_eq(histogram.counts[ 6], 0 + 1); // SEC_ERROR_UNTRUSTED_CERT
michael@0 60 do_check_eq(histogram.counts[ 7], 0 + 1); // SEC_ERROR_INADEQUATE_KEY_USAGE
michael@0 61 do_check_eq(histogram.counts[ 8], 2 + 2); // SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED
michael@0 62 do_check_eq(histogram.counts[ 9], 4 + 4); // SSL_ERROR_BAD_CERT_DOMAIN
michael@0 63 do_check_eq(histogram.counts[10], 5 + 5); // SEC_ERROR_EXPIRED_CERTIFICATE
michael@0 64 run_next_test();
michael@0 65 }
michael@0 66
michael@0 67 function run_test() {
michael@0 68 add_tls_server_setup("BadCertServer");
michael@0 69
michael@0 70 let fakeOCSPResponder = new HttpServer();
michael@0 71 fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
michael@0 72 response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
michael@0 73 });
michael@0 74 fakeOCSPResponder.start(8080);
michael@0 75
michael@0 76 add_tests_in_mode(true);
michael@0 77 add_tests_in_mode(false);
michael@0 78
michael@0 79 add_test(function () {
michael@0 80 fakeOCSPResponder.stop(check_telemetry);
michael@0 81 });
michael@0 82
michael@0 83 run_next_test();
michael@0 84 }
michael@0 85
michael@0 86 function add_tests_in_mode(useMozillaPKIX) {
michael@0 87 add_test(function () {
michael@0 88 Services.prefs.setBoolPref("security.use_mozillapkix_verification",
michael@0 89 useMozillaPKIX);
michael@0 90 run_next_test();
michael@0 91 });
michael@0 92
michael@0 93 add_simple_tests(useMozillaPKIX);
michael@0 94 add_combo_tests(useMozillaPKIX);
michael@0 95 add_distrust_tests(useMozillaPKIX);
michael@0 96
michael@0 97 add_test(function () {
michael@0 98 certOverrideService.clearValidityOverride("all:temporary-certificates", 0);
michael@0 99 run_next_test();
michael@0 100 });
michael@0 101 }
michael@0 102
michael@0 103 function add_simple_tests(useMozillaPKIX) {
michael@0 104 add_cert_override_test("expired.example.com",
michael@0 105 Ci.nsICertOverrideService.ERROR_TIME,
michael@0 106 getXPCOMStatusFromNSS(SEC_ERROR_EXPIRED_CERTIFICATE));
michael@0 107 if (useMozillaPKIX) {
michael@0 108 add_cert_override_test("selfsigned.example.com",
michael@0 109 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 110 getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
michael@0 111 } else {
michael@0 112 add_cert_override_test("selfsigned.example.com",
michael@0 113 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 114 getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID));
michael@0 115 }
michael@0 116 add_cert_override_test("unknownissuer.example.com",
michael@0 117 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 118 getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
michael@0 119 add_cert_override_test("expiredissuer.example.com",
michael@0 120 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 121 getXPCOMStatusFromNSS(
michael@0 122 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 123 : SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE));
michael@0 124 add_cert_override_test("md5signature.example.com",
michael@0 125 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 126 getXPCOMStatusFromNSS(
michael@0 127 SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
michael@0 128 add_cert_override_test("mismatch.example.com",
michael@0 129 Ci.nsICertOverrideService.ERROR_MISMATCH,
michael@0 130 getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
michael@0 131
michael@0 132 // A Microsoft IIS utility generates self-signed certificates with
michael@0 133 // properties similar to the one this "host" will present (see
michael@0 134 // tlsserver/generate_certs.sh).
michael@0 135 // One of the errors classic verification collects is that this
michael@0 136 // certificate has an inadequate key usage to sign a certificate
michael@0 137 // (i.e. itself). As a result, to be able to override this,
michael@0 138 // SEC_ERROR_INADEQUATE_KEY_USAGE must be overridable (although,
michael@0 139 // confusingly, this isn't the main error reported).
michael@0 140 // mozilla::pkix just says this certificate's issuer is unknown.
michael@0 141 if (useMozillaPKIX) {
michael@0 142 add_cert_override_test("selfsigned-inadequateEKU.example.com",
michael@0 143 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 144 getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
michael@0 145 } else {
michael@0 146 add_cert_override_test("selfsigned-inadequateEKU.example.com",
michael@0 147 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 148 getXPCOMStatusFromNSS(SEC_ERROR_CA_CERT_INVALID));
michael@0 149 }
michael@0 150
michael@0 151 // SEC_ERROR_INADEQUATE_KEY_USAGE is overridable in general for
michael@0 152 // classic verification, but not for mozilla::pkix verification.
michael@0 153 if (useMozillaPKIX) {
michael@0 154 add_non_overridable_test("inadequatekeyusage.example.com",
michael@0 155 SEC_ERROR_INADEQUATE_KEY_USAGE);
michael@0 156 } else {
michael@0 157 add_cert_override_test("inadequatekeyusage.example.com",
michael@0 158 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 159 getXPCOMStatusFromNSS(SEC_ERROR_INADEQUATE_KEY_USAGE));
michael@0 160 }
michael@0 161
michael@0 162 // Bug 990603: Apache documentation has recommended generating a self-signed
michael@0 163 // test certificate with basic constraints: CA:true. For compatibility, this
michael@0 164 // is a scenario in which an override is allowed.
michael@0 165 add_cert_override_test("self-signed-end-entity-with-cA-true.example.com",
michael@0 166 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 167 getXPCOMStatusFromNSS(
michael@0 168 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 169 : SEC_ERROR_UNTRUSTED_ISSUER));
michael@0 170 }
michael@0 171
michael@0 172 function add_combo_tests(useMozillaPKIX) {
michael@0 173 // Note that "untrusted" here really is "unknown issuer" in the
michael@0 174 // mozilla::pkix case.
michael@0 175
michael@0 176 add_cert_override_test("mismatch-expired.example.com",
michael@0 177 Ci.nsICertOverrideService.ERROR_MISMATCH |
michael@0 178 Ci.nsICertOverrideService.ERROR_TIME,
michael@0 179 getXPCOMStatusFromNSS(SSL_ERROR_BAD_CERT_DOMAIN));
michael@0 180 add_cert_override_test("mismatch-untrusted.example.com",
michael@0 181 Ci.nsICertOverrideService.ERROR_MISMATCH |
michael@0 182 Ci.nsICertOverrideService.ERROR_UNTRUSTED,
michael@0 183 getXPCOMStatusFromNSS(
michael@0 184 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 185 : SEC_ERROR_UNTRUSTED_ISSUER));
michael@0 186 add_cert_override_test("untrusted-expired.example.com",
michael@0 187 Ci.nsICertOverrideService.ERROR_UNTRUSTED |
michael@0 188 Ci.nsICertOverrideService.ERROR_TIME,
michael@0 189 getXPCOMStatusFromNSS(
michael@0 190 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 191 : SEC_ERROR_UNTRUSTED_ISSUER));
michael@0 192 add_cert_override_test("mismatch-untrusted-expired.example.com",
michael@0 193 Ci.nsICertOverrideService.ERROR_MISMATCH |
michael@0 194 Ci.nsICertOverrideService.ERROR_UNTRUSTED |
michael@0 195 Ci.nsICertOverrideService.ERROR_TIME,
michael@0 196 getXPCOMStatusFromNSS(
michael@0 197 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 198 : SEC_ERROR_UNTRUSTED_ISSUER));
michael@0 199
michael@0 200 add_cert_override_test("md5signature-expired.example.com",
michael@0 201 Ci.nsICertOverrideService.ERROR_UNTRUSTED |
michael@0 202 Ci.nsICertOverrideService.ERROR_TIME,
michael@0 203 getXPCOMStatusFromNSS(
michael@0 204 SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED));
michael@0 205 }
michael@0 206
michael@0 207 function add_distrust_tests(useMozillaPKIX) {
michael@0 208 // Before we specifically distrust this certificate, it should be trusted.
michael@0 209 add_connection_test("untrusted.example.com", Cr.NS_OK);
michael@0 210
michael@0 211 // XXX(Bug 975777): Active distrust is an overridable error when NSS-based
michael@0 212 // verification is used.
michael@0 213 add_distrust_override_test("tlsserver/default-ee.der",
michael@0 214 "untrusted.example.com",
michael@0 215 getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT),
michael@0 216 useMozillaPKIX
michael@0 217 ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_CERT)
michael@0 218 : Cr.NS_OK);
michael@0 219
michael@0 220 // XXX(Bug 975777): Active distrust is an overridable error when NSS-based
michael@0 221 // verification is used.
michael@0 222 add_distrust_override_test("tlsserver/other-test-ca.der",
michael@0 223 "untrustedissuer.example.com",
michael@0 224 getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER),
michael@0 225 useMozillaPKIX
michael@0 226 ? getXPCOMStatusFromNSS(SEC_ERROR_UNTRUSTED_ISSUER)
michael@0 227 : Cr.NS_OK);
michael@0 228 }
michael@0 229
michael@0 230 function add_distrust_override_test(certFileName, hostName,
michael@0 231 expectedResultBefore, expectedResultAfter) {
michael@0 232 let certToDistrust = constructCertFromFile(certFileName);
michael@0 233
michael@0 234 add_test(function () {
michael@0 235 // Add an entry to the NSS certDB that says to distrust the cert
michael@0 236 setCertTrust(certToDistrust, "pu,,");
michael@0 237 clearSessionCache();
michael@0 238 run_next_test();
michael@0 239 });
michael@0 240 add_connection_test(hostName, expectedResultBefore, null,
michael@0 241 function (securityInfo) {
michael@0 242 securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
michael@0 243 // XXX(Bug 754369): SSLStatus isn't available for
michael@0 244 // non-overridable errors.
michael@0 245 if (securityInfo.SSLStatus) {
michael@0 246 certOverrideService.rememberValidityOverride(
michael@0 247 hostName, 8443, securityInfo.SSLStatus.serverCert,
michael@0 248 Ci.nsICertOverrideService.ERROR_UNTRUSTED, true);
michael@0 249 } else {
michael@0 250 // A missing SSLStatus probably means (due to bug
michael@0 251 // 754369) that the error was non-overridable, which
michael@0 252 // is what we're trying to test, though we'd rather
michael@0 253 // not test it this way.
michael@0 254 do_check_neq(expectedResultAfter, Cr.NS_OK);
michael@0 255 }
michael@0 256 clearSessionCache();
michael@0 257 });
michael@0 258 add_connection_test(hostName, expectedResultAfter, null,
michael@0 259 function () {
michael@0 260 setCertTrust(certToDistrust, "u,,");
michael@0 261 });
michael@0 262 }

mercurial