Bug 1333651 - Part 2: Spoofing Navigator object when 'privacy.resistFingerprinting' is true. r?Ehsan,arthuredelstein
This patch makes navigator object to return spoofed value for fields have fingerprintable
concerns. This changes the worker navigator as well.
MozReview-Commit-ID: E2SLNZRfuVP
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -56,16 +56,17 @@
#include "mozilla/StaticPtr.h"
#include "Connection.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "nsGlobalWindow.h"
#include "nsIIdleObserver.h"
#include "nsIPermissionManager.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
+#include "nsRFPService.h"
#include "nsStringStream.h"
#include "nsComponentManagerUtils.h"
#include "nsIStringStream.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "TimeManager.h"
#include "nsStreamUtils.h"
#include "WidgetUtils.h"
@@ -460,16 +461,23 @@ Navigator::GetPlatform(nsAString& aPlatf
}
}
void
Navigator::GetOscpu(nsAString& aOSCPU, CallerType aCallerType,
ErrorResult& aRv) const
{
if (aCallerType != CallerType::System) {
+ // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
+ // for details about spoofed values.
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aOSCPU.AssignLiteral(SPOOFED_OSCPU);
+ return;
+ }
+
const nsAdoptingString& override =
Preferences::GetString("general.oscpu.override");
if (override) {
aOSCPU = override;
return;
}
}
@@ -512,17 +520,17 @@ Navigator::GetProduct(nsAString& aProduc
aProduct.AssignLiteral("Gecko");
return NS_OK;
}
NS_IMETHODIMP
Navigator::GetProductSub(nsAString& aProductSub)
{
// Legacy build ID hardcoded for backward compatibility (bug 776376)
- aProductSub.AssignLiteral("20100101");
+ aProductSub.AssignLiteral(LEGACY_BUILD_ID);
return NS_OK;
}
nsMimeTypeArray*
Navigator::GetMimeTypes(ErrorResult& aRv)
{
if (!mMimeTypes) {
if (!mWindow) {
@@ -634,16 +642,22 @@ Navigator::OnLine()
return !NS_IsOffline();
}
void
Navigator::GetBuildID(nsAString& aBuildID, CallerType aCallerType,
ErrorResult& aRv) const
{
if (aCallerType != CallerType::System) {
+ // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
+ // for details about spoofed values.
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aBuildID.AssignLiteral(LEGACY_BUILD_ID);
+ return;
+ }
const nsAdoptingString& override =
Preferences::GetString("general.buildID.override");
if (override) {
aBuildID = override;
return;
}
}
@@ -1764,16 +1778,22 @@ Navigator::GetWindowFromGlobal(JSObject*
}
nsresult
Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue)
{
MOZ_ASSERT(NS_IsMainThread());
if (aUsePrefOverriddenValue) {
+ // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
+ // for details about spoofed values.
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aPlatform.AssignLiteral(SPOOFED_PLATFORM);
+ return NS_OK;
+ }
const nsAdoptingString& override =
mozilla::Preferences::GetString("general.platform.override");
if (override) {
aPlatform = override;
return NS_OK;
}
}
@@ -1809,16 +1829,22 @@ Navigator::GetPlatform(nsAString& aPlatf
}
/* static */ nsresult
Navigator::GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue)
{
MOZ_ASSERT(NS_IsMainThread());
if (aUsePrefOverriddenValue) {
+ // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
+ // for details about spoofed values.
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aAppVersion.AssignLiteral(SPOOFED_APPVERSION);
+ return NS_OK;
+ }
const nsAdoptingString& override =
mozilla::Preferences::GetString("general.appversion.override");
if (override) {
aAppVersion = override;
return NS_OK;
}
}
@@ -1846,16 +1872,23 @@ Navigator::GetAppVersion(nsAString& aApp
}
/* static */ void
Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue)
{
MOZ_ASSERT(NS_IsMainThread());
if (aUsePrefOverriddenValue) {
+ // If fingerprinting resistance is on, we will spoof this value. See nsRFPService.h
+ // for details about spoofed values.
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aAppName.AssignLiteral(SPOOFED_APPNAME);
+ return;
+ }
+
const nsAdoptingString& override =
mozilla::Preferences::GetString("general.appname.override");
if (override) {
aAppName = override;
return;
}
}
@@ -1871,17 +1904,20 @@ Navigator::ClearUserAgentCache()
nsresult
Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow,
bool aIsCallerChrome,
nsAString& aUserAgent)
{
MOZ_ASSERT(NS_IsMainThread());
- if (!aIsCallerChrome) {
+ // We will skip the override and pass to httpHandler to get spoofed userAgent
+ // when 'privacy.resistFingerprinting' is true.
+ if (!aIsCallerChrome &&
+ !nsContentUtils::ShouldResistFingerprinting()) {
const nsAdoptingString& override =
mozilla::Preferences::GetString("general.useragent.override");
if (override) {
aUserAgent = override;
return NS_OK;
}
}
@@ -1896,17 +1932,21 @@ Navigator::GetUserAgent(nsPIDOMWindowInn
nsAutoCString ua;
rv = service->GetUserAgent(ua);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
CopyASCIItoUTF16(ua, aUserAgent);
- if (!aWindow) {
+ // When the caller is content, we will always return spoofed userAgent and
+ // ignore the User-Agent header from the document channel when
+ // 'privacy.resistFingerprinting' is true.
+ if (!aWindow ||
+ (nsContentUtils::ShouldResistFingerprinting() && !aIsCallerChrome)) {
return NS_OK;
}
// Copy the User-Agent header from the document channel which has already been
// subject to UA overrides.
nsCOMPtr<nsIDocument> doc = aWindow->GetExtantDoc();
if (!doc) {
return NS_OK;
--- a/dom/workers/WorkerNavigator.cpp
+++ b/dom/workers/WorkerNavigator.cpp
@@ -8,16 +8,17 @@
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/PromiseWorkerProxy.h"
#include "mozilla/dom/StorageManager.h"
#include "mozilla/dom/WorkerNavigator.h"
#include "mozilla/dom/WorkerNavigatorBinding.h"
#include "mozilla/dom/network/Connection.h"
#include "nsProxyRelease.h"
+#include "nsRFPService.h"
#include "RuntimeService.h"
#include "nsIDocument.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"
@@ -74,49 +75,61 @@ WorkerNavigator::SetLanguages(const nsTA
}
void
WorkerNavigator::GetAppName(nsString& aAppName, CallerType aCallerType) const
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- if (!mProperties.mAppNameOverridden.IsEmpty() &&
+ if ((!mProperties.mAppNameOverridden.IsEmpty() ||
+ workerPrivate->ResistFingerprintingEnabled()) &&
!workerPrivate->UsesSystemPrincipal()) {
- aAppName = mProperties.mAppNameOverridden;
+ // We will spoof this value when 'privacy.resistFingerprinting' is true.
+ // See nsRFPService.h for spoofed value.
+ aAppName = workerPrivate->ResistFingerprintingEnabled() ?
+ NS_LITERAL_STRING(SPOOFED_APPNAME) : mProperties.mAppNameOverridden;
} else {
aAppName = mProperties.mAppName;
}
}
void
WorkerNavigator::GetAppVersion(nsString& aAppVersion, CallerType aCallerType,
ErrorResult& aRv) const
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- if (!mProperties.mAppVersionOverridden.IsEmpty() &&
+ if ((!mProperties.mAppVersionOverridden.IsEmpty() ||
+ workerPrivate->ResistFingerprintingEnabled()) &&
!workerPrivate->UsesSystemPrincipal()) {
- aAppVersion = mProperties.mAppVersionOverridden;
+ // We will spoof this value when 'privacy.resistFingerprinting' is true.
+ // See nsRFPService.h for spoofed value.
+ aAppVersion = workerPrivate->ResistFingerprintingEnabled() ?
+ NS_LITERAL_STRING(SPOOFED_APPVERSION) : mProperties.mAppVersionOverridden;
} else {
aAppVersion = mProperties.mAppVersion;
}
}
void
WorkerNavigator::GetPlatform(nsString& aPlatform, CallerType aCallerType,
ErrorResult& aRv) const
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
- if (!mProperties.mPlatformOverridden.IsEmpty() &&
+ if ((!mProperties.mPlatformOverridden.IsEmpty() ||
+ workerPrivate->ResistFingerprintingEnabled()) &&
!workerPrivate->UsesSystemPrincipal()) {
- aPlatform = mProperties.mPlatformOverridden;
+ // We will spoof this value when 'privacy.resistFingerprinting' is true.
+ // See nsRFPService.h for spoofed value.
+ aPlatform = workerPrivate->ResistFingerprintingEnabled() ?
+ NS_LITERAL_STRING(SPOOFED_PLATFORM) : mProperties.mPlatformOverridden;
} else {
aPlatform = mProperties.mPlatform;
}
}
namespace {
class GetUserAgentRunnable final : public WorkerMainThreadRunnable
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -51,16 +51,17 @@
#include "nsHttpChannelAuthProvider.h"
#include "nsServiceManagerUtils.h"
#include "nsComponentManagerUtils.h"
#include "nsSocketTransportService2.h"
#include "nsIOService.h"
#include "nsISupportsPrimitives.h"
#include "nsIXULRuntime.h"
#include "nsCharSeparatedTokenizer.h"
+#include "nsRFPService.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/NeckoParent.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Unused.h"
#include "mozilla/BasePrincipal.h"
@@ -438,18 +439,18 @@ nsHttpHandler::Init()
// Generating the spoofed userAgent for fingerprinting resistance. We will
// round the version to the nearest 10. By doing so, the anonymity group will
// cover more versions instead of one version.
uint32_t spoofedVersion = mAppVersion.ToInteger(&rv);
if (NS_SUCCEEDED(rv)) {
spoofedVersion = spoofedVersion - (spoofedVersion % 10);
mSpoofedUserAgent.Assign(nsPrintfCString(
- "Mozilla/5.0 (Windows NT 6.1; rv:%d.0) Gecko/20100101 Firefox/%d.0",
- spoofedVersion, spoofedVersion));
+ "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0",
+ SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion));
}
mSessionStartTime = NowInSeconds();
mHandlerActive = true;
rv = mAuthCache.Init();
if (NS_FAILED(rv)) return rv;
@@ -460,17 +461,17 @@ nsHttpHandler::Init()
if (NS_FAILED(rv)) return rv;
mRequestContextService =
do_GetService("@mozilla.org/network/request-context-service;1");
#if defined(ANDROID) || defined(MOZ_MULET)
mProductSub.AssignLiteral(MOZILLA_UAVERSION);
#else
- mProductSub.AssignLiteral("20100101");
+ mProductSub.AssignLiteral(LEGACY_BUILD_ID);
#endif
#if DEBUG
// dump user agent prefs
LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
LOG(("> platform = %s\n", mPlatform.get()));
LOG(("> oscpu = %s\n", mOscpu.get()));
--- a/toolkit/components/resistfingerprinting/nsRFPService.h
+++ b/toolkit/components/resistfingerprinting/nsRFPService.h
@@ -6,16 +6,25 @@
#ifndef __nsRFPService_h__
#define __nsRFPService_h__
#include "mozilla/Atomics.h"
#include "nsIObserver.h"
#include "nsString.h"
+// Defines regarding spoofed values of Navigator object. These spoofed values
+// are returned when 'privacy.resistFingerprinting' is true.
+#define SPOOFED_APPNAME "Netscape"
+#define SPOOFED_APPVERSION "5.0 (Windows)"
+#define SPOOFED_OSCPU "Windows NT 6.1"
+#define SPOOFED_PLATFORM "Win32"
+
+#define LEGACY_BUILD_ID "20100101"
+
namespace mozilla {
class nsRFPService final : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER