Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / test / unit / test_httpssvc_iphint.js
blob70e4f5b7a0bf327d1e60eccdba1a0ea1ecff37e4
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/. */
5 "use strict";
7 let h2Port;
8 let trrServer;
10 const certOverrideService = Cc[
11 "@mozilla.org/security/certoverride;1"
12 ].getService(Ci.nsICertOverrideService);
13 const { TestUtils } = ChromeUtils.importESModule(
14 "resource://testing-common/TestUtils.sys.mjs"
17 add_setup(async function setup() {
18 h2Port = Services.env.get("MOZHTTP2_PORT");
19 Assert.notEqual(h2Port, null);
20 Assert.notEqual(h2Port, "");
22 trr_test_setup();
24 Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true);
25 Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true);
26 Services.prefs.setBoolPref(
27 "network.dns.https_rr.check_record_with_cname",
28 false
31 registerCleanupFunction(async () => {
32 trr_clear_prefs();
33 Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr");
34 Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc");
35 Services.prefs.clearUserPref("network.dns.disablePrefetch");
36 Services.prefs.clearUserPref(
37 "network.dns.https_rr.check_record_with_cname"
39 await trrServer.stop();
40 });
42 if (mozinfo.socketprocess_networking) {
43 Services.dns; // Needed to trigger socket process.
44 await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched);
46 });
48 // Test if IP hint addresses can be accessed as regular A/AAAA records.
49 add_task(async function testStoreiphint() {
50 trrServer = new TRRServer();
51 registerCleanupFunction(async () => {
52 await trrServer.stop();
53 });
54 await trrServer.start();
56 Services.prefs.setIntPref("network.trr.mode", 3);
57 Services.prefs.setCharPref(
58 "network.trr.uri",
59 `https://foo.example.com:${trrServer.port()}/dns-query`
62 await trrServer.registerDoHAnswers("test.iphint.com", "HTTPS", {
63 answers: [
65 name: "test.iphint.com",
66 ttl: 999,
67 type: "HTTPS",
68 flush: false,
69 data: {
70 priority: 1,
71 name: "test.iphint.com",
72 values: [
73 { key: "alpn", value: ["h2", "h3"] },
74 { key: "port", value: 8888 },
75 { key: "ipv4hint", value: ["1.2.3.4", "5.6.7.8"] },
76 { key: "ipv6hint", value: ["::1", "fe80::794f:6d2c:3d5e:7836"] },
81 });
83 let { inRecord } = await new TRRDNSListener("test.iphint.com", {
84 type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
85 });
87 let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
88 Assert.equal(inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).ttl, 999);
89 Assert.equal(answer[0].priority, 1);
90 Assert.equal(answer[0].name, "test.iphint.com");
91 Assert.equal(answer[0].values.length, 4);
92 Assert.deepEqual(
93 answer[0].values[0].QueryInterface(Ci.nsISVCParamAlpn).alpn,
94 ["h2", "h3"],
95 "got correct answer"
97 Assert.equal(
98 answer[0].values[1].QueryInterface(Ci.nsISVCParamPort).port,
99 8888,
100 "got correct answer"
102 Assert.equal(
103 answer[0].values[2].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[0]
104 .address,
105 "1.2.3.4",
106 "got correct answer"
108 Assert.equal(
109 answer[0].values[2].QueryInterface(Ci.nsISVCParamIPv4Hint).ipv4Hint[1]
110 .address,
111 "5.6.7.8",
112 "got correct answer"
114 Assert.equal(
115 answer[0].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[0]
116 .address,
117 "::1",
118 "got correct answer"
120 Assert.equal(
121 answer[0].values[3].QueryInterface(Ci.nsISVCParamIPv6Hint).ipv6Hint[1]
122 .address,
123 "fe80::794f:6d2c:3d5e:7836",
124 "got correct answer"
127 async function verifyAnswer(domain, flags, expectedAddresses) {
128 // eslint-disable-next-line no-shadow
129 let { inRecord } = await new TRRDNSListener(domain, {
130 flags,
131 expectedSuccess: false,
133 Assert.ok(inRecord);
134 inRecord.QueryInterface(Ci.nsIDNSAddrRecord);
135 let addresses = [];
136 while (inRecord.hasMore()) {
137 addresses.push(inRecord.getNextAddrAsString());
139 Assert.deepEqual(addresses, expectedAddresses);
140 Assert.equal(inRecord.ttl, 999);
143 await verifyAnswer("test.iphint.com", Ci.nsIDNSService.RESOLVE_IP_HINT, [
144 "1.2.3.4",
145 "5.6.7.8",
146 "::1",
147 "fe80::794f:6d2c:3d5e:7836",
150 await verifyAnswer(
151 "test.iphint.com",
152 Ci.nsIDNSService.RESOLVE_IP_HINT | Ci.nsIDNSService.RESOLVE_DISABLE_IPV4,
153 ["::1", "fe80::794f:6d2c:3d5e:7836"]
156 await verifyAnswer(
157 "test.iphint.com",
158 Ci.nsIDNSService.RESOLVE_IP_HINT | Ci.nsIDNSService.RESOLVE_DISABLE_IPV6,
159 ["1.2.3.4", "5.6.7.8"]
162 info("checking that IPv6 hints are ignored when disableIPv6 is true");
163 Services.prefs.setBoolPref("network.dns.disableIPv6", true);
164 await trrServer.registerDoHAnswers("testv6.iphint.com", "HTTPS", {
165 answers: [
167 name: "testv6.iphint.com",
168 ttl: 999,
169 type: "HTTPS",
170 flush: false,
171 data: {
172 priority: 1,
173 name: "testv6.iphint.com",
174 values: [
175 { key: "alpn", value: ["h2", "h3"] },
176 { key: "port", value: 8888 },
177 { key: "ipv4hint", value: ["1.2.3.4", "5.6.7.8"] },
178 { key: "ipv6hint", value: ["::1", "fe80::794f:6d2c:3d5e:7836"] },
185 ({ inRecord } = await new TRRDNSListener("testv6.iphint.com", {
186 type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
187 }));
188 Services.prefs.setBoolPref("network.dns.disableIPv6", false);
190 await verifyAnswer("testv6.iphint.com", Ci.nsIDNSService.RESOLVE_IP_HINT, [
191 "1.2.3.4",
192 "5.6.7.8",
195 await verifyAnswer(
196 "testv6.iphint.com",
197 Ci.nsIDNSService.RESOLVE_IP_HINT | Ci.nsIDNSService.RESOLVE_DISABLE_IPV6,
198 ["1.2.3.4", "5.6.7.8"]
201 await trrServer.stop();
204 function makeChan(url) {
205 let chan = NetUtil.newChannel({
206 uri: url,
207 loadUsingSystemPrincipal: true,
208 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
209 }).QueryInterface(Ci.nsIHttpChannel);
210 return chan;
213 function channelOpenPromise(chan, flags) {
214 return new Promise(resolve => {
215 function finish(req, buffer) {
216 resolve([req, buffer]);
218 chan.asyncOpen(new ChannelListener(finish, null, flags));
222 // Test if we can connect to the server with the IP hint address.
223 add_task(async function testConnectionWithiphint() {
224 Services.dns.clearCache(true);
225 Services.prefs.setIntPref("network.trr.mode", 3);
226 Services.prefs.setCharPref(
227 "network.trr.uri",
228 "https://127.0.0.1:" + h2Port + "/httpssvc_use_iphint"
231 // Resolving test.iphint.com should be failed.
232 let { inStatus } = await new TRRDNSListener("test.iphint.com", {
233 expectedSuccess: false,
235 Assert.equal(
236 inStatus,
237 Cr.NS_ERROR_UNKNOWN_HOST,
238 "status is NS_ERROR_UNKNOWN_HOST"
241 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
242 true
245 // The connection should be succeeded since the IP hint is 127.0.0.1.
246 let chan = makeChan(`http://test.iphint.com:8080/server-timing`);
247 // Note that the partitionKey stored in DNS cache would be
248 // "%28https%2Ciphint.com%29". The http request to test.iphint.com will be
249 // upgraded to https and the ip hint address will be used by the https
250 // request in the end.
251 let [req] = await channelOpenPromise(chan);
252 req.QueryInterface(Ci.nsIHttpChannel);
253 Assert.equal(req.getResponseHeader("x-connection-http2"), "yes");
255 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
256 false
259 await trrServer.stop();
262 // Test the case that we failed to use IP Hint address because DNS cache
263 // is bypassed.
264 add_task(async function testiphintWithFreshDNS() {
265 trrServer = new TRRServer();
266 await trrServer.start();
267 Services.prefs.setIntPref("network.trr.mode", 3);
268 Services.prefs.setCharPref(
269 "network.trr.uri",
270 `https://foo.example.com:${trrServer.port()}/dns-query`
272 // To make sure NS_HTTP_REFRESH_DNS not be cleared.
273 Services.prefs.setBoolPref("network.dns.disablePrefetch", true);
275 await trrServer.registerDoHAnswers("test.iphint.org", "HTTPS", {
276 answers: [
278 name: "test.iphint.org",
279 ttl: 55,
280 type: "HTTPS",
281 flush: false,
282 data: {
283 priority: 0,
284 name: "svc.iphint.net",
285 values: [],
291 await trrServer.registerDoHAnswers("svc.iphint.net", "HTTPS", {
292 answers: [
294 name: "svc.iphint.net",
295 ttl: 55,
296 type: "HTTPS",
297 flush: false,
298 data: {
299 priority: 1,
300 name: "svc.iphint.net",
301 values: [
302 { key: "alpn", value: "h2" },
303 { key: "port", value: h2Port },
304 { key: "ipv4hint", value: "127.0.0.1" },
311 let { inRecord } = await new TRRDNSListener("test.iphint.org", {
312 type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC,
315 let answer = inRecord.QueryInterface(Ci.nsIDNSHTTPSSVCRecord).records;
316 Assert.equal(answer[0].priority, 1);
317 Assert.equal(answer[0].name, "svc.iphint.net");
319 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
320 true
323 let chan = makeChan(`https://test.iphint.org/server-timing`);
324 chan.loadFlags |= Ci.nsIRequest.LOAD_FRESH_CONNECTION;
325 let [req] = await channelOpenPromise(
326 chan,
327 CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL
329 // Failed because there no A record for "svc.iphint.net".
330 Assert.equal(req.status, Cr.NS_ERROR_UNKNOWN_HOST);
332 await trrServer.registerDoHAnswers("svc.iphint.net", "A", {
333 answers: [
335 name: "svc.iphint.net",
336 ttl: 55,
337 type: "A",
338 flush: false,
339 data: "127.0.0.1",
344 chan = makeChan(`https://test.iphint.org/server-timing`);
345 chan.loadFlags |= Ci.nsIRequest.LOAD_FRESH_CONNECTION;
346 [req] = await channelOpenPromise(chan);
347 Assert.equal(req.protocolVersion, "h2");
348 let internal = req.QueryInterface(Ci.nsIHttpChannelInternal);
349 Assert.equal(internal.remotePort, h2Port);
351 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
352 false
354 await trrServer.stop();