Bug 1165162 - Rework the nsIScriptSecurityManager principal-minting API to be originAttributes-centric. r=gabor,r=bholley,sr=sicking

This commit is contained in:
Bobby Holley 2015-05-15 13:43:11 -07:00
parent 49895f610e
commit cbfe84ef74
8 changed files with 154 additions and 129 deletions

View File

@ -8,6 +8,10 @@
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsPrincipal.h"
#include "nsNetUtil.h"
#include "nsNullPrincipal.h"
#include "nsScriptSecurityManager.h"
#include "mozilla/dom/ToJSValue.h"
@ -15,7 +19,7 @@
namespace mozilla {
void
BasePrincipal::OriginAttributes::CreateSuffix(nsACString& aStr)
OriginAttributes::CreateSuffix(nsACString& aStr)
{
aStr.Truncate();
MOZ_RELEASE_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
@ -32,14 +36,14 @@ BasePrincipal::OriginAttributes::CreateSuffix(nsACString& aStr)
}
void
BasePrincipal::OriginAttributes::Serialize(nsIObjectOutputStream* aStream) const
OriginAttributes::Serialize(nsIObjectOutputStream* aStream) const
{
aStream->Write32(mAppId);
aStream->WriteBoolean(mInBrowser);
}
nsresult
BasePrincipal::OriginAttributes::Deserialize(nsIObjectInputStream* aStream)
OriginAttributes::Deserialize(nsIObjectInputStream* aStream)
{
nsresult rv = aStream->Read32(&mAppId);
NS_ENSURE_SUCCESS(rv, rv);
@ -179,4 +183,36 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
return NS_OK;
}
already_AddRefed<BasePrincipal>
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs)
{
// If the URI is supposed to inherit the security context of whoever loads it,
// we shouldn't make a codebase principal for it.
bool inheritsPrincipal;
nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
&inheritsPrincipal);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(rv) || inheritsPrincipal) {
return nsNullPrincipal::Create();
}
// Check whether the URI knows what its principal is supposed to be.
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (!principal) {
return nsNullPrincipal::Create();
}
nsRefPtr<BasePrincipal> concrete = Cast(principal);
return concrete.forget();
}
// Mint a codebase principal.
nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
rv = codebase->Init(aURI, aAttrs);
NS_ENSURE_SUCCESS(rv, nullptr);
return codebase.forget();
}
} // namespace mozilla

View File

@ -18,6 +18,35 @@ class nsIObjectInputStream;
namespace mozilla {
class OriginAttributes : public dom::OriginAttributesDictionary
{
public:
OriginAttributes() {}
OriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
bool operator==(const OriginAttributes& aOther) const
{
return mAppId == aOther.mAppId &&
mInBrowser == aOther.mInBrowser;
}
bool operator!=(const OriginAttributes& aOther) const
{
return !(*this == aOther);
}
// Serializes non-default values into the suffix format, i.e.
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
// returns an empty string.
void CreateSuffix(nsACString& aStr);
void Serialize(nsIObjectOutputStream* aStream) const;
nsresult Deserialize(nsIObjectInputStream* aStream);
};
/*
* Base class from which all nsIPrincipal implementations inherit. Use this for
* default implementations and other commonalities between principal
@ -51,33 +80,7 @@ public:
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
struct OriginAttributes : public dom::OriginAttributesDictionary {
OriginAttributes() {}
OriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
bool operator==(const OriginAttributes& aOther) const
{
return mAppId == aOther.mAppId &&
mInBrowser == aOther.mInBrowser;
}
bool operator!=(const OriginAttributes& aOther) const
{
return !(*this == aOther);
}
// Serializes non-default values into the suffix format, i.e.
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
// returns an empty string.
void CreateSuffix(nsACString& aStr);
void Serialize(nsIObjectOutputStream* aStream) const;
nsresult Deserialize(nsIObjectInputStream* aStream);
};
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs);
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
uint32_t AppId() const { return mOriginAttributes.mAppId; }

View File

@ -26,7 +26,7 @@ class DomainPolicyClone;
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
[scriptable, uuid(ba602ca6-dc7a-457e-a57a-ee5b343fd863)]
[scriptable, uuid(f4c578b8-5bac-4ba1-9582-f1140e09a3b4)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@ -179,12 +179,28 @@ interface nsIScriptSecurityManager : nsISupports
nsIPrincipal getNoAppCodebasePrincipal(in nsIURI uri);
/**
* Legacy name for getNoAppCodebasePrincipal.
* Legacy method for getting a principal with no origin attributes.
*
* @deprecated use getNoAppCodebasePrincipal instead.
* @deprecated use createCodebasePrincipal instead.
*/
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
/**
* Returns a principal whose origin is composed of |uri| and |originAttributes|.
* See nsIPrincipal.h for a description of origin attributes, and
* SystemDictionaries.webidl for a list of origin attributes and their defaults.
*/
[implicit_jscontext]
nsIPrincipal createCodebasePrincipal(in nsIURI uri, in jsval originAttributes);
/**
* Returns a unique nonce principal with |originAttributes|.
* See nsIPrincipal.h for a description of origin attributes, and
* SystemDictionaries.webidl for a list of origin attributes and their defaults.
*/
[implicit_jscontext]
nsIPrincipal createNullPrincipal(in jsval originAttributes);
/**
* Returns OK if aSourceURI and target have the same "origin"
* (scheme, host, and port).

View File

@ -54,9 +54,9 @@ public:
// Returns null on failure.
static already_AddRefed<nsNullPrincipal>
Create(const OriginAttributes& aOriginAttributes = OriginAttributes());
Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
nsresult Init(const OriginAttributes& aOriginAttributes = OriginAttributes());
nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
virtual void GetScriptLocation(nsACString &aStr) override;

View File

@ -34,7 +34,7 @@ public:
nsPrincipal();
// Init() must be called before the principal is in a usable state.
nsresult Init(nsIURI* aCodebase, const OriginAttributes& aOriginAttributes);
nsresult Init(nsIURI* aCodebase, const mozilla::OriginAttributes& aOriginAttributes);
virtual void GetScriptLocation(nsACString& aStr) override;
void SetURI(nsIURI* aURI);

View File

@ -19,6 +19,7 @@
#include "nsINestedURI.h"
#include "nspr.h"
#include "nsJSPrincipals.h"
#include "mozilla/BasePrincipal.h"
#include "nsSystemPrincipal.h"
#include "nsPrincipal.h"
#include "nsNullPrincipal.h"
@ -378,8 +379,10 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
return GetLoadContextCodebasePrincipal(uri, loadContext, aPrincipal);
}
return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID,
/* isInBrowserElement */ false, aPrincipal);
OriginAttributes attrs(UNKNOWN_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -979,55 +982,24 @@ nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
return NS_OK;
}
nsresult
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal **result)
{
// I _think_ it's safe to not create null principals here based on aURI.
// At least all the callers would do the right thing in those cases, as far
// as I can tell. --bz
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (!principal) {
principal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
}
principal.forget(result);
return NS_OK;
}
BasePrincipal::OriginAttributes attrs(aAppId, aInMozBrowser);
nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
nsresult rv = codebase->Init(aURI, attrs);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*result = codebase);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI,
nsIScriptSecurityManager::UNKNOWN_APP_ID,
false, aPrincipal);
OriginAttributes attrs(UNKNOWN_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI, nsIScriptSecurityManager::NO_APP_ID,
false, aPrincipal);
OriginAttributes attrs(NO_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1037,6 +1009,33 @@ nsScriptSecurityManager::GetCodebasePrincipal(nsIURI* aURI,
return GetNoAppCodebasePrincipal(aURI, aPrincipal);
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(attrs);
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
prin.forget(aPrincipal);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
uint32_t aAppId,
@ -1046,7 +1045,10 @@ nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
NS_ERROR_INVALID_ARG);
return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal);
OriginAttributes attrs(aAppId, aInMozBrowser);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1055,14 +1057,13 @@ nsScriptSecurityManager::
nsILoadContext* aLoadContext,
nsIPrincipal** aPrincipal)
{
uint32_t appId;
aLoadContext->GetAppId(&appId);
bool isInBrowserElement;
aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
return GetCodebasePrincipalInternal(aURI,
appId,
isInBrowserElement,
aPrincipal);
// XXXbholley - Make this more general in bug 1165466.
OriginAttributes attrs;
aLoadContext->GetAppId(&attrs.mAppId);
aLoadContext->GetIsInBrowserElement(&attrs.mInBrowser);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1070,37 +1071,11 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
nsIDocShell* aDocShell,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI,
aDocShell->GetAppId(),
aDocShell->GetIsInBrowserElement(),
aPrincipal);
}
nsresult
nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI,
uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal **result)
{
NS_ENSURE_ARG(aURI);
bool inheritsPrincipal;
nsresult rv =
NS_URIChainHasFlags(aURI,
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
&inheritsPrincipal);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(rv) || inheritsPrincipal) {
principal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
} else {
rv = CreateCodebasePrincipal(aURI, aAppId, aInMozBrowser,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
}
principal.forget(result);
return NS_OK;
// XXXbholley - Make this more general in bug 1165466.
OriginAttributes attrs(aDocShell->GetAppId(), aDocShell->GetIsInBrowserElement());
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
// static

View File

@ -22,6 +22,10 @@ class nsIIOService;
class nsIStringBundle;
class nsSystemPrincipal;
namespace mozilla {
class OriginAttributes;
}
/////////////////////////////
// nsScriptSecurityManager //
/////////////////////////////
@ -99,15 +103,6 @@ private:
// should error out at that point.
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
nsresult
GetCodebasePrincipalInternal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal** result);
nsresult
CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
nsIPrincipal** result);
nsresult
Init();

View File

@ -12,9 +12,9 @@
* attributes.
*
* IMPORTANT: If you add any members here, you need to update the
* CreateSuffix, Serialize, and Deserialize implementations in BasePrincipal,
* and bump the CIDs of all the principal implementations that invoke those
* methods.
* methods on mozilla::OriginAttributes, and bump the CIDs of all
* the principal implementations that use OriginAttributes in their
* nsISerializable implementations.
*/
dictionary OriginAttributesDictionary {
unsigned long appId = 0;