зеркало из https://github.com/mozilla/pjs.git
bug 580128 - Allow calling functions cross origin. r=gal
This commit is contained in:
Родитель
a0d344d742
Коммит
edeb6cc86e
|
@ -87,17 +87,17 @@ JSWrapper::~JSWrapper()
|
|||
{
|
||||
}
|
||||
|
||||
#define CHECKED(op, set) \
|
||||
#define CHECKED(op, act) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!enter(cx, wrapper, id, set)) \
|
||||
if (!enter(cx, wrapper, id, act)) \
|
||||
return false; \
|
||||
bool ok = (op); \
|
||||
leave(cx, wrapper); \
|
||||
return ok; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define SET(action) CHECKED(action, true)
|
||||
#define GET(action) CHECKED(action, false)
|
||||
#define SET(action) CHECKED(action, SET)
|
||||
#define GET(action) CHECKED(action, GET)
|
||||
|
||||
bool
|
||||
JSWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
|
@ -223,7 +223,7 @@ bool
|
|||
JSWrapper::call(JSContext *cx, JSObject *wrapper, uintN argc, Value *vp)
|
||||
{
|
||||
const jsid id = JSID_VOID;
|
||||
GET(JSProxyHandler::call(cx, wrapper, argc, vp));
|
||||
CHECKED(JSProxyHandler::call(cx, wrapper, argc, vp), CALL);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -237,7 +237,7 @@ JSString *
|
|||
JSWrapper::obj_toString(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
JSString *str;
|
||||
if (!enter(cx, wrapper, JSID_VOID, false))
|
||||
if (!enter(cx, wrapper, JSID_VOID, GET))
|
||||
return NULL;
|
||||
str = JSProxyHandler::obj_toString(cx, wrapper);
|
||||
leave(cx, wrapper);
|
||||
|
@ -248,7 +248,7 @@ JSString *
|
|||
JSWrapper::fun_toString(JSContext *cx, JSObject *wrapper, uintN indent)
|
||||
{
|
||||
JSString *str;
|
||||
if (!enter(cx, wrapper, JSID_VOID, false))
|
||||
if (!enter(cx, wrapper, JSID_VOID, GET))
|
||||
return NULL;
|
||||
str = JSProxyHandler::fun_toString(cx, wrapper, indent);
|
||||
leave(cx, wrapper);
|
||||
|
@ -262,7 +262,7 @@ JSWrapper::trace(JSTracer *trc, JSObject *wrapper)
|
|||
}
|
||||
|
||||
bool
|
||||
JSWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, bool set)
|
||||
JSWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,8 @@ class JSWrapper : public js::JSProxyHandler {
|
|||
virtual JS_FRIEND_API(void) trace(JSTracer *trc, JSObject *wrapper);
|
||||
|
||||
/* Policy enforcement traps. */
|
||||
virtual JS_FRIEND_API(bool) enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
|
||||
enum Action { GET, SET, CALL };
|
||||
virtual JS_FRIEND_API(bool) enter(JSContext *cx, JSObject *wrapper, jsid id, Action act);
|
||||
virtual JS_FRIEND_API(void) leave(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static JS_FRIEND_API(JSWrapper) singleton;
|
||||
|
|
|
@ -163,11 +163,15 @@ IsWindow(const char *name)
|
|||
}
|
||||
|
||||
bool
|
||||
AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid id, bool set)
|
||||
AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
JSWrapper::Action act)
|
||||
{
|
||||
if (!XPCWrapper::GetSecurityManager())
|
||||
return true;
|
||||
|
||||
if (act == JSWrapper::CALL)
|
||||
return true;
|
||||
|
||||
JSObject *obj = JSWrapper::wrappedObject(wrapper);
|
||||
|
||||
const char *name;
|
||||
|
@ -182,14 +186,14 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext *cx, JSObject *wrapper, jsid
|
|||
if (JSID_IS_ATOM(id)) {
|
||||
JSString *str = ATOM_TO_STRING(JSID_TO_ATOM(id));
|
||||
const char *prop = JS_GetStringBytes(str);
|
||||
if (IsPermitted(name, prop, set))
|
||||
if (IsPermitted(name, prop, act == JSWrapper::SET))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsWindow(name) && IsFrameId(cx, obj, id))
|
||||
return true;
|
||||
|
||||
return set
|
||||
return (act == JSWrapper::SET)
|
||||
? nsContentUtils::IsCallerTrustedForWrite()
|
||||
: nsContentUtils::IsCallerTrustedForRead();
|
||||
}
|
||||
|
@ -270,7 +274,8 @@ AccessCheck::deny(JSContext *cx, jsid id)
|
|||
typedef enum { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 } Access;
|
||||
|
||||
bool
|
||||
ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm)
|
||||
ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act,
|
||||
Permission &perm)
|
||||
{
|
||||
JSObject *holder = JSWrapper::wrappedObject(wrapper);
|
||||
|
||||
|
@ -351,8 +356,8 @@ ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, bool set
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((set && !(access & WRITE)) ||
|
||||
(!set && !(access & READ))) {
|
||||
if ((act == JSWrapper::SET && !(access & WRITE)) ||
|
||||
(act != JSWrapper::SET && !(access & READ))) {
|
||||
return true; // Deny
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,8 @@ class AccessCheck {
|
|||
public:
|
||||
static bool isSameOrigin(JSCompartment *a, JSCompartment *b);
|
||||
static bool isChrome(JSCompartment *compartment);
|
||||
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id, bool set);
|
||||
static bool isCrossOriginAccessPermitted(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWrapper::Action act);
|
||||
static bool isSystemOnlyAccessPermitted(JSContext *cx);
|
||||
|
||||
static bool needsSystemOnlyWrapper(JSObject *obj);
|
||||
|
@ -64,7 +65,8 @@ struct Policy {
|
|||
|
||||
// This policy permits access to all properties.
|
||||
struct Permissive : public Policy {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act,
|
||||
Permission &perm) {
|
||||
perm = PermitObjectAccess;
|
||||
return true;
|
||||
}
|
||||
|
@ -73,7 +75,8 @@ struct Permissive : public Policy {
|
|||
// This policy only permits access to the object if the subject can touch
|
||||
// system objects.
|
||||
struct OnlyIfSubjectIsSystem : public Policy {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act,
|
||||
Permission &perm) {
|
||||
perm = DenyAccess;
|
||||
if (AccessCheck::isSystemOnlyAccessPermitted(cx))
|
||||
perm = PermitObjectAccess;
|
||||
|
@ -84,9 +87,10 @@ struct OnlyIfSubjectIsSystem : public Policy {
|
|||
// This policy only permits access to properties that are safe to be used
|
||||
// across origins.
|
||||
struct CrossOriginAccessiblePropertiesOnly : public Policy {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm) {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act,
|
||||
Permission &perm) {
|
||||
perm = DenyAccess;
|
||||
if (AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, set))
|
||||
if (AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act))
|
||||
perm = PermitPropertyAccess;
|
||||
return true;
|
||||
}
|
||||
|
@ -95,7 +99,8 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy {
|
|||
// This policy only permits access to properties if they appear in the
|
||||
// objects exposed properties list.
|
||||
struct ExposedPropertiesOnly : public Policy {
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm);
|
||||
static bool check(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act,
|
||||
Permission &perm);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ GetCompartmentPrincipal(JSCompartment *compartment)
|
|||
}
|
||||
|
||||
bool
|
||||
CrossOriginWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, bool set)
|
||||
CrossOriginWrapper::enter(JSContext *cx, JSObject *wrapper, jsid id, Action act)
|
||||
{
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (!ssm) {
|
||||
|
|
|
@ -50,7 +50,7 @@ class CrossOriginWrapper : public JSCrossCompartmentWrapper {
|
|||
CrossOriginWrapper(uintN flags);
|
||||
virtual ~CrossOriginWrapper();
|
||||
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act);
|
||||
virtual void leave(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static CrossOriginWrapper singleton;
|
||||
|
|
|
@ -72,7 +72,7 @@ Filter(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
|||
for (size_t n = 0; n < props.length(); ++n) {
|
||||
jsid id = props[n];
|
||||
Permission perm;
|
||||
if (perm != PermitObjectAccess && !Policy::check(cx, wrapper, id, false, perm))
|
||||
if (perm != PermitObjectAccess && !Policy::check(cx, wrapper, id, JSWrapper::GET, perm))
|
||||
return false; // Error
|
||||
if (perm != DenyAccess) {
|
||||
props[w++] = id;
|
||||
|
@ -84,9 +84,9 @@ Filter(JSContext *cx, JSObject *wrapper, AutoIdVector &props)
|
|||
|
||||
template <typename Policy>
|
||||
static bool
|
||||
CheckAndReport(JSContext *cx, JSObject *wrapper, jsid id, bool set, Permission &perm)
|
||||
CheckAndReport(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act, Permission &perm)
|
||||
{
|
||||
if (!Policy::check(cx, wrapper, id, set, perm)) {
|
||||
if (!Policy::check(cx, wrapper, id, act, perm)) {
|
||||
return false;
|
||||
}
|
||||
if (perm == DenyAccess) {
|
||||
|
@ -141,11 +141,12 @@ FilteringWrapper<Base, Policy>::iterate(JSContext *cx, JSObject *wrapper, uintN
|
|||
|
||||
template <typename Base, typename Policy>
|
||||
bool
|
||||
FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id, bool set)
|
||||
FilteringWrapper<Base, Policy>::enter(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
JSWrapper::Action act)
|
||||
{
|
||||
Permission perm;
|
||||
return CheckAndReport<Policy>(cx, wrapper, id, set, perm) &&
|
||||
Base::enter(cx, wrapper, id, set);
|
||||
return CheckAndReport<Policy>(cx, wrapper, id, act, perm) &&
|
||||
Base::enter(cx, wrapper, id, act);
|
||||
}
|
||||
|
||||
#define SOW FilteringWrapper<JSCrossCompartmentWrapper, OnlyIfSubjectIsSystem>
|
||||
|
|
|
@ -53,7 +53,7 @@ class FilteringWrapper : public Base {
|
|||
virtual bool enumerateOwn(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, uintN flags, js::Value *vp);
|
||||
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, bool set);
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, JSWrapper::Action act);
|
||||
|
||||
static FilteringWrapper singleton;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче