test_trr_cname_chain.js (5836B)
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 let trrServer; 8 9 function makeChan(url) { 10 let chan = NetUtil.newChannel({ 11 uri: url, 12 loadUsingSystemPrincipal: true, 13 }).QueryInterface(Ci.nsIHttpChannel); 14 return chan; 15 } 16 17 function channelOpenPromise(chan) { 18 return new Promise(resolve => { 19 function finish(req, buffer) { 20 resolve([req, buffer]); 21 } 22 chan.asyncOpen(new ChannelListener(finish)); 23 }); 24 } 25 26 add_setup(async function setup() { 27 trr_test_setup(); 28 registerCleanupFunction(async () => { 29 trr_clear_prefs(); 30 }); 31 32 trrServer = new TRRServer(); 33 registerCleanupFunction(async () => { 34 await trrServer.stop(); 35 }); 36 await trrServer.start(); 37 dump(`port = ${trrServer.port()}\n`); 38 let chan = makeChan(`https://localhost:${trrServer.port()}/test?bla=some`); 39 let [, resp] = await channelOpenPromise(chan); 40 equal(resp, "<h1> 404 Path not found: /test</h1>"); 41 42 Services.dns.clearCache(true); 43 Services.prefs.setIntPref("network.trr.mode", 3); 44 Services.prefs.setCharPref( 45 "network.trr.uri", 46 `https://foo.example.com:${trrServer.port()}/dns-query` 47 ); 48 }); 49 50 add_task(async function test_follow_cnames_same_response() { 51 await trrServer.registerDoHAnswers("something.foo", "A", { 52 answers: [ 53 { 54 name: "something.foo", 55 ttl: 55, 56 type: "CNAME", 57 flush: false, 58 data: "other.foo", 59 }, 60 { 61 name: "other.foo", 62 ttl: 55, 63 type: "CNAME", 64 flush: false, 65 data: "bla.foo", 66 }, 67 { 68 name: "bla.foo", 69 ttl: 55, 70 type: "CNAME", 71 flush: false, 72 data: "xyz.foo", 73 }, 74 { 75 name: "xyz.foo", 76 ttl: 55, 77 type: "A", 78 flush: false, 79 data: "1.2.3.4", 80 }, 81 ], 82 }); 83 let { inRecord } = await new TRRDNSListener("something.foo", { 84 expectedAnswer: "1.2.3.4", 85 flags: Ci.nsIDNSService.RESOLVE_CANONICAL_NAME, 86 }); 87 equal(inRecord.QueryInterface(Ci.nsIDNSAddrRecord).canonicalName, "xyz.foo"); 88 89 await trrServer.registerDoHAnswers("a.foo", "A", { 90 answers: [ 91 { 92 name: "a.foo", 93 ttl: 55, 94 type: "CNAME", 95 flush: false, 96 data: "b.foo", 97 }, 98 ], 99 }); 100 await trrServer.registerDoHAnswers("b.foo", "A", { 101 answers: [ 102 { 103 name: "b.foo", 104 ttl: 55, 105 type: "A", 106 flush: false, 107 data: "2.3.4.5", 108 }, 109 ], 110 }); 111 await new TRRDNSListener("a.foo", { expectedAnswer: "2.3.4.5" }); 112 }); 113 114 add_task(async function test_cname_nodata() { 115 // Test that we don't needlessly follow cname chains when the RA flag is set 116 // on the response. 117 118 await trrServer.registerDoHAnswers("first.foo", "A", { 119 flags: 0x80, 120 answers: [ 121 { 122 name: "first.foo", 123 ttl: 55, 124 type: "CNAME", 125 flush: false, 126 data: "second.foo", 127 }, 128 { 129 name: "second.foo", 130 ttl: 55, 131 type: "A", 132 flush: false, 133 data: "1.2.3.4", 134 }, 135 ], 136 }); 137 await trrServer.registerDoHAnswers("first.foo", "AAAA", { 138 flags: 0x80, 139 answers: [ 140 { 141 name: "first.foo", 142 ttl: 55, 143 type: "CNAME", 144 flush: false, 145 data: "second.foo", 146 }, 147 ], 148 }); 149 150 await new TRRDNSListener("first.foo", { expectedAnswer: "1.2.3.4" }); 151 equal(await trrServer.requestCount("first.foo", "A"), 1); 152 equal(await trrServer.requestCount("first.foo", "AAAA"), 1); 153 equal(await trrServer.requestCount("second.foo", "A"), 0); 154 equal(await trrServer.requestCount("second.foo", "AAAA"), 0); 155 156 await trrServer.registerDoHAnswers("first.bar", "A", { 157 answers: [ 158 { 159 name: "first.bar", 160 ttl: 55, 161 type: "CNAME", 162 flush: false, 163 data: "second.bar", 164 }, 165 { 166 name: "second.bar", 167 ttl: 55, 168 type: "A", 169 flush: false, 170 data: "1.2.3.4", 171 }, 172 ], 173 }); 174 await trrServer.registerDoHAnswers("first.bar", "AAAA", { 175 answers: [ 176 { 177 name: "first.bar", 178 ttl: 55, 179 type: "CNAME", 180 flush: false, 181 data: "second.bar", 182 }, 183 ], 184 }); 185 186 await new TRRDNSListener("first.bar", { expectedAnswer: "1.2.3.4" }); 187 equal(await trrServer.requestCount("first.bar", "A"), 1); 188 equal(await trrServer.requestCount("first.bar", "AAAA"), 1); 189 equal(await trrServer.requestCount("second.bar", "A"), 0); // addr included in first response 190 equal(await trrServer.requestCount("second.bar", "AAAA"), 1); // will follow cname because no flag is set 191 192 // Check that it also works for HTTPS records 193 194 await trrServer.registerDoHAnswers("first.bar", "HTTPS", { 195 flags: 0x80, 196 answers: [ 197 { 198 name: "second.bar", 199 ttl: 55, 200 type: "HTTPS", 201 flush: false, 202 data: { 203 priority: 1, 204 name: "h3pool", 205 values: [ 206 { key: "alpn", value: ["h2", "h3"] }, 207 { key: "no-default-alpn" }, 208 { key: "port", value: 8888 }, 209 { key: "ipv4hint", value: "1.2.3.4" }, 210 { key: "echconfig", value: "123..." }, 211 { key: "ipv6hint", value: "::1" }, 212 ], 213 }, 214 }, 215 { 216 name: "first.bar", 217 ttl: 55, 218 type: "CNAME", 219 flush: false, 220 data: "second.bar", 221 }, 222 ], 223 }); 224 225 let { inStatus } = await new TRRDNSListener("first.bar", { 226 type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC, 227 }); 228 Assert.ok(Components.isSuccessCode(inStatus), `${inStatus} should work`); 229 equal(await trrServer.requestCount("first.bar", "HTTPS"), 1); 230 equal(await trrServer.requestCount("second.bar", "HTTPS"), 0); 231 });