Bug 1333651 - Part 1: Spoofing the User-Agent header when 'privacy.resistFingerprinting' is true. r?mcmanus,arthuredelstein draft
authorTim Huang <tihuang@mozilla.com>
Thu, 08 Jun 2017 14:38:21 +0800
changeset 596578 3f3177958f78a6f48f4551cf4d7df343b2994bdd
parent 596561 d39cd452b52bf82fa4a717172a62d62ab9e5366f
child 596579 536ab4f3ca16618b6a4ae0f8da58fc646f697045
push id64684
push userbmo:tihuang@mozilla.com
push dateMon, 19 Jun 2017 13:26:45 +0000
reviewersmcmanus, arthuredelstein
bugs1333651
milestone56.0a1
Bug 1333651 - Part 1: Spoofing the User-Agent header when 'privacy.resistFingerprinting' is true. r?mcmanus,arthuredelstein This patch makes nsHttpHandler to use a spoofed userAgent in the User-Agent header when 'privacy.resistFingerprinting' is true, the spoofed userAgent string has a fixed appName, platform and buildID. The only variant in it is the version number, it will be rounded to the nearest 10(e.g. 40, 50, 60) for reducing fingerprinting across release versions. MozReview-Commit-ID: BTGuIJp94U1
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -431,16 +431,27 @@ nsHttpHandler::Init()
           appInfo->GetName(mAppName);
         }
         appInfo->GetVersion(mAppVersion);
         mAppName.StripChars(R"( ()<>@,;:\"/[]?={})");
     } else {
         mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
     }
 
+    // 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));
+    }
+
     mSessionStartTime = NowInSeconds();
     mHandlerActive = true;
 
     rv = mAuthCache.Init();
     if (NS_FAILED(rv)) return rv;
 
     rv = mPrivateAuthCache.Init();
     if (NS_FAILED(rv)) return rv;
@@ -773,16 +784,22 @@ nsHttpHandler::GenerateHostPort(const ns
 
 //-----------------------------------------------------------------------------
 // nsHttpHandler <private>
 //-----------------------------------------------------------------------------
 
 const nsAFlatCString &
 nsHttpHandler::UserAgent()
 {
+    if (nsContentUtils::ShouldResistFingerprinting() &&
+        !mSpoofedUserAgent.IsEmpty()) {
+        LOG(("using spoofed userAgent : %s\n", mSpoofedUserAgent.get()));
+        return mSpoofedUserAgent;
+    }
+
     if (mUserAgentOverride) {
         LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
         return mUserAgentOverride;
     }
 
     if (mUserAgentIsDirty) {
         BuildUserAgent();
         mUserAgentIsDirty = false;
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -487,16 +487,17 @@ private:
     nsXPIDLCString mAppName;
     nsXPIDLCString mAppVersion;
     nsCString      mCompatFirefox;
     bool           mCompatFirefoxEnabled;
     nsXPIDLCString mCompatDevice;
     nsCString      mDeviceModelId;
 
     nsCString      mUserAgent;
+    nsCString      mSpoofedUserAgent;
     nsXPIDLCString mUserAgentOverride;
     bool           mUserAgentIsDirty; // true if mUserAgent should be rebuilt
     bool           mAcceptLanguagesIsDirty;
 
 
     bool           mPromptTempRedirect;
 
     // Persistent HTTPS caching flag