From 03cd461c063e26941509dc404ae3d570678f5210 Mon Sep 17 00:00:00 2001 From: Christoph Kerschbaumer Date: Sun, 19 Jul 2015 19:11:57 -0700 Subject: [PATCH] Bug 1143922 - Add AsyncOpen2 to nsIChannel and perform security checks when opening a channel - loadinfo changes (r=sicking,tanvi,sworkman) --- ipc/glue/BackgroundUtils.cpp | 4 + netwerk/base/LoadInfo.cpp | 71 ++++++++++++++ netwerk/base/LoadInfo.h | 24 +++-- netwerk/base/nsILoadInfo.idl | 136 ++++++++++++++++++++++++++- netwerk/ipc/NeckoChannelParams.ipdlh | 2 + 5 files changed, 224 insertions(+), 13 deletions(-) diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 0d0ba2f8c7a..1db7fee623d 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -261,6 +261,8 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), + aLoadInfo->GetEnforceSecurity(), + aLoadInfo->GetInitialSecurityCheckDone(), redirectChain); return NS_OK; @@ -303,6 +305,8 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs, loadInfoArgs.innerWindowID(), loadInfoArgs.outerWindowID(), loadInfoArgs.parentOuterWindowID(), + loadInfoArgs.enforceSecurity(), + loadInfoArgs.initialSecurityCheckDone(), redirectChain); loadInfo.forget(outLoadInfo); diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 6b2f47acdfa..c4465a07fd9 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -37,6 +37,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(0) , mOuterWindowID(0) , mParentOuterWindowID(0) + , mEnforceSecurity(false) + , mInitialSecurityCheckDone(false) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -91,6 +93,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, nsTArray>& aRedirectChain) : mLoadingPrincipal(aLoadingPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal) @@ -100,6 +104,8 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, , mInnerWindowID(aInnerWindowID) , mOuterWindowID(aOuterWindowID) , mParentOuterWindowID(aParentOuterWindowID) + , mEnforceSecurity(aEnforceSecurity) + , mInitialSecurityCheckDone(aInitialSecurityCheckDone) { MOZ_ASSERT(mLoadingPrincipal); MOZ_ASSERT(mTriggeringPrincipal); @@ -164,6 +170,26 @@ LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetSecurityMode(uint32_t *aFlags) +{ + *aFlags = (mSecurityFlags & + (nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS | + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL | + nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)); + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetRequireCorsWithCredentials(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetForceInheritPrincipal(bool* aInheritPrincipal) { @@ -179,6 +205,14 @@ LoadInfo::GetLoadingSandboxed(bool* aLoadingSandboxed) return NS_OK; } +NS_IMETHODIMP +LoadInfo::GetAboutBlankInherits(bool* aResult) +{ + *aResult = + (mSecurityFlags & nsILoadInfo::SEC_ABOUT_BLANK_INHERITS); + return NS_OK; +} + NS_IMETHODIMP LoadInfo::GetContentPolicyType(nsContentPolicyType* aResult) { @@ -234,6 +268,43 @@ LoadInfo::GetParentOuterWindowID(uint64_t* aResult) return NS_OK; } +NS_IMETHODIMP +LoadInfo::SetEnforceSecurity(bool aEnforceSecurity) +{ + // Indicates whether the channel was openend using AsyncOpen2. Once set + // to true, it must remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aEnforceSecurity, "aEnforceSecurity must be true"); + mEnforceSecurity = mEnforceSecurity || aEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetEnforceSecurity(bool* aResult) +{ + *aResult = mEnforceSecurity; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::SetInitialSecurityCheckDone(bool aInitialSecurityCheckDone) +{ + // Indicates whether the channel was ever evaluated by the + // ContentSecurityManager. Once set to true, this flag must + // remain true throughout the lifetime of the channel. + // Setting it to anything else than true will be discarded. + MOZ_ASSERT(aInitialSecurityCheckDone, "aInitialSecurityCheckDone must be true"); + mInitialSecurityCheckDone = mInitialSecurityCheckDone || aInitialSecurityCheckDone; + return NS_OK; +} + +NS_IMETHODIMP +LoadInfo::GetInitialSecurityCheckDone(bool* aResult) +{ + *aResult = mInitialSecurityCheckDone; + return NS_OK; +} + NS_IMETHODIMP LoadInfo::AppendRedirectedPrincipal(nsIPrincipal* aPrincipal) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index f4d05eab654..23f096245f7 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -64,6 +64,8 @@ private: uint64_t aInnerWindowID, uint64_t aOuterWindowID, uint64_t aParentOuterWindowID, + bool aEnforceSecurity, + bool aInitialSecurityCheckDone, nsTArray>& aRedirectChain); friend nsresult @@ -73,16 +75,18 @@ private: ~LoadInfo(); - nsCOMPtr mLoadingPrincipal; - nsCOMPtr mTriggeringPrincipal; - nsWeakPtr mLoadingContext; - nsSecurityFlags mSecurityFlags; - nsContentPolicyType mContentPolicyType; - nsCOMPtr mBaseURI; - bool mUpgradeInsecureRequests; - uint64_t mInnerWindowID; - uint64_t mOuterWindowID; - uint64_t mParentOuterWindowID; + nsCOMPtr mLoadingPrincipal; + nsCOMPtr mTriggeringPrincipal; + nsWeakPtr mLoadingContext; + nsSecurityFlags mSecurityFlags; + nsContentPolicyType mContentPolicyType; + nsCOMPtr mBaseURI; + bool mUpgradeInsecureRequests; + uint64_t mInnerWindowID; + uint64_t mOuterWindowID; + uint64_t mParentOuterWindowID; + bool mEnforceSecurity; + bool mInitialSecurityCheckDone; nsTArray> mRedirectChain; }; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 8e59bcb2983..66efc5a85b0 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -23,7 +23,7 @@ typedef unsigned long nsSecurityFlags; /** * An nsILoadOwner represents per-load information about who started the load. */ -[scriptable, builtinclass, uuid(5c724690-7ba9-49c4-af9c-c9c4f6776871)] +[scriptable, builtinclass, uuid(cc51498e-f8f8-469d-85ba-6dcba17027e4)] interface nsILoadInfo : nsISupports { /** @@ -31,6 +31,64 @@ interface nsILoadInfo : nsISupports */ const unsigned long SEC_NORMAL = 0; + /** + * The following five flags determine the security mode and hence what kind of + * security checks should be performed throughout the lifetime of the channel. + * + * * SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS + * * SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED + * * SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS + * * SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL + * * SEC_REQUIRE_CORS_DATA_INHERITS + * + * Exactly one of these flags are required to be set in order to allow + * the channel to perform the correct security checks (SOP, CORS, ...) and + * return the correct result principal. If none or more than one of these + * flags are set AsyncOpen2 will fail. + */ + + /* + * Enforce the same origin policy where data: loads inherit + * the principal. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS = (1<<0); + + /* + * Enforce the same origin policy but data: loads are blocked. + */ + const unsigned long SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED = (1<<1); + + /** + * Allow loads from other origins. Loads from data: will inherit + * the principal of the origin that triggered the load. + * Commonly used by plain ,