mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backout bug 754202 (all patches, rather than just patches 3-7).
This commit is contained in:
parent
9aae70bdc5
commit
c9bf4416ea
@ -9,7 +9,7 @@
|
|||||||
interface nsIURI;
|
interface nsIURI;
|
||||||
interface nsIChannel;
|
interface nsIChannel;
|
||||||
|
|
||||||
[scriptable, uuid(cdb27711-492b-4973-938b-de81ac124658)]
|
[scriptable, uuid(3708aa92-e2d9-4fd1-9e46-edfa3eb5ebf5)]
|
||||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||||
{
|
{
|
||||||
///////////////// Security Checks //////////////////
|
///////////////// Security Checks //////////////////
|
||||||
@ -260,6 +260,29 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||||||
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
|
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
|
||||||
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipalAndFrame(in JSContextPtr cx,
|
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipalAndFrame(in JSContextPtr cx,
|
||||||
out JSStackFramePtr fp);
|
out JSStackFramePtr fp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If no scripted code is running "above" (or called from) fp, then
|
||||||
|
* instead of looking at cx->globalObject, we will return |principal|.
|
||||||
|
* This function only affects |cx|. If someone pushes another context onto
|
||||||
|
* the context stack, then it supersedes this call.
|
||||||
|
* NOTE: If |fp| is non-null popContextPrincipal must be called before fp
|
||||||
|
* has finished executing.
|
||||||
|
*
|
||||||
|
* @param cx The context to clamp.
|
||||||
|
* @param fp The frame pointer to clamp at. May be 'null'.
|
||||||
|
* @param principal The principal to clamp to.
|
||||||
|
*/
|
||||||
|
[noscript] void pushContextPrincipal(in JSContextPtr cx,
|
||||||
|
in JSStackFramePtr fp,
|
||||||
|
in nsIPrincipal principal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a clamp set by pushContextPrincipal from cx. This must be
|
||||||
|
* called in a stack-like fashion (e.g., given two contexts |a| and |b|,
|
||||||
|
* it is not legal to do: push(a) push(b) pop(a)).
|
||||||
|
*/
|
||||||
|
[noscript] void popContextPrincipal(in JSContextPtr cx);
|
||||||
};
|
};
|
||||||
|
|
||||||
%{C++
|
%{C++
|
||||||
|
@ -403,11 +403,12 @@ private:
|
|||||||
|
|
||||||
// Returns null if a principal cannot be found; generally callers
|
// Returns null if a principal cannot be found; generally callers
|
||||||
// should error out at that point.
|
// should error out at that point.
|
||||||
static nsIPrincipal* doGetObjectPrincipal(JSObject *obj);
|
|
||||||
#ifdef DEBUG
|
|
||||||
static nsIPrincipal*
|
static nsIPrincipal*
|
||||||
old_doGetObjectPrincipal(JSObject *obj, bool aAllowShortCircuit = true);
|
doGetObjectPrincipal(JSObject *obj
|
||||||
|
#ifdef DEBUG
|
||||||
|
, bool aAllowShortCircuit = true
|
||||||
#endif
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||||
// when this happens -- this means that there was no JS running.
|
// when this happens -- this means that there was no JS running.
|
||||||
@ -553,6 +554,17 @@ private:
|
|||||||
PrintPolicyDB();
|
PrintPolicyDB();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct ContextPrincipal {
|
||||||
|
ContextPrincipal(ContextPrincipal *next, JSContext *cx,
|
||||||
|
JSStackFrame *fp, nsIPrincipal *principal)
|
||||||
|
: mNext(next), mCx(cx), mFp(fp), mPrincipal(principal) {}
|
||||||
|
|
||||||
|
ContextPrincipal *mNext;
|
||||||
|
JSContext *mCx;
|
||||||
|
JSStackFrame *mFp;
|
||||||
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
|
};
|
||||||
|
|
||||||
// JS strings we need to clean up on shutdown
|
// JS strings we need to clean up on shutdown
|
||||||
static jsid sEnabledID;
|
static jsid sEnabledID;
|
||||||
|
|
||||||
@ -565,6 +577,7 @@ private:
|
|||||||
|
|
||||||
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
||||||
nsCOMPtr<nsIPrincipal> mSystemCertificate;
|
nsCOMPtr<nsIPrincipal> mSystemCertificate;
|
||||||
|
ContextPrincipal *mContextPrincipals;
|
||||||
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
|
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
|
||||||
bool mPrefInitialized;
|
bool mPrefInitialized;
|
||||||
bool mIsJavaScriptEnabled;
|
bool mIsJavaScriptEnabled;
|
||||||
|
@ -162,6 +162,44 @@ GetScriptContext(JSContext *cx)
|
|||||||
return GetScriptContextFromJSContext(cx);
|
return GetScriptContextFromJSContext(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Callbacks for the JS engine to use to push/pop context principals.
|
||||||
|
static JSBool
|
||||||
|
PushPrincipalCallback(JSContext *cx, JSPrincipals *principals)
|
||||||
|
{
|
||||||
|
// We should already be in the compartment of the given principal.
|
||||||
|
MOZ_ASSERT(principals ==
|
||||||
|
JS_GetCompartmentPrincipals((js::GetContextCompartment(cx))));
|
||||||
|
|
||||||
|
// Get the security manager.
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if (!ssm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the principal.
|
||||||
|
JSStackFrame *fp = NULL;
|
||||||
|
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp),
|
||||||
|
nsJSPrincipals::get(principals));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
JS_ReportOutOfMemory(cx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
PopPrincipalCallback(JSContext *cx)
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if (ssm) {
|
||||||
|
ssm->PopContextPrincipal(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void SetPendingException(JSContext *cx, const char *aMsg)
|
inline void SetPendingException(JSContext *cx, const char *aMsg)
|
||||||
{
|
{
|
||||||
JSAutoRequest ar(cx);
|
JSAutoRequest ar(cx);
|
||||||
@ -366,6 +404,34 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra
|
|||||||
return principal;
|
return principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
|
||||||
|
JSStackFrame *fp,
|
||||||
|
nsIPrincipal *principal)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(principal, "Must pass a non-null principal");
|
||||||
|
|
||||||
|
ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp,
|
||||||
|
principal);
|
||||||
|
if (!cp)
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
mContextPrincipals = cp;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsScriptSecurityManager::PopContextPrincipal(JSContext *cx)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop");
|
||||||
|
|
||||||
|
ContextPrincipal *next = mContextPrincipals->mNext;
|
||||||
|
delete mContextPrincipals;
|
||||||
|
mContextPrincipals = next;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// Policy Storage //
|
// Policy Storage //
|
||||||
////////////////////
|
////////////////////
|
||||||
@ -2237,10 +2303,24 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
|
|||||||
|
|
||||||
if (cx)
|
if (cx)
|
||||||
{
|
{
|
||||||
|
JSStackFrame *target = nsnull;
|
||||||
|
nsIPrincipal *targetPrincipal = nsnull;
|
||||||
|
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
|
||||||
|
{
|
||||||
|
if (cp->mCx == cx)
|
||||||
|
{
|
||||||
|
target = cp->mFp;
|
||||||
|
targetPrincipal = cp->mPrincipal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get principals from innermost JavaScript frame.
|
// Get principals from innermost JavaScript frame.
|
||||||
JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
|
JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
|
||||||
for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
|
for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
|
||||||
{
|
{
|
||||||
|
if (fp == target)
|
||||||
|
break;
|
||||||
nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
|
nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -2250,6 +2330,25 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If targetPrincipal is non-null, then it means that someone wants to
|
||||||
|
// clamp the principals on this context to this principal. Note that
|
||||||
|
// fp might not equal target here (fp might be null) because someone
|
||||||
|
// could have set aside the frame chain in the meantime.
|
||||||
|
if (targetPrincipal)
|
||||||
|
{
|
||||||
|
if (fp && fp == target)
|
||||||
|
{
|
||||||
|
*frameResult = fp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSStackFrame *inner = nsnull;
|
||||||
|
*frameResult = JS_FrameIterator(cx, &inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetPrincipal;
|
||||||
|
}
|
||||||
|
|
||||||
nsIScriptContextPrincipal* scp =
|
nsIScriptContextPrincipal* scp =
|
||||||
GetScriptContextPrincipalFromJSContext(cx);
|
GetScriptContextPrincipalFromJSContext(cx);
|
||||||
if (scp)
|
if (scp)
|
||||||
@ -2280,15 +2379,9 @@ nsIPrincipal*
|
|||||||
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
||||||
nsresult* rv)
|
nsresult* rv)
|
||||||
{
|
{
|
||||||
*rv = NS_OK;
|
NS_PRECONDITION(rv, "Null out param");
|
||||||
JSCompartment *compartment = js::GetContextCompartment(cx);
|
JSStackFrame *fp;
|
||||||
|
return GetPrincipalAndFrame(cx, &fp, rv);
|
||||||
// The context should always be in a compartment, either one it has entered
|
|
||||||
// or the one associated with its global.
|
|
||||||
MOZ_ASSERT(!!compartment);
|
|
||||||
|
|
||||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
|
||||||
return nsJSPrincipals::get(principals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -2304,33 +2397,19 @@ nsScriptSecurityManager::GetObjectPrincipal(JSContext *aCx, JSObject *aObj,
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
nsIPrincipal*
|
nsIPrincipal*
|
||||||
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj)
|
nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
|
||||||
{
|
|
||||||
JSCompartment *compartment = js::GetObjectCompartment(aObj);
|
|
||||||
JSPrincipals *principals = JS_GetCompartmentPrincipals(compartment);
|
|
||||||
nsIPrincipal *principal = nsJSPrincipals::get(principals);
|
|
||||||
|
|
||||||
// We leave the old code in for a little while to make sure that pulling
|
|
||||||
// object principals directly off the compartment always gives an equivalent
|
|
||||||
// result (from a security perspective).
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
nsIPrincipal *old = old_doGetObjectPrincipal(aObj);
|
, bool aAllowShortCircuit
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(CheckSameOriginPrincipal(principal, old)));
|
|
||||||
#endif
|
#endif
|
||||||
|
)
|
||||||
return principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// static
|
|
||||||
nsIPrincipal*
|
|
||||||
nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|
||||||
bool aAllowShortCircuit)
|
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
|
NS_ASSERTION(aObj, "Bad call to doGetObjectPrincipal()!");
|
||||||
nsIPrincipal* result = nsnull;
|
nsIPrincipal* result = nsnull;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
JSObject* origObj = aObj;
|
JSObject* origObj = aObj;
|
||||||
|
#endif
|
||||||
|
|
||||||
js::Class *jsClass = js::GetObjectClass(aObj);
|
js::Class *jsClass = js::GetObjectClass(aObj);
|
||||||
|
|
||||||
// A common case seen in this code is that we enter this function
|
// A common case seen in this code is that we enter this function
|
||||||
@ -2364,7 +2443,12 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|||||||
|
|
||||||
if (IS_WRAPPER_CLASS(jsClass)) {
|
if (IS_WRAPPER_CLASS(jsClass)) {
|
||||||
result = sXPConnect->GetPrincipal(aObj,
|
result = sXPConnect->GetPrincipal(aObj,
|
||||||
aAllowShortCircuit);
|
#ifdef DEBUG
|
||||||
|
aAllowShortCircuit
|
||||||
|
#else
|
||||||
|
true
|
||||||
|
#endif
|
||||||
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2380,6 +2464,7 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|||||||
priv = nsnull;
|
priv = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
if (aAllowShortCircuit) {
|
if (aAllowShortCircuit) {
|
||||||
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
|
nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
|
||||||
do_QueryInterface(priv);
|
do_QueryInterface(priv);
|
||||||
@ -2389,6 +2474,7 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|||||||
"Uh, an nsIXPConnectWrappedNative with the "
|
"Uh, an nsIXPConnectWrappedNative with the "
|
||||||
"wrong JSClass or getObjectOps hooks!");
|
"wrong JSClass or getObjectOps hooks!");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
|
nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
|
||||||
do_QueryInterface(priv);
|
do_QueryInterface(priv);
|
||||||
@ -2410,8 +2496,9 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|||||||
jsClass = js::GetObjectClass(aObj);
|
jsClass = js::GetObjectClass(aObj);
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
if (aAllowShortCircuit) {
|
if (aAllowShortCircuit) {
|
||||||
nsIPrincipal *principal = old_doGetObjectPrincipal(origObj, false);
|
nsIPrincipal *principal = doGetObjectPrincipal(origObj, false);
|
||||||
|
|
||||||
// Because of inner window reuse, we can have objects with one principal
|
// Because of inner window reuse, we can have objects with one principal
|
||||||
// living in a scope with a different (but same-origin) principal. So
|
// living in a scope with a different (but same-origin) principal. So
|
||||||
@ -2419,10 +2506,10 @@ nsScriptSecurityManager::old_doGetObjectPrincipal(JSObject *aObj,
|
|||||||
NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
|
NS_ASSERTION(NS_SUCCEEDED(CheckSameOriginPrincipal(result, principal)),
|
||||||
"Principal mismatch. Not good");
|
"Principal mismatch. Not good");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
///////////////// Capabilities API /////////////////////
|
///////////////// Capabilities API /////////////////////
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -2434,11 +2521,27 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
|
|||||||
JSContext *cx = GetCurrentJSContext();
|
JSContext *cx = GetCurrentJSContext();
|
||||||
fp = cx ? JS_FrameIterator(cx, &fp) : nsnull;
|
fp = cx ? JS_FrameIterator(cx, &fp) : nsnull;
|
||||||
|
|
||||||
|
JSStackFrame *target = nsnull;
|
||||||
|
nsIPrincipal *targetPrincipal = nsnull;
|
||||||
|
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
|
||||||
|
{
|
||||||
|
if (cp->mCx == cx)
|
||||||
|
{
|
||||||
|
target = cp->mFp;
|
||||||
|
targetPrincipal = cp->mPrincipal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
// No script code on stack. We don't have enough information and have
|
// No script code on stack. If we had a principal pushed for this
|
||||||
// to allow execution.
|
// context and fp is null, then we use that principal. Otherwise, we
|
||||||
*result = true;
|
// don't have enough information and have to allow execution.
|
||||||
|
|
||||||
|
*result = (targetPrincipal && !target)
|
||||||
|
? (targetPrincipal == mSystemPrincipal)
|
||||||
|
: true;
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2482,7 +2585,7 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
|
|||||||
// the JS engine via JS_EvaluateScript or similar APIs.
|
// the JS engine via JS_EvaluateScript or similar APIs.
|
||||||
if (JS_IsGlobalFrame(cx, fp))
|
if (JS_IsGlobalFrame(cx, fp))
|
||||||
break;
|
break;
|
||||||
} while ((fp = JS_FrameIterator(cx, &fp)) != nsnull);
|
} while (fp != target && (fp = JS_FrameIterator(cx, &fp)) != nsnull);
|
||||||
|
|
||||||
if (!previousPrincipal)
|
if (!previousPrincipal)
|
||||||
{
|
{
|
||||||
@ -2966,6 +3069,7 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
|
|||||||
: mOriginToPolicyMap(nsnull),
|
: mOriginToPolicyMap(nsnull),
|
||||||
mDefaultPolicy(nsnull),
|
mDefaultPolicy(nsnull),
|
||||||
mCapabilities(nsnull),
|
mCapabilities(nsnull),
|
||||||
|
mContextPrincipals(nsnull),
|
||||||
mPrefInitialized(false),
|
mPrefInitialized(false),
|
||||||
mIsJavaScriptEnabled(false),
|
mIsJavaScriptEnabled(false),
|
||||||
mIsWritingPrefs(false),
|
mIsWritingPrefs(false),
|
||||||
@ -3026,7 +3130,9 @@ nsresult nsScriptSecurityManager::Init()
|
|||||||
CheckObjectAccess,
|
CheckObjectAccess,
|
||||||
nsJSPrincipals::Subsume,
|
nsJSPrincipals::Subsume,
|
||||||
ObjectPrincipalFinder,
|
ObjectPrincipalFinder,
|
||||||
ContentSecurityPolicyPermitsJSAction
|
ContentSecurityPolicyPermitsJSAction,
|
||||||
|
PushPrincipalCallback,
|
||||||
|
PopPrincipalCallback
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
|
MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime));
|
||||||
@ -3045,6 +3151,7 @@ jsid nsScriptSecurityManager::sEnabledID = JSID_VOID;
|
|||||||
nsScriptSecurityManager::~nsScriptSecurityManager(void)
|
nsScriptSecurityManager::~nsScriptSecurityManager(void)
|
||||||
{
|
{
|
||||||
Preferences::RemoveObservers(this, kObservedPrefs);
|
Preferences::RemoveObservers(this, kObservedPrefs);
|
||||||
|
NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
|
||||||
delete mOriginToPolicyMap;
|
delete mOriginToPolicyMap;
|
||||||
if(mDefaultPolicy)
|
if(mDefaultPolicy)
|
||||||
mDefaultPolicy->Drop();
|
mDefaultPolicy->Drop();
|
||||||
|
@ -1198,29 +1198,27 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||||||
xpc_UnmarkGrayObject(aScopeObject);
|
xpc_UnmarkGrayObject(aScopeObject);
|
||||||
nsAutoMicroTask mt;
|
nsAutoMicroTask mt;
|
||||||
|
|
||||||
// Ignore the principal that was passed in, and just assert that it matches
|
// Safety first: get an object representing the script's principals, i.e.,
|
||||||
// the one we pull off the global.
|
// the entities who signed this script, or the fully-qualified-domain-name
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
// or "codebase" from which it was loaded.
|
||||||
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = do_QueryInterface(GetGlobalObject());
|
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||||
if (!objPrincipal)
|
nsresult rv;
|
||||||
return NS_ERROR_FAILURE;
|
if (!aPrincipal) {
|
||||||
principal = objPrincipal->GetPrincipal();
|
nsIScriptGlobalObject *global = GetGlobalObject();
|
||||||
if (!principal)
|
if (!global)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
#ifdef DEBUG
|
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
|
||||||
bool equal = false;
|
do_QueryInterface(global, &rv);
|
||||||
principal->Equals(aPrincipal, &equal);
|
if (NS_FAILED(rv))
|
||||||
MOZ_ASSERT(equal);
|
return NS_ERROR_FAILURE;
|
||||||
nsIPrincipal *scopeObjectPrincipal =
|
principal = objPrincipal->GetPrincipal();
|
||||||
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject)));
|
if (!principal)
|
||||||
equal = false;
|
return NS_ERROR_FAILURE;
|
||||||
principal->Equals(scopeObjectPrincipal, &equal);
|
}
|
||||||
MOZ_ASSERT(equal);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
nsresult rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
|
rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@ -1237,6 +1235,9 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||||||
|
|
||||||
jsval val;
|
jsval val;
|
||||||
|
|
||||||
|
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsJSContext::TerminationFuncHolder holder(this);
|
nsJSContext::TerminationFuncHolder holder(this);
|
||||||
|
|
||||||
// SecurityManager said "ok", but don't compile if aVersion is unknown.
|
// SecurityManager said "ok", but don't compile if aVersion is unknown.
|
||||||
@ -1292,6 +1293,8 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sSecurityManager->PopContextPrincipal(mContext);
|
||||||
|
|
||||||
// Pop here, after JS_ValueToString and any other possible evaluation.
|
// Pop here, after JS_ValueToString and any other possible evaluation.
|
||||||
if (NS_FAILED(stack->Pop(nsnull)))
|
if (NS_FAILED(stack->Pop(nsnull)))
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@ -1397,25 +1400,19 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||||||
|
|
||||||
xpc_UnmarkGrayObject(aScopeObject);
|
xpc_UnmarkGrayObject(aScopeObject);
|
||||||
|
|
||||||
// Ignore the principal that was passed in, and just assert that it matches
|
// Safety first: get an object representing the script's principals, i.e.,
|
||||||
// the one we pull off the global.
|
// the entities who signed this script, or the fully-qualified-domain-name
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
// or "codebase" from which it was loaded.
|
||||||
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal = do_QueryInterface(GetGlobalObject());
|
nsCOMPtr<nsIPrincipal> principal = aPrincipal;
|
||||||
if (!objPrincipal)
|
if (!aPrincipal) {
|
||||||
return NS_ERROR_FAILURE;
|
nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
|
||||||
principal = objPrincipal->GetPrincipal();
|
do_QueryInterface(GetGlobalObject());
|
||||||
if (!principal)
|
if (!objPrincipal)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
#ifdef DEBUG
|
principal = objPrincipal->GetPrincipal();
|
||||||
bool equal = false;
|
if (!principal)
|
||||||
principal->Equals(aPrincipal, &equal);
|
return NS_ERROR_FAILURE;
|
||||||
MOZ_ASSERT(equal);
|
}
|
||||||
nsIPrincipal *scopeObjectPrincipal =
|
|
||||||
nsJSPrincipals::get(JS_GetCompartmentPrincipals(js::GetObjectCompartment(aScopeObject)));
|
|
||||||
equal = false;
|
|
||||||
principal->Equals(scopeObjectPrincipal, &equal);
|
|
||||||
MOZ_ASSERT(equal);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
@ -1440,6 +1437,9 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||||||
jsval val = JSVAL_VOID;
|
jsval val = JSVAL_VOID;
|
||||||
jsval* vp = aRetValue ? &val : NULL;
|
jsval* vp = aRetValue ? &val : NULL;
|
||||||
|
|
||||||
|
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsJSContext::TerminationFuncHolder holder(this);
|
nsJSContext::TerminationFuncHolder holder(this);
|
||||||
|
|
||||||
++mExecuteDepth;
|
++mExecuteDepth;
|
||||||
@ -1491,6 +1491,8 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||||||
|
|
||||||
--mExecuteDepth;
|
--mExecuteDepth;
|
||||||
|
|
||||||
|
sSecurityManager->PopContextPrincipal(mContext);
|
||||||
|
|
||||||
// Pop here, after JS_ValueToString and any other possible evaluation.
|
// Pop here, after JS_ValueToString and any other possible evaluation.
|
||||||
if (NS_FAILED(stack->Pop(nsnull)))
|
if (NS_FAILED(stack->Pop(nsnull)))
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@ -1588,6 +1590,15 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
rv = sSecurityManager->GetObjectPrincipal(mContext,
|
||||||
|
JS_GetGlobalFromScript(aScriptObject),
|
||||||
|
getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsJSContext::TerminationFuncHolder holder(this);
|
nsJSContext::TerminationFuncHolder holder(this);
|
||||||
XPCAutoRequest ar(mContext);
|
XPCAutoRequest ar(mContext);
|
||||||
++mExecuteDepth;
|
++mExecuteDepth;
|
||||||
@ -1614,6 +1625,8 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject,
|
|||||||
|
|
||||||
--mExecuteDepth;
|
--mExecuteDepth;
|
||||||
|
|
||||||
|
sSecurityManager->PopContextPrincipal(mContext);
|
||||||
|
|
||||||
// Pop here, after JS_ValueToString and any other possible evaluation.
|
// Pop here, after JS_ValueToString and any other possible evaluation.
|
||||||
if (NS_FAILED(stack->Pop(nsnull)))
|
if (NS_FAILED(stack->Pop(nsnull)))
|
||||||
rv = NS_ERROR_FAILURE;
|
rv = NS_ERROR_FAILURE;
|
||||||
@ -1854,12 +1867,24 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
|
|||||||
jsval *argv = nsnull;
|
jsval *argv = nsnull;
|
||||||
|
|
||||||
JSObject *funobj = aHandler;
|
JSObject *funobj = aHandler;
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
rv = sSecurityManager->GetObjectPrincipal(mContext, funobj,
|
||||||
|
getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
JSStackFrame *currentfp = nsnull;
|
||||||
|
rv = sSecurityManager->PushContextPrincipal(mContext,
|
||||||
|
JS_FrameIterator(mContext, ¤tfp),
|
||||||
|
principal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
jsval funval = OBJECT_TO_JSVAL(funobj);
|
jsval funval = OBJECT_TO_JSVAL(funobj);
|
||||||
JSAutoEnterCompartment ac;
|
JSAutoEnterCompartment ac;
|
||||||
js::ForceFrame ff(mContext, funobj);
|
js::ForceFrame ff(mContext, funobj);
|
||||||
if (!ac.enter(mContext, funobj) || !ff.enter() ||
|
if (!ac.enter(mContext, funobj) || !ff.enter() ||
|
||||||
!JS_WrapObject(mContext, &target)) {
|
!JS_WrapObject(mContext, &target)) {
|
||||||
ReportPendingException();
|
ReportPendingException();
|
||||||
|
sSecurityManager->PopContextPrincipal(mContext);
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1902,6 +1927,8 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
|
|||||||
// nested calls through XPConnect.
|
// nested calls through XPConnect.
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
ReportPendingException();
|
ReportPendingException();
|
||||||
|
|
||||||
|
sSecurityManager->PopContextPrincipal(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
pusher.Pop();
|
pusher.Pop();
|
||||||
|
@ -177,15 +177,32 @@ nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
|
|||||||
JSAutoRequest ar(cx);
|
JSAutoRequest ar(cx);
|
||||||
|
|
||||||
JSAutoEnterCompartment ac;
|
JSAutoEnterCompartment ac;
|
||||||
|
nsIScriptSecurityManager *ssm = nsnull;
|
||||||
if (value->isObject()) {
|
if (value->isObject()) {
|
||||||
JSObject *obj = &value->toObject();
|
JSObject *obj = &value->toObject();
|
||||||
if (!ac.enter(cx, obj)) {
|
if (!ac.enter(cx, obj)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
|
ssm = nsContentUtils::GetSecurityManager();
|
||||||
|
nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(principal));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
JSStackFrame *fp = nsnull;
|
||||||
|
rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJSONWriter writer;
|
nsJSONWriter writer;
|
||||||
if (!JS_Stringify(cx, value, NULL, JSVAL_NULL, WriteCallback, &writer)) {
|
JSBool ok = JS_Stringify(cx, value, NULL, JSVAL_NULL,
|
||||||
|
WriteCallback, &writer);
|
||||||
|
|
||||||
|
if (ssm) {
|
||||||
|
ssm->PopContextPrincipal(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@
|
|||||||
|
|
||||||
function respond(msg)
|
function respond(msg)
|
||||||
{
|
{
|
||||||
SpecialPowers.wrap(window).parent.postMessage(msg, "*");
|
// ...so get privileges and test that this works with privileges
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
window.parent.postMessage(msg, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("message", receiveMessage, false);
|
window.addEventListener("message", receiveMessage, false);
|
||||||
|
@ -93,6 +93,10 @@ function chromePathIsSet(evt)
|
|||||||
function receiveContent(evt)
|
function receiveContent(evt)
|
||||||
{
|
{
|
||||||
is(evt.isTrusted, true, "should have sent a trusted event");
|
is(evt.isTrusted, true, "should have sent a trusted event");
|
||||||
|
is(evt.origin, "http://example.org", "content response event has wrong URI");
|
||||||
|
is(evt.source, window.frames.contentDomain,
|
||||||
|
"wrong source for same-domain message!");
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,6 +880,20 @@ FullTrustSecMan::GetCxSubjectPrincipalAndFrame(JSContext *cx,
|
|||||||
return mSystemPrincipal;
|
return mSystemPrincipal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FullTrustSecMan::PushContextPrincipal(JSContext *cx,
|
||||||
|
JSStackFrame *fp,
|
||||||
|
nsIPrincipal *principal)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FullTrustSecMan::PopContextPrincipal(JSContext *cx)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(nsrefcnt)
|
NS_IMETHODIMP_(nsrefcnt)
|
||||||
XPCShellDirProvider::AddRef()
|
XPCShellDirProvider::AddRef()
|
||||||
{
|
{
|
||||||
|
@ -1671,6 +1671,16 @@ typedef JSPrincipals *
|
|||||||
typedef JSBool
|
typedef JSBool
|
||||||
(* JSCSPEvalChecker)(JSContext *cx);
|
(* JSCSPEvalChecker)(JSContext *cx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Security callbacks for pushing and popping context principals. These are only
|
||||||
|
* temporarily necessary and will hopefully be gone again in a matter of weeks.
|
||||||
|
*/
|
||||||
|
typedef JSBool
|
||||||
|
(* JSPushContextPrincipalOp)(JSContext *cx, JSPrincipals *principals);
|
||||||
|
|
||||||
|
typedef JSBool
|
||||||
|
(* JSPopContextPrincipalOp)(JSContext *cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback used to ask the embedding for the cross compartment wrapper handler
|
* Callback used to ask the embedding for the cross compartment wrapper handler
|
||||||
* that implements the desired prolicy for this kind of object in the
|
* that implements the desired prolicy for this kind of object in the
|
||||||
@ -4339,6 +4349,8 @@ struct JSSecurityCallbacks {
|
|||||||
JSSubsumePrincipalsOp subsumePrincipals;
|
JSSubsumePrincipalsOp subsumePrincipals;
|
||||||
JSObjectPrincipalsFinder findObjectPrincipals;
|
JSObjectPrincipalsFinder findObjectPrincipals;
|
||||||
JSCSPEvalChecker contentSecurityPolicyAllows;
|
JSCSPEvalChecker contentSecurityPolicyAllows;
|
||||||
|
JSPushContextPrincipalOp pushContextPrincipal;
|
||||||
|
JSPopContextPrincipalOp popContextPrincipal;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
|
@ -472,6 +472,37 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
|
|||||||
return out.writePair(obj->isArray() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
|
return out.writePair(obj->isArray() ? SCTAG_ARRAY_OBJECT : SCTAG_OBJECT_OBJECT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AutoEnterCompartmentAndPushPrincipal : public JSAutoEnterCompartment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool enter(JSContext *cx, JSObject *target) {
|
||||||
|
// First, enter the compartment.
|
||||||
|
if (!JSAutoEnterCompartment::enter(cx, target))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We only need to push a principal if we changed compartments.
|
||||||
|
if (state != STATE_OTHER_COMPARTMENT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Push.
|
||||||
|
const JSSecurityCallbacks *cb = cx->runtime->securityCallbacks;
|
||||||
|
if (cb->pushContextPrincipal)
|
||||||
|
return cb->pushContextPrincipal(cx, target->principals(cx));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
~AutoEnterCompartmentAndPushPrincipal() {
|
||||||
|
// Pop the principal if necessary.
|
||||||
|
if (state == STATE_OTHER_COMPARTMENT) {
|
||||||
|
AutoCompartment *ac = getAutoCompartment();
|
||||||
|
const JSSecurityCallbacks *cb = ac->context->runtime->securityCallbacks;
|
||||||
|
if (cb->popContextPrincipal)
|
||||||
|
cb->popContextPrincipal(ac->context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSStructuredCloneWriter::startWrite(const Value &v)
|
JSStructuredCloneWriter::startWrite(const Value &v)
|
||||||
{
|
{
|
||||||
@ -498,7 +529,7 @@ JSStructuredCloneWriter::startWrite(const Value &v)
|
|||||||
|
|
||||||
// If we unwrapped above, we'll need to enter the underlying compartment.
|
// If we unwrapped above, we'll need to enter the underlying compartment.
|
||||||
// Let the AutoEnterCompartment do the right thing for us.
|
// Let the AutoEnterCompartment do the right thing for us.
|
||||||
JSAutoEnterCompartment ac;
|
AutoEnterCompartmentAndPushPrincipal ac;
|
||||||
if (!ac.enter(context(), obj))
|
if (!ac.enter(context(), obj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -543,7 +574,7 @@ JSStructuredCloneWriter::write(const Value &v)
|
|||||||
RootedObject obj(context(), &objs.back().toObject());
|
RootedObject obj(context(), &objs.back().toObject());
|
||||||
|
|
||||||
// The objects in |obj| can live in other compartments.
|
// The objects in |obj| can live in other compartments.
|
||||||
JSAutoEnterCompartment ac;
|
AutoEnterCompartmentAndPushPrincipal ac;
|
||||||
if (!ac.enter(context(), obj))
|
if (!ac.enter(context(), obj))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1395,6 +1395,20 @@ FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
|
|||||||
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [noscript] void popContextPrincipal (in JSContextPtr cx); */
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FullTrustSecMan::PopContextPrincipal(JSContext * cx)
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* [noscript] nsIPrincipal getSystemPrincipal (); */
|
/* [noscript] nsIPrincipal getSystemPrincipal (); */
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)
|
FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)
|
||||||
|
@ -1116,6 +1116,17 @@ nsXPCWrappedJSClass::CheckForException(XPCCallContext & ccx,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContextPrincipalGuard
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm;
|
||||||
|
XPCCallContext &ccx;
|
||||||
|
public:
|
||||||
|
ContextPrincipalGuard(XPCCallContext &ccx)
|
||||||
|
: ssm(nsnull), ccx(ccx) {}
|
||||||
|
void principalPushed(nsIScriptSecurityManager *ssm) { this->ssm = ssm; }
|
||||||
|
~ContextPrincipalGuard() { if (ssm) ssm->PopContextPrincipal(ccx); }
|
||||||
|
};
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
||||||
const XPTMethodDescriptor* info,
|
const XPTMethodDescriptor* info,
|
||||||
@ -1159,6 +1170,7 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
|||||||
|
|
||||||
JS::AutoValueVector args(cx);
|
JS::AutoValueVector args(cx);
|
||||||
AutoScriptEvaluate scriptEval(cx);
|
AutoScriptEvaluate scriptEval(cx);
|
||||||
|
ContextPrincipalGuard principalGuard(ccx);
|
||||||
|
|
||||||
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
// XXX ASSUMES that retval is last arg. The xpidl compiler ensures this.
|
||||||
uint8_t paramCount = info->num_args;
|
uint8_t paramCount = info->num_args;
|
||||||
@ -1172,6 +1184,28 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16_t methodIndex,
|
|||||||
xpcc->SetException(nsnull);
|
xpcc->SetException(nsnull);
|
||||||
ccx.GetThreadData()->SetException(nsnull);
|
ccx.GetThreadData()->SetException(nsnull);
|
||||||
|
|
||||||
|
if (XPCPerThreadData::IsMainThread(ccx)) {
|
||||||
|
// TODO Remove me in favor of security wrappers.
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if (ssm) {
|
||||||
|
nsIPrincipal *objPrincipal =
|
||||||
|
xpc::AccessCheck::getPrincipal(js::GetObjectCompartment(obj));
|
||||||
|
if (objPrincipal) {
|
||||||
|
JSStackFrame* fp = nsnull;
|
||||||
|
nsresult rv =
|
||||||
|
ssm->PushContextPrincipal(ccx, JS_FrameIterator(ccx, &fp),
|
||||||
|
objPrincipal);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
JS_ReportOutOfMemory(ccx);
|
||||||
|
retval = NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto pre_call_clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
principalGuard.principalPushed(ssm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We use js_Invoke so that the gcthings we use as args will be rooted by
|
// We use js_Invoke so that the gcthings we use as args will be rooted by
|
||||||
// the engine as we do conversions and prepare to do the function call.
|
// the engine as we do conversions and prepare to do the function call.
|
||||||
|
|
||||||
|
@ -15,7 +15,15 @@
|
|||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
CrossOriginWrapper::CrossOriginWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
|
NoWaiverWrapper::NoWaiverWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NoWaiverWrapper::~NoWaiverWrapper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CrossOriginWrapper::CrossOriginWrapper(unsigned flags) : NoWaiverWrapper(flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,4 +70,36 @@ CrossOriginWrapper::construct(JSContext *cx, JSObject *wrapper,
|
|||||||
WrapperFactory::WaiveXrayAndWrap(cx, rval);
|
WrapperFactory::WaiveXrayAndWrap(cx, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
NoWaiverWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp)
|
||||||
|
{
|
||||||
|
*bp = true; // always allowed
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if (!ssm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: By the time enter is called here, CrossCompartmentWrapper has
|
||||||
|
// already pushed the fake stack frame onto cx. Because of this, the frame
|
||||||
|
// that we're clamping is the one that we want (the one in our compartment).
|
||||||
|
JSStackFrame *fp = NULL;
|
||||||
|
nsIPrincipal *principal = GetCompartmentPrincipal(js::GetObjectCompartment(wrappedObject(wrapper)));
|
||||||
|
nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), principal);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("Not allowing call because we're out of memory");
|
||||||
|
JS_ReportOutOfMemory(cx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
NoWaiverWrapper::leave(JSContext *cx, JSObject *wrapper)
|
||||||
|
{
|
||||||
|
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||||
|
if (ssm) {
|
||||||
|
ssm->PopContextPrincipal(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,18 @@
|
|||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
class CrossOriginWrapper : public js::CrossCompartmentWrapper {
|
class NoWaiverWrapper : public js::CrossCompartmentWrapper {
|
||||||
|
public:
|
||||||
|
NoWaiverWrapper(unsigned flags);
|
||||||
|
virtual ~NoWaiverWrapper();
|
||||||
|
|
||||||
|
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp) MOZ_OVERRIDE;
|
||||||
|
virtual void leave(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
static NoWaiverWrapper singleton;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CrossOriginWrapper : public NoWaiverWrapper {
|
||||||
public:
|
public:
|
||||||
CrossOriginWrapper(unsigned flags);
|
CrossOriginWrapper(unsigned flags);
|
||||||
virtual ~CrossOriginWrapper();
|
virtual ~CrossOriginWrapper();
|
||||||
|
@ -31,6 +31,13 @@ namespace xpc {
|
|||||||
// we know to not apply an X-ray wrapper.
|
// we know to not apply an X-ray wrapper.
|
||||||
Wrapper WaiveXrayWrapperWrapper(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
|
Wrapper WaiveXrayWrapperWrapper(WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG);
|
||||||
|
|
||||||
|
// Objects that haven't been explicitly waived, but have been exposed
|
||||||
|
// to chrome don't want a CrossOriginWrapper, since that deeply-waives
|
||||||
|
// but need the transparent behavior of a CrossOriginWrapper. The
|
||||||
|
// NoWaiverWrapper is like a CrossOriginWrapper that can also hand out
|
||||||
|
// XrayWrappers as return values.
|
||||||
|
NoWaiverWrapper NoWaiverWrapper::singleton(0);
|
||||||
|
|
||||||
// When objects for which we waived the X-ray wrapper cross into
|
// When objects for which we waived the X-ray wrapper cross into
|
||||||
// chrome, we wrap them into a special cross-compartment wrapper
|
// chrome, we wrap them into a special cross-compartment wrapper
|
||||||
// that transitively extends the waiver to all properties we get
|
// that transitively extends the waiver to all properties we get
|
||||||
@ -334,7 +341,7 @@ WrapperFactory::Rewrap(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSO
|
|||||||
usingXray = true;
|
usingXray = true;
|
||||||
wrapper = &Xray::singleton;
|
wrapper = &Xray::singleton;
|
||||||
} else {
|
} else {
|
||||||
wrapper = &CrossCompartmentWrapper::singleton;
|
wrapper = &NoWaiverWrapper::singleton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user