diff options
Diffstat (limited to 'netwerk/test/unit')
-rw-r--r-- | netwerk/test/unit/test_client_auth_with_proxy.js | 185 | ||||
-rw-r--r-- | netwerk/test/unit/xpcshell.ini | 2 |
2 files changed, 187 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_client_auth_with_proxy.js b/netwerk/test/unit/test_client_auth_with_proxy.js new file mode 100644 index 0000000000..0584dba69d --- /dev/null +++ b/netwerk/test/unit/test_client_auth_with_proxy.js @@ -0,0 +1,185 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/* import-globals-from head_cache.js */ +/* import-globals-from head_cookies.js */ +/* import-globals-from head_channels.js */ +/* import-globals-from head_servers.js */ + +const { MockRegistrar } = ChromeUtils.importESModule( + "resource://testing-common/MockRegistrar.sys.mjs" +); + +const certOverrideService = Cc[ + "@mozilla.org/security/certoverride;1" +].getService(Ci.nsICertOverrideService); + +function makeChan(uri) { + let chan = NetUtil.newChannel({ + uri, + loadUsingSystemPrincipal: true, + }).QueryInterface(Ci.nsIHttpChannel); + chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI; + return chan; +} + +function channelOpenPromise(chan, flags) { + return new Promise(resolve => { + function finish(req, buffer) { + resolve([req, buffer]); + } + chan.asyncOpen(new ChannelListener(finish, null, flags)); + }); +} + +class SecurityObserver { + constructor(input, output) { + this.input = input; + this.output = output; + } + + onHandshakeDone(socket, status) { + info("TLS handshake done"); + + let output = this.output; + this.input.asyncWait( + { + onInputStreamReady(readyInput) { + let request = NetUtil.readInputStreamToString( + readyInput, + readyInput.available() + ); + ok( + request.startsWith("GET /") && request.includes("HTTP/1.1"), + "expecting an HTTP/1.1 GET request" + ); + let response = + "HTTP/1.1 200 OK\r\nContent-Type:text/plain\r\n" + + "Connection:Close\r\nContent-Length:2\r\n\r\nOK"; + output.write(response, response.length); + }, + }, + 0, + 0, + Services.tm.currentThread + ); + } +} + +function startServer(cert) { + let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"].createInstance( + Ci.nsITLSServerSocket + ); + tlsServer.init(-1, true, -1); + tlsServer.serverCert = cert; + + let securityObservers = []; + + let listener = { + onSocketAccepted(socket, transport) { + info("Accepted TLS client connection"); + let connectionInfo = transport.securityCallbacks.getInterface( + Ci.nsITLSServerConnectionInfo + ); + let input = transport.openInputStream(0, 0, 0); + let output = transport.openOutputStream(0, 0, 0); + connectionInfo.setSecurityObserver(new SecurityObserver(input, output)); + }, + + onStopListening() { + info("onStopListening"); + for (let securityObserver of securityObservers) { + securityObserver.input.close(); + securityObserver.output.close(); + } + }, + }; + + tlsServer.setSessionTickets(false); + tlsServer.setRequestClientCertificate(Ci.nsITLSServerSocket.REQUEST_ALWAYS); + + tlsServer.asyncListen(listener); + + return tlsServer; +} + +// Replace the UI dialog that prompts the user to pick a client certificate. +const gClientAuthDialogs = { + chooseCertificate( + hostname, + port, + organization, + issuerOrg, + certList, + selectedIndex, + rememberClientAuthCertificate + ) { + return true; + }, + + QueryInterface: ChromeUtils.generateQI(["nsIClientAuthDialogs"]), +}; + +let server; +add_setup(async function setup() { + do_get_profile(); + + let clientAuthDialogsCID = MockRegistrar.register( + "@mozilla.org/nsClientAuthDialogs;1", + gClientAuthDialogs + ); + + let cert = getTestServerCertificate(); + ok(!!cert, "Got self-signed cert"); + server = startServer(cert); + + certOverrideService.rememberValidityOverride( + "localhost", + server.port, + {}, + cert, + true + ); + + registerCleanupFunction(async function () { + MockRegistrar.unregister(clientAuthDialogsCID); + certOverrideService.clearValidityOverride("localhost", server.port, {}); + server.close(); + }); +}); + +add_task(async function test_client_auth_with_proxy() { + let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService( + Ci.nsIX509CertDB + ); + addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u"); + addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u"); + + let proxies = [ + NodeHTTPProxyServer, + NodeHTTPSProxyServer, + NodeHTTP2ProxyServer, + ]; + + for (let p of proxies) { + info(`Test with proxy:${p.name}`); + let proxy = new p(); + await proxy.start(); + registerCleanupFunction(async () => { + await proxy.stop(); + }); + + let chan = makeChan(`https://localhost:${server.port}`); + let [req, buff] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL); + equal(req.status, Cr.NS_OK); + equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200); + equal(buff, "OK"); + req.QueryInterface(Ci.nsIProxiedChannel); + ok(!!req.proxyInfo); + notEqual(req.proxyInfo.type, "direct"); + await proxy.stop(); + } +}); diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index ed69ad2627..52433261bc 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -775,3 +775,5 @@ skip-if = os == 'win' && msix true run-sequentially = node server exceptions dont replay well +[test_client_auth_with_proxy.js] +skip-if = os == "android" |