1 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
2 // Any copyright is dedicated to the Public Domain.
3 // http://creativecommons.org/publicdomain/zero/1.0/
7 // a fork of test_be_conservative
9 // Tests that nsIHttpChannelInternal.tlsFlags can be used to set the
10 // client max version level. Flags can also be used to set the
11 // level of intolerance rollback and to test out an experimental 1.3
12 // hello, though they are not tested here.
14 // Get a profile directory and ensure PSM initializes NSS.
16 Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
18 class InputStreamCallback {
24 onInputStreamReady(stream) {
25 info("input stream ready");
27 info("input stream callback stopped - bailing");
32 available = stream.available();
34 // onInputStreamReady may fire when the stream has been closed.
37 Cr.NS_BASE_STREAM_CLOSED,
38 "error should be NS_BASE_STREAM_CLOSED"
42 let request = NetUtil.readInputStreamToString(stream, available, {
46 request.startsWith("GET / HTTP/1.1\r\n"),
47 "Should get a simple GET / HTTP/1.1 request"
50 "HTTP/1.1 200 OK\r\n" +
51 "Content-Length: 2\r\n" +
52 "Content-Type: text/plain\r\n" +
54 let written = this.output.write(response, response.length);
58 "should have been able to write entire response"
62 info("done with input stream ready");
71 class TLSServerSecurityObserver {
72 constructor(input, output, expectedVersion) {
75 this.expectedVersion = expectedVersion;
80 onHandshakeDone(socket, status) {
81 info("TLS handshake done");
82 info(`TLS version used: ${status.tlsVersionUsed}`);
83 info(this.expectedVersion);
85 status.tlsVersionUsed,
87 "expected version check"
90 info("handshake done callback stopped - bailing");
94 let callback = new InputStreamCallback(this.output);
95 this.callbacks.push(callback);
96 this.input.asyncWait(callback, 0, 0, Services.tm.currentThread);
103 this.callbacks.forEach(callback => {
109 function startServer(
115 let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"].createInstance(
116 Ci.nsITLSServerSocket
118 tlsServer.init(-1, true, -1);
119 tlsServer.serverCert = cert;
120 tlsServer.setVersionRange(minServerVersion, maxServerVersion);
121 tlsServer.setSessionTickets(false);
124 securityObservers: [],
126 onSocketAccepted(socket, transport) {
127 info("accepted TLS client connection");
128 let connectionInfo = transport.securityCallbacks.getInterface(
129 Ci.nsITLSServerConnectionInfo
131 let input = transport.openInputStream(0, 0, 0);
132 let output = transport.openOutputStream(0, 0, 0);
133 let securityObserver = new TLSServerSecurityObserver(
138 this.securityObservers.push(securityObserver);
139 connectionInfo.setSecurityObserver(securityObserver);
142 // For some reason we get input stream callback events after we've stopped
143 // listening, so this ensures we just drop those events.
145 info("onStopListening");
146 this.securityObservers.forEach(observer => {
151 tlsServer.asyncListen(listener);
155 const hostname = "example.com";
157 function storeCertOverride(port, cert) {
158 let certOverrideService = Cc[
159 "@mozilla.org/security/certoverride;1"
160 ].getService(Ci.nsICertOverrideService);
161 certOverrideService.rememberValidityOverride(hostname, port, {}, cert, true);
164 function startClient(port, tlsFlags, expectSuccess) {
165 let req = new XMLHttpRequest();
166 req.open("GET", `https://${hostname}:${port}`);
167 let internalChannel = req.channel.QueryInterface(Ci.nsIHttpChannelInternal);
168 internalChannel.tlsFlags = tlsFlags;
169 return new Promise((resolve, reject) => {
173 `should ${expectSuccess ? "" : "not "}have gotten load event`
175 equal(req.responseText, "OK", "response text should be 'OK'");
178 req.onerror = () => {
181 `should ${!expectSuccess ? "" : "not "}have gotten an error`
190 add_task(async function () {
191 Services.prefs.setIntPref("security.tls.version.max", 4);
192 Services.prefs.setCharPref("network.dns.localDomains", hostname);
193 let cert = getTestServerCertificate();
195 // server that accepts 1.1->1.3 and a client max 1.3. expect 1.3
197 let server = startServer(
199 Ci.nsITLSClientStatus.TLS_VERSION_1_1,
200 Ci.nsITLSClientStatus.TLS_VERSION_1_3,
201 Ci.nsITLSClientStatus.TLS_VERSION_1_3
203 storeCertOverride(server.port, cert);
204 await startClient(server.port, 4, true /*should succeed*/);
207 // server that accepts 1.1->1.3 and a client max 1.1. expect 1.1
209 server = startServer(
211 Ci.nsITLSClientStatus.TLS_VERSION_1_1,
212 Ci.nsITLSClientStatus.TLS_VERSION_1_3,
213 Ci.nsITLSClientStatus.TLS_VERSION_1_1
215 storeCertOverride(server.port, cert);
216 await startClient(server.port, 2, true);
219 // server that accepts 1.2->1.2 and a client max 1.3. expect 1.2
221 server = startServer(
223 Ci.nsITLSClientStatus.TLS_VERSION_1_2,
224 Ci.nsITLSClientStatus.TLS_VERSION_1_2,
225 Ci.nsITLSClientStatus.TLS_VERSION_1_2
227 storeCertOverride(server.port, cert);
228 await startClient(server.port, 4, true);
231 // server that accepts 1.2->1.2 and a client max 1.1. expect fail
233 server = startServer(
235 Ci.nsITLSClientStatus.TLS_VERSION_1_2,
236 Ci.nsITLSClientStatus.TLS_VERSION_1_2,
239 storeCertOverride(server.port, cert);
240 await startClient(server.port, 2, false);
245 registerCleanupFunction(function () {
246 Services.prefs.clearUserPref("security.tls.version.max");
247 Services.prefs.clearUserPref("network.dns.localDomains");