[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