test_httpssvc_ech_with_alpn.js (7136B)
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 const certOverrideService = Cc[ 10 "@mozilla.org/security/certoverride;1" 11 ].getService(Ci.nsICertOverrideService); 12 13 add_setup(async function setup() { 14 // Allow telemetry probes which may otherwise be disabled for some 15 // applications (e.g. Thunderbird). 16 Services.prefs.setBoolPref( 17 "toolkit.telemetry.testing.overrideProductsCheck", 18 true 19 ); 20 21 trr_test_setup(); 22 23 Services.prefs.setBoolPref("network.dns.upgrade_with_https_rr", true); 24 Services.prefs.setBoolPref("network.dns.use_https_rr_as_altsvc", true); 25 Services.prefs.setBoolPref("network.dns.echconfig.enabled", true); 26 Services.prefs.setBoolPref("network.dns.http3_echconfig.enabled", false); 27 Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0); 28 Services.prefs.setIntPref("network.trr.mode", Ci.nsIDNSService.MODE_TRRONLY); 29 30 // Set the server to always select http/1.1 31 Services.env.set("MOZ_TLS_ECH_ALPN_FLAG", 1); 32 33 await asyncStartTLSTestServer( 34 "EncryptedClientHelloServer", 35 "../../../security/manager/ssl/tests/unit/test_encrypted_client_hello" 36 ); 37 }); 38 39 registerCleanupFunction(async () => { 40 trr_clear_prefs(); 41 Services.prefs.clearUserPref("network.trr.mode"); 42 Services.prefs.clearUserPref("network.trr.uri"); 43 Services.prefs.clearUserPref("network.dns.upgrade_with_https_rr"); 44 Services.prefs.clearUserPref("network.dns.use_https_rr_as_altsvc"); 45 Services.prefs.clearUserPref("network.dns.echconfig.enabled"); 46 Services.prefs.clearUserPref("network.dns.http3_echconfig.enabled"); 47 Services.prefs.clearUserPref( 48 "network.dns.echconfig.fallback_to_origin_when_all_failed" 49 ); 50 Services.prefs.clearUserPref("network.http.speculative-parallel-limit"); 51 Services.prefs.clearUserPref("network.dns.port_prefixed_qname_https_rr"); 52 Services.env.set("MOZ_TLS_ECH_ALPN_FLAG", ""); 53 if (trrServer) { 54 await trrServer.stop(); 55 } 56 }); 57 58 function makeChan(url) { 59 let chan = NetUtil.newChannel({ 60 uri: url, 61 loadUsingSystemPrincipal: true, 62 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, 63 }).QueryInterface(Ci.nsIHttpChannel); 64 return chan; 65 } 66 67 function channelOpenPromise(chan, flags) { 68 return new Promise(resolve => { 69 function finish(req, buffer) { 70 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData( 71 false 72 ); 73 resolve([req, buffer]); 74 } 75 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData( 76 true 77 ); 78 chan.asyncOpen(new ChannelListener(finish, null, flags)); 79 }); 80 } 81 82 function ActivityObserver() {} 83 84 ActivityObserver.prototype = { 85 activites: [], 86 observeConnectionActivity( 87 aHost, 88 aPort, 89 aSSL, 90 aHasECH, 91 aIsHttp3, 92 aActivityType, 93 aActivitySubtype, 94 aTimestamp, 95 aExtraStringData 96 ) { 97 dump( 98 "*** Connection Activity 0x" + 99 aActivityType.toString(16) + 100 " 0x" + 101 aActivitySubtype.toString(16) + 102 " " + 103 aExtraStringData + 104 "\n" 105 ); 106 this.activites.push({ host: aHost, subType: aActivitySubtype }); 107 }, 108 }; 109 110 function checkHttpActivities(activites) { 111 let foundDNSAndSocket = false; 112 let foundSettingECH = false; 113 let foundConnectionCreated = false; 114 for (let activity of activites) { 115 switch (activity.subType) { 116 case Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_DNSANDSOCKET_CREATED: 117 case Ci.nsIHttpActivityObserver 118 .ACTIVITY_SUBTYPE_SPECULATIVE_DNSANDSOCKET_CREATED: 119 foundDNSAndSocket = true; 120 break; 121 case Ci.nsIHttpActivityDistributor.ACTIVITY_SUBTYPE_ECH_SET: 122 foundSettingECH = true; 123 break; 124 case Ci.nsIHttpActivityDistributor.ACTIVITY_SUBTYPE_CONNECTION_CREATED: 125 foundConnectionCreated = true; 126 break; 127 default: 128 break; 129 } 130 } 131 132 Assert.equal(foundDNSAndSocket, true, "Should have one DnsAndSock created"); 133 Assert.equal(foundSettingECH, true, "Should have echConfig"); 134 Assert.equal( 135 foundConnectionCreated, 136 true, 137 "Should have one connection created" 138 ); 139 } 140 141 async function testWrapper(alpnAdvertisement) { 142 const ECH_CONFIG_FIXED = 143 "AEn+DQBFTQAgACCKB1Y5SfrGIyk27W82xPpzWTDs3q72c04xSurDWlb9CgAEAAEAA2QWZWNoLXB1YmxpYy5leGFtcGxlLmNvbQAA"; 144 trrServer = new TRRServer(); 145 await trrServer.start(); 146 147 let observerService = Cc[ 148 "@mozilla.org/network/http-activity-distributor;1" 149 ].getService(Ci.nsIHttpActivityDistributor); 150 let observer = new ActivityObserver(); 151 observerService.addObserver(observer); 152 observerService.observeConnection = true; 153 154 Services.prefs.setCharPref( 155 "network.trr.uri", 156 `https://foo.example.com:${trrServer.port()}/dns-query` 157 ); 158 159 // Only the last record is valid to use. 160 await trrServer.registerDoHAnswers("ech-private.example.com", "HTTPS", { 161 answers: [ 162 { 163 name: "ech-private.example.com", 164 ttl: 55, 165 type: "HTTPS", 166 flush: false, 167 data: { 168 priority: 1, 169 name: "ech-private.example.com", 170 values: [ 171 { key: "alpn", value: alpnAdvertisement }, 172 { key: "port", value: 8443 }, 173 { 174 key: "echconfig", 175 value: ECH_CONFIG_FIXED, 176 needBase64Decode: true, 177 }, 178 ], 179 }, 180 }, 181 ], 182 }); 183 184 await trrServer.registerDoHAnswers("ech-private.example.com", "A", { 185 answers: [ 186 { 187 name: "ech-private.example.com", 188 ttl: 55, 189 type: "A", 190 flush: false, 191 data: "127.0.0.1", 192 }, 193 ], 194 }); 195 196 await new TRRDNSListener("ech-private.example.com", { 197 type: Ci.nsIDNSService.RESOLVE_TYPE_HTTPSSVC, 198 }); 199 200 HandshakeTelemetryHelpers.resetHistograms(); 201 let chan = makeChan(`https://ech-private.example.com`); 202 await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL); 203 let securityInfo = chan.securityInfo; 204 Assert.ok(securityInfo.isAcceptedEch, "This host should have accepted ECH"); 205 206 // Only check telemetry if network process is disabled. 207 if (!mozinfo.socketprocess_networking) { 208 HandshakeTelemetryHelpers.checkSuccess(["", "_ECH", "_FIRST_TRY"]); 209 HandshakeTelemetryHelpers.checkEmpty(["_CONSERVATIVE", "_ECH_GREASE"]); 210 } 211 212 await trrServer.stop(); 213 observerService.removeObserver(observer); 214 observerService.observeConnection = false; 215 216 let filtered = observer.activites.filter( 217 activity => activity.host === "ech-private.example.com" 218 ); 219 checkHttpActivities(filtered); 220 } 221 222 add_task(async function h1Advertised() { 223 await testWrapper(["http/1.1"]); 224 }); 225 226 add_task(async function h2Advertised() { 227 await testWrapper(["h2"]); 228 }); 229 230 add_task(async function h3Advertised() { 231 await testWrapper(["h3"]); 232 }); 233 234 add_task(async function h1h2Advertised() { 235 await testWrapper(["http/1.1", "h2"]); 236 }); 237 238 add_task(async function h2h3Advertised() { 239 await testWrapper(["h3", "h2"]); 240 }); 241 242 add_task(async function unknownAdvertised() { 243 await testWrapper(["foo"]); 244 });