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 // Allow telemetry probes which may otherwise be disabled for some
8 // applications (e.g. Thunderbird).
9 Services
.prefs
.setBoolPref(
10 "toolkit.telemetry.testing.overrideProductsCheck",
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
) {
79 onHandshakeDone(socket
, status
) {
80 info("TLS handshake done");
81 info(`TLS version used: ${status.tlsVersionUsed}`);
84 info("handshake done callback stopped - bailing");
88 let callback
= new InputStreamCallback(this.output
);
89 this.callbacks
.push(callback
);
90 this.input
.asyncWait(callback
, 0, 0, Services
.tm
.currentThread
);
97 this.callbacks
.forEach(callback
=> {
103 class ServerSocketListener
{
105 this.securityObservers
= [];
108 onSocketAccepted(socket
, transport
) {
109 info("accepted TLS client connection");
110 let connectionInfo
= transport
.securityCallbacks
.getInterface(
111 Ci
.nsITLSServerConnectionInfo
113 let input
= transport
.openInputStream(0, 0, 0);
114 let output
= transport
.openOutputStream(0, 0, 0);
115 let securityObserver
= new TLSServerSecurityObserver(input
, output
);
116 this.securityObservers
.push(securityObserver
);
117 connectionInfo
.setSecurityObserver(securityObserver
);
120 // For some reason we get input stream callback events after we've stopped
121 // listening, so this ensures we just drop those events.
123 info("onStopListening");
124 this.securityObservers
.forEach(observer
=> {
130 function startServer(
131 minServerVersion
= Ci
.nsITLSClientStatus
.TLS_VERSION_1_2
,
132 maxServerVersion
= Ci
.nsITLSClientStatus
.TLS_VERSION_1_3
134 let tlsServer
= Cc
["@mozilla.org/network/tls-server-socket;1"].createInstance(
135 Ci
.nsITLSServerSocket
137 tlsServer
.init(-1, true, -1);
138 tlsServer
.serverCert
= getTestServerCertificate();
139 tlsServer
.setVersionRange(minServerVersion
, maxServerVersion
);
140 tlsServer
.setSessionTickets(false);
141 tlsServer
.asyncListen(new ServerSocketListener());
142 storeCertOverride(tlsServer
.port
, tlsServer
.serverCert
);
146 const hostname
= "example.com";
148 function storeCertOverride(port
, cert
) {
149 let certOverrideService
= Cc
[
150 "@mozilla.org/security/certoverride;1"
151 ].getService(Ci
.nsICertOverrideService
);
152 certOverrideService
.rememberValidityOverride(hostname
, port
, {}, cert
, true);
155 function startClient(port
, useGREASE
, beConservative
) {
156 HandshakeTelemetryHelpers
.resetHistograms();
157 let flavors
= ["", "_FIRST_TRY"];
158 let nonflavors
= ["_ECH"];
161 Services
.prefs
.setIntPref("security.tls.ech.grease_probability", 100);
163 Services
.prefs
.setIntPref("security.tls.ech.grease_probability", 0);
166 let req
= new XMLHttpRequest();
167 req
.open("GET", `https://${hostname}:${port}`);
169 if (beConservative
) {
170 // We don't have a way to set DONT_TRY_ECH at the moment.
171 let internalChannel
= req
.channel
.QueryInterface(Ci
.nsIHttpChannelInternal
);
172 internalChannel
.beConservative
= beConservative
;
173 flavors
.push("_CONSERVATIVE");
175 nonflavors
.push("_CONSERVATIVE");
178 //GREASE is only used if enabled and not in conservative mode.
179 if (useGREASE
&& !beConservative
) {
180 flavors
.push("_ECH_GREASE");
182 nonflavors
.push("_ECH_GREASE");
185 return new Promise(resolve
=> {
187 equal(req
.responseText
, "OK", "response text should be 'OK'");
189 // Only check telemetry if network process is disabled.
190 if (!mozinfo
.socketprocess_networking
) {
191 HandshakeTelemetryHelpers
.checkSuccess(flavors
);
192 HandshakeTelemetryHelpers
.checkEmpty(nonflavors
);
197 req
.onerror
= () => {
198 ok(false, `should not have gotten an error`);
207 Services
.prefs
.setIntPref("security.tls.version.max", 4);
208 Services
.prefs
.setCharPref("network.dns.localDomains", hostname
);
209 Services
.prefs
.setIntPref("network.http.speculative-parallel-limit", 0);
213 add_task(async
function GreaseYConservativeN() {
214 // First run a server that accepts TLS 1.2 and 1.3. A conservative client
215 // should succeed in connecting.
216 let server
= startServer();
220 true /*be conservative*/,
221 false /*should succeed*/
226 add_task(async
function GreaseNConservativeY() {
227 // First run a server that accepts TLS 1.2 and 1.3. A conservative client
228 // should succeed in connecting.
229 let server
= startServer();
233 false /*be conservative*/,
234 true /*should succeed*/
239 add_task(async
function GreaseYConservativeY() {
240 // First run a server that accepts TLS 1.2 and 1.3. A conservative client
241 // should succeed in connecting.
242 let server
= startServer();
246 true /*be conservative*/,
247 true /*should succeed*/
252 add_task(async
function GreaseNConservativeN() {
253 // First run a server that accepts TLS 1.2 and 1.3. A conservative client
254 // should succeed in connecting.
255 let server
= startServer();
259 false /*be conservative*/,
260 false /*should succeed*/
265 registerCleanupFunction(function () {
266 Services
.prefs
.clearUserPref("security.tls.version.max");
267 Services
.prefs
.clearUserPref("network.dns.localDomains");
268 Services
.prefs
.clearUserPref("security.tls.ech.grease_probability");
269 Services
.prefs
.clearUserPref("network.http.speculative-parallel-limit");