Bug 1940967 - Vendor glean_parser v16.2.0 r=TravisLong,mach-reviewers,ahal
[gecko.git] / security / manager / ssl / tests / unit / test_ocsp_stapling_expired.js
blob9d533c03da49426674abaa255785b876fb5c934d
1 // -*- indent-tabs-mode: nil; js-indent-level: 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 // Enable the collection (during test) for all products so even products
8 // that don't collect the data will be able to run the test without failure.
9 Services.prefs.setBoolPref(
10   "toolkit.telemetry.testing.overrideProductsCheck",
11   true
14 // In which we connect to a number of domains (as faked by a server running
15 // locally) with OCSP stapling enabled to determine that good things happen
16 // and bad things don't, specifically with respect to various expired OCSP
17 // responses (stapled and otherwise).
18 // According to RFC 6066, if a stapled OCSP response can't be satisfactorilly
19 // verified, the client should terminate the connection. Unfortunately, due to
20 // some bugs where servers will staple any old garbage without verifying it, we
21 // can't be this strict in practice. Originally this caveat only applied to
22 // expired responses, but recent high-profile failures have caused us to expand
23 // this to "try later" responses and responses where the signing certificate
24 // doesn't verify successfully.
26 var gCurrentOCSPResponse = null;
27 var gOCSPRequestCount = 0;
29 function add_ocsp_test(
30   aHost,
31   aExpectedResult,
32   aOCSPResponseToServe,
33   aExpectedRequestCount
34 ) {
35   add_connection_test(
36     aHost,
37     aExpectedResult,
38     function () {
39       clearOCSPCache();
40       clearSessionCache();
41       gCurrentOCSPResponse = aOCSPResponseToServe;
42       gOCSPRequestCount = 0;
43     },
44     function () {
45       equal(
46         gOCSPRequestCount,
47         aExpectedRequestCount,
48         "Should have made " +
49           aExpectedRequestCount +
50           " fallback OCSP request" +
51           (aExpectedRequestCount == 1 ? "" : "s")
52       );
53     }
54   );
57 do_get_profile();
58 Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
59 Services.prefs.setIntPref("security.OCSP.enabled", 1);
60 // Sometimes this test will fail on android due to an OCSP request timing out.
61 // That aspect of OCSP requests is not what we're testing here, so we can just
62 // bump the timeout and hopefully avoid these failures.
63 Services.prefs.setIntPref("security.OCSP.timeoutMilliseconds.soft", 5000);
64 var args = [
65   ["good", "default-ee", "unused", 0],
66   ["expiredresponse", "default-ee", "unused", 0],
67   ["oldvalidperiod", "default-ee", "unused", 0],
68   ["revoked", "default-ee", "unused", 0],
69   ["unknown", "default-ee", "unused", 0],
70   ["good", "must-staple-ee", "unused", 0],
72 var ocspResponses = generateOCSPResponses(args, "ocsp_certs");
73 // Fresh response, certificate is good.
74 var ocspResponseGood = ocspResponses[0];
75 // Expired response, certificate is good.
76 var expiredOCSPResponseGood = ocspResponses[1];
77 // Fresh signature, old validity period, certificate is good.
78 var oldValidityPeriodOCSPResponseGood = ocspResponses[2];
79 // Fresh signature, certificate is revoked.
80 var ocspResponseRevoked = ocspResponses[3];
81 // Fresh signature, certificate is unknown.
82 var ocspResponseUnknown = ocspResponses[4];
83 var ocspResponseGoodMustStaple = ocspResponses[5];
85 // sometimes we expect a result without re-fetch
86 var willNotRetry = 1;
87 // but sometimes, since a bad response is in the cache, OCSP fetch will be
88 // attempted for each validation - in practice, for these test certs, this
89 // means 2 requests because various key sizes are tried.
90 var willRetry = 2;
92 function run_test() {
93   let ocspResponder = new HttpServer();
94   ocspResponder.registerPrefixHandler("/", function (request, response) {
95     if (gCurrentOCSPResponse) {
96       response.setStatusLine(request.httpVersion, 200, "OK");
97       response.setHeader("Content-Type", "application/ocsp-response");
98       response.write(gCurrentOCSPResponse);
99     } else {
100       response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
101       response.write("Internal Server Error");
102     }
103     gOCSPRequestCount++;
104   });
105   ocspResponder.start(8888);
106   add_tls_server_setup("OCSPStaplingServer", "ocsp_certs");
108   // In these tests, the OCSP stapling server gives us a stapled
109   // response based on the host name ("ocsp-stapling-expired" or
110   // "ocsp-stapling-expired-fresh-ca"). We then ensure that we're
111   // properly falling back to fetching revocation information.
112   // For ocsp-stapling-expired.example.com, the OCSP stapling server
113   // staples an expired OCSP response. The certificate has not expired.
114   // For ocsp-stapling-expired-fresh-ca.example.com, the OCSP stapling
115   // server staples an OCSP response with a recent signature but with an
116   // out-of-date validity period. The certificate has not expired.
117   add_ocsp_test(
118     "ocsp-stapling-expired.example.com",
119     PRErrorCodeSuccess,
120     ocspResponseGood,
121     willNotRetry
122   );
123   add_ocsp_test(
124     "ocsp-stapling-expired-fresh-ca.example.com",
125     PRErrorCodeSuccess,
126     ocspResponseGood,
127     willNotRetry
128   );
129   // if we can't fetch a more recent response when
130   // given an expired stapled response, we terminate the connection.
131   add_ocsp_test(
132     "ocsp-stapling-expired.example.com",
133     SEC_ERROR_OCSP_OLD_RESPONSE,
134     expiredOCSPResponseGood,
135     willRetry
136   );
137   add_ocsp_test(
138     "ocsp-stapling-expired-fresh-ca.example.com",
139     SEC_ERROR_OCSP_OLD_RESPONSE,
140     expiredOCSPResponseGood,
141     willRetry
142   );
143   add_ocsp_test(
144     "ocsp-stapling-expired.example.com",
145     SEC_ERROR_OCSP_OLD_RESPONSE,
146     oldValidityPeriodOCSPResponseGood,
147     willRetry
148   );
149   add_ocsp_test(
150     "ocsp-stapling-expired-fresh-ca.example.com",
151     SEC_ERROR_OCSP_OLD_RESPONSE,
152     oldValidityPeriodOCSPResponseGood,
153     willRetry
154   );
155   add_ocsp_test(
156     "ocsp-stapling-expired.example.com",
157     SEC_ERROR_OCSP_OLD_RESPONSE,
158     null,
159     willNotRetry
160   );
161   add_ocsp_test(
162     "ocsp-stapling-expired.example.com",
163     SEC_ERROR_OCSP_OLD_RESPONSE,
164     null,
165     willNotRetry
166   );
167   // Of course, if the newer response indicates Revoked or Unknown,
168   // that status must be returned.
169   add_ocsp_test(
170     "ocsp-stapling-expired.example.com",
171     SEC_ERROR_REVOKED_CERTIFICATE,
172     ocspResponseRevoked,
173     willNotRetry
174   );
175   add_ocsp_test(
176     "ocsp-stapling-expired-fresh-ca.example.com",
177     SEC_ERROR_REVOKED_CERTIFICATE,
178     ocspResponseRevoked,
179     willNotRetry
180   );
181   add_ocsp_test(
182     "ocsp-stapling-expired.example.com",
183     SEC_ERROR_OCSP_UNKNOWN_CERT,
184     ocspResponseUnknown,
185     willRetry
186   );
187   add_ocsp_test(
188     "ocsp-stapling-expired-fresh-ca.example.com",
189     SEC_ERROR_OCSP_UNKNOWN_CERT,
190     ocspResponseUnknown,
191     willRetry
192   );
194   // If the response is expired but indicates Revoked or Unknown and a
195   // newer status can't be fetched, the Revoked or Unknown status will
196   // be returned.
197   add_ocsp_test(
198     "ocsp-stapling-revoked-old.example.com",
199     SEC_ERROR_REVOKED_CERTIFICATE,
200     null,
201     willNotRetry
202   );
203   add_ocsp_test(
204     "ocsp-stapling-unknown-old.example.com",
205     SEC_ERROR_OCSP_UNKNOWN_CERT,
206     null,
207     willNotRetry
208   );
209   // If the response is expired but indicates Revoked or Unknown and
210   // a newer status can be fetched and successfully verified, this
211   // should result in a successful certificate verification.
212   add_ocsp_test(
213     "ocsp-stapling-revoked-old.example.com",
214     PRErrorCodeSuccess,
215     ocspResponseGood,
216     willNotRetry
217   );
218   add_ocsp_test(
219     "ocsp-stapling-unknown-old.example.com",
220     PRErrorCodeSuccess,
221     ocspResponseGood,
222     willNotRetry
223   );
224   // If a newer status can be fetched but it fails to verify, the
225   // Revoked or Unknown status of the expired stapled response
226   // should be returned.
227   add_ocsp_test(
228     "ocsp-stapling-revoked-old.example.com",
229     SEC_ERROR_REVOKED_CERTIFICATE,
230     expiredOCSPResponseGood,
231     willRetry
232   );
233   add_ocsp_test(
234     "ocsp-stapling-unknown-old.example.com",
235     SEC_ERROR_OCSP_UNKNOWN_CERT,
236     expiredOCSPResponseGood,
237     willRetry
238   );
240   // These tests are verifying that an valid but very old response
241   // is rejected as a valid stapled response, requiring a fetch
242   // from the ocsp responder.
243   add_ocsp_test(
244     "ocsp-stapling-ancient-valid.example.com",
245     PRErrorCodeSuccess,
246     ocspResponseGood,
247     willNotRetry
248   );
249   add_ocsp_test(
250     "ocsp-stapling-ancient-valid.example.com",
251     SEC_ERROR_REVOKED_CERTIFICATE,
252     ocspResponseRevoked,
253     willNotRetry
254   );
255   add_ocsp_test(
256     "ocsp-stapling-ancient-valid.example.com",
257     SEC_ERROR_OCSP_UNKNOWN_CERT,
258     ocspResponseUnknown,
259     willRetry
260   );
262   // Test how OCSP-must-staple (i.e. TLS feature) interacts with stapled OCSP
263   // responses that don't successfully verify.
264   // A strict reading of the relevant RFCs might say that these connections
265   // should all fail because a satisfactory stapled OCSP response is not
266   // present, but for compatibility reasons we fall back to active OCSP fetching
267   // in these situations. If the fetch succeeds, then connection succeeds.
268   add_ocsp_test(
269     "ocsp-stapling-must-staple-expired.example.com",
270     PRErrorCodeSuccess,
271     ocspResponseGoodMustStaple,
272     willNotRetry
273   );
274   add_ocsp_test(
275     "ocsp-stapling-must-staple-try-later.example.com",
276     PRErrorCodeSuccess,
277     ocspResponseGoodMustStaple,
278     willNotRetry
279   );
280   add_ocsp_test(
281     "ocsp-stapling-must-staple-invalid-signer.example.com",
282     PRErrorCodeSuccess,
283     ocspResponseGoodMustStaple,
284     willNotRetry
285   );
287   add_test(function () {
288     ocspResponder.stop(run_next_test);
289   });
290   add_test(check_ocsp_stapling_telemetry);
291   run_next_test();
294 function check_ocsp_stapling_telemetry() {
295   let histogram = Services.telemetry
296     .getHistogramById("SSL_OCSP_STAPLING")
297     .snapshot();
298   equal(
299     histogram.values[0] || 0,
300     0,
301     "Should have 0 connections for unused histogram bucket 0"
302   );
303   equal(
304     histogram.values[1] || 0,
305     0,
306     "Actual and expected connections with a good response should match"
307   );
308   equal(
309     histogram.values[2] || 0,
310     0,
311     "Actual and expected connections with no stapled response should match"
312   );
313   equal(
314     histogram.values[3],
315     22,
316     "Actual and expected connections with an expired response should match"
317   );
318   equal(
319     histogram.values[4],
320     2,
321     "Actual and expected connections with bad responses should match"
322   );
323   run_next_test();