test_trr_https_rr_with_cname.js (6199B)
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/. */ 4 5 "use strict"; 6 7 var { setTimeout } = ChromeUtils.importESModule( 8 "resource://gre/modules/Timer.sys.mjs" 9 ); 10 11 const { TestUtils } = ChromeUtils.importESModule( 12 "resource://testing-common/TestUtils.sys.mjs" 13 ); 14 15 let h2Port; 16 let h3Port; 17 let h3EchConfig; 18 19 function makeChan(url) { 20 let chan = NetUtil.newChannel({ 21 uri: url, 22 loadUsingSystemPrincipal: true, 23 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, 24 }).QueryInterface(Ci.nsIHttpChannel); 25 return chan; 26 } 27 28 function channelOpenPromise(chan, flags) { 29 return new Promise(resolve => { 30 function finish(req, buffer) { 31 resolve([req, buffer]); 32 } 33 chan.asyncOpen(new ChannelListener(finish, null, flags)); 34 }); 35 } 36 37 add_setup(async function setup() { 38 if (mozinfo.socketprocess_networking) { 39 Services.dns; // Needed to trigger socket process. 40 await TestUtils.waitForCondition(() => Services.io.socketProcessLaunched); 41 } 42 43 Services.prefs.setBoolPref("network.dns.port_prefixed_qname_https_rr", false); 44 45 trr_test_setup(); 46 registerCleanupFunction(async () => { 47 trr_clear_prefs(); 48 Services.prefs.clearUserPref("network.dns.port_prefixed_qname_https_rr"); 49 }); 50 51 h2Port = Services.env.get("MOZHTTP2_PORT"); 52 Assert.notEqual(h2Port, null); 53 Assert.notEqual(h2Port, ""); 54 55 h3Port = Services.env.get("MOZHTTP3_PORT_ECH"); 56 Assert.notEqual(h3Port, null); 57 Assert.notEqual(h3Port, ""); 58 59 h3EchConfig = Services.env.get("MOZHTTP3_ECH"); 60 Assert.notEqual(h3EchConfig, null); 61 Assert.notEqual(h3EchConfig, ""); 62 }); 63 64 async function do_test_https_rr_records( 65 host, 66 targetName1, 67 port1, 68 targetName2, 69 port2, 70 cname, 71 expectedVersion 72 ) { 73 Services.obs.notifyObservers(null, "net:cancel-all-connections"); 74 // eslint-disable-next-line mozilla/no-arbitrary-setTimeout 75 await new Promise(resolve => setTimeout(resolve, 1000)); 76 77 Services.dns.clearCache(true); 78 79 let trrServer = new TRRServer(); 80 registerCleanupFunction(async () => { 81 await trrServer.stop(); 82 }); 83 await trrServer.start(); 84 Services.prefs.setIntPref("network.trr.mode", 3); 85 Services.prefs.setCharPref( 86 "network.trr.uri", 87 `https://foo.example.com:${trrServer.port()}/dns-query` 88 ); 89 90 await trrServer.registerDoHAnswers(host, "HTTPS", { 91 answers: [ 92 { 93 name: host, 94 ttl: 55, 95 type: "HTTPS", 96 flush: false, 97 data: { 98 priority: 1, 99 name: targetName1, 100 values: [ 101 { key: "alpn", value: "h3" }, 102 { key: "port", value: port1 }, 103 { 104 key: "echconfig", 105 value: h3EchConfig, 106 needBase64Decode: true, 107 }, 108 ], 109 }, 110 }, 111 { 112 name: host, 113 ttl: 55, 114 type: "HTTPS", 115 flush: false, 116 data: { 117 priority: 1, 118 name: targetName2, 119 values: [ 120 { key: "alpn", value: "h3" }, 121 { key: "port", value: port2 }, 122 { 123 key: "echconfig", 124 value: h3EchConfig, 125 needBase64Decode: true, 126 }, 127 ], 128 }, 129 }, 130 ], 131 }); 132 133 await trrServer.registerDoHAnswers(host, "A", { 134 answers: [ 135 { 136 name: host, 137 ttl: 55, 138 type: "CNAME", 139 flush: false, 140 data: cname, 141 }, 142 { 143 name: cname, 144 ttl: 55, 145 type: "A", 146 flush: false, 147 data: "127.0.0.1", 148 }, 149 ], 150 }); 151 152 await trrServer.registerDoHAnswers(cname, "A", { 153 answers: [ 154 { 155 name: cname, 156 ttl: 55, 157 type: "A", 158 flush: false, 159 data: "127.0.0.1", 160 }, 161 ], 162 }); 163 164 let { inRecord } = await new TRRDNSListener(host, { 165 expectedAnswer: "127.0.0.1", 166 flags: Ci.nsIDNSService.RESOLVE_CANONICAL_NAME, 167 }); 168 equal(inRecord.QueryInterface(Ci.nsIDNSAddrRecord).canonicalName, cname); 169 170 let chan = makeChan(`https://${host}:${h2Port}/`); 171 let [req] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL); 172 Assert.equal(req.protocolVersion, expectedVersion); 173 await trrServer.stop(); 174 } 175 176 // Test the case that the pref is off and the cname is not the same as the 177 // targetName. The expected protocol version being "h3" means that the last 178 // svcb record is used. 179 add_task(async function test_https_rr_with_unmatched_cname() { 180 Services.prefs.setBoolPref( 181 "network.dns.https_rr.check_record_with_cname", 182 false 183 ); 184 await do_test_https_rr_records( 185 "alt1.example.com", 186 "alt1.example.com", 187 h3Port, 188 "not_used", 189 h3Port, 190 "test.cname1.com", 191 "h3" 192 ); 193 }); 194 195 // Test the case that the pref is on and the cname is not the same as the 196 // targetName. Since there is no svcb record can be used, we fallback to "h2". 197 add_task(async function test_https_rr_with_unmatched_cname_1() { 198 Services.prefs.setBoolPref( 199 "network.dns.https_rr.check_record_with_cname", 200 true 201 ); 202 await do_test_https_rr_records( 203 "alt1.example.com", 204 "alt1.example.com", 205 h3Port, 206 "not_used", 207 h3Port, 208 "test.cname1.com", 209 "h2" 210 ); 211 }); 212 213 // Test the case that the pref is on and the cname is matched. We failed to 214 // connect to the first record, but we successfully connect with the second one. 215 add_task(async function test_https_rr_with_matched_cname() { 216 Services.prefs.setBoolPref( 217 "network.dns.https_rr.check_record_with_cname", 218 true 219 ); 220 await do_test_https_rr_records( 221 "alt1.example.com", 222 "not_used", 223 h3Port, 224 "alt2.example.com", 225 h3Port, 226 "alt2.example.com", 227 "h3" 228 ); 229 }); 230 231 // Test the case that the pref is on and both records are failed to connect. 232 // We can only fallback to "h2" when another pref is on. 233 add_task(async function test_https_rr_with_matched_cname_1() { 234 Services.prefs.setBoolPref( 235 "network.dns.echconfig.fallback_to_origin_when_all_failed", 236 true 237 ); 238 await do_test_https_rr_records( 239 "alt1.example.com", 240 "not_used", 241 h3Port, 242 "alt2.example.com", 243 h2Port, 244 "alt2.example.com", 245 "h2" 246 ); 247 });