Bug 1525036 - Respect CrossOriginPolicy in nsHttpChannel r=nika
authorValentin Gosu <valentin.gosu@gmail.com>
Tue, 12 Mar 2019 08:05:03 +0000
changeset 463613 e8c317d99a9981648624d28f9bac5dd6fc7b1ad0
parent 463612 b77be7643141a8f3646257e599b38a3be862e6e0
child 463614 5dcadd5237115f3374ff2cad0dc189f517064405
push id35689
push userbtara@mozilla.com
push dateTue, 12 Mar 2019 16:08:08 +0000
treeherdermozilla-central@68d86a527385 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika
bugs1525036
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1525036 - Respect CrossOriginPolicy in nsHttpChannel r=nika Differential Revision: https://phabricator.services.mozilla.com/D21415
netwerk/protocol/http/nsHttpAtomList.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
--- a/netwerk/protocol/http/nsHttpAtomList.h
+++ b/netwerk/protocol/http/nsHttpAtomList.h
@@ -36,16 +36,17 @@ HTTP_ATOM(Content_Encoding, "Content-Enc
 HTTP_ATOM(Content_Language, "Content-Language")
 HTTP_ATOM(Content_Length, "Content-Length")
 HTTP_ATOM(Content_Location, "Content-Location")
 HTTP_ATOM(Content_MD5, "Content-MD5")
 HTTP_ATOM(Content_Range, "Content-Range")
 HTTP_ATOM(Content_Type, "Content-Type")
 HTTP_ATOM(Cookie, "Cookie")
 HTTP_ATOM(Cross_Origin_Opener_Policy, "Cross-Origin-Opener-Policy")
+HTTP_ATOM(Cross_Origin, "Cross-Origin")
 HTTP_ATOM(Date, "Date")
 HTTP_ATOM(DAV, "DAV")
 HTTP_ATOM(Depth, "Depth")
 HTTP_ATOM(Destination, "Destination")
 HTTP_ATOM(DoNotTrack, "DNT")
 HTTP_ATOM(ETag, "Etag")
 HTTP_ATOM(Expect, "Expect")
 HTTP_ATOM(Expires, "Expires")
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -2446,16 +2446,23 @@ nsresult nsHttpChannel::ContinueProcessR
     rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
     if (NS_FAILED(rv)) {
       LOG(("  Disconnect failed (%08x)", static_cast<uint32_t>(rv)));
     }
     mAuthProvider = nullptr;
     LOG(("  continuation state has been reset"));
   }
 
+  rv = ProcessCrossOriginHeader();
+  if (NS_FAILED(rv)) {
+    mStatus = NS_ERROR_BLOCKED_BY_POLICY;
+    HandleAsyncAbort();
+    return NS_OK;
+  }
+
   rv = NS_OK;
   if (!mCanceled) {
     // notify "http-on-may-change-process" observers
     gHttpHandler->OnMayChangeProcess(this);
 
     if (mRedirectTabPromise) {
       MOZ_ASSERT(!mOnStartRequestCalled);
 
@@ -7306,16 +7313,83 @@ nsHttpChannel::HasCrossOriginOpenerPolic
       *aMismatch = true;
       return NS_OK;
     }
   }
 
   return NS_OK;
 }
 
+nsresult nsHttpChannel::GetResponseCrossOriginPolicy(
+    nsILoadInfo::CrossOriginPolicy *aResponseCrossOriginPolicy) {
+  if (!mResponseHead) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsILoadInfo::CrossOriginPolicy policy = nsILoadInfo::CROSS_ORIGIN_POLICY_NULL;
+
+  nsAutoCString content;
+  Unused << mResponseHead->GetHeader(nsHttp::Cross_Origin, content);
+
+  // Cross-Origin = %s"anonymous" / %s"use-credentials" ; case-sensitive
+
+  if (content.EqualsLiteral("anonymous")) {
+    policy = nsILoadInfo::CROSS_ORIGIN_POLICY_ANONYMOUS;
+  } else if (content.EqualsLiteral("use-credentials")) {
+    policy = nsILoadInfo::CROSS_ORIGIN_POLICY_USE_CREDENTIALS;
+  }
+
+  *aResponseCrossOriginPolicy = policy;
+  return NS_OK;
+}
+
+nsresult nsHttpChannel::ProcessCrossOriginHeader() {
+  nsresult rv;
+  if (!StaticPrefs::browser_tabs_remote_useCrossOriginPolicy()) {
+    return NS_OK;
+  }
+
+  // Only consider Cross-Origin for document loads.
+  if (mLoadInfo->GetExternalContentPolicyType() !=
+          nsIContentPolicy::TYPE_DOCUMENT &&
+      mLoadInfo->GetExternalContentPolicyType() !=
+          nsIContentPolicy::TYPE_SUBDOCUMENT) {
+    return NS_OK;
+  }
+
+  RefPtr<mozilla::dom::BrowsingContext> ctx;
+  if (mLoadInfo->GetExternalContentPolicyType() ==
+      nsIContentPolicy::TYPE_DOCUMENT) {
+    mLoadInfo->GetBrowsingContext(getter_AddRefs(ctx));
+  } else {
+    mLoadInfo->GetFrameBrowsingContext(getter_AddRefs(ctx));
+  }
+
+  if (!ctx) {
+    return NS_OK;
+  }
+
+  nsILoadInfo::CrossOriginPolicy documentPolicy = ctx->CrossOriginPolicy();
+  nsILoadInfo::CrossOriginPolicy resultPolicy =
+      nsILoadInfo::CROSS_ORIGIN_POLICY_NULL;
+  rv = GetResponseCrossOriginPolicy(&resultPolicy);
+  if (NS_FAILED(rv)) {
+    return NS_OK;
+  }
+
+  ctx->SetCrossOriginPolicy(resultPolicy);
+
+  if (documentPolicy != nsILoadInfo::CROSS_ORIGIN_POLICY_NULL &&
+      resultPolicy == nsILoadInfo::CROSS_ORIGIN_POLICY_NULL) {
+    return NS_ERROR_BLOCKED_BY_POLICY;
+  }
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsHttpChannel::OnStartRequest(nsIRequest *request) {
   nsresult rv;
 
   MOZ_ASSERT(mRequestObserversCalled);
 
   AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK);
 
@@ -7421,16 +7495,23 @@ nsHttpChannel::OnStartRequest(nsIRequest
   }
 
   // avoid crashing if mListener happens to be null...
   if (!mListener) {
     MOZ_ASSERT_UNREACHABLE("mListener is null");
     return NS_OK;
   }
 
+  rv = ProcessCrossOriginHeader();
+  if (NS_FAILED(rv)) {
+    mStatus = NS_ERROR_BLOCKED_BY_POLICY;
+    HandleAsyncAbort();
+    return NS_OK;
+  }
+
   // before we check for redirects, check if the load should be shifted into a
   // new process.
   rv = NS_OK;
   if (!mCanceled) {
     // notify "http-on-may-change-process" observers
     gHttpHandler->OnMayChangeProcess(this);
 
     if (mRedirectTabPromise) {
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -470,16 +470,20 @@ class nsHttpChannel final : public HttpB
   MOZ_MUST_USE nsresult
   ProcessContentSignatureHeader(nsHttpResponseHead *aResponseHead);
 
   /**
    * A function that will, if the feature is enabled, send security reports.
    */
   void ProcessSecurityReport(nsresult status);
 
+  nsresult GetResponseCrossOriginPolicy(
+      nsILoadInfo::CrossOriginPolicy *aResponseCrossOriginPolicy);
+  nsresult ProcessCrossOriginHeader();
+
   /**
    * A function to process a single security header (STS or PKP), assumes
    * some basic sanity checks have been applied to the channel. Called
    * from ProcessSecurityHeaders.
    */
   MOZ_MUST_USE nsresult ProcessSingleSecurityHeader(
       uint32_t aType, nsITransportSecurityInfo *aSecInfo, uint32_t aFlags);