зеркало из https://github.com/mozilla/gecko-dev.git
Bug 504877 - Check for UniversalXPConnect access further down on the stack chain. r=jst sr=bzbarsky
This commit is contained in:
Родитель
0f2fd7938b
Коммит
30d21cb3c9
|
@ -5069,13 +5069,10 @@ nsContentUtils::CanAccessNativeAnon()
|
|||
fp = nsnull;
|
||||
}
|
||||
|
||||
void *annotation = fp ? JS_GetFrameAnnotation(cx, fp) : nsnull;
|
||||
PRBool privileged;
|
||||
if (NS_SUCCEEDED(principal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&privileged)) &&
|
||||
if (NS_SUCCEEDED(sSecurityManager->IsSystemPrincipal(principal, &privileged)) &&
|
||||
privileged) {
|
||||
// UniversalXPConnect things are allowed to touch us.
|
||||
// Chrome things are allowed to touch us.
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -5089,6 +5086,12 @@ nsContentUtils::CanAccessNativeAnon()
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Before we throw, check for UniversalXPConnect.
|
||||
nsresult rv = sSecurityManager->IsCapabilityEnabled("UniversalXPConnect", &privileged);
|
||||
if (NS_SUCCEEDED(rv) && privileged) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ JSExtendedClass sXPC_XOW_JSClass = {
|
|||
// JSClass (JSExtendedClass.base) initialization
|
||||
{ "XPCCrossOriginWrapper",
|
||||
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1),
|
||||
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 2),
|
||||
XPC_XOW_AddProperty, XPC_XOW_DelProperty,
|
||||
XPC_XOW_GetProperty, XPC_XOW_SetProperty,
|
||||
XPC_XOW_Enumerate, (JSResolveOp)XPC_XOW_NewResolve,
|
||||
|
@ -130,6 +130,7 @@ JSExtendedClass sXPC_XOW_JSClass = {
|
|||
// then the map is about to be destroyed anyway, so we don't need to
|
||||
// do anything.
|
||||
static const int XPC_XOW_ScopeSlot = XPCWrapper::sNumSlots;
|
||||
static const int sUXPCObjectSlot = XPCWrapper::sNumSlots + 1;
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
@ -242,8 +243,9 @@ IsValFrame(JSObject *obj, jsval v, XPCWrappedNative *wn)
|
|||
// returns NS_ERROR_DOM_PROP_ACCESS_DENIED, returns another error code on
|
||||
// failure.
|
||||
nsresult
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj)
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj, JSBool *privilegeEnabled)
|
||||
{
|
||||
// TODO bug 508928: Refactor this with the XOW security checking code.
|
||||
// Get the subject principal from the execution stack.
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
|
@ -263,6 +265,10 @@ CanAccessWrapper(JSContext *cx, JSObject *wrappedObj)
|
|||
nsresult rv = ssm->IsSystemPrincipal(subjectPrin, &isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (privilegeEnabled) {
|
||||
*privilegeEnabled = JS_FALSE;
|
||||
}
|
||||
|
||||
// If we somehow end up being called from chrome, just allow full access.
|
||||
// This can happen from components with xpcnativewrappers=no.
|
||||
// Note that this is just an optimization to avoid getting the
|
||||
|
@ -271,18 +277,6 @@ CanAccessWrapper(JSContext *cx, JSObject *wrappedObj)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// There might be no code running, but if there is, we need to see if it is
|
||||
// UniversalXPConnect enabled code.
|
||||
if (fp) {
|
||||
void *annotation = JS_GetFrameAnnotation(cx, fp);
|
||||
rv = subjectPrin->IsCapabilityEnabled("UniversalXPConnect", annotation,
|
||||
&isSystem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isSystem) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> objectPrin;
|
||||
rv = ssm->GetObjectPrincipal(cx, wrappedObj, getter_AddRefs(objectPrin));
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -299,7 +293,17 @@ CanAccessWrapper(JSContext *cx, JSObject *wrappedObj)
|
|||
PRBool subsumes;
|
||||
rv = subjectPrin->Subsumes(objectPrin, &subsumes);
|
||||
if (NS_SUCCEEDED(rv) && !subsumes) {
|
||||
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
// We're about to fail, but make a last effort to see if
|
||||
// UniversalXPConnect was enabled anywhere else on the stack.
|
||||
rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isSystem);
|
||||
if (NS_SUCCEEDED(rv) && isSystem) {
|
||||
rv = NS_OK;
|
||||
if (privilegeEnabled) {
|
||||
*privilegeEnabled = JS_TRUE;
|
||||
}
|
||||
} else {
|
||||
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -344,7 +348,7 @@ XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, JSVAL_TO_OBJECT(funToCall));
|
||||
nsresult rv = CanAccessWrapper(cx, JSVAL_TO_OBJECT(funToCall), nsnull);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
|
@ -511,9 +515,6 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// FIXME: bug 408871, Note that we create outerObj with a null parent
|
||||
// here. We set it later so that we find our nominal prototype in the
|
||||
// same scope as the one that is calling us.
|
||||
outerObj = JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull,
|
||||
parent);
|
||||
if (!outerObj) {
|
||||
|
@ -562,7 +563,8 @@ XPC_XOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
JSBool privilegeEnabled = JS_FALSE;
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, &privilegeEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't override properties on foreign objects.
|
||||
|
@ -588,7 +590,7 @@ XPC_XOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't delete properties on foreign objects.
|
||||
|
@ -637,7 +639,9 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
if (!wrappedObj) {
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
|
||||
JSBool privilegeEnabled;
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, &privilegeEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return JS_FALSE;
|
||||
|
@ -750,7 +754,7 @@ XPC_XOW_Enumerate(JSContext *cx, JSObject *obj)
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't enumerate on foreign objects.
|
||||
|
@ -763,6 +767,72 @@ XPC_XOW_Enumerate(JSContext *cx, JSObject *obj)
|
|||
return XPCWrapper::Enumerate(cx, obj, wrappedObj);
|
||||
}
|
||||
|
||||
// Because of the drastically different ways that same- and cross-origin XOWs
|
||||
// work, we have to call JS_ClearScope when a XOW changes from being same-
|
||||
// origin to cross-origin. Normally, there are defined places in Gecko where
|
||||
// this happens and they notify us. However, UniversalXPConnect causes the
|
||||
// same transition without any notifications. We could try to detect when this
|
||||
// happens, but doing so would require calling JS_ClearScope from random
|
||||
// hooks, which is bad.
|
||||
//
|
||||
// The compromise is the UXPCObject. When resolving a property on a XOW as
|
||||
// same-origin because of UniversalXPConnect, we actually resolve it on the
|
||||
// UXPCObject (which is just a XOW for the same object). This causes the JS
|
||||
// engine to do all of its work on another object, not polluting the main
|
||||
// object. However, if the get results in calling a setter, the engine still
|
||||
// uses the regular object as 'this', ensuring that the UXPCObject doesn't
|
||||
// leak to script.
|
||||
static JSObject *
|
||||
GetUXPCObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(obj) == &sXPC_XOW_JSClass.base, "wrong object");
|
||||
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (HAS_FLAGS(v, FLAG_IS_UXPC_OBJECT)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (!JS_GetReservedSlot(cx, obj, sUXPCObjectSlot, &v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_OBJECT(v)) {
|
||||
return JSVAL_TO_OBJECT(v);
|
||||
}
|
||||
|
||||
JSObject *uxpco =
|
||||
JS_NewObjectWithGivenProto(cx, &sXPC_XOW_JSClass.base, nsnull,
|
||||
STOBJ_GET_PARENT(obj));
|
||||
if (!uxpco) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSAutoTempValueRooter tvr(cx, uxpco);
|
||||
|
||||
jsval wrappedObj, parentScope;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &wrappedObj) ||
|
||||
!JS_GetReservedSlot(cx, obj, XPC_XOW_ScopeSlot, &parentScope)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sWrappedObjSlot, wrappedObj) ||
|
||||
!JS_SetReservedSlot(cx, uxpco, XPCWrapper::sFlagsSlot,
|
||||
INT_TO_JSVAL(FLAG_IS_UXPC_OBJECT)) ||
|
||||
!JS_SetReservedSlot(cx, uxpco, XPC_XOW_ScopeSlot, parentScope)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!JS_SetReservedSlot(cx, obj, sUXPCObjectSlot, OBJECT_TO_JSVAL(uxpco))) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return uxpco;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp)
|
||||
|
@ -781,7 +851,8 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
JSBool privilegeEnabled;
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, &privilegeEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return JS_FALSE;
|
||||
|
@ -800,9 +871,10 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
if (!ssm) {
|
||||
return ThrowException(NS_ERROR_NOT_INITIALIZED, cx);
|
||||
}
|
||||
|
||||
PRUint32 action = (flags & JSRESOLVE_ASSIGNING)
|
||||
? (PRUint32)nsIXPCSecurityManager::ACCESS_SET_PROPERTY
|
||||
: (PRUint32)nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
|
||||
? XPCWrapper::sSecMgrSetProp
|
||||
: XPCWrapper::sSecMgrGetProp;
|
||||
rv = ssm->CheckPropertyAccess(cx, wrappedObj,
|
||||
STOBJ_GET_CLASS(wrappedObj)->name,
|
||||
id, action);
|
||||
|
@ -818,6 +890,10 @@ XPC_XOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
|
||||
}
|
||||
|
||||
if (privilegeEnabled && !(obj = GetUXPCObject(cx, obj))) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
|
||||
jsval oldSlotVal;
|
||||
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sFlagsSlot, &oldSlotVal) ||
|
||||
|
@ -869,7 +945,7 @@ XPC_XOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
|
|||
}
|
||||
|
||||
// Note: JSTYPE_VOID and JSTYPE_STRING are equivalent.
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv) &&
|
||||
(rv != NS_ERROR_DOM_PROP_ACCESS_DENIED ||
|
||||
(type != JSTYPE_STRING && type != JSTYPE_VOID))) {
|
||||
|
@ -943,7 +1019,7 @@ XPC_XOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't call.
|
||||
|
@ -980,7 +1056,7 @@ XPC_XOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't construct.
|
||||
|
@ -1007,7 +1083,7 @@ XPC_XOW_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, iface);
|
||||
nsresult rv = CanAccessWrapper(cx, iface, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Don't do this test across origins.
|
||||
|
@ -1093,7 +1169,7 @@ XPC_XOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
// Can't create iterators for foreign objects.
|
||||
|
@ -1160,7 +1236,7 @@ XPC_XOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj);
|
||||
nsresult rv = CanAccessWrapper(cx, wrappedObj, nsnull);
|
||||
if (rv == NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
|
|
|
@ -214,17 +214,14 @@ EnsureLegalActivity(JSContext *cx, JSObject *obj,
|
|||
JSStackFrame *fp;
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp);
|
||||
if (!subjectPrincipal || !fp) {
|
||||
// We must allow the access if there is no code running.
|
||||
// We must allow access if there is no code running.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// This might be chrome code or content code with UniversalXPConnect.
|
||||
void *annotation = JS_GetFrameAnnotation(cx, fp);
|
||||
PRBool isPrivileged = PR_FALSE;
|
||||
nsresult rv = subjectPrincipal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&isPrivileged);
|
||||
if (NS_SUCCEEDED(rv) && isPrivileged) {
|
||||
PRBool isSystem;
|
||||
if (NS_SUCCEEDED(ssm->IsSystemPrincipal(subjectPrincipal, &isSystem)) &&
|
||||
isSystem) {
|
||||
// Chrome code is running.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -236,6 +233,13 @@ EnsureLegalActivity(JSContext *cx, JSObject *obj,
|
|||
PRBool subsumes;
|
||||
if (NS_FAILED(subjectPrincipal->Subsumes(objectPrincipal, &subsumes)) ||
|
||||
!subsumes) {
|
||||
// This might be chrome code or content code with UniversalXPConnect.
|
||||
PRBool isPrivileged = PR_FALSE;
|
||||
nsresult rv =
|
||||
ssm->IsCapabilityEnabled("UniversalXPConnect", &isPrivileged);
|
||||
if (NS_SUCCEEDED(rv) && isPrivileged) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject* flatObj;
|
||||
if (!JSVAL_IS_VOID(id) &&
|
||||
|
@ -291,32 +295,20 @@ XPCNativeWrapper::GetWrappedNative(JSContext *cx, JSObject *obj,
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSStackFrame *fp;
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipalAndFrame(cx, &fp);
|
||||
nsIPrincipal *subjectPrincipal = ssm->GetCxSubjectPrincipal(cx);
|
||||
if (!subjectPrincipal) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
void *annotation = JS_GetFrameAnnotation(cx, fp);
|
||||
|
||||
PRBool isPrivileged;
|
||||
nsresult rv =
|
||||
subjectPrincipal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&isPrivileged);
|
||||
if (NS_SUCCEEDED(rv) && isPrivileged) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope *scope = wn->GetScope();
|
||||
nsIPrincipal *objectPrincipal = scope->GetPrincipal();
|
||||
|
||||
PRBool subsumes;
|
||||
nsresult rv = subjectPrincipal->Subsumes(objectPrincipal, &subsumes);
|
||||
if (NS_FAILED(rv) || !subsumes) {
|
||||
return JS_FALSE;
|
||||
PRBool isPrivileged;
|
||||
rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &isPrivileged);
|
||||
return NS_SUCCEEDED(rv) && isPrivileged;
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
|
|
|
@ -136,6 +136,7 @@ FindPrincipals(JSContext *cx, JSObject *obj, nsIPrincipal **objectPrincipal,
|
|||
static PRBool
|
||||
CanCallerAccess(JSContext *cx, JSObject *unsafeObj)
|
||||
{
|
||||
// TODO bug 508928: Refactor this with the XOW security checking code.
|
||||
nsCOMPtr<nsIPrincipal> subjPrincipal, objPrincipal;
|
||||
nsCOMPtr<nsIScriptSecurityManager> ssm;
|
||||
nsresult rv = FindPrincipals(cx, unsafeObj, getter_AddRefs(objPrincipal),
|
||||
|
|
|
@ -164,6 +164,7 @@ GetWrappedObject(JSContext *cx, JSObject *wrapper)
|
|||
JSBool
|
||||
AllowedToAct(JSContext *cx, jsval idval)
|
||||
{
|
||||
// TODO bug 508928: Refactor this with the XOW security checking code.
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
return JS_TRUE;
|
||||
|
@ -189,13 +190,10 @@ AllowedToAct(JSContext *cx, jsval idval)
|
|||
fp = nsnull;
|
||||
}
|
||||
|
||||
void *annotation = fp ? JS_GetFrameAnnotation(cx, fp) : nsnull;
|
||||
PRBool privileged;
|
||||
if (NS_SUCCEEDED(principal->IsCapabilityEnabled("UniversalXPConnect",
|
||||
annotation,
|
||||
&privileged)) &&
|
||||
if (NS_SUCCEEDED(ssm->IsSystemPrincipal(principal, &privileged)) &&
|
||||
privileged) {
|
||||
// UniversalXPConnect things are allowed to touch us.
|
||||
// Chrome things are allowed to touch us.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -209,6 +207,12 @@ AllowedToAct(JSContext *cx, jsval idval)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Before we throw, check for UniversalXPConnect.
|
||||
nsresult rv = ssm->IsCapabilityEnabled("UniversalXPConnect", &privileged);
|
||||
if (NS_SUCCEEDED(rv) && privileged) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
if (JSVAL_IS_VOID(idval)) {
|
||||
ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
|
||||
} else {
|
||||
|
|
|
@ -82,7 +82,7 @@ XPCWrapper::Unwrap(JSContext *cx, JSObject *wrapper)
|
|||
if (clasp == &sXPC_SJOW_JSClass.base) {
|
||||
JSObject *wrappedObj = STOBJ_GET_PARENT(wrapper);
|
||||
|
||||
if (NS_FAILED(CanAccessWrapper(cx, wrappedObj))) {
|
||||
if (NS_FAILED(CanAccessWrapper(cx, wrappedObj, nsnull))) {
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
return nsnull;
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
// FLAG_RESOLVING is used to tag an XPCNativeWrapper when while it's calling
|
||||
// the newResolve hook on the XPCWrappedNative's scriptable info.
|
||||
#define FLAG_RESOLVING 0x4
|
||||
// FLAG_IS_UXPC_OBJECT is used to tag a XPCCrossOriginWrapper that we created
|
||||
// to deal with a cross origin XOW that has UniversalXPConnect privileges.
|
||||
#define FLAG_IS_UXPC_OBJECT (1 << 29)
|
||||
|
||||
#define HAS_FLAGS(_val, _flags) \
|
||||
((PRUint32(JSVAL_TO_INT(_val)) & (_flags)) != 0)
|
||||
|
@ -79,7 +82,7 @@ XPC_XOW_WrapperMoved(JSContext *cx, XPCWrappedNative *innerObj,
|
|||
XPCWrappedNativeScope *newScope);
|
||||
|
||||
nsresult
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj);
|
||||
CanAccessWrapper(JSContext *cx, JSObject *wrappedObj, JSBool *privilegeEnabled);
|
||||
|
||||
// Used by UnwrapSOW below.
|
||||
JSBool
|
||||
|
@ -282,7 +285,7 @@ public:
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper);
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
|
@ -297,7 +300,7 @@ public:
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper);
|
||||
nsresult rv = CanAccessWrapper(cx, wrapper, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
JS_ClearPendingException(cx);
|
||||
wrapper = nsnull;
|
||||
|
|
|
@ -47,6 +47,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
_TEST_FILES = bug500931_helper.html \
|
||||
inner.html \
|
||||
bug92773_helper.html \
|
||||
bug504877_helper.html \
|
||||
test_bug92773.html \
|
||||
test_bug361111.xul \
|
||||
test_bug384632.html \
|
||||
|
@ -64,6 +65,7 @@ _TEST_FILES = bug500931_helper.html \
|
|||
test_bug500691.html \
|
||||
test_bug502959.html \
|
||||
test_bug503926.html \
|
||||
test_bug504877.html \
|
||||
test_bug505915.html \
|
||||
test_bug517163.html \
|
||||
test_cows.html \
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<script>
|
||||
foopy = 42;
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=504877
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 504877</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=504877">Mozilla Bug 504877</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 504877 **/
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var p = 0;
|
||||
function go() {
|
||||
var ifr = $('ifr').contentWindow;
|
||||
function test1() {
|
||||
try {
|
||||
ifr.foopy;
|
||||
ok(false, "should have thrown a cross-origin access exception");
|
||||
} catch (e) {
|
||||
ok(/Permission denied/.test(e), "Threw a permission denied exception");
|
||||
}
|
||||
|
||||
var loc = ifr.location;
|
||||
(function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
try {
|
||||
ifr.blat = 42;
|
||||
} catch (e) {
|
||||
ok(/UniversalXPConnect/.test(e), "not able to set properties using UniversalXPConnect");
|
||||
}
|
||||
|
||||
is(ifr.foopy, 42, "able to use UniversalXPConnect to get random properties");
|
||||
|
||||
loc.replace; // resolves the property onto the wrapper.
|
||||
})();
|
||||
|
||||
loc.replace("http://localhost:8888/");
|
||||
ok(true, "able to set location on the cross origin(!) frame");
|
||||
}
|
||||
|
||||
function test2() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
switch (++p) {
|
||||
case 1: return test1();
|
||||
case 2: return test2();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<iframe src="http://example.org/tests/js/src/xpconnect/tests/mochitest/bug504877_helper.html" id="ifr" onload="go()"></iframe>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче