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