work on bug 7270.

r=mstoltz.
Implement netscape.security.PrivilegeManager callbacks.


git-svn-id: svn://10.0.0.236/trunk@52128 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
norris%netscape.com 1999-10-28 22:09:03 +00:00
parent 58da4d1cc2
commit a825f1738a
3 changed files with 192 additions and 163 deletions

View File

@ -52,16 +52,20 @@ interface nsIScriptSecurityManager : nsISupports
boolean CanExecuteFunction(in voidStar jsFunction); boolean CanExecuteFunction(in voidStar jsFunction);
boolean CanEnableCapability(in nsIPrincipal principal, in string capability); boolean CanEnableCapability(in nsIPrincipal principal,
in string capability);
void SetCanEnableCapability(in nsIPrincipal principal, in string capability, void SetCanEnableCapability(in nsIPrincipal principal,
in string capability,
in boolean canEnable); in boolean canEnable);
void EnableCapability(in nsIScriptContext cx, in string capability); boolean IsCapabilityEnabled(in string capability);
void RevertCapability(in nsIScriptContext cx, in string capability); void EnableCapability(in string capability);
void DisableCapability(in nsIScriptContext cx, in string capability); void RevertCapability(in string capability);
void DisableCapability(in string capability);
}; };
%{C++ %{C++

View File

@ -25,6 +25,7 @@
#include "jsdbgapi.h" #include "jsdbgapi.h"
#include "nsIScriptContext.h" #include "nsIScriptContext.h"
#include "nsIXPCSecurityManager.h" #include "nsIXPCSecurityManager.h"
#include "nsIScriptExternalNameSet.h"
#define NS_SCRIPTSECURITYMANAGER_CID \ #define NS_SCRIPTSECURITYMANAGER_CID \
{ 0x7ee2a4c0, 0x4b93, 0x17d3, \ { 0x7ee2a4c0, 0x4b93, 0x17d3, \
@ -47,9 +48,6 @@ public:
GetScriptSecurityManager(); GetScriptSecurityManager();
private: private:
JSContext *
GetCurrentContext();
NS_IMETHOD NS_IMETHOD
GetSubjectPrincipal(JSContext *aCx, nsIPrincipal **result); GetSubjectPrincipal(JSContext *aCx, nsIPrincipal **result);
@ -74,4 +72,16 @@ private:
nsIPrincipal *mSystemPrincipal; nsIPrincipal *mSystemPrincipal;
}; };
class nsSecurityNameSet : public nsIScriptExternalNameSet
{
public:
nsSecurityNameSet();
virtual ~nsSecurityNameSet();
NS_DECL_ISUPPORTS
NS_IMETHOD InitializeClasses(nsIScriptContext* aScriptContext);
NS_IMETHOD AddNameSet(nsIScriptContext* aScriptContext);
};
#endif /*_NS_SCRIPT_SECURITY_MANAGER_H_*/ #endif /*_NS_SCRIPT_SECURITY_MANAGER_H_*/

View File

@ -31,8 +31,12 @@
#include "nsIJSContextStack.h" #include "nsIJSContextStack.h"
#include "nsDOMError.h" #include "nsDOMError.h"
#include "xpcexception.h" #include "xpcexception.h"
#include "nsDOMCID.h"
#include "nsIScriptNameSetRegistry.h"
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
static NS_DEFINE_CID(kCScriptNameSetRegistryCID,
NS_SCRIPT_NAMESET_REGISTRY_CID);
enum { enum {
SCRIPT_SECURITY_SAME_DOMAIN_ACCESS, SCRIPT_SECURITY_SAME_DOMAIN_ACCESS,
@ -179,6 +183,20 @@ nsScriptSecurityManager::CheckURI(nsIScriptContext *aContext,
return NS_OK; return NS_OK;
} }
static JSContext *
GetCurrentContext() {
// Get JSContext from stack.
nsresult rv;
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack",
&rv);
if (NS_FAILED(rv))
return nsnull;
JSContext *cx;
if (NS_FAILED(stack->Peek(&cx)))
return nsnull;
return cx;
}
NS_IMETHODIMP NS_IMETHODIMP
nsScriptSecurityManager::HasSubjectPrincipal(PRBool *result) nsScriptSecurityManager::HasSubjectPrincipal(PRBool *result)
{ {
@ -290,22 +308,26 @@ nsScriptSecurityManager::SetCanEnableCapability(nsIPrincipal *principal,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsScriptSecurityManager::EnableCapability(nsIScriptContext *cx, nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
const char *capability) PRBool *result)
{ {
return NS_ERROR_FAILURE; // not yet implemented return NS_ERROR_FAILURE; // not yet implemented
} }
NS_IMETHODIMP NS_IMETHODIMP
nsScriptSecurityManager::RevertCapability(nsIScriptContext *cx, nsScriptSecurityManager::EnableCapability(const char *capability)
const char *capability)
{ {
return NS_ERROR_FAILURE; // not yet implemented return NS_ERROR_FAILURE; // not yet implemented
} }
NS_IMETHODIMP NS_IMETHODIMP
nsScriptSecurityManager::DisableCapability(nsIScriptContext *cx, nsScriptSecurityManager::RevertCapability(const char *capability)
const char *capability) {
return NS_ERROR_FAILURE; // not yet implemented
}
NS_IMETHODIMP
nsScriptSecurityManager::DisableCapability(const char *capability)
{ {
return NS_ERROR_FAILURE; // not yet implemented return NS_ERROR_FAILURE; // not yet implemented
} }
@ -390,23 +412,17 @@ nsScriptSecurityManager *
nsScriptSecurityManager::GetScriptSecurityManager() nsScriptSecurityManager::GetScriptSecurityManager()
{ {
static nsScriptSecurityManager *ssecMan = NULL; static nsScriptSecurityManager *ssecMan = NULL;
if (!ssecMan) if (!ssecMan) {
ssecMan = new nsScriptSecurityManager(); ssecMan = new nsScriptSecurityManager();
return ssecMan;
}
JSContext *
nsScriptSecurityManager::GetCurrentContext() {
// Get JSContext from stack.
nsresult rv; nsresult rv;
NS_WITH_SERVICE(nsIJSContextStack, stack, "nsThreadJSContextStack", NS_WITH_SERVICE(nsIScriptNameSetRegistry, registry,
&rv); kCScriptNameSetRegistryCID, &rv);
if (NS_FAILED(rv)) if (NS_SUCCEEDED(rv)) {
return nsnull; nsSecurityNameSet* nameSet = new nsSecurityNameSet();
JSContext *cx; registry->AddExternalNameSet(nameSet);
if (NS_FAILED(stack->Peek(&cx))) }
return nsnull; }
return cx; return ssecMan;
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -610,18 +626,6 @@ nsScriptSecurityManager::GetSitePolicy(const char *org)
NS_IMETHODIMP NS_IMETHODIMP
nsScriptSecurityManager::CheckXPCPermissions(JSContext *aJSContext) nsScriptSecurityManager::CheckXPCPermissions(JSContext *aJSContext)
{ {
// Temporary: only enforce if security.checkxpconnect pref is enabled
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
PRBool enabled;
if (NS_SUCCEEDED(prefs->GetBoolPref("security.checkxpconnect", &enabled)) &&
!enabled)
{
return NS_OK;
}
}
nsCOMPtr<nsIPrincipal> subject; nsCOMPtr<nsIPrincipal> subject;
PRBool ok = PR_FALSE; PRBool ok = PR_FALSE;
if (NS_SUCCEEDED(GetSubjectPrincipal(aJSContext, getter_AddRefs(subject)))) if (NS_SUCCEEDED(GetSubjectPrincipal(aJSContext, getter_AddRefs(subject))))
@ -629,120 +633,175 @@ nsScriptSecurityManager::CheckXPCPermissions(JSContext *aJSContext)
if (!ok || NS_FAILED(subject->CanAccess("UniversalXPConnect", &ok))) if (!ok || NS_FAILED(subject->CanAccess("UniversalXPConnect", &ok)))
ok = PR_FALSE; ok = PR_FALSE;
if (!ok) { if (!ok) {
// Check the pref "security.checkxpconnect". If it exists and is
// set to false, don't report an error.
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
PRBool enabled;
if (NS_SUCCEEDED(prefs->GetBoolPref("security.checkxpconnect",
&enabled)) &&
!enabled)
{
return NS_OK;
}
}
static const char msg[] = "Access denied to XPConnect service."; static const char msg[] = "Access denied to XPConnect service.";
JS_SetPendingException(aJSContext, JS_SetPendingException(aJSContext,
STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, msg))); STRING_TO_JSVAL(JS_NewStringCopyZ(aJSContext, msg)));
//JS_ReportError(aJSContext, msg);
return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED; return NS_ERROR_DOM_XPCONNECT_ACCESS_DENIED;
} }
return NS_OK; return NS_OK;
} }
#if 0 ///////////////////////
static JSBool // nsSecurityNameSet //
callCapsCode(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, ///////////////////////
jsval *rval, nsCapsFn fn, char *name)
{
JSString *str;
char *cstr;
struct nsTarget *target;
nsSecurityNameSet::nsSecurityNameSet()
{
NS_INIT_REFCNT();
}
nsSecurityNameSet::~nsSecurityNameSet()
{
}
NS_IMPL_ISUPPORTS(nsSecurityNameSet, NS_GET_IID(nsIScriptExternalNameSet));
NS_IMETHODIMP
nsSecurityNameSet::InitializeClasses(nsIScriptContext* aScriptContext)
{
return NS_OK;
}
static char *
getStringArgument(JSContext *cx, JSObject *obj, uintN argc, jsval *argv)
{
if (argc == 0 || !JSVAL_IS_STRING(argv[0])) { if (argc == 0 || !JSVAL_IS_STRING(argv[0])) {
JS_ReportError(cx, "String argument expected for %s.", name); JS_ReportError(cx, "String argument expected");
return JS_FALSE; return nsnull;
} }
/* /*
* We don't want to use JS_ValueToString because we want to be able * We don't want to use JS_ValueToString because we want to be able
* to have an object to represent a target in subsequent versions. * to have an object to represent a target in subsequent versions.
* XXX but then use of an object will cause errors here....
*/ */
str = JSVAL_TO_STRING(argv[0]); JSString *str = JSVAL_TO_STRING(argv[0]);
if (!str) if (!str)
return JS_FALSE; return nsnull;
cstr = JS_GetStringBytes(str); return JS_GetStringBytes(str);
if (cstr == NULL)
return JS_FALSE;
target = nsCapsFindTarget(cstr);
if (target == NULL)
return JS_FALSE;
/* stack depth of 1: first frame is for the native function called */
if (!(*fn)(cx, target, 1)) {
/* XXX report error, later, throw exception */
return JS_FALSE;
}
return JS_TRUE;
} }
PR_STATIC_CALLBACK(JSBool) PR_STATIC_CALLBACK(JSBool)
netscape_security_isPrivilegeEnabled(JSContext *cx, JSObject *obj, uintN argc, netscape_security_isPrivilegeEnabled(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval) jsval *argv, jsval *rval)
{ {
return callCapsCode(cx, obj, argc, argv, rval, nsCapsIsPrivilegeEnabled, JSBool result = JS_FALSE;
isPrivilegeEnabledStr); char *cap = getStringArgument(cx, obj, argc, argv);
if (cap) {
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
rv = securityManager->IsCapabilityEnabled(cap, &result);
if (NS_FAILED(rv))
result = JS_FALSE;
} }
}
*rval = BOOLEAN_TO_JSVAL(result);
return JS_TRUE;
}
PR_STATIC_CALLBACK(JSBool) PR_STATIC_CALLBACK(JSBool)
netscape_security_enablePrivilege(JSContext *cx, JSObject *obj, uintN argc, netscape_security_enablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval) jsval *argv, jsval *rval)
{ {
return callCapsCode(cx, obj, argc, argv, rval, nsCapsEnablePrivilege, char *cap = getStringArgument(cx, obj, argc, argv);
enablePrivilegeStr); if (!cap)
return JS_FALSE;
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_FAILED(rv))
return JS_FALSE;
NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
if (NS_FAILED(securityManager->EnableCapability(cap)))
return JS_FALSE;
return JS_TRUE;
} }
PR_STATIC_CALLBACK(JSBool) PR_STATIC_CALLBACK(JSBool)
netscape_security_disablePrivilege(JSContext *cx, JSObject *obj, uintN argc, netscape_security_disablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval) jsval *argv, jsval *rval)
{ {
return callCapsCode(cx, obj, argc, argv, rval, nsCapsDisablePrivilege, char *cap = getStringArgument(cx, obj, argc, argv);
disablePrivilegeStr); if (!cap)
return JS_FALSE;
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_FAILED(rv))
return JS_FALSE;
NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
if (NS_FAILED(securityManager->DisableCapability(cap)))
return JS_FALSE;
return JS_TRUE;
} }
PR_STATIC_CALLBACK(JSBool) PR_STATIC_CALLBACK(JSBool)
netscape_security_revertPrivilege(JSContext *cx, JSObject *obj, uintN argc, netscape_security_revertPrivilege(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval) jsval *argv, jsval *rval)
{ {
return callCapsCode(cx, obj, argc, argv, rval, nsCapsRevertPrivilege, char *cap = getStringArgument(cx, obj, argc, argv);
revertPrivilegeStr); if (!cap)
return JS_FALSE;
nsresult rv;
NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager,
NS_SCRIPTSECURITYMANAGER_PROGID, &rv);
if (NS_FAILED(rv))
return JS_FALSE;
NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
if (NS_FAILED(securityManager->RevertCapability(cap)))
return JS_FALSE;
return JS_TRUE;
} }
static JSFunctionSpec PrivilegeManager_static_methods[] = { static JSFunctionSpec PrivilegeManager_static_methods[] = {
{ isPrivilegeEnabledStr, netscape_security_isPrivilegeEnabled, 1}, { "isPrivilegeEnabled", netscape_security_isPrivilegeEnabled, 1},
{ enablePrivilegeStr, netscape_security_enablePrivilege, 1}, { "enablePrivilege", netscape_security_enablePrivilege, 1},
{ disablePrivilegeStr, netscape_security_disablePrivilege, 1}, { "disablePrivilege", netscape_security_disablePrivilege, 1},
{ revertPrivilegeStr, netscape_security_revertPrivilege, 1}, { "revertPrivilege", netscape_security_revertPrivilege, 1},
{0} {0}
}; };
JSBool
lm_InitSecurity(MochaDecoder *decoder)
{
JSContext *cx;
JSObject *obj;
JSObject *proto;
JSClass *objectClass;
jsval v;
JSObject *securityObj;
/* /*
* "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege, * "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege,
* et. al. so that code that worked with 4.0 can still work. * et. al. so that code that worked with 4.0 can still work.
*/ */
NS_IMETHODIMP
nsSecurityNameSet::AddNameSet(nsIScriptContext* aScriptContext)
{
JSContext *cx = (JSContext *) aScriptContext->GetNativeContext();
JSObject *global = JS_GetGlobalObject(cx);
/* /*
* Find Object.prototype's class by walking up the window object's * Find Object.prototype's class by walking up the global object's
* prototype chain. * prototype chain.
*/ */
cx = decoder->js_context; JSObject *obj = global;
obj = decoder->window_object; JSObject *proto;
while (proto = JS_GetPrototype(cx, obj)) while (proto = JS_GetPrototype(cx, obj))
obj = proto; obj = proto;
objectClass = JS_GetClass(cx, obj); JSClass *objectClass = JS_GetClass(cx, obj);
if (!JS_GetProperty(cx, decoder->window_object, "netscape", &v)) jsval v;
return JS_FALSE; if (!JS_GetProperty(cx, global, "netscape", &v))
return NS_ERROR_FAILURE;
JSObject *securityObj;
if (JSVAL_IS_OBJECT(v)) { if (JSVAL_IS_OBJECT(v)) {
/* /*
* "netscape" property of window object exists; must be LiveConnect * "netscape" property of window object exists; must be LiveConnect
@ -750,71 +809,27 @@ lm_InitSecurity(MochaDecoder *decoder)
*/ */
obj = JSVAL_TO_OBJECT(v); obj = JSVAL_TO_OBJECT(v);
if (!JS_GetProperty(cx, obj, "security", &v) || !JSVAL_IS_OBJECT(v)) if (!JS_GetProperty(cx, obj, "security", &v) || !JSVAL_IS_OBJECT(v))
return JS_FALSE; return NS_ERROR_FAILURE;
securityObj = JSVAL_TO_OBJECT(v); securityObj = JSVAL_TO_OBJECT(v);
} else { } else {
/* define netscape.security object */ /* define netscape.security object */
obj = JS_DefineObject(cx, decoder->window_object, "netscape", obj = JS_DefineObject(cx, global, "netscape", objectClass, nsnull, 0);
objectClass, NULL, 0); if (obj == nsnull)
if (obj == NULL) return NS_ERROR_FAILURE;
return JS_FALSE;
securityObj = JS_DefineObject(cx, obj, "security", objectClass, securityObj = JS_DefineObject(cx, obj, "security", objectClass,
NULL, 0); nsnull, 0);
if (securityObj == NULL) if (securityObj == nsnull)
return JS_FALSE; return NS_ERROR_FAILURE;
} }
/* Define PrivilegeManager object with the necessary "static" methods. */ /* Define PrivilegeManager object with the necessary "static" methods. */
obj = JS_DefineObject(cx, securityObj, "PrivilegeManager", objectClass, obj = JS_DefineObject(cx, securityObj, "PrivilegeManager", objectClass,
NULL, 0); nsnull, 0);
if (obj == NULL) if (obj == nsnull)
return JS_FALSE; return NS_ERROR_FAILURE;
return JS_DefineFunctions(cx, obj, PrivilegeManager_static_methods); return JS_DefineFunctions(cx, obj, PrivilegeManager_static_methods)
? NS_OK
: NS_ERROR_FAILURE;
} }
JSBool lm_CheckSetParentSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSObject *newParent;
if (!JSVAL_IS_OBJECT(*vp))
return JS_TRUE;
newParent = JSVAL_TO_OBJECT(*vp);
if (newParent) {
const char *oldOrigin = lm_GetObjectOriginURL(cx, obj);
const char *newOrigin = lm_GetObjectOriginURL(cx, newParent);
if (!sameOrigins(cx, oldOrigin, newOrigin))
return JS_TRUE;
} else {
if (!JS_InstanceOf(cx, obj, &lm_layer_class, 0) &&
!JS_InstanceOf(cx, obj, &lm_window_class, 0))
{
return JS_TRUE;
}
if (lm_GetContainerPrincipals(cx, obj) == NULL) {
JSPrincipals *principals;
principals = lm_GetInnermostPrincipals(cx, obj, NULL);
if (principals == NULL)
return JS_FALSE;
lm_SetContainerPrincipals(cx, obj, principals);
}
}
return JS_TRUE;
}
752 JSBool win_check_access(JSContext *cx, JSObject *obj, jsval id,
753 JSAccessMode mode, jsval *vp)
754 {
755 if(mode == JSACC_PARENT) {
756 return lm_CheckSetParentSlot(cx, obj, id, vp);
757 }
758 return JS_TRUE;
759 }
760
761 JSClass lm_window_class = {
762 "Window", JSCLASS_HAS_PRIVATE,
763 JS_PropertyStub, JS_PropertyStub, win_getProperty, win_setProperty,
764 win_list_properties, win_resolve_name, JS_ConvertStub, win_finalize,
765 NULL, win_check_access
766 };
#endif