Bug 1534971: Add helper function within CSP to check if two CSPs are equal. r=jkt
authorChristoph Kerschbaumer <ckerschb@christophkerschbaumer.com>
Fri, 15 Mar 2019 12:20:52 +0000
changeset 522032 6343f4a4d75eca45559003206bce65c8c3c14f3e
parent 522031 ad59be7ee0c20a42f70989bcce84308fdd66619a
child 522033 f8fa30e286ff96d6aaa2ef8febc35d9c224bdbd4
child 522072 79995994a23fe694827bbbc3ec3f7b7819c8c6f2
push id10871
push usercbrindusan@mozilla.com
push dateMon, 18 Mar 2019 15:49:32 +0000
treeherdermozilla-beta@018abdd16060 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjkt
bugs1534971
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 1534971: Add helper function within CSP to check if two CSPs are equal. r=jkt Differential Revision: https://phabricator.services.mozilla.com/D23567
caps/nsScriptSecurityManager.cpp
docshell/base/nsDocShell.cpp
dom/security/nsCSPContext.cpp
dom/security/nsCSPContext.h
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -57,16 +57,17 @@
 #include "nsIResProtocolHandler.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Components.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/NullPrincipal.h"
 #include <stdint.h>
+#include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsILoadInfo.h"
@@ -284,36 +285,17 @@ static void InheritAndSetCSPOnPrincipalI
 
   // if the principalToInherit had a CSP, add it to the before
   // created NullPrincipal (unless it already has one)
   MOZ_ASSERT(aPrincipal->GetIsNullPrincipal(),
              "inheriting the CSP only valid for NullPrincipal");
   nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP;
   aPrincipal->GetCsp(getter_AddRefs(nullPrincipalCSP));
   if (nullPrincipalCSP) {
-#ifdef DEBUG
-    {
-      uint32_t nullPrincipalCSPCount = 0;
-      nullPrincipalCSP->GetPolicyCount(&nullPrincipalCSPCount);
-
-      uint32_t originalCSPCount = 0;
-      originalCSP->GetPolicyCount(&originalCSPCount);
-
-      MOZ_ASSERT(nullPrincipalCSPCount == originalCSPCount,
-                 "There should be no other CSP here.");
-
-      nsAutoString nullPrincipalCSPStr, originalCSPStr;
-      for (uint32_t i = 0; i < originalCSPCount; ++i) {
-        originalCSP->GetPolicyString(i, originalCSPStr);
-        nullPrincipalCSP->GetPolicyString(i, nullPrincipalCSPStr);
-        MOZ_ASSERT(originalCSPStr.Equals(nullPrincipalCSPStr),
-                   "There should be no other CSP string here.");
-      }
-    }
-#endif
+    MOZ_ASSERT(nsCSPContext::Equals(originalCSP, nullPrincipalCSP));
     // CSPs are equal, no need to set it again.
     return;
   }
 
   // After 965637 all that magical CSP inheritance goes away. For now,
   // we have to create a clone of the current CSP and have to manually
   // set it on the Principal.
   uint32_t count = 0;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -54,16 +54,17 @@
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ServiceWorkerInterceptController.h"
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/dom/SessionStorageManager.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/ChildSHistory.h"
+#include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
 
 #include "mozilla/net/ReferrerPolicy.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "ReferrerInfo.h"
 
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
@@ -9907,44 +9908,19 @@ nsresult nsDocShell::DoURILoad(nsDocShel
   }
 
   // Navigational requests that are same origin need to be upgraded in case
   // upgrade-insecure-requests is present. Please note that in that case
   // the triggeringPrincipal is holding the CSP that potentially
   // holds upgrade-insecure-requests.
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   aLoadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp));
-
 #ifdef DEBUG
-  {
-    // After Bug 965637 we move the CSP from the Principal into the Client,
-    // hence we need an explicit CSP argument passed to docshell. Let's make
-    // sure the explicit CSP is the same as the CSP on the Principal.
-    uint32_t principalCSPCount = 0;
-    if (csp) {
-      csp->GetPolicyCount(&principalCSPCount);
-    }
-
-    nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
-    uint32_t argCSPCount = 0;
-    if (argsCSP) {
-      argsCSP->GetPolicyCount(&argCSPCount);
-    }
-
-    MOZ_ASSERT(principalCSPCount == argCSPCount,
-               "Different PolicyCount for CSP as arg and Principal");
-
-    nsAutoString principalPolicyStr, argPolicyStr;
-    for (uint32_t i = 0; i < principalCSPCount; ++i) {
-      csp->GetPolicyString(i, principalPolicyStr);
-      argsCSP->GetPolicyString(i, argPolicyStr);
-      MOZ_ASSERT(principalPolicyStr.Equals(argPolicyStr),
-                 "Different PolicyStr for CSP as arg and Principal");
-    }
-  }
+  nsCOMPtr<nsIContentSecurityPolicy> argsCSP = aLoadState->Csp();
+  MOZ_ASSERT(nsCSPContext::Equals(csp, argsCSP));
 #endif
 
   if (csp) {
     bool upgradeInsecureRequests = false;
     csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
     if (upgradeInsecureRequests) {
       // only upgrade if the navigation is same origin
       nsCOMPtr<nsIPrincipal> resultPrincipal;
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -248,16 +248,50 @@ nsCSPContext::nsCSPContext()
 
 nsCSPContext::~nsCSPContext() {
   CSPCONTEXTLOG(("nsCSPContext::~nsCSPContext"));
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     delete mPolicies[i];
   }
 }
 
+/* static */
+bool nsCSPContext::Equals(nsIContentSecurityPolicy* aCSP,
+                          nsIContentSecurityPolicy* aOtherCSP) {
+  if (aCSP == aOtherCSP) {
+    // fast path for pointer equality
+    return true;
+  }
+
+  uint32_t policyCount = 0;
+  if (aCSP) {
+    aCSP->GetPolicyCount(&policyCount);
+  }
+
+  uint32_t otherPolicyCount = 0;
+  if (aOtherCSP) {
+    aOtherCSP->GetPolicyCount(&otherPolicyCount);
+  }
+
+  if (policyCount != otherPolicyCount) {
+    return false;
+  }
+
+  nsAutoString policyStr, otherPolicyStr;
+  for (uint32_t i = 0; i < policyCount; ++i) {
+    aCSP->GetPolicyString(i, policyStr);
+    aOtherCSP->GetPolicyString(i, otherPolicyStr);
+    if (!policyStr.Equals(otherPolicyStr)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
 nsresult nsCSPContext::InitFromOther(nsCSPContext* aOtherContext,
                                      Document* aDoc, nsIPrincipal* aPrincipal) {
   NS_ENSURE_ARG(aOtherContext);
 
   nsresult rv = SetRequestContext(aDoc, aPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (auto policy : aOtherContext->mPolicies) {
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -49,16 +49,19 @@ class nsCSPContext : public nsIContentSe
   NS_DECL_NSISERIALIZABLE
 
  protected:
   virtual ~nsCSPContext();
 
  public:
   nsCSPContext();
 
+  static bool Equals(nsIContentSecurityPolicy* aCSP,
+                     nsIContentSecurityPolicy* aOtherCSP);
+
   nsresult InitFromOther(nsCSPContext* otherContext,
                          mozilla::dom::Document* aDoc,
                          nsIPrincipal* aPrincipal);
 
   void SetIPCPolicies(
       const nsTArray<mozilla::ipc::ContentSecurityPolicy>& policies);
 
   /**