[tbb-commits] [tor-browser/tor-browser-31.4.0esr-4.5-1] Bug 13900: Remove 3rd party HTTP auth tokens.

mikeperry at torproject.org mikeperry at torproject.org
Fri Feb 13 05:16:13 UTC 2015


commit b6be541aaa22422ecf9e70680282aa9c7dc05f06
Author: Kathy Brade <brade at pearlcrescent.com>
Date:   Wed Feb 4 10:38:44 2015 -0500

    Bug 13900: Remove 3rd party HTTP auth tokens.
    
    Prevent user tracking via HTTP Basic Authentication by
    removing Authorization headers from third party requests.
    
    This is a port of a piece of the Stanford SafeCache code that
    previously was included in Torbutton.
---
 content/base/src/ThirdPartyUtil.cpp        |   21 ++++++---
 netwerk/base/public/mozIThirdPartyUtil.idl |   22 ++++++++-
 netwerk/protocol/http/nsHttpChannel.cpp    |   70 ++++++++++++++++++++++++++++
 netwerk/protocol/http/nsHttpChannel.h      |    1 +
 4 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/content/base/src/ThirdPartyUtil.cpp b/content/base/src/ThirdPartyUtil.cpp
index e2287eb..695392f 100644
--- a/content/base/src/ThirdPartyUtil.cpp
+++ b/content/base/src/ThirdPartyUtil.cpp
@@ -412,20 +412,28 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
   return NS_OK;
 }
 
-// Returns true if First Party Isolation is currently active for the given nsIChannel.
-// Depends on Preference setting and possibly the state of Private Browsing mode.
-bool ThirdPartyUtil::IsFirstPartyIsolationActive(nsIChannel *aChannel, nsIDocument *aDoc)
+// Determine if First Party Isolation is currently active for the given
+// nsIChannel or nsIDocument.  Depends on preference setting and
+// possibly the state of Private Browsing mode.
+NS_IMETHODIMP
+ThirdPartyUtil::IsFirstPartyIsolationActive(nsIChannel *aChannel,
+                                            nsIDocument *aDoc,
+                                            bool* aResult)
 {
+  NS_ASSERTION(aResult, "null outparam pointer");
+
   int32_t isolationState = mozilla::Preferences::GetInt("privacy.thirdparty.isolate");
   if (isolationState == 1) {
     if (!aChannel && aDoc) {
       // No channel passed directly. Can we get a channel from aDoc?
       aChannel = aDoc->GetChannel();
     }
-    return aChannel && NS_UsePrivateBrowsing(aChannel);
+    *aResult = aChannel && NS_UsePrivateBrowsing(aChannel);
   } else { // (isolationState == 0) || (isolationState == 2)
-    return (isolationState == 2);
+    *aResult = (isolationState == 2);
   }
+
+  return NS_OK;
 }
 
 // Produces a URI that uniquely identifies the first party to which
@@ -435,7 +443,8 @@ bool ThirdPartyUtil::IsFirstPartyIsolationActive(nsIChannel *aChannel, nsIDocume
 NS_IMETHODIMP
 ThirdPartyUtil::GetFirstPartyIsolationURI(nsIChannel *aChannel, nsIDocument *aDoc, nsIURI **aOutput)
 {
-  bool isolationActive = IsFirstPartyIsolationActive(aChannel, aDoc);
+  bool isolationActive = false;
+  (void)IsFirstPartyIsolationActive(aChannel, aDoc, &isolationActive);
   if (isolationActive) {
     return GetFirstPartyURI(aChannel, aDoc, aOutput);
   } else {
diff --git a/netwerk/base/public/mozIThirdPartyUtil.idl b/netwerk/base/public/mozIThirdPartyUtil.idl
index 87fb630..0bb632b 100644
--- a/netwerk/base/public/mozIThirdPartyUtil.idl
+++ b/netwerk/base/public/mozIThirdPartyUtil.idl
@@ -13,7 +13,7 @@ interface nsIDocument;
  * Utility functions for determining whether a given URI, channel, or window
  * hierarchy is third party with respect to a known URI.
  */
-[scriptable, uuid(d994fd1d-d2fe-4372-9ae7-88b08b7d9d90)]
+[scriptable, uuid(b538074d-5e00-40b3-b5c4-e060ae010b83)]
 interface mozIThirdPartyUtil : nsISupports
 {
   /**
@@ -165,6 +165,26 @@ interface mozIThirdPartyUtil : nsISupports
                                      in nsIDocument aDoc);
 
   /**
+   * isFirstPartyIsolationActive
+   *
+   * Determine if First Party Isolation is currently active for the given
+   * nsIChannel or nsIDocument.  Depends on preference setting and
+   * possibly the state of Private Browsing mode.
+   *
+   * @param aChannel
+   *        An arbitrary channel for some content element of a first party
+   *        load. Can be null.
+   *
+   * @param aDoc
+   *        An arbitrary third party document. Can be null.
+   *
+   * @return true if first party isolation is active.
+   */
+
+  [noscript] bool isFirstPartyIsolationActive(in nsIChannel aChannel,
+                                              in nsIDocument aDoc);
+
+  /**
    * getFirstPartyIsolationURI
    *
    * If first-party isolation is active, then
diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp
index b37b60b..59ba71b 100644
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4600,6 +4600,8 @@ nsHttpChannel::BeginConnect()
     // notify "http-on-modify-request" observers
     CallOnModifyRequestObservers();
 
+    RemoveAuthorizationHeaderIfAppropriate();
+
     // Check to see if we should redirect this channel elsewhere by
     // nsIHttpChannel.redirectTo API request
     if (mAPIRedirectToURI) {
@@ -5750,6 +5752,72 @@ nsHttpChannel::ResumeAt(uint64_t aStartPos,
     return NS_OK;
 }
 
+// Remove the Authorization header if first party isolation is active and
+// this channel is processing a third party request. This prevents user
+// tracking via HTTP Basic Authentication.
+// Note that this approach disables authentication for 3rd party domains. It
+// would be better if we could isolate the authentication while still allowing
+// it to be transmitted... but HTTP authentication is rarely used anyway.
+void
+nsHttpChannel::RemoveAuthorizationHeaderIfAppropriate()
+{
+    if (!mRequestHead.PeekHeader(nsHttp::Authorization)) {
+        return; // No Authorization header is present.
+    }
+
+    nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc
+                                = do_GetService(THIRDPARTYUTIL_CONTRACTID);
+    bool isolationActive = true;
+    (void)thirdPartySvc->IsFirstPartyIsolationActive(this, nullptr,
+                                                     &isolationActive);
+    if (!isolationActive)
+        return; // First party isolation is disabled for this channel.
+
+    bool isAuthAllowed = false;
+    nsCOMPtr<nsIURI> firstPartyURI;
+    nsresult rv = thirdPartySvc->GetFirstPartyURIFromChannel(this, false,
+                                               getter_AddRefs(firstPartyURI));
+    if (NS_SUCCEEDED(rv) && firstPartyURI) {
+        isAuthAllowed = (mURI == firstPartyURI)
+                        || HostPartIsTheSame(firstPartyURI);
+    } else {
+        // We failed to get the first party URI. Check the document URI so
+        // that we can allow authentication if the request originates from the
+        // the browser chrome, e.g., some favicon requests. If there is no
+        // document URI associated with this request, it cannot be associated
+        // with a content document, so it must be a special request (e.g.,
+        // favicon fetch or OSCP), for which we also allow authenication.
+        nsCOMPtr<nsIURI> docURI;
+        rv = GetDocumentURI(getter_AddRefs(docURI));
+        if (NS_FAILED(rv) || !docURI) {
+            isAuthAllowed = true;
+        } else {
+            nsAutoCString docURISpec;
+            docURI->GetAsciiSpec(docURISpec);
+            if (docURISpec == "chrome://browser/content/browser.xul")
+                isAuthAllowed = true;
+        }
+    }
+
+    if (!isAuthAllowed) {
+        mRequestHead.ClearHeader(nsHttp::Authorization);
+        mRequestHead.ClearHeader(nsHttp::Cache_Control);
+        mRequestHead.ClearHeader(nsHttp::Pragma);
+
+#ifdef PR_LOGGING
+        nsAutoCString requestURIStr, firstPartyURIStr;
+        mURI->GetAsciiSpec(requestURIStr);
+        if (firstPartyURI)
+            firstPartyURI->GetAsciiSpec(firstPartyURIStr);
+        else
+            firstPartyURIStr = "--N/A--";
+        LOG(("Removed Authorization header from third party request"
+              " [Request URI=%s, First Party URI=%s]\n",
+              requestURIStr.get(), firstPartyURIStr.get()));
+#endif
+    }
+}
+
 nsresult
 nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
 {
@@ -5771,6 +5839,8 @@ nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
     // notify "http-on-modify-request" observers
     CallOnModifyRequestObservers();
 
+    RemoveAuthorizationHeaderIfAppropriate();
+
     mIsPending = true;
 
     // get rid of the old response headers
diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h
index 8d3d23d..a76ed8e 100644
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -282,6 +282,7 @@ private:
     nsresult ProcessPartialContent();
     nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
 
+    void     RemoveAuthorizationHeaderIfAppropriate();
     nsresult DoAuthRetry(nsAHttpConnection *);
 
     void     HandleAsyncRedirectChannelToHttps();





More information about the tbb-commits mailing list