author | Francois Marier <francois@mozilla.com> |
Fri, 13 Apr 2018 18:52:28 -0700 | |
changeset 413913 | 38a419def0a7ecbd8e4ae37423c6fe8de316bbea |
parent 413912 | a22a88728d52c16a24b8f8daf844dfef8ae4517b |
child 413914 | c6aaeb90c4b07f8b3c1b6f073f391a744710f483 |
push id | 33853 |
push user | cbrindusan@mozilla.com |
push date | Tue, 17 Apr 2018 09:51:13 +0000 |
treeherder | mozilla-central@8b0ba3f7d099 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ckerschb, valentin |
bugs | 1452699 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/security/test/general/test_same_site_cookies_cross_origin_context.html +++ b/dom/security/test/general/test_same_site_cookies_cross_origin_context.html @@ -19,36 +19,55 @@ * in the context of http://mochi.test * 2) We load an iframe from http://example.com and check if the cookie * is available. * 3) We observe that: * (a) same site cookie has been discarded in a cross origin context. * (b) the regular cookie is available. */ +SimpleTest.registerCleanupFunction(() => { + SpecialPowers.clearUserPref("network.cookie.same-site.enabled"); +}); SimpleTest.waitForExplicitFinish(); const CROSS_ORIGIN = "http://example.com/"; const PATH = "tests/dom/security/test/general/file_same_site_cookies_cross_origin_context.sjs"; let curTest = 0; var tests = [ { - description: "regular cookie in cross origin context", + description: "regular cookie in cross origin context (same-site: on)", imgSRC: CROSS_ORIGIN + PATH + "?setRegularCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=regularCookie", }, { - description: "same-site cookie in cross origin context", + description: "same-site cookie in cross origin context (same-site: on)", imgSRC: CROSS_ORIGIN + PATH + "?setSameSiteCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "", // no cookie should be set }, + { + description: "regular cookie in cross origin context (same-site: off)", + imgSRC: CROSS_ORIGIN + PATH + "?setRegularCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=regularCookie", + }, + { + description: "same-site cookie in cross origin context (same-site: off)", + imgSRC: CROSS_ORIGIN + PATH + "?setSameSiteCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=strictSameSiteCookie", + }, ]; window.addEventListener("message", receiveMessage); function receiveMessage(event) { is(event.data.result, tests[curTest].result, tests[curTest].description); curTest += 1; @@ -63,16 +82,17 @@ function receiveMessage(event) { } function setupQueryResultAndRunTest() { let testframe = document.getElementById("testframe"); testframe.src = tests[curTest].frameSRC + curTest; } function setCookieAndInitTest() { + SpecialPowers.setBoolPref("network.cookie.same-site.enabled", tests[curTest].sameSiteEnabled); var cookieImage = document.getElementById("cookieImage"); cookieImage.onload = function() { ok(true, "trying to set cookie for test (" + tests[curTest].description + ")"); setupQueryResultAndRunTest(); } cookieImage.onerror = function() { ok(false, "could not load image for test (" + tests[curTest].description + ")"); }
--- a/dom/security/test/general/test_same_site_cookies_from_script.html +++ b/dom/security/test/general/test_same_site_cookies_from_script.html @@ -18,37 +18,56 @@ * inline script in top-level context of http://mochi.test. * 2) We load an iframe from http://example.com and check if the cookie * is available. * 3) We observe that: * (a) same site cookie is available in same origin context. * (a) same site cookie has been discarded in a cross origin context. */ +SimpleTest.registerCleanupFunction(() => { + SpecialPowers.clearUserPref("network.cookie.same-site.enabled"); +}); SimpleTest.waitForExplicitFinish(); const SAME_ORIGIN = "http://mochi.test:8888/"; const CROSS_ORIGIN = "http://example.com/"; const PATH = "tests/dom/security/test/general/file_same_site_cookies_from_script.sjs"; let curTest = 0; var tests = [ { description: "same-site cookie inline script within same-site context", setCookieSrc: SAME_ORIGIN + PATH + "?setSameSiteCookieUsingInlineScript", getCookieSrc: SAME_ORIGIN + PATH + "?getCookieFrame", + sameSiteEnabled: true, result: "myKey=sameSiteCookieInlineScript", }, { description: "same-site cookie inline script within cross-site context", setCookieSrc: CROSS_ORIGIN + PATH + "?setSameSiteCookieUsingInlineScript", getCookieSrc: CROSS_ORIGIN + PATH + "?getCookieFrame", + sameSiteEnabled: true, result: "", // same-site cookie should be discarded in cross site context }, + { + description: "same-site cookie inline script within same-site context", + setCookieSrc: SAME_ORIGIN + PATH + "?setSameSiteCookieUsingInlineScript", + getCookieSrc: SAME_ORIGIN + PATH + "?getCookieFrame", + sameSiteEnabled: false, + result: "myKey=sameSiteCookieInlineScript", + }, + { + description: "same-site cookie inline script within cross-site context", + setCookieSrc: CROSS_ORIGIN + PATH + "?setSameSiteCookieUsingInlineScript", + getCookieSrc: CROSS_ORIGIN + PATH + "?getCookieFrame", + sameSiteEnabled: false, + result: "myKey=sameSiteCookieInlineScript", + }, ]; window.addEventListener("message", receiveMessage); function receiveMessage(event) { is(event.data.result, tests[curTest].result, tests[curTest].description); curTest += 1; // lets see if we ran all the tests @@ -62,16 +81,17 @@ function receiveMessage(event) { } function setupQueryResultAndRunTest() { let getCookieFrame = document.getElementById("getCookieFrame"); getCookieFrame.src = tests[curTest].getCookieSrc + curTest; } function setCookieAndInitTest() { + SpecialPowers.setBoolPref("network.cookie.same-site.enabled", tests[curTest].sameSiteEnabled); var cookieFrame = document.getElementById("setCookieFrame"); setCookieFrame.onload = function() { ok(true, "trying to set cookie for test (" + tests[curTest].description + ")"); setupQueryResultAndRunTest(); } setCookieFrame.onerror = function() { ok(false, "could not load image for test (" + tests[curTest].description + ")"); }
--- a/dom/security/test/general/test_same_site_cookies_subrequest.html +++ b/dom/security/test/general/test_same_site_cookies_subrequest.html @@ -22,49 +22,84 @@ * * In detail: * We perform an XHR request to the *.sjs file which is processed async on * the server and waits till the image request has been processed by the server. * Once the image requets was processed, the server responds to the initial * XHR request with the expecuted result (the cookie value). */ +SimpleTest.registerCleanupFunction(() => { + SpecialPowers.clearUserPref("network.cookie.same-site.enabled"); +}); SimpleTest.waitForExplicitFinish(); const SAME_ORIGIN = "http://mochi.test:8888/"; const CROSS_ORIGIN = "http://example.com/"; const PATH = "tests/dom/security/test/general/file_same_site_cookies_subrequest.sjs"; let curTest = 0; var tests = [ { description: "same origin site using cookie policy 'samesite=strict'", imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=strictSameSiteCookie", }, { description: "cross origin site using cookie policy 'samesite=strict'", imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=noCookie", }, { description: "same origin site using cookie policy 'samesite=lax'", imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=laxSameSiteCookie", }, { description: "cross origin site using cookie policy 'samesite=lax'", imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=noCookie", }, + { + description: "same origin site using cookie policy 'samesite=strict'", + imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", + frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=strictSameSiteCookie", + }, + { + description: "cross origin site using cookie policy 'samesite=strict'", + imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=strictSameSiteCookie", + }, + { + description: "same origin site using cookie policy 'samesite=lax'", + imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", + frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=laxSameSiteCookie", + }, + { + description: "cross origin site using cookie policy 'samesite=lax'", + imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=laxSameSiteCookie", + }, ]; function checkResult(aCookieVal) { is(aCookieVal, tests[curTest].result, tests[curTest].description); curTest += 1; // lets see if we ran all the tests if (curTest == tests.length) { @@ -89,16 +124,17 @@ function setupQueryResultAndRunTest() { // give it some time and load the test frame SimpleTest.executeSoon(function() { let testframe = document.getElementById("testframe"); testframe.src = tests[curTest].frameSRC + curTest; }); } function setCookieAndInitTest() { + SpecialPowers.setBoolPref("network.cookie.same-site.enabled", tests[curTest].sameSiteEnabled); var cookieImage = document.getElementById("cookieImage"); cookieImage.onload = function() { ok(true, "set cookie for test (" + tests[curTest].description + ")"); setupQueryResultAndRunTest(); } cookieImage.onerror = function() { ok(false, "could not set cookie for test (" + tests[curTest].description + ")"); }
--- a/dom/security/test/general/test_same_site_cookies_toplevel_nav.html +++ b/dom/security/test/general/test_same_site_cookies_toplevel_nav.html @@ -23,47 +23,82 @@ * * In detail: * We perform an XHR request to the *.sjs file which is processed async on * the server and waits till the image request has been processed by the server. * Once the image requets was processed, the server responds to the initial * XHR request with the expecuted result (the cookie value). */ +SimpleTest.registerCleanupFunction(() => { + SpecialPowers.clearUserPref("network.cookie.same-site.enabled"); +}); SimpleTest.waitForExplicitFinish(); const SAME_ORIGIN = "http://mochi.test:8888/"; const CROSS_ORIGIN = "http://example.com/"; const PATH = "tests/dom/security/test/general/file_same_site_cookies_toplevel_nav.sjs"; let curTest = 0; var tests = [ { description: "same origin navigation using cookie policy 'samesite=strict'", imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=strictSameSiteCookie", }, { description: "cross origin navigation using cookie policy 'samesite=strict'", imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=noCookie", }, { description: "same origin navigation using cookie policy 'samesite=lax'", imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, result: "myKey=laxSameSiteCookie", }, { description: "cross origin navigation using cookie policy 'samesite=lax'", imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: true, + result: "myKey=laxSameSiteCookie", + }, + { + description: "same origin navigation using cookie policy 'samesite=strict'", + imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", + frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=strictSameSiteCookie", + }, + { + description: "cross origin navigation using cookie policy 'samesite=strict'", + imgSRC: SAME_ORIGIN + PATH + "?setStrictSameSiteCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=strictSameSiteCookie", + }, + { + description: "same origin navigation using cookie policy 'samesite=lax'", + imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", + frameSRC: SAME_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, + result: "myKey=laxSameSiteCookie", + }, + { + description: "cross origin navigation using cookie policy 'samesite=lax'", + imgSRC: SAME_ORIGIN + PATH + "?setLaxSameSiteCookie", + frameSRC: CROSS_ORIGIN + PATH + "?loadFrame", + sameSiteEnabled: false, result: "myKey=laxSameSiteCookie", }, ]; function checkResult(aCookieVal) { is(aCookieVal, tests[curTest].result, tests[curTest].description); curTest += 1; @@ -90,16 +125,17 @@ function setupQueryResultAndRunTest() { // give it some time and load the test window SimpleTest.executeSoon(function() { let testframe = document.getElementById("testframe"); testframe.src = tests[curTest].frameSRC + curTest; }); } function setCookieAndInitTest() { + SpecialPowers.setBoolPref("network.cookie.same-site.enabled", tests[curTest].sameSiteEnabled); var cookieImage = document.getElementById("cookieImage"); cookieImage.onload = function() { ok(true, "set cookie for test (" + tests[curTest].description + ")"); setupQueryResultAndRunTest(); } cookieImage.onerror = function() { ok(false, "could not set cookie for test (" + tests[curTest].description + ")"); }
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -2234,16 +2234,17 @@ pref("network.proxy.failover_timeout", pref("network.online", true); //online/offline pref("network.cookie.cookieBehavior", 0); // 0-Accept, 1-dontAcceptForeign, 2-dontAcceptAny, 3-limitForeign #ifdef ANDROID pref("network.cookie.cookieBehavior", 0); // Keep the old default of accepting all cookies #endif pref("network.cookie.thirdparty.sessionOnly", false); pref("network.cookie.thirdparty.nonsecureSessionOnly", false); pref("network.cookie.leave-secure-alone", true); +pref("network.cookie.same-site.enabled", true); // Honor the SameSite cookie attribute pref("network.cookie.ipc.sync", false); pref("network.cookie.lifetimePolicy", 0); // 0-accept, 1-dontUse 2-acceptForSession, 3-acceptForNDays pref("network.cookie.prefsMigrated", false); pref("network.cookie.lifetime.days", 90); // Ignored unless network.cookie.lifetimePolicy is 3. // The PAC file to load. Ignored unless network.proxy.type is 2. pref("network.proxy.autoconfig_url", ""); // Strip off paths when sending URLs to PAC scripts
--- a/netwerk/cookie/CookieServiceChild.cpp +++ b/netwerk/cookie/CookieServiceChild.cpp @@ -309,17 +309,17 @@ CookieServiceChild::GetCookieStringFromC continue; // if the cookie is secure and the host scheme isn't, we can't send it if (cookie->IsSecure() && !isSecure) continue; int32_t sameSiteAttr = 0; cookie->GetSameSite(&sameSiteAttr); - if (aIsSameSiteForeign) { + if (aIsSameSiteForeign && nsCookieService::IsSameSiteEnabled()) { // it if's a cross origin request and the cookie is same site only (strict) // don't send it if (sameSiteAttr == nsICookie2::SAMESITE_STRICT) { continue; } // if it's a cross origin request, the cookie is same site lax, but it's not // a top-level navigation, don't send it if (sameSiteAttr == nsICookie2::SAMESITE_LAX && !aIsSafeTopLevelNav) {
--- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -71,16 +71,17 @@ using namespace mozilla::net; nsCookieKey(baseDomain, OriginAttributes()) /****************************************************************************** * nsCookieService impl: * useful types & constants ******************************************************************************/ static StaticRefPtr<nsCookieService> gCookieService; +bool nsCookieService::sSameSiteEnabled = false; // XXX_hack. See bug 178993. // This is a hack to hide HttpOnly cookies from older browsers #define HTTP_ONLY_PREFIX "#HttpOnly_" #define COOKIES_FILE "cookies.sqlite" #define COOKIES_SCHEMA_VERSION 9 @@ -3070,16 +3071,28 @@ nsCookieService::DomainMatches(nsCookie* // first, check for an exact host or domain cookie match, e.g. "google.com" // or ".google.com"; second a subdomain match, e.g. // host = "mail.google.com", cookie domain = ".google.com". return aCookie->RawHost() == aHost || (aCookie->IsDomain() && StringEndsWith(aHost, aCookie->Host())); } bool +nsCookieService::IsSameSiteEnabled() +{ + static bool prefInitialized = false; + if (!prefInitialized) { + Preferences::AddBoolVarCache(&sSameSiteEnabled, + "network.cookie.same-site.enabled", false); + prefInitialized = true; + } + return sSameSiteEnabled; +} + +bool nsCookieService::PathMatches(nsCookie* aCookie, const nsACString& aPath) { // calculate cookie path length, excluding trailing '/' uint32_t cookiePathLen = aCookie->Path().Length(); if (cookiePathLen > 0 && aCookie->Path().Last() == '/') --cookiePathLen; @@ -3199,17 +3212,17 @@ nsCookieService::GetCookiesForURI(nsIURI continue; // if the cookie is secure and the host scheme isn't, we can't send it if (cookie->IsSecure() && !isSecure) continue; int32_t sameSiteAttr = 0; cookie->GetSameSite(&sameSiteAttr); - if (aIsSameSiteForeign) { + if (aIsSameSiteForeign && IsSameSiteEnabled()) { // it if's a cross origin request and the cookie is same site only (strict) // don't send it if (sameSiteAttr == nsICookie2::SAMESITE_STRICT) { continue; } // if it's a cross origin request, the cookie is same site lax, but it's not // a top-level navigation, don't send it if (sameSiteAttr == nsICookie2::SAMESITE_LAX && !aIsSafeTopLevelNav) { @@ -3466,17 +3479,18 @@ nsCookieService::CanSetCookie(nsIURI* "non-https cookie can't set secure flag"); Telemetry::Accumulate(Telemetry::COOKIE_LEAVE_SECURE_ALONE, BLOCKED_SECURE_SET_FROM_HTTP); return newCookie; } // If the new cookie is same-site but in a cross site context, // browser must ignore the cookie. - if (aCookieAttributes.sameSite != nsICookie2::SAMESITE_UNSET) { + if ((aCookieAttributes.sameSite != nsICookie2::SAMESITE_UNSET) && + IsSameSiteEnabled()) { bool isThirdParty = NS_IsSameSiteForeign(aChannel, aHostURI); if (isThirdParty) { COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "failed the samesite tests"); return newCookie; } }
--- a/netwerk/cookie/nsCookieService.h +++ b/netwerk/cookie/nsCookieService.h @@ -237,16 +237,18 @@ class nsCookieService final : public nsI , public nsICookieManager , public nsIObserver , public nsSupportsWeakReference , public nsIMemoryReporter { private: size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + static bool sSameSiteEnabled; // cached pref + public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER NS_DECL_NSICOOKIESERVICE NS_DECL_NSICOOKIEMANAGER NS_DECL_NSIMEMORYREPORTER nsCookieService(); @@ -259,16 +261,17 @@ class nsCookieService final : public nsI * (thus instantiating it, if necessary) and clear all the cookies for that * app. */ static void AppClearDataObserverInit(); static nsCString GetPathFromURI(nsIURI *aHostURI); static nsresult GetBaseDomain(nsIEffectiveTLDService *aTLDService, nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch); static nsresult GetBaseDomainFromHost(nsIEffectiveTLDService *aTLDService, const nsACString &aHost, nsCString &aBaseDomain); static bool DomainMatches(nsCookie* aCookie, const nsACString& aHost); + static bool IsSameSiteEnabled(); static bool PathMatches(nsCookie* aCookie, const nsACString& aPath); static bool CanSetCookie(nsIURI *aHostURI, const nsCookieKey& aKey, nsCookieAttributes &aCookieAttributes, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel, bool aLeaveSercureAlone, bool &aSetCookie, mozIThirdPartyUtil* aThirdPartyUtil); static CookieStatus CheckPrefs(nsICookiePermission *aPermissionServices, uint8_t aCookieBehavior, bool aThirdPartySession, bool aThirdPartyNonsecureSession, nsIURI *aHostURI, bool aIsForeign, const char *aCookieHeader, const int aNumOfCookies, const OriginAttributes& aOriginAttrs); static int64_t ParseServerTime(const nsCString &aServerTime); void GetCookiesForURI(nsIURI *aHostURI, bool aIsForeign, bool aIsSafeTopLevelNav, bool aIsTopLevelForeign, bool aHttpBound, const OriginAttributes& aOriginAttrs, nsTArray<nsCookie*>& aCookieList); protected: virtual ~nsCookieService();