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/.
6 "use strict";
8 // XXX: The isDebugBuild tests you see are here because the test EV root is
9 // only enabled for EV in debug builds, as a security measure. An ugly hack.
11 do_get_profile(); // must be called before getting nsIX509CertDB
12 const certdb = Cc["@mozilla.org/security/x509certdb;1"]
13 .getService(Ci.nsIX509CertDB);
15 const evrootnick = "XPCShell EV Testing (untrustworthy) CA - Mozilla - " +
16 "EV debug test CA";
18 // This is the list of certificates needed for the test
19 // The certificates prefixed by 'int-' are intermediates
20 let certList = [
21 // Test for successful EV validation
22 'int-ev-valid',
23 'ev-valid',
24 'ev-valid-anypolicy-int',
25 'int-ev-valid-anypolicy-int',
26 'no-ocsp-url-cert', // a cert signed by the EV auth that has no OCSP url
27 // but that contains a valid CRLDP.
29 // Testing a root that looks like EV but is not EV enabled
30 'int-non-ev-root',
31 'non-ev-root',
32 ]
34 function load_ca(ca_name) {
35 var ca_filename = ca_name + ".der";
36 addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
37 }
39 const SERVER_PORT = 8888;
41 function failingOCSPResponder() {
42 return getFailingHttpServer(SERVER_PORT,
43 ["www.example.com", "crl.example.com"]);
44 }
46 function start_ocsp_responder(expectedCertNames) {
47 let expectedPaths = expectedCertNames.slice();
48 return startOCSPResponder(SERVER_PORT, "www.example.com", ["crl.example.com"],
49 "test_ev_certs", expectedCertNames, expectedPaths);
50 }
52 function check_cert_err(cert_name, expected_error) {
53 let cert = certdb.findCertByNickname(null, cert_name);
54 let hasEVPolicy = {};
55 let verifiedChain = {};
56 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
57 NO_FLAGS, verifiedChain, hasEVPolicy);
58 do_check_eq(error, expected_error);
59 }
62 function check_ee_for_ev(cert_name, expected_ev) {
63 let cert = certdb.findCertByNickname(null, cert_name);
64 let hasEVPolicy = {};
65 let verifiedChain = {};
66 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
67 NO_FLAGS, verifiedChain, hasEVPolicy);
68 do_check_eq(hasEVPolicy.value, expected_ev);
69 do_check_eq(0, error);
70 }
72 function run_test() {
73 for (let i = 0 ; i < certList.length; i++) {
74 let cert_filename = certList[i] + ".der";
75 addCertFromFile(certdb, "test_ev_certs/" + cert_filename, ',,');
76 }
77 load_ca("evroot");
78 load_ca("non-evroot-ca");
80 // setup and start ocsp responder
81 Services.prefs.setCharPref("network.dns.localDomains",
82 'www.example.com, crl.example.com');
83 add_tests_in_mode(true);
84 add_tests_in_mode(false);
85 run_next_test();
86 }
88 function add_tests_in_mode(useMozillaPKIX)
89 {
90 add_test(function () {
91 Services.prefs.setBoolPref("security.use_mozillapkix_verification",
92 useMozillaPKIX);
93 run_next_test();
94 });
96 add_test(function () {
97 clearOCSPCache();
98 let ocspResponder = start_ocsp_responder(
99 isDebugBuild ? ["int-ev-valid", "ev-valid"]
100 : ["ev-valid"]);
101 check_ee_for_ev("ev-valid", isDebugBuild);
102 ocspResponder.stop(run_next_test);
103 });
106 add_test(function () {
107 clearOCSPCache();
109 let ocspResponder = start_ocsp_responder(
110 isDebugBuild ? ["int-ev-valid-anypolicy-int", "ev-valid-anypolicy-int"]
111 : ["ev-valid-anypolicy-int"]);
112 check_ee_for_ev("ev-valid-anypolicy-int", isDebugBuild);
113 ocspResponder.stop(run_next_test);
114 });
116 add_test(function() {
117 clearOCSPCache();
118 let ocspResponder = start_ocsp_responder(["non-ev-root"]);
119 check_ee_for_ev("non-ev-root", false);
120 ocspResponder.stop(run_next_test);
121 });
123 add_test(function() {
124 clearOCSPCache();
125 // libpkix will attempt to validate the intermediate, which does have an
126 // OCSP URL.
127 let ocspResponder = isDebugBuild ? start_ocsp_responder(["int-ev-valid"])
128 : failingOCSPResponder();
129 check_ee_for_ev("no-ocsp-url-cert", false);
130 ocspResponder.stop(run_next_test);
131 });
133 // bug 917380: Chcek that an untrusted EV root is untrusted.
134 const nsIX509Cert = Ci.nsIX509Cert;
135 add_test(function() {
136 let evRootCA = certdb.findCertByNickname(null, evrootnick);
137 certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT, 0);
139 clearOCSPCache();
140 let ocspResponder = failingOCSPResponder();
141 check_cert_err("ev-valid",
142 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
143 : SEC_ERROR_UNTRUSTED_ISSUER);
144 ocspResponder.stop(run_next_test);
145 });
147 // bug 917380: Chcek that a trusted EV root is trusted after disabling and
148 // re-enabling trust.
149 add_test(function() {
150 let evRootCA = certdb.findCertByNickname(null, evrootnick);
151 certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT,
152 Ci.nsIX509CertDB.TRUSTED_SSL |
153 Ci.nsIX509CertDB.TRUSTED_EMAIL |
154 Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
156 clearOCSPCache();
157 let ocspResponder = start_ocsp_responder(
158 isDebugBuild ? ["int-ev-valid", "ev-valid"]
159 : ["ev-valid"]);
160 check_ee_for_ev("ev-valid", isDebugBuild);
161 ocspResponder.stop(run_next_test);
162 });
164 add_test(function () {
165 check_no_ocsp_requests("ev-valid",
166 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
167 : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
168 : SEC_ERROR_EXTENSION_NOT_FOUND));
169 });
171 add_test(function () {
172 check_no_ocsp_requests("non-ev-root",
173 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
174 : (isDebugBuild ? SEC_ERROR_UNTRUSTED_ISSUER
175 : SEC_ERROR_EXTENSION_NOT_FOUND));
176 });
178 add_test(function () {
179 check_no_ocsp_requests("no-ocsp-url-cert",
180 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
181 : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
182 : SEC_ERROR_EXTENSION_NOT_FOUND));
183 });
186 // Test the EV continues to work with flags after successful EV verification
187 add_test(function () {
188 clearOCSPCache();
189 let ocspResponder = start_ocsp_responder(
190 isDebugBuild ? ["int-ev-valid", "ev-valid"]
191 : ["ev-valid"]);
192 check_ee_for_ev("ev-valid", isDebugBuild);
193 ocspResponder.stop(function () {
194 // without net it must be able to EV verify
195 let failingOcspResponder = failingOCSPResponder();
196 let cert = certdb.findCertByNickname(null, "ev-valid");
197 let hasEVPolicy = {};
198 let verifiedChain = {};
199 let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
200 Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
202 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
203 flags, verifiedChain, hasEVPolicy);
204 do_check_eq(hasEVPolicy.value, isDebugBuild);
205 do_check_eq(error,
206 isDebugBuild ? 0
207 : (useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
208 : SEC_ERROR_EXTENSION_NOT_FOUND));
209 failingOcspResponder.stop(run_next_test);
210 });
211 });
213 // Bug 991815 old but valid intermediates are OK
214 add_test(function () {
215 clearOCSPCache();
216 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
217 "test_ev_certs",
218 isDebugBuild ? ["int-ev-valid", "ev-valid"]
219 : ["ev-valid"],
220 [], [],
221 isDebugBuild ? ["longvalidityalmostold", "good"]
222 : ["good"]);
223 check_ee_for_ev("ev-valid", isDebugBuild);
224 ocspResponder.stop(run_next_test);
225 });
227 // Bug 991815 old but valid end-entities are NOT OK for EV
228 // Unfortunatelly because of soft-fail we consider these OK for DV
229 // libpkix does not enforce the age restriction and thus EV is valid
230 add_test(function () {
231 clearOCSPCache();
232 // Since Mozilla::pkix does not consider the old amost invalid OCSP
233 // response valid, it does not cache the old response and thus
234 // makes a separate request for DV
235 let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
236 let debugResponseArray = ["good", "longvalidityalmostold",
237 "longvalidityalmostold"];
238 if (!useMozillaPKIX) {
239 debugCertNickArray = ["int-ev-valid", "ev-valid"];
240 debugResponseArray = ["good", "longvalidityalmostold"];
241 }
242 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
243 "test_ev_certs",
244 isDebugBuild ? debugCertNickArray : ["ev-valid"],
245 [], [],
246 isDebugBuild ? debugResponseArray
247 : ["longvalidityalmostold"]);
248 check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
249 ocspResponder.stop(run_next_test);
250 });
252 // Bug 991815 Valid but Ancient (almost two year old) responses are Not OK for
253 // EV (still OK for soft fail DV)
254 add_test(function () {
255 clearOCSPCache();
256 let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
257 let debugResponseArray = ["good", "ancientstillvalid",
258 "ancientstillvalid"];
259 if (!useMozillaPKIX) {
260 debugCertNickArray = ["int-ev-valid", "ev-valid"];
261 debugResponseArray = ["good", "ancientstillvalid"];
262 }
263 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
264 "test_ev_certs",
265 isDebugBuild ? debugCertNickArray : ["ev-valid"],
266 [], [],
267 isDebugBuild ? debugResponseArray
268 : ["ancientstillvalid"]);
269 check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
270 ocspResponder.stop(run_next_test);
271 });
272 }
274 // bug 950240: add FLAG_MUST_BE_EV to CertVerifier::VerifyCert
275 // to prevent spurious OCSP requests that race with OCSP stapling.
276 // This has the side-effect of saying an EV certificate is not EV if
277 // it hasn't already been verified (e.g. on the verification thread when
278 // connecting to a site).
279 // This flag is mostly a hack that should be removed once FLAG_LOCAL_ONLY
280 // works as intended.
281 function check_no_ocsp_requests(cert_name, expected_error) {
282 clearOCSPCache();
283 let ocspResponder = failingOCSPResponder();
284 let cert = certdb.findCertByNickname(null, cert_name);
285 let hasEVPolicy = {};
286 let verifiedChain = {};
287 let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
288 Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
289 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer, flags,
290 verifiedChain, hasEVPolicy);
291 // Since we're not doing OCSP requests, no certificate will be EV.
292 do_check_eq(hasEVPolicy.value, false);
293 do_check_eq(expected_error, error);
294 // Also check that isExtendedValidation doesn't cause OCSP requests.
295 let identityInfo = cert.QueryInterface(Ci.nsIIdentityInfo);
296 do_check_eq(identityInfo.isExtendedValidation, false);
297 ocspResponder.stop(run_next_test);
298 }