test_ip_address_space_lna_glean.js (7411B)
1 "use strict"; 2 3 const override = Cc["@mozilla.org/network/native-dns-override;1"].getService( 4 Ci.nsINativeDNSResolverOverride 5 ); 6 const mockNetwork = Cc[ 7 "@mozilla.org/network/mock-network-controller;1" 8 ].getService(Ci.nsIMockNetworkLayerController); 9 const certOverrideService = Cc[ 10 "@mozilla.org/security/certoverride;1" 11 ].getService(Ci.nsICertOverrideService); 12 13 const { AppConstants } = ChromeUtils.importESModule( 14 "resource://gre/modules/AppConstants.sys.mjs" 15 ); 16 17 const { NodeHTTPServer, NodeHTTPSServer } = ChromeUtils.importESModule( 18 "resource://testing-common/NodeServer.sys.mjs" 19 ); 20 21 const DOMAIN = "example.org"; 22 23 function makeChan(url, expected) { 24 let chan = NetUtil.newChannel({ 25 uri: url, 26 loadUsingSystemPrincipal: true, 27 contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT, 28 }).QueryInterface(Ci.nsIHttpChannel); 29 30 if ( 31 expected.PublicToPrivateHttp !== undefined || 32 expected.PublicToLocalHttp !== undefined || 33 expected.PublicToPublicHttp !== undefined || 34 expected.PublicToPrivateHttps !== undefined || 35 expected.PublicToLocalHttps !== undefined || 36 expected.PublicToPublicHttp !== undefined 37 ) { 38 chan.loadInfo.parentIpAddressSpace = Ci.nsILoadInfo.Public; 39 } else if ( 40 expected.PrivateToLocalHttp !== undefined || 41 expected.PrivateToPrivateHttp !== undefined || 42 expected.PrivateToLocalHttps !== undefined || 43 expected.PrivateToPrivateHttps !== undefined 44 ) { 45 chan.loadInfo.parentIpAddressSpace = Ci.nsILoadInfo.Private; 46 } 47 return chan; 48 } 49 50 function channelOpenPromise(chan, flags) { 51 return new Promise(resolve => { 52 function finish(req, buffer) { 53 resolve([req, buffer]); 54 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData( 55 false 56 ); 57 } 58 certOverrideService.setDisableAllSecurityChecksAndLetAttackersInterceptMyData( 59 true 60 ); 61 chan.asyncOpen(new ChannelListener(finish, null, flags)); 62 }); 63 } 64 65 let server; 66 67 add_setup(async function setup() { 68 Services.prefs.setBoolPref("network.socket.attach_mock_network_layer", true); 69 70 Services.fog.initializeFOG(); 71 72 server = new NodeHTTPServer(); 73 await server.start(); 74 registerCleanupFunction(async () => { 75 Services.prefs.clearUserPref("network.disable-localhost-when-offline"); 76 Services.prefs.clearUserPref("network.dns.use_override_as_peer_address"); 77 Services.prefs.clearUserPref("dom.security.https_only_mode"); 78 Services.prefs.clearUserPref("dom.security.https_first"); 79 Services.prefs.clearUserPref("dom.security.https_first_schemeless"); 80 Services.prefs.clearUserPref("network.socket.attach_mock_network_layer"); 81 await server.stop(); 82 }); 83 }); 84 85 function verifyGleanValues(aDescription, aExpected) { 86 info(aDescription); 87 88 let privateToLocalHttp = aExpected.PrivateToLocalHttp || null; 89 let publicToPrivateHttp = aExpected.PublicToPrivateHttp || null; 90 let publicToLocalHttp = aExpected.PublicToLocalHttp || null; 91 let privateToLocalHttps = aExpected.PrivateToLocalHttps || null; 92 let publicToPrivateHttps = aExpected.PublicToPrivateHttps || null; 93 let publicToLocalHttps = aExpected.PublicToLocalHttps || null; 94 95 let glean = Glean.networking.localNetworkAccess; 96 Assert.equal( 97 glean.private_to_local_http.testGetValue(), 98 privateToLocalHttp, 99 "verify private_to_local_http" 100 ); 101 Assert.equal( 102 glean.public_to_private_http.testGetValue(), 103 publicToPrivateHttp, 104 "verify public_to_private_http" 105 ); 106 Assert.equal( 107 glean.public_to_local_http.testGetValue(), 108 publicToLocalHttp, 109 "verify public_to_local_http" 110 ); 111 Assert.equal( 112 glean.private_to_local_https.testGetValue(), 113 privateToLocalHttps, 114 "verify private_to_local_http" 115 ); 116 Assert.equal( 117 glean.public_to_private_https.testGetValue(), 118 publicToPrivateHttps, 119 "verify public_to_private_http" 120 ); 121 Assert.equal( 122 glean.public_to_local_https.testGetValue(), 123 publicToLocalHttps, 124 "verify public_to_local_http" 125 ); 126 127 Assert.equal( 128 glean.public_to_local_https.testGetValue(), 129 publicToLocalHttps, 130 "verify public_to_local_http" 131 ); 132 133 if ( 134 privateToLocalHttp || 135 publicToPrivateHttp || 136 publicToLocalHttp || 137 privateToLocalHttps || 138 publicToPrivateHttps || 139 publicToLocalHttps 140 ) { 141 Assert.equal( 142 glean.success.testGetValue(), 143 1, 144 "verify local_network_access_success" 145 ); 146 // XXX (sunil) add test for local_network_access_failure cases 147 } 148 } 149 150 async function do_test(ip, expected, srcPort, dstPort) { 151 Services.fog.testResetFOG(); 152 153 override.addIPOverride(DOMAIN, ip); 154 let fromAddr = mockNetwork.createScriptableNetAddr(ip, srcPort ?? 80); 155 let toAddr = mockNetwork.createScriptableNetAddr( 156 fromAddr.family == Ci.nsINetAddr.FAMILY_INET ? "127.0.0.1" : "::1", 157 dstPort ?? server.port() 158 ); 159 160 mockNetwork.addNetAddrOverride(fromAddr, toAddr); 161 162 info(`do_test ${ip}, ${fromAddr} -> ${toAddr}`); 163 164 let chan = makeChan(`http://${DOMAIN}`, expected); 165 let [req] = await channelOpenPromise(chan); 166 167 info( 168 "req.remoteAddress=" + 169 req.QueryInterface(Ci.nsIHttpChannelInternal).remoteAddress 170 ); 171 172 if (expected.PublicToPrivateHttp) { 173 Assert.equal(chan.loadInfo.ipAddressSpace, Ci.nsILoadInfo.Private); 174 } else if (expected.PrivateToLocalHttp || expected.PrivateToLocalHttp) { 175 Assert.equal(chan.loadInfo.ipAddressSpace, Ci.nsILoadInfo.Local); 176 } 177 178 verifyGleanValues(`test ip=${ip}`, expected); 179 180 Services.dns.clearCache(false); 181 override.clearOverrides(); 182 mockNetwork.clearNetAddrOverrides(); 183 Services.obs.notifyObservers(null, "net:prune-all-connections"); 184 } 185 186 add_task(async function test_lna_http() { 187 Services.prefs.setBoolPref("dom.security.https_only_mode", false); 188 Services.prefs.setBoolPref("dom.security.https_first", false); 189 Services.prefs.setBoolPref("dom.security.https_first_schemeless", false); 190 191 await do_test("10.0.0.1", { PublicToPrivateHttp: 1 }); 192 193 // NO LNA access do not increment 194 await do_test("10.0.0.1", { PrivateToPrivateHttp: 0 }); 195 await do_test("2.2.2.2", { PublicToPublicHttp: 0 }); 196 197 await do_test("100.64.0.1", { PublicToPrivateHttp: 1 }); 198 await do_test("127.0.0.1", { PublicToLocalHttp: 1 }); 199 await do_test("127.0.0.1", { PrivateToLocalHttp: 1 }); 200 if (AppConstants.platform != "android") { 201 await do_test("::1", { PrivateToLocalHttp: 1 }); 202 } 203 }); 204 205 add_task(async function test_lna_https() { 206 Services.prefs.setBoolPref("dom.security.https_only_mode", true); 207 let httpsServer = new NodeHTTPSServer(); 208 await httpsServer.start(); 209 registerCleanupFunction(async () => { 210 await httpsServer.stop(); 211 }); 212 await do_test( 213 "10.0.0.1", 214 { PublicToPrivateHttps: 1 }, 215 443, 216 httpsServer.port() 217 ); 218 219 // NO LNA access do not increment 220 await do_test( 221 "10.0.0.1", 222 { PrivateToPrivateHttps: 0 }, 223 443, 224 httpsServer.port() 225 ); 226 await do_test( 227 "2.2.2.2", 228 { PublicToPublicHttps: 0 }, 229 443, 230 httpsServer.port(), 231 true 232 ); 233 234 await do_test( 235 "100.64.0.1", 236 { PublicToPrivateHttps: 1 }, 237 443, 238 httpsServer.port() 239 ); 240 await do_test( 241 "127.0.0.1", 242 { PublicToLocalHttps: 1 }, 243 443, 244 httpsServer.port() 245 ); 246 await do_test( 247 "127.0.0.1", 248 { PrivateToLocalHttps: 1 }, 249 443, 250 httpsServer.port() 251 ); 252 if (AppConstants.platform != "android") { 253 await do_test("::1", { PrivateToLocalHttps: 1 }, 443, httpsServer.port()); 254 } 255 });