1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/tests/unit/head_psm.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,493 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + */ 1.8 +"use strict"; 1.9 + 1.10 +const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components; 1.11 + 1.12 +let { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {}); 1.13 +let { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {}); 1.14 +let { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); 1.15 +let { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); 1.16 +let { HttpServer } = Cu.import("resource://testing-common/httpd.js", {}); 1.17 +let { ctypes } = Cu.import("resource://gre/modules/ctypes.jsm"); 1.18 + 1.19 +let gIsWindows = ("@mozilla.org/windows-registry-key;1" in Cc); 1.20 + 1.21 +const isDebugBuild = Cc["@mozilla.org/xpcom/debug;1"] 1.22 + .getService(Ci.nsIDebug2).isDebugBuild; 1.23 + 1.24 +const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE; 1.25 +const SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE; 1.26 + 1.27 +// Sort in numerical order 1.28 +const SEC_ERROR_INVALID_ARGS = SEC_ERROR_BASE + 5; // -8187 1.29 +const SEC_ERROR_BAD_DER = SEC_ERROR_BASE + 9; 1.30 +const SEC_ERROR_EXPIRED_CERTIFICATE = SEC_ERROR_BASE + 11; 1.31 +const SEC_ERROR_REVOKED_CERTIFICATE = SEC_ERROR_BASE + 12; // -8180 1.32 +const SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13; 1.33 +const SEC_ERROR_BAD_DATABASE = SEC_ERROR_BASE + 18; 1.34 +const SEC_ERROR_UNTRUSTED_ISSUER = SEC_ERROR_BASE + 20; // -8172 1.35 +const SEC_ERROR_UNTRUSTED_CERT = SEC_ERROR_BASE + 21; // -8171 1.36 +const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = SEC_ERROR_BASE + 30; // -8162 1.37 +const SEC_ERROR_EXTENSION_VALUE_INVALID = SEC_ERROR_BASE + 34; // -8158 1.38 +const SEC_ERROR_EXTENSION_NOT_FOUND = SEC_ERROR_BASE + 35; // -8157 1.39 +const SEC_ERROR_CA_CERT_INVALID = SEC_ERROR_BASE + 36; 1.40 +const SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION = SEC_ERROR_BASE + 41; 1.41 +const SEC_ERROR_INADEQUATE_KEY_USAGE = SEC_ERROR_BASE + 90; // -8102 1.42 +const SEC_ERROR_INADEQUATE_CERT_TYPE = SEC_ERROR_BASE + 91; // -8101 1.43 +const SEC_ERROR_CERT_NOT_IN_NAME_SPACE = SEC_ERROR_BASE + 112; // -8080 1.44 +const SEC_ERROR_CERT_BAD_ACCESS_LOCATION = SEC_ERROR_BASE + 117; // -8075 1.45 +const SEC_ERROR_OCSP_MALFORMED_REQUEST = SEC_ERROR_BASE + 120; 1.46 +const SEC_ERROR_OCSP_SERVER_ERROR = SEC_ERROR_BASE + 121; // -8071 1.47 +const SEC_ERROR_OCSP_TRY_SERVER_LATER = SEC_ERROR_BASE + 122; 1.48 +const SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = SEC_ERROR_BASE + 123; 1.49 +const SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = SEC_ERROR_BASE + 124; 1.50 +const SEC_ERROR_OCSP_UNKNOWN_CERT = SEC_ERROR_BASE + 126; // -8066 1.51 +const SEC_ERROR_OCSP_MALFORMED_RESPONSE = SEC_ERROR_BASE + 129; 1.52 +const SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE = SEC_ERROR_BASE + 130; 1.53 +const SEC_ERROR_OCSP_OLD_RESPONSE = SEC_ERROR_BASE + 132; 1.54 +const SEC_ERROR_OCSP_INVALID_SIGNING_CERT = SEC_ERROR_BASE + 144; 1.55 +const SEC_ERROR_POLICY_VALIDATION_FAILED = SEC_ERROR_BASE + 160; // -8032 1.56 +const SEC_ERROR_OCSP_BAD_SIGNATURE = SEC_ERROR_BASE + 157; 1.57 +const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = SEC_ERROR_BASE + 176; 1.58 +const SEC_ERROR_APPLICATION_CALLBACK_ERROR = SEC_ERROR_BASE + 178; 1.59 + 1.60 +const SSL_ERROR_BAD_CERT_DOMAIN = SSL_ERROR_BASE + 12; 1.61 + 1.62 +// Supported Certificate Usages 1.63 +const certificateUsageSSLClient = 0x0001; 1.64 +const certificateUsageSSLServer = 0x0002; 1.65 +const certificateUsageSSLCA = 0x0008; 1.66 +const certificateUsageEmailSigner = 0x0010; 1.67 +const certificateUsageEmailRecipient = 0x0020; 1.68 +const certificateUsageObjectSigner = 0x0040; 1.69 +const certificateUsageVerifyCA = 0x0100; 1.70 +const certificateUsageStatusResponder = 0x0400; 1.71 + 1.72 +const NO_FLAGS = 0; 1.73 + 1.74 +function readFile(file) { 1.75 + let fstream = Cc["@mozilla.org/network/file-input-stream;1"] 1.76 + .createInstance(Ci.nsIFileInputStream); 1.77 + fstream.init(file, -1, 0, 0); 1.78 + let data = NetUtil.readInputStreamToString(fstream, fstream.available()); 1.79 + fstream.close(); 1.80 + return data; 1.81 +} 1.82 + 1.83 +function addCertFromFile(certdb, filename, trustString) { 1.84 + let certFile = do_get_file(filename, false); 1.85 + let der = readFile(certFile); 1.86 + certdb.addCert(der, trustString, null); 1.87 +} 1.88 + 1.89 +function constructCertFromFile(filename) { 1.90 + let certFile = do_get_file(filename, false); 1.91 + let certDER = readFile(certFile); 1.92 + let certdb = Cc["@mozilla.org/security/x509certdb;1"] 1.93 + .getService(Ci.nsIX509CertDB); 1.94 + return certdb.constructX509(certDER, certDER.length); 1.95 +} 1.96 + 1.97 +function setCertTrust(cert, trustString) { 1.98 + let certdb = Cc["@mozilla.org/security/x509certdb;1"] 1.99 + .getService(Ci.nsIX509CertDB); 1.100 + certdb.setCertTrustFromString(cert, trustString); 1.101 +} 1.102 + 1.103 +function getXPCOMStatusFromNSS(statusNSS) { 1.104 + let nssErrorsService = Cc["@mozilla.org/nss_errors_service;1"] 1.105 + .getService(Ci.nsINSSErrorsService); 1.106 + return nssErrorsService.getXPCOMFromNSSError(statusNSS); 1.107 +} 1.108 + 1.109 +function checkCertErrorGeneric(certdb, cert, expectedError, usage) { 1.110 + let hasEVPolicy = {}; 1.111 + let verifiedChain = {}; 1.112 + let error = certdb.verifyCertNow(cert, usage, NO_FLAGS, verifiedChain, 1.113 + hasEVPolicy); 1.114 + // expected error == -1 is a special marker for any error is OK 1.115 + if (expectedError != -1 ) { 1.116 + do_check_eq(error, expectedError); 1.117 + } else { 1.118 + do_check_neq (error, 0); 1.119 + } 1.120 +} 1.121 + 1.122 +function _getLibraryFunctionWithNoArguments(functionName, libraryName) { 1.123 + // Open the NSS library. copied from services/crypto/modules/WeaveCrypto.js 1.124 + let path = ctypes.libraryName(libraryName); 1.125 + 1.126 + // XXX really want to be able to pass specific dlopen flags here. 1.127 + let nsslib; 1.128 + try { 1.129 + nsslib = ctypes.open(path); 1.130 + } catch(e) { 1.131 + // In case opening the library without a full path fails, 1.132 + // try again with a full path. 1.133 + let file = Services.dirsvc.get("GreD", Ci.nsILocalFile); 1.134 + file.append(path); 1.135 + nsslib = ctypes.open(file.path); 1.136 + } 1.137 + 1.138 + let SECStatus = ctypes.int; 1.139 + let func = nsslib.declare(functionName, ctypes.default_abi, SECStatus); 1.140 + return func; 1.141 +} 1.142 + 1.143 +function clearOCSPCache() { 1.144 + let certdb = Cc["@mozilla.org/security/x509certdb;1"] 1.145 + .getService(Ci.nsIX509CertDB); 1.146 + certdb.clearOCSPCache(); 1.147 +} 1.148 + 1.149 +function clearSessionCache() { 1.150 + let SSL_ClearSessionCache = null; 1.151 + try { 1.152 + SSL_ClearSessionCache = 1.153 + _getLibraryFunctionWithNoArguments("SSL_ClearSessionCache", "ssl3"); 1.154 + } catch (e) { 1.155 + // On Windows, this is actually in the nss3 library. 1.156 + SSL_ClearSessionCache = 1.157 + _getLibraryFunctionWithNoArguments("SSL_ClearSessionCache", "nss3"); 1.158 + } 1.159 + if (!SSL_ClearSessionCache || SSL_ClearSessionCache() != 0) { 1.160 + throw "Failed to clear SSL session cache"; 1.161 + } 1.162 +} 1.163 + 1.164 +// Set up a TLS testing environment that has a TLS server running and 1.165 +// ready to accept connections. This async function starts the server and 1.166 +// waits for the server to indicate that it is ready. 1.167 +// 1.168 +// Each test should have its own subdomain of example.com, for example 1.169 +// my-first-connection-test.example.com. The server can use the server 1.170 +// name (passed through the SNI TLS extension) to determine what behavior 1.171 +// the server side of the text should exhibit. See TLSServer.h for more 1.172 +// information on how to write the server side of tests. 1.173 +// 1.174 +// Create a new source file for your new server executable in 1.175 +// security/manager/ssl/tests/unit/tlsserver/cmd similar to the other ones in 1.176 +// that directory, and add a reference to it to the sources variable in that 1.177 +// directory's moz.build. 1.178 +// 1.179 +// Modify TEST_HARNESS_BINS in 1.180 +// testing/mochitest/Makefile.in and NO_PKG_FILES in 1.181 +// toolkit/mozapps/installer/packager.mk to make sure the new executable 1.182 +// gets included in the packages used for shipping the tests to the test 1.183 +// runners in our build/test farm. (Things will work fine locally without 1.184 +// these changes but will break on TBPL.) 1.185 +// 1.186 +// Your test script should look something like this: 1.187 +/* 1.188 + 1.189 +// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.190 +// This Source Code Form is subject to the terms of the Mozilla Public 1.191 +// License, v. 2.0. If a copy of the MPL was not distributed with this 1.192 +// file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.193 +"use strict"; 1.194 + 1.195 +// <documentation on your test> 1.196 + 1.197 +function run_test() { 1.198 + do_get_profile(); 1.199 + add_tls_server_setup("<test-server-name>"); 1.200 + 1.201 + add_connection_test("<test-name-1>.example.com", 1.202 + getXPCOMStatusFromNSS(SEC_ERROR_xxx), 1.203 + function() { ... }, 1.204 + function(aTransportSecurityInfo) { ... }); 1.205 + [...] 1.206 + add_connection_test("<test-name-n>.example.com", Cr.NS_OK); 1.207 + 1.208 + run_next_test(); 1.209 +} 1.210 + 1.211 +*/ 1.212 +function add_tls_server_setup(serverBinName) { 1.213 + add_test(function() { 1.214 + _setupTLSServerTest(serverBinName); 1.215 + }); 1.216 +} 1.217 + 1.218 +// Add a TLS connection test case. aHost is the hostname to pass in the SNI TLS 1.219 +// extension; this should unambiguously identifiy which test is being run. 1.220 +// aExpectedResult is the expected nsresult of the connection. 1.221 +// aBeforeConnect is a callback function that takes no arguments that will be 1.222 +// called before the connection is attempted. 1.223 +// aWithSecurityInfo is a callback function that takes an 1.224 +// nsITransportSecurityInfo, which is called after the TLS handshake succeeds. 1.225 +function add_connection_test(aHost, aExpectedResult, 1.226 + aBeforeConnect, aWithSecurityInfo) { 1.227 + const REMOTE_PORT = 8443; 1.228 + 1.229 + function Connection(aHost) { 1.230 + this.host = aHost; 1.231 + let threadManager = Cc["@mozilla.org/thread-manager;1"] 1.232 + .getService(Ci.nsIThreadManager); 1.233 + this.thread = threadManager.currentThread; 1.234 + this.defer = Promise.defer(); 1.235 + let sts = Cc["@mozilla.org/network/socket-transport-service;1"] 1.236 + .getService(Ci.nsISocketTransportService); 1.237 + this.transport = sts.createTransport(["ssl"], 1, aHost, REMOTE_PORT, null); 1.238 + this.transport.setEventSink(this, this.thread); 1.239 + this.inputStream = null; 1.240 + this.outputStream = null; 1.241 + this.connected = false; 1.242 + } 1.243 + 1.244 + Connection.prototype = { 1.245 + // nsITransportEventSink 1.246 + onTransportStatus: function(aTransport, aStatus, aProgress, aProgressMax) { 1.247 + if (!this.connected && aStatus == Ci.nsISocketTransport.STATUS_CONNECTED_TO) { 1.248 + this.connected = true; 1.249 + this.outputStream.asyncWait(this, 0, 0, this.thread); 1.250 + } 1.251 + }, 1.252 + 1.253 + // nsIInputStreamCallback 1.254 + onInputStreamReady: function(aStream) { 1.255 + try { 1.256 + // this will throw if the stream has been closed by an error 1.257 + let str = NetUtil.readInputStreamToString(aStream, aStream.available()); 1.258 + do_check_eq(str, "0"); 1.259 + this.inputStream.close(); 1.260 + this.outputStream.close(); 1.261 + this.result = Cr.NS_OK; 1.262 + } catch (e) { 1.263 + this.result = e.result; 1.264 + } 1.265 + this.defer.resolve(this); 1.266 + }, 1.267 + 1.268 + // nsIOutputStreamCallback 1.269 + onOutputStreamReady: function(aStream) { 1.270 + let sslSocketControl = this.transport.securityInfo 1.271 + .QueryInterface(Ci.nsISSLSocketControl); 1.272 + sslSocketControl.proxyStartSSL(); 1.273 + this.outputStream.write("0", 1); 1.274 + let inStream = this.transport.openInputStream(0, 0, 0) 1.275 + .QueryInterface(Ci.nsIAsyncInputStream); 1.276 + this.inputStream = inStream; 1.277 + this.inputStream.asyncWait(this, 0, 0, this.thread); 1.278 + }, 1.279 + 1.280 + go: function() { 1.281 + this.outputStream = this.transport.openOutputStream(0, 0, 0) 1.282 + .QueryInterface(Ci.nsIAsyncOutputStream); 1.283 + return this.defer.promise; 1.284 + } 1.285 + }; 1.286 + 1.287 + /* Returns a promise to connect to aHost that resolves to the result of that 1.288 + * connection */ 1.289 + function connectTo(aHost) { 1.290 + Services.prefs.setCharPref("network.dns.localDomains", aHost); 1.291 + let connection = new Connection(aHost); 1.292 + return connection.go(); 1.293 + } 1.294 + 1.295 + add_test(function() { 1.296 + if (aBeforeConnect) { 1.297 + aBeforeConnect(); 1.298 + } 1.299 + connectTo(aHost).then(function(conn) { 1.300 + do_check_eq(conn.result, aExpectedResult); 1.301 + if (aWithSecurityInfo) { 1.302 + aWithSecurityInfo(conn.transport.securityInfo 1.303 + .QueryInterface(Ci.nsITransportSecurityInfo)); 1.304 + } 1.305 + run_next_test(); 1.306 + }); 1.307 + }); 1.308 +} 1.309 + 1.310 +function _getBinaryUtil(binaryUtilName) { 1.311 + let directoryService = Cc["@mozilla.org/file/directory_service;1"] 1.312 + .getService(Ci.nsIProperties); 1.313 + 1.314 + let utilBin = directoryService.get("CurProcD", Ci.nsILocalFile); 1.315 + utilBin.append(binaryUtilName + (gIsWindows ? ".exe" : "")); 1.316 + // If we're testing locally, the above works. If not, the server executable 1.317 + // is in another location. 1.318 + if (!utilBin.exists()) { 1.319 + utilBin = directoryService.get("CurWorkD", Ci.nsILocalFile); 1.320 + while (utilBin.path.indexOf("xpcshell") != -1) { 1.321 + utilBin = utilBin.parent; 1.322 + } 1.323 + utilBin.append("bin"); 1.324 + utilBin.append(binaryUtilName + (gIsWindows ? ".exe" : "")); 1.325 + } 1.326 + do_check_true(utilBin.exists()); 1.327 + return utilBin; 1.328 +} 1.329 + 1.330 +// Do not call this directly; use add_tls_server_setup 1.331 +function _setupTLSServerTest(serverBinName) 1.332 +{ 1.333 + let certdb = Cc["@mozilla.org/security/x509certdb;1"] 1.334 + .getService(Ci.nsIX509CertDB); 1.335 + // The trusted CA that is typically used for "good" certificates. 1.336 + addCertFromFile(certdb, "tlsserver/test-ca.der", "CTu,u,u"); 1.337 + 1.338 + const CALLBACK_PORT = 8444; 1.339 + 1.340 + let directoryService = Cc["@mozilla.org/file/directory_service;1"] 1.341 + .getService(Ci.nsIProperties); 1.342 + let envSvc = Cc["@mozilla.org/process/environment;1"] 1.343 + .getService(Ci.nsIEnvironment); 1.344 + let greDir = directoryService.get("GreD", Ci.nsIFile); 1.345 + envSvc.set("DYLD_LIBRARY_PATH", greDir.path); 1.346 + envSvc.set("LD_LIBRARY_PATH", greDir.path); 1.347 + envSvc.set("MOZ_TLS_SERVER_DEBUG_LEVEL", "3"); 1.348 + envSvc.set("MOZ_TLS_SERVER_CALLBACK_PORT", CALLBACK_PORT); 1.349 + 1.350 + let httpServer = new HttpServer(); 1.351 + httpServer.registerPathHandler("/", 1.352 + function handleServerCallback(aRequest, aResponse) { 1.353 + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); 1.354 + aResponse.setHeader("Content-Type", "text/plain"); 1.355 + let responseBody = "OK!"; 1.356 + aResponse.bodyOutputStream.write(responseBody, responseBody.length); 1.357 + do_execute_soon(function() { 1.358 + httpServer.stop(run_next_test); 1.359 + }); 1.360 + }); 1.361 + httpServer.start(CALLBACK_PORT); 1.362 + 1.363 + let serverBin = _getBinaryUtil(serverBinName); 1.364 + let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); 1.365 + process.init(serverBin); 1.366 + let certDir = directoryService.get("CurWorkD", Ci.nsILocalFile); 1.367 + certDir.append("tlsserver"); 1.368 + do_check_true(certDir.exists()); 1.369 + process.run(false, [certDir.path], 1); 1.370 + 1.371 + do_register_cleanup(function() { 1.372 + process.kill(); 1.373 + }); 1.374 +} 1.375 + 1.376 +// Returns an Array of OCSP responses for a given ocspRespArray and a location 1.377 +// for a nssDB where the certs and public keys are prepopulated. 1.378 +// ocspRespArray is an array of arrays like: 1.379 +// [ [typeOfResponse, certnick, extracertnick]...] 1.380 +function generateOCSPResponses(ocspRespArray, nssDBlocation) 1.381 +{ 1.382 + let utilBinName = "GenerateOCSPResponse"; 1.383 + let ocspGenBin = _getBinaryUtil(utilBinName); 1.384 + let retArray = new Array(); 1.385 + 1.386 + for (let i = 0; i < ocspRespArray.length; i++) { 1.387 + let argArray = new Array(); 1.388 + let ocspFilepre = do_get_file(i.toString() + ".ocsp", true); 1.389 + let filename = ocspFilepre.path; 1.390 + argArray.push(nssDBlocation); 1.391 + argArray.push(ocspRespArray[i][0]); // ocsRespType; 1.392 + argArray.push(ocspRespArray[i][1]); // nick; 1.393 + argArray.push(ocspRespArray[i][2]); // extranickname 1.394 + argArray.push(filename); 1.395 + do_print("arg_array ="+argArray); 1.396 + 1.397 + let process = Cc["@mozilla.org/process/util;1"] 1.398 + .createInstance(Ci.nsIProcess); 1.399 + process.init(ocspGenBin); 1.400 + process.run(true, argArray, 5); 1.401 + do_check_eq(0, process.exitValue); 1.402 + let ocspFile = do_get_file(i.toString() + ".ocsp", false); 1.403 + retArray.push(readFile(ocspFile)); 1.404 + ocspFile.remove(false); 1.405 + } 1.406 + return retArray; 1.407 +} 1.408 + 1.409 +// Starts and returns an http responder that will cause a test failure if it is 1.410 +// queried. The server identities are given by a non-empty array 1.411 +// serverIdentities. 1.412 +function getFailingHttpServer(serverPort, serverIdentities) { 1.413 + let httpServer = new HttpServer(); 1.414 + httpServer.registerPrefixHandler("/", function(request, response) { 1.415 + do_check_true(false); 1.416 + }); 1.417 + httpServer.identity.setPrimary("http", serverIdentities.shift(), serverPort); 1.418 + serverIdentities.forEach(function(identity) { 1.419 + httpServer.identity.add("http", identity, serverPort); 1.420 + }); 1.421 + httpServer.start(serverPort); 1.422 + return httpServer; 1.423 +} 1.424 + 1.425 +// Starts an http OCSP responder that serves good OCSP responses and 1.426 +// returns an object with a method stop that should be called to stop 1.427 +// the http server. 1.428 +// NB: Because generating OCSP responses inside the HTTP request 1.429 +// handler can cause timeouts, the expected responses are pre-generated 1.430 +// all at once before starting the server. This means that their producedAt 1.431 +// times will all be the same. If a test depends on this not being the case, 1.432 +// perhaps calling startOCSPResponder twice (at different times) will be 1.433 +// necessary. 1.434 +// 1.435 +// serverPort is the port of the http OCSP responder 1.436 +// identity is the http hostname that will answer the OCSP requests 1.437 +// invalidIdentities is an array of identities that if used an 1.438 +// will cause a test failure 1.439 +// nssDBlocaion is the location of the NSS database from where the OCSP 1.440 +// responses will be generated (assumes appropiate keys are present) 1.441 +// expectedCertNames is an array of nicks of the certs to be responsed 1.442 +// expectedBasePaths is an optional array that is used to indicate 1.443 +// what is the expected base path of the OCSP request. 1.444 +function startOCSPResponder(serverPort, identity, invalidIdentities, 1.445 + nssDBLocation, expectedCertNames, 1.446 + expectedBasePaths, expectedMethods, 1.447 + expectedResponseTypes) { 1.448 + let ocspResponseGenerationArgs = expectedCertNames.map( 1.449 + function(expectedNick) { 1.450 + let responseType = "good"; 1.451 + if (expectedResponseTypes && expectedResponseTypes.length >= 1) { 1.452 + responseType = expectedResponseTypes.shift(); 1.453 + } 1.454 + return [responseType, expectedNick, "unused"]; 1.455 + } 1.456 + ); 1.457 + let ocspResponses = generateOCSPResponses(ocspResponseGenerationArgs, 1.458 + nssDBLocation); 1.459 + let httpServer = new HttpServer(); 1.460 + httpServer.registerPrefixHandler("/", 1.461 + function handleServerCallback(aRequest, aResponse) { 1.462 + invalidIdentities.forEach(function(identity) { 1.463 + do_check_neq(aRequest.host, identity) 1.464 + }); 1.465 + do_print("got request for: " + aRequest.path); 1.466 + let basePath = aRequest.path.slice(1).split("/")[0]; 1.467 + if (expectedBasePaths.length >= 1) { 1.468 + do_check_eq(basePath, expectedBasePaths.shift()); 1.469 + } 1.470 + do_check_true(expectedCertNames.length >= 1); 1.471 + if (expectedMethods && expectedMethods.length >= 1) { 1.472 + do_check_eq(aRequest.method, expectedMethods.shift()); 1.473 + } 1.474 + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); 1.475 + aResponse.setHeader("Content-Type", "application/ocsp-response"); 1.476 + aResponse.write(ocspResponses.shift()); 1.477 + }); 1.478 + httpServer.identity.setPrimary("http", identity, serverPort); 1.479 + invalidIdentities.forEach(function(identity) { 1.480 + httpServer.identity.add("http", identity, serverPort); 1.481 + }); 1.482 + httpServer.start(serverPort); 1.483 + return { 1.484 + stop: function(callback) { 1.485 + // make sure we consumed each expected response 1.486 + do_check_eq(ocspResponses.length, 0); 1.487 + if (expectedBasePaths) { 1.488 + do_check_eq(expectedBasePaths.length, 0); 1.489 + } 1.490 + if (expectedResponseTypes) { 1.491 + do_check_eq(expectedResponseTypes.length, 0); 1.492 + } 1.493 + httpServer.stop(callback); 1.494 + } 1.495 + }; 1.496 +}