diff options
author | Pale Moon <git-repo@palemoon.org> | 2017-01-26 18:15:21 +0100 |
---|---|---|
committer | Pale Moon <git-repo@palemoon.org> | 2017-01-26 18:15:21 +0100 |
commit | 7e4c1aed1611b909fd94cec88146f8e9276b7aa1 (patch) | |
tree | 9a09f01bc8f827faca18c49d18af45b4b12757ec /dom/storage | |
parent | 1d62955d4ebe27b797cbb68f36b42d4e5f189f33 (diff) | |
download | palemoon-gre-7e4c1aed1611b909fd94cec88146f8e9276b7aa1.tar.gz |
Make DOM storage from 3rd parties honor 3rd party cookie setting.
- restricts usage of DOM storage by 3rd parties if the use has set 3rd party cookies to be blocked.
- extends "cookie-like" handling for DOM storage to enhance privacy and combat cross-origin tracking.
This resolves #860
Diffstat (limited to 'dom/storage')
-rw-r--r-- | dom/storage/DOMStorage.cpp | 41 | ||||
-rw-r--r-- | dom/storage/DOMStorage.h | 11 |
2 files changed, 37 insertions, 15 deletions
diff --git a/dom/storage/DOMStorage.cpp b/dom/storage/DOMStorage.cpp index a147fedeb..aa143ce40 100644 --- a/dom/storage/DOMStorage.cpp +++ b/dom/storage/DOMStorage.cpp @@ -12,6 +12,7 @@ #include "nsIPermissionManager.h" #include "nsIPrincipal.h" #include "nsICookiePermission.h" +#include "mozIThirdPartyUtil.h" #include "mozilla/dom/StorageBinding.h" #include "mozilla/dom/StorageEvent.h" @@ -68,7 +69,7 @@ DOMStorage::WrapObject(JSContext* aCx) uint32_t DOMStorage::GetLength(ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return 0; } @@ -81,7 +82,7 @@ DOMStorage::GetLength(ErrorResult& aRv) void DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } @@ -92,7 +93,7 @@ DOMStorage::Key(uint32_t aIndex, nsAString& aResult, ErrorResult& aRv) void DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult, ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } @@ -104,7 +105,7 @@ void DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData, ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } @@ -137,7 +138,7 @@ DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData, void DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } @@ -156,7 +157,7 @@ DOMStorage::RemoveItem(const nsAString& aKey, ErrorResult& aRv) void DOMStorage::Clear(ErrorResult& aRv) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } @@ -229,7 +230,13 @@ DOMStorage::BroadcastChangeNotification(const nsSubstring& aKey, static const uint32_t ASK_BEFORE_ACCEPT = 1; static const uint32_t ACCEPT_SESSION = 2; -static const uint32_t BEHAVIOR_REJECT = 2; + +// Behavior pref constants taken from nsCookieService.cpp +static const uint32_t BEHAVIOR_ACCEPT = 0; // allow all cookies +static const uint32_t BEHAVIOR_REJECTFOREIGN = 1; // reject all third-party cookies +static const uint32_t BEHAVIOR_REJECT = 2; // reject all cookies +static const uint32_t BEHAVIOR_LIMITFOREIGN = 3; // reject third-party cookies unless the + // eTLD already has at least one cookie static const char kPermissionType[] = "cookie"; static const char kStorageEnabled[] = "dom.storage.enabled"; @@ -238,7 +245,7 @@ static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy"; // static, public bool -DOMStorage::CanUseStorage(DOMStorage* aStorage) +DOMStorage::CanUseStorage(nsIDOMWindow* aWindow, DOMStorage* aStorage) { // This method is responsible for correct setting of mIsSessionOnly. // It doesn't work with mIsPrivate flag at all, since it is checked @@ -285,6 +292,22 @@ DOMStorage::CanUseStorage(DOMStorage* aStorage) return false; } + // Reject storage from 3rd party embedded content. + // If we don't have a window, then we can assume that the content is not + // originated from a 3rd party, because storage was not obtained through + // the window object. + if (aWindow && cookieBehavior == BEHAVIOR_REJECTFOREIGN) { + nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = + do_GetService(THIRDPARTYUTIL_CONTRACTID); + MOZ_ASSERT(thirdPartyUtil); + + bool thirdPartyWindow = false; + if (NS_SUCCEEDED(thirdPartyUtil->IsThirdPartyWindow( + aWindow, nullptr, &thirdPartyWindow)) && thirdPartyWindow) { + return false; + } + } + if (lifetimePolicy == ACCEPT_SESSION && aStorage) { aStorage->mIsSessionOnly = true; } @@ -328,7 +351,7 @@ DOMStorage::CanAccess(nsIPrincipal* aPrincipal) void DOMStorage::GetSupportedNames(unsigned, nsTArray<nsString>& aKeys) { - if (!CanUseStorage(this)) { + if (!CanUseStorage(mWindow, this)) { // return just an empty array aKeys.Clear(); return; diff --git a/dom/storage/DOMStorage.h b/dom/storage/DOMStorage.h index 1005454c2..663280132 100644 --- a/dom/storage/DOMStorage.h +++ b/dom/storage/DOMStorage.h @@ -114,14 +114,13 @@ public: void Clear(ErrorResult& aRv); - // The method checks whether the caller can use a storage. + // This method checks whether the caller can use storage. // CanUseStorage is called before any DOM initiated operation - // on a storage is about to happen and ensures that the storage's + // on storage is about to happen and ensures that the storage's // session-only flag is properly set according the current settings. - // It is an optimization since the privileges check and session only - // state determination are complex and share the code (comes hand in - // hand together). - static bool CanUseStorage(DOMStorage* aStorage = nullptr); + // It is an optimization, since the privileges check and session-only + // state determination are complex and share code (goes hand in hand). + static bool CanUseStorage(nsIDOMWindow* aWindow, DOMStorage* aStorage = nullptr); bool IsPrivate() const { return mIsPrivate; } bool IsSessionOnly() const { return mIsSessionOnly; } |