summaryrefslogtreecommitdiff
path: root/dom/storage
diff options
context:
space:
mode:
authorPale Moon <git-repo@palemoon.org>2017-01-26 18:15:21 +0100
committerPale Moon <git-repo@palemoon.org>2017-01-26 18:15:21 +0100
commit7e4c1aed1611b909fd94cec88146f8e9276b7aa1 (patch)
tree9a09f01bc8f827faca18c49d18af45b4b12757ec /dom/storage
parent1d62955d4ebe27b797cbb68f36b42d4e5f189f33 (diff)
downloadpalemoon-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.cpp41
-rw-r--r--dom/storage/DOMStorage.h11
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; }