Bug 1162772, part 3 - Add a getChannelResultPrincipalIfNotSandboxed method to nsIScriptSecurityManager. r=bz
authorJonathan Watt <jwatt@jwatt.org>
Thu, 28 Apr 2016 11:13:09 +0100
changeset 295689 287b9a36761979eaf256dfe509e9554b060cc5ae
parent 295688 bc0204d48f0fb8dac87d7687c7724ab2cb74c9dd
child 295690 934c2b89e9e2fdbe068af6884046e945405d0dbd
push id19015
push usercbook@mozilla.com
push dateMon, 02 May 2016 09:39:23 +0000
treeherderfx-team@2080375bc69d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1162772
milestone49.0a1
Bug 1162772, part 3 - Add a getChannelResultPrincipalIfNotSandboxed method to nsIScriptSecurityManager. r=bz MozReview-Commit-ID: 4QwM1y6wRb
caps/nsIScriptSecurityManager.idl
caps/nsScriptSecurityManager.cpp
caps/nsScriptSecurityManager.h
--- a/caps/nsIScriptSecurityManager.idl
+++ b/caps/nsIScriptSecurityManager.idl
@@ -21,17 +21,17 @@ class DomainPolicyClone;
 }
 }
 %}
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
 
-[scriptable, uuid(b7ae2310-576e-11e5-a837-0800200c9a66)]
+[scriptable, uuid(da831650-4241-4892-806c-cce8465a2ba8)]
 interface nsIScriptSecurityManager : nsISupports
 {
     /**
      * For each of these hooks returning NS_OK means 'let the action continue'.
      * Returning an error code means 'veto the action'. XPConnect will return
      * false to the js engine if the action is vetoed. The implementor of this
      * interface is responsible for setting a JS exception into the JSContext
      * if that is appropriate.
@@ -238,16 +238,34 @@ interface nsIScriptSecurityManager : nsI
     /**
      * Get the principal for the given channel.  This will typically be the
      * channel owner if there is one, and the codebase principal for the
      * channel's URI otherwise.  aChannel must not be null.
      */
     nsIPrincipal getChannelResultPrincipal(in nsIChannel aChannel);
 
     /**
+     * Temporary API until bug 1220687 is fixed.
+     *
+     * Returns the same value as getChannelResultPrincipal, but ignoring
+     * sandboxing.  Specifically, if sandboxing would have prevented the
+     * channel's triggering principal from being returned by
+     * getChannelResultPrincipal, the triggering principal will be returned
+     * by this method.
+     *
+     * Note that this method only ignores sandboxing of the channel in
+     * question, it does not ignore sandboxing of any channels further up a
+     * document chain.  The triggering principal itself may still be the null
+     * principal due to sandboxing further up a document chain.  In that regard
+     * the ignoring of sandboxing is limited.
+     */
+    [noscript, nostdcall]
+    nsIPrincipal getChannelResultPrincipalIfNotSandboxed(in nsIChannel aChannel);
+
+    /**
      * Get the codebase principal for the channel's URI.
      * aChannel must not be null.
      */
     nsIPrincipal getChannelURIPrincipal(in nsIChannel aChannel);
 
     /**
      * Check whether a given principal is a system principal.  This allows us
      * to avoid handing back the system principal to script while allowing
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -6,16 +6,17 @@
 
 #include "nsScriptSecurityManager.h"
 
 #include "mozilla/ArrayUtils.h"
 
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "nsIAppsService.h"
+#include "nsIInputStreamChannel.h"
 #include "nsILoadContext.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsINestedURI.h"
 #include "nspr.h"
 #include "nsJSPrincipals.h"
@@ -324,47 +325,74 @@ nsScriptSecurityManager::AppStatusForPri
  * the load doesn't require sandboxing or inheriting, it will return the same
  * principal as GetChannelURIPrincipal. Namely the principal of the URI
  * that is being loaded.
  */
 NS_IMETHODIMP
 nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
                                                    nsIPrincipal** aPrincipal)
 {
+  return GetChannelResultPrincipal(aChannel, aPrincipal,
+                                   /*aIgnoreSandboxing*/ false);
+}
+
+nsresult
+nsScriptSecurityManager::GetChannelResultPrincipalIfNotSandboxed(nsIChannel* aChannel,
+                                                                 nsIPrincipal** aPrincipal)
+{
+  return GetChannelResultPrincipal(aChannel, aPrincipal,
+                                   /*aIgnoreSandboxing*/ true);
+}
+
+nsresult
+nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
+                                                   nsIPrincipal** aPrincipal,
+                                                   bool aIgnoreSandboxing)
+{
     NS_PRECONDITION(aChannel, "Must have channel!");
     nsCOMPtr<nsISupports> owner;
     aChannel->GetOwner(getter_AddRefs(owner));
     if (owner) {
         CallQueryInterface(owner, aPrincipal);
         if (*aPrincipal) {
             return NS_OK;
         }
     }
 
     // Check whether we have an nsILoadInfo that says what we should do.
     nsCOMPtr<nsILoadInfo> loadInfo;
     aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
     if (loadInfo) {
-        if (loadInfo->GetLoadingSandboxed()) {
+        if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
             RefPtr<nsNullPrincipal> prin;
             if (loadInfo->LoadingPrincipal()) {
               prin =
                 nsNullPrincipal::CreateWithInheritedAttributes(loadInfo->LoadingPrincipal());
             } else {
               NeckoOriginAttributes nAttrs;
               loadInfo->GetOriginAttributes(&nAttrs);
               PrincipalOriginAttributes pAttrs;
               pAttrs.InheritFromNecko(nAttrs);
               prin = nsNullPrincipal::Create(pAttrs);
             }
             prin.forget(aPrincipal);
             return NS_OK;
         }
 
-        if (loadInfo->GetForceInheritPrincipal()) {
+        bool forceInterit = loadInfo->GetForceInheritPrincipal();
+        if (aIgnoreSandboxing && !forceInterit) {
+          // Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
+          // sandboxing:
+          if (loadInfo->GetLoadingSandboxed() &&
+              (loadInfo->GetSecurityFlags() &
+               nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL_WAS_DROPPED)) {
+            forceInterit = true;
+          }
+        }
+        if (forceInterit) {
             NS_ADDREF(*aPrincipal = loadInfo->TriggeringPrincipal());
             return NS_OK;
         }
 
         nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
         if (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
             securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
             securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -115,16 +115,20 @@ private:
     ScriptSecurityPrefChanged();
 
     inline void
     AddSitesToFileURIWhitelist(const nsCString& aSiteList);
 
     // If aURI is a moz-extension:// URI, set mAddonId to the associated addon.
     nsresult MaybeSetAddonIdFromURI(mozilla::PrincipalOriginAttributes& aAttrs, nsIURI* aURI);
 
+    nsresult GetChannelResultPrincipal(nsIChannel* aChannel,
+                                       nsIPrincipal** aPrincipal,
+                                       bool aIgnoreSandboxing);
+
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
     bool mPrefInitialized;
     bool mIsJavaScriptEnabled;
     nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
 
     // This machinery controls new-style domain policies. The old-style
     // policy machinery will be removed soon.
     nsCOMPtr<nsIDomainPolicy> mDomainPolicy;