bug 580128 - Allow calling functions cross origin. r=gal

This commit is contained in:
Blake Kaplan 2010-09-17 14:54:40 -07:00
Родитель a0d344d742
Коммит edeb6cc86e
8 изменённых файлов: 42 добавлений и 30 удалений

Просмотреть файл

@ -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;
};