test_ocsp_stapling.js (9887B)
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"; 6 7 // In which we connect to a number of domains (as faked by a server running 8 // locally) with and without OCSP stapling enabled to determine that good 9 // things happen and bad things don't. 10 11 // Enable the collection (during test) for all products so even products 12 // that don't collect the data will be able to run the test without failure. 13 Services.prefs.setBoolPref( 14 "toolkit.telemetry.testing.overrideProductsCheck", 15 true 16 ); 17 18 var gExpectOCSPRequest; 19 20 function add_ocsp_test( 21 aHost, 22 aExpectedResult, 23 aStaplingEnabled, 24 aExpectOCSPRequest = false 25 ) { 26 add_connection_test(aHost, aExpectedResult, function () { 27 gExpectOCSPRequest = aExpectOCSPRequest; 28 clearOCSPCache(); 29 clearSessionCache(); 30 Services.prefs.setBoolPref( 31 "security.ssl.enable_ocsp_stapling", 32 aStaplingEnabled 33 ); 34 }); 35 } 36 37 function add_tests() { 38 // In the absence of OCSP stapling, these should actually all work. 39 add_ocsp_test( 40 "ocsp-stapling-good.example.com", 41 PRErrorCodeSuccess, 42 false, 43 true 44 ); 45 add_ocsp_test( 46 "ocsp-stapling-revoked.example.com", 47 PRErrorCodeSuccess, 48 false, 49 true 50 ); 51 add_ocsp_test( 52 "ocsp-stapling-good-other-ca.example.com", 53 PRErrorCodeSuccess, 54 false, 55 true 56 ); 57 add_ocsp_test( 58 "ocsp-stapling-malformed.example.com", 59 PRErrorCodeSuccess, 60 false, 61 true 62 ); 63 add_ocsp_test( 64 "ocsp-stapling-srverr.example.com", 65 PRErrorCodeSuccess, 66 false, 67 true 68 ); 69 add_ocsp_test( 70 "ocsp-stapling-trylater.example.com", 71 PRErrorCodeSuccess, 72 false, 73 true 74 ); 75 add_ocsp_test( 76 "ocsp-stapling-needssig.example.com", 77 PRErrorCodeSuccess, 78 false, 79 true 80 ); 81 add_ocsp_test( 82 "ocsp-stapling-unauthorized.example.com", 83 PRErrorCodeSuccess, 84 false, 85 true 86 ); 87 add_ocsp_test( 88 "ocsp-stapling-unknown.example.com", 89 PRErrorCodeSuccess, 90 false, 91 true 92 ); 93 add_ocsp_test( 94 "ocsp-stapling-good-other.example.com", 95 PRErrorCodeSuccess, 96 false, 97 true 98 ); 99 add_ocsp_test( 100 "ocsp-stapling-none.example.com", 101 PRErrorCodeSuccess, 102 false, 103 true 104 ); 105 add_ocsp_test( 106 "ocsp-stapling-expired.example.com", 107 PRErrorCodeSuccess, 108 false, 109 true 110 ); 111 add_ocsp_test( 112 "ocsp-stapling-expired-fresh-ca.example.com", 113 PRErrorCodeSuccess, 114 false, 115 true 116 ); 117 add_ocsp_test( 118 "ocsp-stapling-skip-responseBytes.example.com", 119 PRErrorCodeSuccess, 120 false, 121 true 122 ); 123 add_ocsp_test( 124 "ocsp-stapling-critical-extension.example.com", 125 PRErrorCodeSuccess, 126 false, 127 true 128 ); 129 add_ocsp_test( 130 "ocsp-stapling-noncritical-extension.example.com", 131 PRErrorCodeSuccess, 132 false, 133 true 134 ); 135 add_ocsp_test( 136 "ocsp-stapling-empty-extensions.example.com", 137 PRErrorCodeSuccess, 138 false, 139 true 140 ); 141 142 // Now test OCSP stapling 143 // The following error codes are defined in security/nss/lib/util/SECerrs.h 144 145 add_ocsp_test("ocsp-stapling-good.example.com", PRErrorCodeSuccess, true); 146 147 add_ocsp_test( 148 "ocsp-stapling-revoked.example.com", 149 SEC_ERROR_REVOKED_CERTIFICATE, 150 true 151 ); 152 153 // This stapled response is from a CA that is untrusted and did not issue 154 // the server's certificate. 155 let certDB = Cc["@mozilla.org/security/x509certdb;1"].getService( 156 Ci.nsIX509CertDB 157 ); 158 let otherTestCA = constructCertFromFile("ocsp_certs/other-test-ca.pem"); 159 add_test(function () { 160 certDB.setCertTrust( 161 otherTestCA, 162 Ci.nsIX509Cert.CA_CERT, 163 Ci.nsIX509CertDB.UNTRUSTED 164 ); 165 run_next_test(); 166 }); 167 add_ocsp_test( 168 "ocsp-stapling-good-other-ca.example.com", 169 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 170 true, 171 true 172 ); 173 174 // The stapled response is from a CA that is trusted but did not issue the 175 // server's certificate. 176 add_test(function () { 177 certDB.setCertTrust( 178 otherTestCA, 179 Ci.nsIX509Cert.CA_CERT, 180 Ci.nsIX509CertDB.TRUSTED_SSL 181 ); 182 run_next_test(); 183 }); 184 // TODO(bug 979055): When using ByName instead of ByKey, the error here is 185 // SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE. We should be testing both cases. 186 add_ocsp_test( 187 "ocsp-stapling-good-other-ca.example.com", 188 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 189 true, 190 true 191 ); 192 193 // TODO: Test the case where the signing cert can't be found at all, which 194 // will result in SEC_ERROR_BAD_DATABASE in the NSS classic case. 195 196 add_ocsp_test( 197 "ocsp-stapling-malformed.example.com", 198 SEC_ERROR_OCSP_MALFORMED_REQUEST, 199 true 200 ); 201 add_ocsp_test( 202 "ocsp-stapling-srverr.example.com", 203 SEC_ERROR_OCSP_SERVER_ERROR, 204 true 205 ); 206 add_ocsp_test( 207 "ocsp-stapling-trylater.example.com", 208 SEC_ERROR_OCSP_TRY_SERVER_LATER, 209 true, 210 true 211 ); 212 add_ocsp_test( 213 "ocsp-stapling-needssig.example.com", 214 SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, 215 true 216 ); 217 add_ocsp_test( 218 "ocsp-stapling-unauthorized.example.com", 219 SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, 220 true 221 ); 222 add_ocsp_test( 223 "ocsp-stapling-unknown.example.com", 224 SEC_ERROR_OCSP_UNKNOWN_CERT, 225 true 226 ); 227 // If the server staples an OCSP response that doesn't contain a status for 228 // the server certificate, we defer returning the error and attempt to fetch 229 // a more suitable response. If that fails, the deferred error is returned. 230 add_ocsp_test( 231 "ocsp-stapling-good-other.example.com", 232 MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING, 233 true, 234 true 235 ); 236 // If the server doesn't staple an OCSP response, we continue as normal 237 // (this means that even though stapling is enabled, we expect an OCSP 238 // request). 239 add_ocsp_test( 240 "ocsp-stapling-none.example.com", 241 PRErrorCodeSuccess, 242 true, 243 true 244 ); 245 add_ocsp_test( 246 "ocsp-stapling-empty.example.com", 247 SEC_ERROR_OCSP_MALFORMED_RESPONSE, 248 true 249 ); 250 251 add_ocsp_test( 252 "ocsp-stapling-skip-responseBytes.example.com", 253 SEC_ERROR_OCSP_MALFORMED_RESPONSE, 254 true 255 ); 256 257 add_ocsp_test( 258 "ocsp-stapling-critical-extension.example.com", 259 SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, 260 true 261 ); 262 add_ocsp_test( 263 "ocsp-stapling-noncritical-extension.example.com", 264 PRErrorCodeSuccess, 265 true 266 ); 267 // TODO(bug 997994): Disallow empty Extensions in responses 268 add_ocsp_test( 269 "ocsp-stapling-empty-extensions.example.com", 270 PRErrorCodeSuccess, 271 true 272 ); 273 274 add_ocsp_test( 275 "ocsp-stapling-delegated-included.example.com", 276 PRErrorCodeSuccess, 277 true 278 ); 279 add_ocsp_test( 280 "ocsp-stapling-delegated-included-last.example.com", 281 PRErrorCodeSuccess, 282 true 283 ); 284 add_ocsp_test( 285 "ocsp-stapling-delegated-missing.example.com", 286 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 287 true, 288 true 289 ); 290 add_ocsp_test( 291 "ocsp-stapling-delegated-missing-multiple.example.com", 292 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 293 true, 294 true 295 ); 296 add_ocsp_test( 297 "ocsp-stapling-delegated-no-extKeyUsage.example.com", 298 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 299 true, 300 true 301 ); 302 add_ocsp_test( 303 "ocsp-stapling-delegated-from-intermediate.example.com", 304 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 305 true, 306 true 307 ); 308 add_ocsp_test( 309 "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", 310 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 311 true, 312 true 313 ); 314 add_ocsp_test( 315 "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", 316 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 317 true, 318 true 319 ); 320 321 // ocsp-stapling-expired.example.com and 322 // ocsp-stapling-expired-fresh-ca.example.com are handled in 323 // test_ocsp_stapling_expired.js 324 325 // Check that OCSP responder certificates with key sizes below 1024 bits are 326 // rejected, even when the main certificate chain keys are at least 1024 bits. 327 add_ocsp_test( 328 "keysize-ocsp-delegated.example.com", 329 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, 330 true, 331 true 332 ); 333 334 add_ocsp_test( 335 "revoked-ca-cert-used-as-end-entity.example.com", 336 SEC_ERROR_REVOKED_CERTIFICATE, 337 true 338 ); 339 } 340 341 function check_ocsp_stapling_telemetry() { 342 let histogram = Services.telemetry 343 .getHistogramById("SSL_OCSP_STAPLING") 344 .snapshot(); 345 equal( 346 histogram.values[0], 347 0, 348 "Should have 0 connections for unused histogram bucket 0" 349 ); 350 equal( 351 histogram.values[1], 352 5, 353 "Actual and expected connections with a good response should match" 354 ); 355 equal( 356 histogram.values[2], 357 18, 358 "Actual and expected connections with no stapled response should match" 359 ); 360 equal( 361 histogram.values[3] || 0, 362 0, 363 "Actual and expected connections with an expired response should match" 364 ); 365 equal( 366 histogram.values[4], 367 21, 368 "Actual and expected connections with bad responses should match" 369 ); 370 run_next_test(); 371 } 372 373 function run_test() { 374 do_get_profile(); 375 Services.prefs.setIntPref("security.OCSP.enabled", 1); 376 // This test may sometimes fail on android due to an OCSP request timing out. 377 // That aspect of OCSP requests is not what we're testing here, so we can just 378 // bump the timeout and hopefully avoid these failures. 379 Services.prefs.setIntPref("security.OCSP.timeoutMilliseconds.soft", 5000); 380 381 let fakeOCSPResponder = new HttpServer(); 382 fakeOCSPResponder.registerPrefixHandler("/", function (request, response) { 383 response.setStatusLine(request.httpVersion, 500, "Internal Server Error"); 384 ok( 385 gExpectOCSPRequest, 386 "Should be getting an OCSP request only when expected" 387 ); 388 }); 389 fakeOCSPResponder.start(8888); 390 391 add_tls_server_setup("OCSPStaplingServer", "ocsp_certs"); 392 393 add_tests(); 394 395 add_test(function () { 396 fakeOCSPResponder.stop(check_ocsp_stapling_telemetry); 397 }); 398 399 run_next_test(); 400 }