1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* import-globals-from head_cache.js */
8 /* import-globals-from head_cookies.js */
9 /* import-globals-from head_channels.js */
10 /* import-globals-from head_servers.js */
12 const { MockRegistrar
} = ChromeUtils
.importESModule(
13 "resource://testing-common/MockRegistrar.sys.mjs"
16 const certOverrideService
= Cc
[
17 "@mozilla.org/security/certoverride;1"
18 ].getService(Ci
.nsICertOverrideService
);
20 function makeChan(uri
) {
21 let chan
= NetUtil
.newChannel({
23 loadUsingSystemPrincipal
: true,
24 }).QueryInterface(Ci
.nsIHttpChannel
);
25 chan
.loadFlags
= Ci
.nsIChannel
.LOAD_INITIAL_DOCUMENT_URI
;
29 function channelOpenPromise(chan
, flags
) {
30 return new Promise(resolve
=> {
31 function finish(req
, buffer
) {
32 resolve([req
, buffer
]);
34 chan
.asyncOpen(new ChannelListener(finish
, null, flags
));
38 class SecurityObserver
{
39 constructor(input
, output
) {
45 info("TLS handshake done");
47 let output
= this.output
;
50 onInputStreamReady(readyInput
) {
51 let request
= NetUtil
.readInputStreamToString(
53 readyInput
.available()
56 request
.startsWith("GET /") && request
.includes("HTTP/1.1"),
57 "expecting an HTTP/1.1 GET request"
60 "HTTP/1.1 200 OK\r\nContent-Type:text/plain\r\n" +
61 "Connection:Close\r\nContent-Length:2\r\n\r\nOK";
62 output
.write(response
, response
.length
);
67 Services
.tm
.currentThread
72 function startServer(cert
) {
73 let tlsServer
= Cc
["@mozilla.org/network/tls-server-socket;1"].createInstance(
76 tlsServer
.init(-1, true, -1);
77 tlsServer
.serverCert
= cert
;
79 let securityObservers
= [];
82 onSocketAccepted(socket
, transport
) {
83 info("Accepted TLS client connection");
84 let connectionInfo
= transport
.securityCallbacks
.getInterface(
85 Ci
.nsITLSServerConnectionInfo
87 let input
= transport
.openInputStream(0, 0, 0);
88 let output
= transport
.openOutputStream(0, 0, 0);
89 connectionInfo
.setSecurityObserver(new SecurityObserver(input
, output
));
93 info("onStopListening");
94 for (let securityObserver
of securityObservers
) {
95 securityObserver
.input
.close();
96 securityObserver
.output
.close();
101 tlsServer
.setSessionTickets(false);
102 tlsServer
.setRequestClientCertificate(Ci
.nsITLSServerSocket
.REQUEST_ALWAYS
);
104 tlsServer
.asyncListen(listener
);
109 // Replace the UI dialog that prompts the user to pick a client certificate.
110 const clientAuthDialogService
= {
111 chooseCertificate(hostname
, certArray
, loadContext
, callback
) {
112 callback
.certificateChosen(certArray
[0], false);
114 QueryInterface
: ChromeUtils
.generateQI(["nsIClientAuthDialogService"]),
118 add_setup(async
function setup() {
121 let clientAuthDialogServiceCID
= MockRegistrar
.register(
122 "@mozilla.org/security/ClientAuthDialogService;1",
123 clientAuthDialogService
126 let cert
= getTestServerCertificate();
127 ok(!!cert
, "Got self-signed cert");
128 server
= startServer(cert
);
130 certOverrideService
.rememberValidityOverride(
138 registerCleanupFunction(async
function () {
139 MockRegistrar
.unregister(clientAuthDialogServiceCID
);
140 certOverrideService
.clearValidityOverride("localhost", server
.port
, {});
145 add_task(async
function test_client_auth_with_proxy() {
146 let certdb
= Cc
["@mozilla.org/security/x509certdb;1"].getService(
149 addCertFromFile(certdb
, "http2-ca.pem", "CTu,u,u");
150 addCertFromFile(certdb
, "proxy-ca.pem", "CTu,u,u");
154 NodeHTTPSProxyServer
,
155 NodeHTTP2ProxyServer
,
158 for (let p
of proxies
) {
159 info(`Test with proxy:${p.name}`);
162 registerCleanupFunction(async () => {
166 let chan
= makeChan(`https://localhost:${server.port}`);
167 let [req
, buff
] = await
channelOpenPromise(chan
, CL_ALLOW_UNKNOWN_CL
);
168 equal(req
.status
, Cr
.NS_OK
);
169 equal(req
.QueryInterface(Ci
.nsIHttpChannel
).responseStatus
, 200);
171 req
.QueryInterface(Ci
.nsIProxiedChannel
);
173 notEqual(req
.proxyInfo
.type
, "direct");