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/. */
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
, "");
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",
31 registerCleanupFunction(async () => {
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();
42 if (mozinfo
.socketprocess_networking
) {
43 Services
.dns
; // Needed to trigger socket process.
44 await TestUtils
.waitForCondition(() => Services
.io
.socketProcessLaunched
);
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();
54 await trrServer
.start();
56 Services
.prefs
.setIntPref("network.trr.mode", 3);
57 Services
.prefs
.setCharPref(
59 `https://foo.example.com:${trrServer.port()}/dns-query`
62 await trrServer
.registerDoHAnswers("test.iphint.com", "HTTPS", {
65 name
: "test.iphint.com",
71 name
: "test.iphint.com",
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"] },
83 let { inRecord
} = await
new TRRDNSListener("test.iphint.com", {
84 type
: Ci
.nsIDNSService
.RESOLVE_TYPE_HTTPSSVC
,
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);
93 answer
[0].values
[0].QueryInterface(Ci
.nsISVCParamAlpn
).alpn
,
98 answer
[0].values
[1].QueryInterface(Ci
.nsISVCParamPort
).port
,
103 answer
[0].values
[2].QueryInterface(Ci
.nsISVCParamIPv4Hint
).ipv4Hint
[0]
109 answer
[0].values
[2].QueryInterface(Ci
.nsISVCParamIPv4Hint
).ipv4Hint
[1]
115 answer
[0].values
[3].QueryInterface(Ci
.nsISVCParamIPv6Hint
).ipv6Hint
[0]
121 answer
[0].values
[3].QueryInterface(Ci
.nsISVCParamIPv6Hint
).ipv6Hint
[1]
123 "fe80::794f:6d2c:3d5e:7836",
127 async
function verifyAnswer(domain
, flags
, expectedAddresses
) {
128 // eslint-disable-next-line no-shadow
129 let { inRecord
} = await
new TRRDNSListener(domain
, {
131 expectedSuccess
: false,
134 inRecord
.QueryInterface(Ci
.nsIDNSAddrRecord
);
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
, [
147 "fe80::794f:6d2c:3d5e:7836",
152 Ci
.nsIDNSService
.RESOLVE_IP_HINT
| Ci
.nsIDNSService
.RESOLVE_DISABLE_IPV4
,
153 ["::1", "fe80::794f:6d2c:3d5e:7836"]
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", {
167 name
: "testv6.iphint.com",
173 name
: "testv6.iphint.com",
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
,
188 Services
.prefs
.setBoolPref("network.dns.disableIPv6", false);
190 await
verifyAnswer("testv6.iphint.com", Ci
.nsIDNSService
.RESOLVE_IP_HINT
, [
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({
207 loadUsingSystemPrincipal
: true,
208 contentPolicyType
: Ci
.nsIContentPolicy
.TYPE_DOCUMENT
,
209 }).QueryInterface(Ci
.nsIHttpChannel
);
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(
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,
237 Cr
.NS_ERROR_UNKNOWN_HOST
,
238 "status is NS_ERROR_UNKNOWN_HOST"
241 certOverrideService
.setDisableAllSecurityChecksAndLetAttackersInterceptMyData(
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(
259 await trrServer
.stop();
262 // Test the case that we failed to use IP Hint address because DNS cache
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(
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", {
278 name
: "test.iphint.org",
284 name
: "svc.iphint.net",
291 await trrServer
.registerDoHAnswers("svc.iphint.net", "HTTPS", {
294 name
: "svc.iphint.net",
300 name
: "svc.iphint.net",
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(
323 let chan
= makeChan(`https://test.iphint.org/server-timing`);
324 chan
.loadFlags
|= Ci
.nsIRequest
.LOAD_FRESH_CONNECTION
;
325 let [req
] = await
channelOpenPromise(
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", {
335 name
: "svc.iphint.net",
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(
354 await trrServer
.stop();