зеркало из https://github.com/mozilla/pjs.git
Bug 109113, second half of fix. r=jst, sr=brendan. Adding new CheckObjectAccess
callback to enforce the same-origin policy on function.caller.
This commit is contained in:
Родитель
e191aa0dd4
Коммит
144ebd46ff
|
@ -80,6 +80,7 @@
|
|||
#include "nsIConsoleService.h"
|
||||
#include "nsISecurityCheckedComponent.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
|
||||
static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
@ -150,6 +151,41 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptSecurityManager,
|
|||
///////////////////////////////////////////////////
|
||||
|
||||
///////////////// Security Checks /////////////////
|
||||
static JSBool JS_DLL_CALLBACK
|
||||
CheckJSFunctionCallerAccess(JSContext *cx, JSObject *obj, jsval id,
|
||||
JSAccessMode mode, jsval *vp)
|
||||
{
|
||||
// Currently, this function will be called only when function.caller
|
||||
// is accessed. If that changes, we will need to change this function.
|
||||
NS_ASSERTION(nsCRT::strcmp(JS_GetStringChars(JSVAL_TO_STRING(id)),
|
||||
NS_LITERAL_STRING("caller").get()) == 0,
|
||||
"CheckJSFunctionCallerAccess called for a property other than \'caller\'");
|
||||
|
||||
// Get the security manager
|
||||
//XXX: Any way to avoid this service lookup?
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptSecurityManager> ssm =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("Failed to get security manager service");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Get the caller function object
|
||||
NS_ASSERTION(JSVAL_IS_OBJECT(*vp), "*vp is not an object");
|
||||
JSObject* target = JSVAL_TO_OBJECT(*vp);
|
||||
|
||||
// Do the same-origin check - this sets a JS exception if the check fails
|
||||
rv = ssm->CheckPropertyAccess(cx, target, "Function", "caller",
|
||||
nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return JS_FALSE; // Security check failed
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::CheckPropertyAccess(JSContext* aJSContext,
|
||||
JSObject* aJSObject,
|
||||
|
@ -1071,9 +1107,29 @@ nsScriptSecurityManager::CanExecuteScripts(JSContext* cx,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-- Always allow chrome pages to run scripts
|
||||
// This is for about: URLs, which are chrome but don't
|
||||
// have the system principal
|
||||
nsresult rv;
|
||||
if (!mIsJavaScriptEnabled)
|
||||
{
|
||||
nsCOMPtr<nsICodebasePrincipal> codebase(do_QueryInterface(principal));
|
||||
if (codebase)
|
||||
{
|
||||
nsXPIDLCString origin;
|
||||
rv = codebase->GetOrigin(getter_Copies(origin));
|
||||
static const char chromePrefix[] = "chrome:";
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
(PL_strncmp(origin, chromePrefix, sizeof(chromePrefix)-1) == 0))
|
||||
{
|
||||
*result = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-- See if the current window allows JS execution
|
||||
nsCOMPtr<nsIDocShell> docshell;
|
||||
nsresult rv;
|
||||
rv = GetRootDocShell(cx, getter_AddRefs(docshell));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
|
@ -2059,6 +2115,25 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
|
|||
NS_INIT_REFCNT();
|
||||
InitPrefs();
|
||||
mThreadJSContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
||||
//-- Register security check callback in the JS engine
|
||||
// Currently this is used to control access to function.caller
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIJSRuntimeService> runtimeService =
|
||||
do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get runtime service");
|
||||
|
||||
JSRuntime *rt;
|
||||
rv = runtimeService->GetRuntime(&rt);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get current JS runtime");
|
||||
|
||||
#ifdef DEBUG
|
||||
JSCheckAccessOp oldCallback =
|
||||
JS_SetCheckObjectAccessCallback(rt, CheckJSFunctionCallerAccess);
|
||||
|
||||
// For now, assert that no callback was set previously
|
||||
NS_ASSERTION(!oldCallback, "Someone already set a JS CheckObjectAccess callback");
|
||||
#endif
|
||||
}
|
||||
|
||||
nsScriptSecurityManager::~nsScriptSecurityManager(void)
|
||||
|
|
Загрузка…
Ссылка в новой задаче