forked from mirrors/gecko-dev
Bug 1500533 - Ensure that TLS session resumption tickets are only consumed if the channel isn't isolated by anti-tracking checks; r=michal,baku
Differential Revision: https://phabricator.services.mozilla.com/D26996 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
4b2a06ae0f
commit
ccfae51c32
11 changed files with 122 additions and 2 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -178,6 +178,11 @@ http://another-tracking.example.net:80
|
||||||
http://itisatracker.org:80
|
http://itisatracker.org:80
|
||||||
https://itisatracker.org:443
|
https://itisatracker.org:443
|
||||||
http://trackertest.org:80
|
http://trackertest.org:80
|
||||||
|
#
|
||||||
|
# Used while testing TLS session ticket resumption for third-party trackers (bug 1500533)
|
||||||
|
# (DO NOT USE THIS HOST IN OTHER TESTS!)
|
||||||
|
#
|
||||||
|
https://tlsresumptiontest.example.org:443
|
||||||
|
|
||||||
https://malware.example.com:443
|
https://malware.example.com:443
|
||||||
https://unwanted.example.com:443
|
https://unwanted.example.com:443
|
||||||
|
|
|
||||||
|
|
@ -625,9 +625,13 @@ nsresult nsHttpChannel::ContinueOnBeforeConnect(bool aShouldUpgrade,
|
||||||
mCaps |= NS_HTTP_DISABLE_TRR;
|
mCaps |= NS_HTTP_DISABLE_TRR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isIsolated = mPrivateBrowsing ||
|
||||||
|
!AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
|
||||||
|
this, mURI, nullptr);
|
||||||
|
|
||||||
// Finalize ConnectionInfo flags before SpeculativeConnect
|
// Finalize ConnectionInfo flags before SpeculativeConnect
|
||||||
mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
|
mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
|
||||||
mConnectionInfo->SetPrivate(mPrivateBrowsing);
|
mConnectionInfo->SetPrivate(isIsolated);
|
||||||
mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY);
|
mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY);
|
||||||
mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE) ||
|
mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE) ||
|
||||||
mBeConservative);
|
mBeConservative);
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ add_test(function test_sockets() {
|
||||||
});
|
});
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
|
Services.prefs.setBoolPref("network.cookieSettings.unblocked_for_testing", true);
|
||||||
|
|
||||||
let ioService = Cc["@mozilla.org/network/io-service;1"]
|
let ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||||
.getService(Ci.nsIIOService);
|
.getService(Ci.nsIIOService);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1200,6 +1200,7 @@ function resetPrefs() {
|
||||||
prefs.setBoolPref("network.http.altsvc.enabled", altsvcpref1);
|
prefs.setBoolPref("network.http.altsvc.enabled", altsvcpref1);
|
||||||
prefs.setBoolPref("network.http.altsvc.oe", altsvcpref2);
|
prefs.setBoolPref("network.http.altsvc.oe", altsvcpref2);
|
||||||
prefs.clearUserPref("network.dns.localDomains");
|
prefs.clearUserPref("network.dns.localDomains");
|
||||||
|
prefs.clearUserPref("network.cookieSettings.unblocked_for_testing");
|
||||||
}
|
}
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
|
|
@ -1235,6 +1236,7 @@ function run_test() {
|
||||||
prefs.setBoolPref("network.http.altsvc.enabled", true);
|
prefs.setBoolPref("network.http.altsvc.enabled", true);
|
||||||
prefs.setBoolPref("network.http.altsvc.oe", true);
|
prefs.setBoolPref("network.http.altsvc.oe", true);
|
||||||
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");
|
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");
|
||||||
|
prefs.setBoolPref("network.cookieSettings.unblocked_for_testing", true);
|
||||||
|
|
||||||
loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
|
loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2484,6 +2484,12 @@ static nsresult nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & nsISocketProvider::NO_PERMANENT_STORAGE) {
|
||||||
|
if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_SESSION_TICKETS, false)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ skip-if = serviceworker_e10s
|
||||||
[browser_storageAccessSandboxed.js]
|
[browser_storageAccessSandboxed.js]
|
||||||
skip-if = serviceworker_e10s
|
skip-if = serviceworker_e10s
|
||||||
[browser_storageAccessWithHeuristics.js]
|
[browser_storageAccessWithHeuristics.js]
|
||||||
|
[browser_tlsSessionTickets.js]
|
||||||
[browser_allowPermissionForTracker.js]
|
[browser_allowPermissionForTracker.js]
|
||||||
[browser_denyPermissionForTracker.js]
|
[browser_denyPermissionForTracker.js]
|
||||||
[browser_localStorageEvents.js]
|
[browser_localStorageEvents.js]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
add_task(async function() {
|
||||||
|
info("Starting tlsSessionTickets test");
|
||||||
|
|
||||||
|
await SpecialPowers.flushPrefEnv();
|
||||||
|
await SpecialPowers.pushPrefEnv({"set": [
|
||||||
|
["browser.cache.disk.enable", false],
|
||||||
|
["browser.cache.memory.enable", false],
|
||||||
|
["browser.contentblocking.allowlist.annotations.enabled", true],
|
||||||
|
["browser.contentblocking.allowlist.storage.enabled", true],
|
||||||
|
["network.cookie.cookieBehavior", Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER],
|
||||||
|
["privacy.trackingprotection.enabled", false],
|
||||||
|
["privacy.trackingprotection.pbmode.enabled", false],
|
||||||
|
["privacy.trackingprotection.annotate_channels", true],
|
||||||
|
]});
|
||||||
|
|
||||||
|
await UrlClassifierTestUtils.addTestTrackers();
|
||||||
|
|
||||||
|
info("Creating a new tab");
|
||||||
|
let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE);
|
||||||
|
gBrowser.selectedTab = tab;
|
||||||
|
|
||||||
|
let browser = gBrowser.getBrowserForTab(tab);
|
||||||
|
await BrowserTestUtils.browserLoaded(browser);
|
||||||
|
|
||||||
|
const trackingURL = "https://tlsresumptiontest.example.org/browser/toolkit/components/antitracking/test/browser/empty.js";
|
||||||
|
const kTopic = "http-on-examine-response";
|
||||||
|
|
||||||
|
let resumedState = [];
|
||||||
|
let hashKeys = [];
|
||||||
|
|
||||||
|
function observer(subject, topic, data) {
|
||||||
|
if (topic != kTopic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
subject.QueryInterface(Ci.nsIChannel);
|
||||||
|
if (subject.URI.spec != trackingURL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resumedState.push(subject.securityInfo
|
||||||
|
.QueryInterface(Ci.nsISSLSocketControl)
|
||||||
|
.resumed);
|
||||||
|
hashKeys.push(subject.QueryInterface(Ci.nsIHttpChannelInternal)
|
||||||
|
.connectionInfoHashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.addObserver(observer, kTopic);
|
||||||
|
registerCleanupFunction(() => Services.obs.removeObserver(observer, kTopic));
|
||||||
|
|
||||||
|
info("Loading tracking scripts and tracking images");
|
||||||
|
await ContentTask.spawn(browser, {trackingURL}, async function(obj) {
|
||||||
|
{
|
||||||
|
let src = content.document.createElement("script");
|
||||||
|
let p = new content.Promise(resolve => { src.onload = resolve; });
|
||||||
|
content.document.body.appendChild(src);
|
||||||
|
src.src = obj.trackingURL;
|
||||||
|
await p;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load our tracking URL two more times, but this time in the first-party context.
|
||||||
|
// The TLS session should be resumed the second time here.
|
||||||
|
await fetch(trackingURL);
|
||||||
|
// Wait a little bit before issuing the second load to ensure both don't happen
|
||||||
|
// at the same time.
|
||||||
|
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
|
await fetch(trackingURL).then(() => {
|
||||||
|
is(resumedState.length, 3, "We should have observed 3 loads for " + trackingURL);
|
||||||
|
ok(!resumedState[0], "The first load should NOT have been resumed");
|
||||||
|
ok(!resumedState[1], "The second load should NOT have been resumed");
|
||||||
|
ok(resumedState[2], "The third load SHOULD have been resumed");
|
||||||
|
|
||||||
|
// We also verify that the hashKey of the first connection is different to
|
||||||
|
// both the second and third connections, and that the hashKey of the
|
||||||
|
// second and third connections are the same. The reason why this check is
|
||||||
|
// done is that the private bit on the connection info object is used to
|
||||||
|
// construct the hash key, so when the connection is isolated because it
|
||||||
|
// comes from a third-party tracker context, its hash key must be
|
||||||
|
// different.
|
||||||
|
is(hashKeys.length, 3, "We should have observed 3 loads for " + trackingURL);
|
||||||
|
is(hashKeys[1], hashKeys[2], "The second and third hash keys should match");
|
||||||
|
isnot(hashKeys[0], hashKeys[1], "The first and second hash keys should not match");
|
||||||
|
});
|
||||||
|
|
||||||
|
info("Removing the tab");
|
||||||
|
BrowserTestUtils.removeTab(tab);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function() {
|
||||||
|
info("Cleaning up.");
|
||||||
|
await new Promise(resolve => {
|
||||||
|
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -24,6 +24,7 @@ var UrlClassifierTestUtils = {
|
||||||
let annotationURL2 = "itisatracker.org/";
|
let annotationURL2 = "itisatracker.org/";
|
||||||
let annotationURL3 = "trackertest.org/";
|
let annotationURL3 = "trackertest.org/";
|
||||||
let annotationURL4 = "another-tracking.example.net/";
|
let annotationURL4 = "another-tracking.example.net/";
|
||||||
|
let annotationURL5 = "tlsresumptiontest.example.org/";
|
||||||
let annotationWhitelistedURL = "itisatrap.org/?resource=example.org";
|
let annotationWhitelistedURL = "itisatrap.org/?resource=example.org";
|
||||||
let trackingURL1 = "tracking.example.com/"; // only for TP
|
let trackingURL1 = "tracking.example.com/"; // only for TP
|
||||||
let trackingURL2 = "itisatracker.org/";
|
let trackingURL2 = "itisatracker.org/";
|
||||||
|
|
@ -39,7 +40,9 @@ var UrlClassifierTestUtils = {
|
||||||
"a:3:32:" + annotationURL3.length + "\n" +
|
"a:3:32:" + annotationURL3.length + "\n" +
|
||||||
annotationURL3 + "\n" +
|
annotationURL3 + "\n" +
|
||||||
"a:4:32:" + annotationURL4.length + "\n" +
|
"a:4:32:" + annotationURL4.length + "\n" +
|
||||||
annotationURL4 + "\n";
|
annotationURL4 + "\n" +
|
||||||
|
"a:5:32:" + annotationURL5.length + "\n" +
|
||||||
|
annotationURL5 + "\n";
|
||||||
let annotationWhitelistUpdate =
|
let annotationWhitelistUpdate =
|
||||||
"n:1000\ni:" + ANNOTATION_WHITELIST_TABLE_NAME + "\nad:1\n" +
|
"n:1000\ni:" + ANNOTATION_WHITELIST_TABLE_NAME + "\nad:1\n" +
|
||||||
"a:1:32:" + annotationWhitelistedURL.length + "\n" +
|
"a:1:32:" + annotationWhitelistedURL.length + "\n" +
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue