Bug 451729 - " Allow runtime's security callbacks to be overridden by a context". r=brendan.

This commit is contained in:
Ben Turner 2008-09-05 16:24:53 -07:00
parent 6a65adf854
commit 1e5c70827f
10 changed files with 101 additions and 69 deletions

View File

@ -4136,16 +4136,6 @@ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
}
JS_PUBLIC_API(JSCheckAccessOp)
JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb)
{
JSCheckAccessOp oldacb;
oldacb = rt->checkObjectAccess;
rt->checkObjectAccess = acb;
return oldacb;
}
static JSBool
ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
uint32 index, uint32 limit)
@ -4209,24 +4199,38 @@ JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
}
#endif
JS_PUBLIC_API(JSPrincipalsTranscoder)
JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px)
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks)
{
JSPrincipalsTranscoder oldpx;
JSSecurityCallbacks *oldcallbacks;
oldpx = rt->principalsTranscoder;
rt->principalsTranscoder = px;
return oldpx;
oldcallbacks = rt->securityCallbacks;
rt->securityCallbacks = callbacks;
return oldcallbacks;
}
JS_PUBLIC_API(JSObjectPrincipalsFinder)
JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop)
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
{
JSObjectPrincipalsFinder oldfop;
return rt->securityCallbacks;
}
oldfop = rt->findObjectPrincipals;
rt->findObjectPrincipals = fop;
return oldfop;
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
{
JSSecurityCallbacks *oldcallbacks;
oldcallbacks = cx->securityCallbacks;
cx->securityCallbacks = callbacks;
return oldcallbacks;
}
JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSContext *cx)
{
return cx->securityCallbacks
? cx->securityCallbacks
: cx->runtime->securityCallbacks;
}
JS_PUBLIC_API(JSFunction *)

View File

@ -1794,9 +1794,6 @@ extern JS_PUBLIC_API(JSBool)
JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp, uintN *attrsp);
extern JS_PUBLIC_API(JSCheckAccessOp)
JS_SetCheckObjectAccessCallback(JSRuntime *rt, JSCheckAccessOp acb);
extern JS_PUBLIC_API(JSBool)
JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
@ -1840,11 +1837,24 @@ JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
: (principals)->refcount)
#endif
extern JS_PUBLIC_API(JSPrincipalsTranscoder)
JS_SetPrincipalsTranscoder(JSRuntime *rt, JSPrincipalsTranscoder px);
extern JS_PUBLIC_API(JSObjectPrincipalsFinder)
JS_SetObjectPrincipalsFinder(JSRuntime *rt, JSObjectPrincipalsFinder fop);
struct JSSecurityCallbacks {
JSCheckAccessOp checkObjectAccess;
JSPrincipalsTranscoder principalsTranscoder;
JSObjectPrincipalsFinder findObjectPrincipals;
};
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetRuntimeSecurityCallbacks(JSRuntime *rt);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks);
extern JS_PUBLIC_API(JSSecurityCallbacks *)
JS_GetSecurityCallbacks(JSContext *cx);
/************************************************************************/

View File

@ -391,16 +391,10 @@ struct JSRuntime {
uint32 debuggerMutations;
/*
* Check property accessibility for objects of arbitrary class. Used at
* present to check f.caller accessibility for any function object f.
* Security callbacks set on the runtime are used by each context unless
* an override is set on the context.
*/
JSCheckAccessOp checkObjectAccess;
/* Security principals serialization support. */
JSPrincipalsTranscoder principalsTranscoder;
/* Optional hook to find principals for an object in this runtime. */
JSObjectPrincipalsFinder findObjectPrincipals;
JSSecurityCallbacks *securityCallbacks;
/*
* Shared scope property tree, and arena-pool for allocating its nodes.
@ -887,6 +881,9 @@ struct JSContext {
/* Debug hooks associated with the current context. */
JSDebugHooks *debugHooks;
/* Security callbacks that override any defined on the runtime. */
JSSecurityCallbacks *securityCallbacks;
};
#ifdef JS_THREADSAFE

View File

@ -1007,12 +1007,13 @@ JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(JSPrincipals *)
JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
{
if (fp->fun) {
JSRuntime *rt = cx->runtime;
JSSecurityCallbacks *callbacks;
if (rt->findObjectPrincipals) {
if (fp->fun) {
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals) {
if (FUN_OBJECT(fp->fun) != fp->callee)
return rt->findObjectPrincipals(cx, fp->callee);
return callbacks->findObjectPrincipals(cx, fp->callee);
/* FALL THROUGH */
}
}
@ -1024,12 +1025,12 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(JSPrincipals *)
JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
{
JSRuntime *rt;
JSPrincipals *principals, *callerPrincipals;
JSSecurityCallbacks *callbacks;
rt = cx->runtime;
if (rt->findObjectPrincipals) {
principals = rt->findObjectPrincipals(cx, fp->callee);
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals) {
principals = callbacks->findObjectPrincipals(cx, fp->callee);
} else {
principals = NULL;
}

View File

@ -248,6 +248,7 @@ static JSBool
InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JSString *filename, uintN lineno, JSErrorReport *report)
{
JSSecurityCallbacks *callbacks;
JSCheckAccessOp checkAccess;
JSErrorReporter older;
JSExceptionState *state;
@ -268,7 +269,10 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
* so we can suppress any checkAccess failures. Such failures should stop
* the backtrace procedure, not result in a failure of this constructor.
*/
checkAccess = cx->runtime->checkObjectAccess;
callbacks = JS_GetSecurityCallbacks(cx);
checkAccess = callbacks
? callbacks->checkObjectAccess
: NULL;
older = JS_SetErrorReporter(cx, NULL);
state = JS_SaveExceptionState(cx);

View File

@ -966,6 +966,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
jsint slot;
JSFunction *fun;
JSStackFrame *fp;
JSSecurityCallbacks *callbacks;
if (!JSVAL_IS_INT(id))
return JS_TRUE;
@ -1040,10 +1041,13 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
*vp = OBJECT_TO_JSVAL(fp->down->callee);
else
*vp = JSVAL_NULL;
if (!JSVAL_IS_PRIMITIVE(*vp) && cx->runtime->checkObjectAccess) {
id = ATOM_KEY(cx->runtime->atomState.callerAtom);
if (!cx->runtime->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
return JS_FALSE;
if (!JSVAL_IS_PRIMITIVE(*vp)) {
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->checkObjectAccess) {
id = ATOM_KEY(cx->runtime->atomState.callerAtom);
if (!callbacks->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
return JS_FALSE;
}
}
break;

View File

@ -1408,6 +1408,8 @@ JSBool
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval)
{
JSSecurityCallbacks *callbacks;
/*
* js_InternalInvoke could result in another try to get or set the same id
* again, see bug 355497.
@ -1430,11 +1432,12 @@ js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
* many embeddings have no security policy at all.
*/
JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
if (cx->runtime->checkObjectAccess &&
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks &&
callbacks->checkObjectAccess &&
VALUE_IS_FUNCTION(cx, fval) &&
FUN_INTERPRETED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
!cx->runtime->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode,
&fval)) {
!callbacks->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode, &fval)) {
return JS_FALSE;
}

View File

@ -1083,13 +1083,13 @@ JSBool
js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
JSPrincipals *principals, JSAtom *caller)
{
JSRuntime *rt;
JSSecurityCallbacks *callbacks;
JSPrincipals *scopePrincipals;
const char *callerstr;
rt = cx->runtime;
if (rt->findObjectPrincipals) {
scopePrincipals = rt->findObjectPrincipals(cx, scopeobj);
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals) {
scopePrincipals = callbacks->findObjectPrincipals(cx, scopeobj);
if (!principals || !scopePrincipals ||
!principals->subsume(principals, scopePrincipals)) {
callerstr = js_AtomToPrintableString(cx, caller);
@ -1146,8 +1146,11 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
JSPrincipals *principals, uintN *linenop)
{
uint32 flags;
#ifdef DEBUG
JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
#endif
JS_ASSERT(principals || !cx->runtime->findObjectPrincipals);
JS_ASSERT(principals || !(callbacks && callbacks->findObjectPrincipals));
flags = JS_GetScriptFilenameFlags(caller->script);
if ((flags & JSFILENAME_PROTECTED) &&
principals &&
@ -1370,7 +1373,7 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
void *closure)
{
JSObject *callable;
JSRuntime *rt;
JSSecurityCallbacks *callbacks;
JSStackFrame *caller;
JSPrincipals *subject, *watcher;
JSResolvingKey key;
@ -1381,8 +1384,8 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
callable = (JSObject *) closure;
rt = cx->runtime;
if (rt->findObjectPrincipals) {
callbacks = JS_GetSecurityCallbacks(cx);
if (callbacks && callbacks->findObjectPrincipals) {
/* Skip over any obj_watch_* frames between us and the real subject. */
caller = JS_GetScriptedCaller(cx, cx->fp);
if (caller) {
@ -1390,7 +1393,7 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
* Only call the watch handler if the watcher is allowed to watch
* the currently executing script.
*/
watcher = rt->findObjectPrincipals(cx, callable);
watcher = callbacks->findObjectPrincipals(cx, callable);
subject = JS_StackFramePrincipals(cx, caller);
if (watcher && subject && !watcher->subsume(watcher, subject)) {
@ -4465,6 +4468,7 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
JSProperty *prop;
JSClass *clasp;
JSScopeProperty *sprop;
JSSecurityCallbacks *callbacks;
JSCheckAccessOp check;
writing = (mode & JSACC_WRITE) != 0;
@ -4532,8 +4536,10 @@ js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
*/
clasp = OBJ_GET_CLASS(cx, pobj);
check = clasp->checkAccess;
if (!check)
check = cx->runtime->checkObjectAccess;
if (!check) {
callbacks = JS_GetSecurityCallbacks(cx);
check = callbacks ? callbacks->checkObjectAccess : NULL;
}
return !check || check(cx, pobj, ID_TO_VALUE(id), mode, vp);
}

View File

@ -153,6 +153,7 @@ typedef struct JSString JSString;
typedef struct JSXDRState JSXDRState;
typedef struct JSExceptionState JSExceptionState;
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */

View File

@ -428,6 +428,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
uint32 encodeable;
JSBool filenameWasSaved;
jssrcnote *notes, *sn;
JSSecurityCallbacks *callbacks;
cx = xdr->cx;
script = *scriptp;
@ -547,25 +548,26 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
goto error;
}
callbacks = JS_GetSecurityCallbacks(cx);
if (xdr->mode == JSXDR_ENCODE) {
principals = script->principals;
encodeable = (cx->runtime->principalsTranscoder != NULL);
encodeable = callbacks && callbacks->principalsTranscoder;
if (!JS_XDRUint32(xdr, &encodeable))
goto error;
if (encodeable &&
!cx->runtime->principalsTranscoder(xdr, &principals)) {
!callbacks->principalsTranscoder(xdr, &principals)) {
goto error;
}
} else {
if (!JS_XDRUint32(xdr, &encodeable))
goto error;
if (encodeable) {
if (!cx->runtime->principalsTranscoder) {
if (!(callbacks && callbacks->principalsTranscoder)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_DECODE_PRINCIPALS);
goto error;
}
if (!cx->runtime->principalsTranscoder(xdr, &principals))
if (!callbacks->principalsTranscoder(xdr, &principals))
goto error;
script->principals = principals;
}