Bug 417617 - [p=Olli.Pettay@gmail.com (Smaug) r+sr=jst a=blocking1.9+]

This commit is contained in:
reed@reedloden.com 2008-02-26 18:03:27 -08:00
parent c07735665d
commit 35efe4819f
3 changed files with 103 additions and 38 deletions

View File

@ -96,6 +96,7 @@ class nsVoidArray;
struct JSRuntime;
class nsICaseConversion;
class nsIWidget;
class nsPIDOMWindow;
#ifdef MOZ_XTF
class nsIXTFService;
#endif
@ -371,6 +372,10 @@ public:
// Check if the (JS) caller can access aNode.
static PRBool CanCallerAccess(nsIDOMNode *aNode);
// Check if the (JS) caller can access aWindow.
// aWindow can be either outer or inner window.
static PRBool CanCallerAccess(nsPIDOMWindow* aWindow);
/**
* Get the docshell through the JS context that's currently on the stack.
* If there's no JS context currently on the stack aDocShell will be null.
@ -1188,6 +1193,9 @@ private:
PR_STATIC_CALLBACK(void) DropScriptObject(PRUint32 aLangID, void *aObject,
void *aClosure);
static PRBool CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
nsIPrincipal* aPrincipal);
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
static nsIXPConnect *sXPConnect;

View File

@ -148,6 +148,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIPrivateDOMEvent.h"
#include "nsXULPopupManager.h"
#include "nsIPermissionManager.h"
#include "nsIScriptObjectPrincipal.h"
#ifdef IBMBIDI
#include "nsIBidiKeyboard.h"
@ -890,6 +891,31 @@ nsContentUtils::CheckSameOrigin(nsIDOMNode *aTrustedNode,
return NS_OK;
}
// static
PRBool
nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
nsIPrincipal* aPrincipal)
{
PRBool subsumes;
nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
if (subsumes) {
return PR_TRUE;
}
// The subject doesn't subsume aPrincipal. Allow access only if the subject
// has either "UniversalXPConnect" (if aPrincipal is system principal) or
// "UniversalBrowserRead" (in all other cases).
PRBool isSystem;
rv = sSecurityManager->IsSystemPrincipal(aPrincipal, &isSystem);
isSystem = NS_FAILED(rv) || isSystem;
const char* capability =
NS_FAILED(rv) || isSystem ? "UniversalXPConnect" : "UniversalBrowserRead";
return IsCallerTrustedForCapability(capability);
}
// static
PRBool
nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
@ -909,26 +935,31 @@ nsContentUtils::CanCallerAccess(nsIDOMNode *aNode)
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node, PR_FALSE);
nsIPrincipal* nodePrincipal = node->NodePrincipal();
return CanCallerAccess(subjectPrincipal, node->NodePrincipal());
}
PRBool subsumes;
nsresult rv = subjectPrincipal->Subsumes(nodePrincipal, &subsumes);
NS_ENSURE_SUCCESS(rv, PR_FALSE);
// static
PRBool
nsContentUtils::CanCallerAccess(nsPIDOMWindow* aWindow)
{
// XXXbz why not check the IsCapabilityEnabled thing up front, and not bother
// with the system principal games? But really, there should be a simpler
// API here, dammit.
nsCOMPtr<nsIPrincipal> subjectPrincipal;
sSecurityManager->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
if (!subjectPrincipal) {
// we're running as system, grant access to the node.
if (subsumes) {
return PR_TRUE;
}
// The subject doesn't subsume the node. Allow access only if the subject
// has either "UniversalXPConnect" (if the node has the system principal) or
// "UniversalBrowserRead" (in all other cases).
PRBool isSystem;
rv = sSecurityManager->IsSystemPrincipal(nodePrincipal, &isSystem);
isSystem = NS_FAILED(rv) || isSystem;
const char* capability =
NS_FAILED(rv) || isSystem ? "UniversalXPConnect" : "UniversalBrowserRead";
nsCOMPtr<nsIScriptObjectPrincipal> scriptObject =
do_QueryInterface(aWindow->IsOuterWindow() ?
aWindow->GetCurrentInnerWindow() : aWindow);
NS_ENSURE_TRUE(scriptObject, PR_FALSE);
return IsCallerTrustedForCapability(capability);
return CanCallerAccess(subjectPrincipal, scriptObject->GetPrincipal());
}
//static

View File

@ -4782,8 +4782,9 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native));
if (initializer) {
nsCOMPtr<nsISupports> owner = do_QueryReferent(aWeakOwner);
NS_ENSURE_STATE(owner);
nsCOMPtr<nsPIDOMWindow> owner = do_QueryReferent(aWeakOwner);
NS_ENSURE_STATE(owner && owner->GetOuterWindow() &&
owner->GetOuterWindow()->GetCurrentInnerWindow() == owner);
rv = initializer->Initialize(owner, cx, obj, argc, argv);
if (NS_FAILED(rv)) {
return NS_ERROR_NOT_INITIALIZED;
@ -4890,16 +4891,23 @@ DefineInterfaceConstants(JSContext *cx, JSObject *obj, const nsIID *aIID)
class nsDOMConstructor : public nsIDOMDOMConstructor
{
public:
protected:
nsDOMConstructor(const PRUnichar *aName,
const nsGlobalNameStruct *aNameStruct,
nsISupports* aOwner)
nsPIDOMWindow* aOwner)
: mClassName(aName),
mConstructable(IsConstructable(aNameStruct)),
mWeakOwner(do_GetWeakReference(aOwner))
{
}
public:
static nsresult Create(const PRUnichar* aName,
const nsGlobalNameStruct* aNameStruct,
nsPIDOMWindow* aOwner,
nsDOMConstructor** aResult);
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMDOMCONSTRUCTOR
@ -4980,6 +4988,27 @@ private:
nsWeakPtr mWeakOwner;
};
//static
nsresult
nsDOMConstructor::Create(const PRUnichar* aName,
const nsGlobalNameStruct* aNameStruct,
nsPIDOMWindow* aOwner,
nsDOMConstructor** aResult)
{
*aResult = nsnull;
if (!aOwner->IsOuterWindow()) {
*aResult = new nsDOMConstructor(aName, aNameStruct, aOwner);
} else if (!nsContentUtils::CanCallerAccess(aOwner)) {
return NS_ERROR_DOM_SECURITY_ERR;
} else {
*aResult =
new nsDOMConstructor(aName, aNameStruct, aOwner->GetCurrentInnerWindow());
}
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMPL_ADDREF(nsDOMConstructor)
NS_IMPL_RELEASE(nsDOMConstructor)
NS_INTERFACE_MAP_BEGIN(nsDOMConstructor)
@ -5227,14 +5256,13 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
// We're resolving a name of a DOM interface for which there is no
// direct DOM class, create a constructor object...
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(reinterpret_cast<PRUnichar *>
(::JS_GetStringChars(str)),
name_struct,
static_cast<nsPIDOMWindow*>(aWin));
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsRefPtr<nsDOMConstructor> constructor;
rv = nsDOMConstructor::Create(reinterpret_cast<PRUnichar *>
(::JS_GetStringChars(str)),
name_struct,
static_cast<nsPIDOMWindow*>(aWin),
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
sDoSecurityCheckInAddProperty = PR_FALSE;
@ -5292,12 +5320,11 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
const PRUnichar *name = reinterpret_cast<PRUnichar *>
(::JS_GetStringChars(str));
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(name, name_struct,
static_cast<nsPIDOMWindow*>(aWin));
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsRefPtr<nsDOMConstructor> constructor;
rv = nsDOMConstructor::Create(name, name_struct,
static_cast<nsPIDOMWindow*>(aWin),
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
sDoSecurityCheckInAddProperty = PR_FALSE;
@ -5512,12 +5539,11 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
}
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
nsRefPtr<nsDOMConstructor> constructor =
new nsDOMConstructor(class_name, name_struct,
static_cast<nsPIDOMWindow*>(aWin));
if (!constructor) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsRefPtr<nsDOMConstructor> constructor;
rv = nsDOMConstructor::Create(class_name, name_struct,
static_cast<nsPIDOMWindow*>(aWin),
getter_AddRefs(constructor));
NS_ENSURE_SUCCESS(rv, rv);
jsval val;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;