bug 188229 - [AxPlugin] Security policy should be per-domain configurable r=adamlock, sr=alecf NOTE: these changes are not part of the regular build.

This commit is contained in:
dbradley%netscape.com 2003-03-12 20:05:54 +00:00
Родитель 9f4bb5fbd0
Коммит b9470cc0fa
10 изменённых файлов: 112 добавлений и 108 удалений

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

@ -58,6 +58,7 @@
native COMVARIANT(VARIANT);
[ptr] native COMVARIANTPtr(VARIANT);
native JSVal(jsval);
[ptr] native JSContextPtr(JSContext);
interface IDispatch;
@ -78,20 +79,14 @@ interface nsIDispatchSupport : nsISupports
*/
void JSVal2COMVariant(in JSVal var, out COMVARIANT comvar);
/**
* Instantiate a COM component.
* @param className ProgID or Class ID of the desired object to instantiate
* @return The IDispatch interface pointer if instantiated
*/
IDispatch createInstance(in astring className);
/**
* Test if the class is safe to host.
* @param clsid The nsID representation of the CLSID to test.
* @param classExists Returns containing PR_FALSE if the class is
* not registered.
*/
boolean isClassSafeToHost(in nsCIDRef cid, out boolean classExists);
boolean isClassSafeToHost(in JSContextPtr cx, in nsCIDRef cid,
in boolean capsCheck, out boolean classExists);
/**
* Test if the specified class is marked safe for scripting.
@ -99,7 +94,8 @@ interface nsIDispatchSupport : nsISupports
* @param classExists Returns containing PR_FALSE if the class is not
* registered.
*/
boolean isClassMarkedSafeForScripting(in nsCIDRef cid, out boolean classExists);
boolean isClassMarkedSafeForScripting(in nsCIDRef cid,
out boolean classExists);
/**
* Test if the instantiated object is safe for scripting on the specified
@ -116,7 +112,6 @@ interface nsIDispatchSupport : nsISupports
* only valid value is nsnull.
*/
unsigned long getHostingFlags(in string aContext);
};
%{ C++

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

@ -100,25 +100,25 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
jsval val;
if(JS_GetElement(ccx, obj, index, &val))
{
if (!JSVAL_IS_VOID(val))
if(!JSVAL_IS_VOID(val))
{
if (!array)
if(!array)
{
// Create an array that starts at index, and has len
// elements
array = SafeArrayCreateVector(VT_VARIANT, index, len - index);
if (!array)
if(!array)
{
err = NS_ERROR_OUT_OF_MEMORY;
return JS_FALSE;
}
if (FAILED(SafeArrayAccessData(array, NS_REINTERPRET_CAST(void**,&varArray))))
if(FAILED(SafeArrayAccessData(array, NS_REINTERPRET_CAST(void**,&varArray))))
{
err = NS_ERROR_FAILURE;
return JS_FALSE;
}
}
if (!JSToCOM(ccx, val, *varArray, err))
if(!JSToCOM(ccx, val, *varArray, err))
{
SafeArrayUnaccessData(array);
err = NS_ERROR_FAILURE;
@ -127,7 +127,7 @@ JSBool XPCDispConvert::JSArrayToCOMArray(XPCCallContext& ccx, JSObject *obj,
return JS_FALSE;
}
}
if (varArray)
if(varArray)
++varArray;
}
}
@ -312,7 +312,7 @@ JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
{
JSObject * obj = JSVAL_TO_OBJECT(src);
IUnknown * pUnknown = nsnull;
if (!XPCConvert::JSObject2NativeInterface(
if(!XPCConvert::JSObject2NativeInterface(
ccx,
(void**)&pUnknown,
obj,
@ -348,7 +348,7 @@ JSBool XPCDispConvert::JSToCOM(XPCCallContext& ccx,
}
if(isByRef)
{
if (!xpc_CopyVariantByRef(byRefVariant, dest))
if(!xpc_CopyVariantByRef(byRefVariant, dest))
{
// Avoid cleaning up garabage
dest.vt = VT_EMPTY;

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

@ -73,31 +73,33 @@ XPCDispObject::WrapIDispatch(IDispatch *pDispatch, XPCCallContext &ccx,
return PR_TRUE;
}
HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool enforceSecurity, IDispatch ** result)
HRESULT XPCDispObject::COMCreateInstance(XPCCallContext & ccx, BSTR className,
PRBool enforceSecurity,
IDispatch ** result)
{
// Turn the string into a CLSID
_bstr_t bstrName(className);
CLSID classID = CLSID_NULL;
HRESULT hr = CLSIDFromString(bstrName, &classID);
if (FAILED(hr))
if(FAILED(hr))
hr = CLSIDFromProgID(bstrName, &classID);
if(FAILED(hr) || ::IsEqualCLSID(classID, CLSID_NULL))
return hr;
nsresult rv;
nsCOMPtr<nsIDispatchSupport> dispSupport = do_GetService(NS_IDISPATCH_SUPPORT_CONTRACTID, &rv);
if (NS_FAILED(rv)) return E_UNEXPECTED;
if(NS_FAILED(rv)) return E_UNEXPECTED;
PRUint32 hostingFlags = nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
dispSupport->GetHostingFlags(nsnull, &hostingFlags);
PRBool allowSafeObjects;
if (hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_SAFE_OBJECTS))
allowSafeObjects = PR_TRUE;
else
allowSafeObjects = PR_FALSE;
PRBool allowAnyObjects;
if (hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS))
if(hostingFlags & (nsIActiveXSecurityPolicy::HOSTING_FLAGS_SCRIPT_ALL_OBJECTS))
allowAnyObjects = PR_TRUE;
else
allowAnyObjects = PR_FALSE;
@ -107,15 +109,19 @@ HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool enforceSecurity,
{
return E_FAIL;
}
PRBool classExists = PR_FALSE;
PRBool ok = PR_FALSE;
const nsCID & ourCID = XPCDispCLSID2nsCID(classID);
dispSupport->IsClassSafeToHost(ccx, ourCID, PR_FALSE, &classExists, &ok);
if(classExists && !ok)
return E_FAIL;
// Test if the object is scriptable
PRBool isScriptable = PR_FALSE;
if(enforceSecurity && !allowAnyObjects)
{
nsCID cid;
memcpy(&cid, &classID, sizeof(nsCID));
PRBool classExists = PR_FALSE;
dispSupport->IsClassMarkedSafeForScripting(cid, &classExists, &isScriptable);
dispSupport->IsClassMarkedSafeForScripting(ourCID, &classExists, &isScriptable);
if(!classExists)
return REGDB_E_CLASSNOTREG;
}
@ -131,7 +137,7 @@ HRESULT XPCDispObject::COMCreateInstance(BSTR className, PRBool enforceSecurity,
if(enforceSecurity && !allowAnyObjects && !isScriptable)
{
dispSupport->IsObjectSafeForScripting(disp, NSID_IDISPATCH, &isScriptable);
if (!isScriptable)
if(!isScriptable)
return E_FAIL;
}

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

@ -999,6 +999,7 @@ public:
JSBool Invoke(XPCCallContext & ccx, CallMode mode);
/**
* Instantiates a COM object given a class ID or a prog ID
* @param ccx an XPConnect call context
* @param className a prog ID or a class ID in the form of
* {00000000-0000-0000-0000-000000000000}
* @param enforceSecurity if true, will apply checks to ensure
@ -1007,8 +1008,8 @@ public:
* @param result pointer to the pointer to receive the interface pointer
*/
static
HRESULT COMCreateInstance(BSTR className,
PRBool enforceSecurity, IDispatch ** result);
HRESULT COMCreateInstance(XPCCallContext & ccx, BSTR className,
PRBool enforceSecurity, IDispatch ** result);
/**
* Wraps an IDispatch interface, returning the object as a jsval
* @param pDispatch IDispatch pointer

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

@ -41,11 +41,31 @@ static const char* const IDISPATCH_NAME = "IDispatch";
PRBool XPCIDispatchExtension::mIsEnabled = PR_TRUE;
static JSBool
CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval, PRBool enforceSecurity)
CommonConstructor(JSContext *cx, int name, JSObject *obj, uintN argc,
jsval *argv, jsval *rval, PRBool enforceSecurity)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
XPCJSRuntime *rt = ccx.GetRuntime();
if (!rt)
{
XPCThrower::Throw(NS_ERROR_UNEXPECTED, ccx);
return JS_FALSE;
}
nsIXPCSecurityManager* sm = ccx.GetXPCContext()
->GetAppropriateSecurityManager(nsIXPCSecurityManager::HOOK_CALL_METHOD);
XPCWrappedNative * wrapper = ccx.GetWrapper();
if(!sm || NS_FAILED(sm->CanAccess(nsIXPCSecurityManager::ACCESS_CALL_METHOD,
&ccx, ccx, ccx.GetFlattenedJSObject(),
wrapper->GetIdentityObject(),
wrapper->GetClassInfo(),
rt->GetStringJSVal(name),
wrapper->GetSecurityInfoAddr())))
{
// Security manager will have set an exception
return JS_FALSE;
}
// Check if IDispatch is enabled, fail if not
if (!nsXPConnect::IsIDispatchEnabled())
if(!nsXPConnect::IsIDispatchEnabled())
{
XPCThrower::Throw(NS_ERROR_XPC_IDISPATCH_NOT_ENABLED, ccx);
return JS_FALSE;
@ -66,7 +86,8 @@ CommonConstructor(XPCCallContext &ccx, JSObject *obj, uintN argc, jsval *argv,
}
// Instantiate the desired COM object
CComPtr<IDispatch> pDispatch;
HRESULT rv = XPCDispObject::COMCreateInstance(bstrClassName, enforceSecurity, &pDispatch);
HRESULT rv = XPCDispObject::COMCreateInstance(ccx, bstrClassName,
enforceSecurity, &pDispatch);
if(FAILED(rv))
{
XPCThrower::ThrowCOMError(ccx, rv, NS_ERROR_XPC_COM_CREATE_FAILED);
@ -98,16 +119,16 @@ JS_STATIC_DLL_CALLBACK(JSBool)
COMObjectConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
return CommonConstructor(ccx, obj, argc, argv, rval, PR_FALSE);
return CommonConstructor(cx, XPCJSRuntime::IDX_COM_OBJECT, obj, argc,
argv, rval, PR_FALSE);
}
JS_STATIC_DLL_CALLBACK(JSBool)
ActiveXConstructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
XPCCallContext ccx(JS_CALLER, cx, obj);
return CommonConstructor(ccx, obj, argc, argv, rval, PR_TRUE);
return CommonConstructor(cx, XPCJSRuntime::IDX_ACTIVEX_OBJECT, obj, argc, argv,
rval, PR_TRUE);
}
JSBool XPCIDispatchExtension::Initialize(JSContext * aJSContext,

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

@ -81,7 +81,7 @@ ClassIsListed(HKEY hkeyRoot, const TCHAR *szKey, const CLSID &clsid, PRBool &lis
// Class is listed
return PR_TRUE;
}
} while (1);
} while(1);
// Class not found
return PR_FALSE;
@ -119,7 +119,7 @@ ClassImplementsCategory(const CLSID &clsid, const CATID &catid, PRBool &bClassEx
return PR_FALSE;
// CLSID exists, so try checking what categories it implements
bClassExists = TRUE;
bClassExists = PR_TRUE;
CComPtr<ICatInformation> catInfo;
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
CLSCTX_INPROC_SERVER, __uuidof(ICatInformation), (LPVOID*) &catInfo);
@ -134,7 +134,7 @@ ClassImplementsCategory(const CLSID &clsid, const CATID &catid, PRBool &bClassEx
// Search for matching categories
BOOL bFound = FALSE;
CATID catidNext = GUID_NULL;
while (enumCATID->Next(1, &catidNext, NULL) == S_OK)
while(enumCATID->Next(1, &catidNext, NULL) == S_OK)
{
if(::IsEqualCATID(catid, catidNext))
return PR_TRUE; // Match
@ -185,15 +185,34 @@ NS_IMETHODIMP nsDispatchSupport::JSVal2COMVariant(jsval val, VARIANT * comvar)
}
/* boolean isClassSafeToHost (in nsCIDRef clsid, out boolean classExists); */
NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(const nsCID & cid, PRBool *classExists, PRBool *_retval)
NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(JSContext * cx,
const nsCID & cid,
PRBool ignoreException,
PRBool *classExists,
PRBool *aResult)
{
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(classExists);
*_retval = PR_FALSE;
*aResult = PR_FALSE;
CLSID clsid = XPCDispnsCID2CLSID(cid);
// Ask security manager if it's ok to create this object
XPCCallContext ccx(JS_CALLER, cx);
nsIXPCSecurityManager* sm =
ccx.GetXPCContext()->GetAppropriateSecurityManager(
nsIXPCSecurityManager::HOOK_CREATE_INSTANCE);
*aResult = sm &&
NS_SUCCEEDED(sm->CanCreateInstance(ccx, cid));
if(!*aResult)
{
if (ignoreException)
JS_ClearPendingException(ccx);
*classExists = PR_TRUE;
return NS_OK;
}
*classExists = ClassExists(clsid);
// Test the Internet Explorer black list
@ -221,7 +240,7 @@ NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(const nsCID & cid, PRBool *cl
if(dwFlags & kKillBit)
{
::CoTaskMemFree(szCLSID);
*_retval = PR_FALSE;
*aResult = PR_FALSE;
return NS_OK;
}
}
@ -230,52 +249,26 @@ NS_IMETHODIMP nsDispatchSupport::IsClassSafeToHost(const nsCID & cid, PRBool *cl
}
}
// Registry keys containing lists of controls that the Gecko explicitly does
// or does not support.
const TCHAR kControlsToDenyKey[] = _T("Software\\Mozilla\\ActiveX\\Blacklist\\CLSID");
const TCHAR kControlsToAllowKey[] = _T("Software\\Mozilla\\ActiveX\\Whitelist\\CLSID");
// Check if the CLSID belongs to a list that the Gecko does not support
PRBool listIsEmpty = PR_FALSE;
if(ClassIsListed(HKEY_LOCAL_MACHINE, kControlsToDenyKey, clsid, listIsEmpty))
{
*_retval = PR_FALSE;
return NS_OK;
}
// Check if the CLSID is in the whitelist. This test only cares that the
// CLSID is not present when the whitelist is non-empty, to indicates that it is being used.
listIsEmpty = PR_FALSE;
if(!ClassIsListed(HKEY_LOCAL_MACHINE, kControlsToAllowKey, clsid, listIsEmpty) &&
!listIsEmpty)
{
*_retval = PR_FALSE;
return NS_OK;
}
*_retval = PR_TRUE;
*aResult = PR_TRUE;
return NS_OK;
}
/* boolean isClassMarkedSafeForScripting (in nsCIDRef clsid, out boolean classExists); */
NS_IMETHODIMP nsDispatchSupport::IsClassMarkedSafeForScripting(const nsCID & cid, PRBool *classExists, PRBool *_retval)
NS_IMETHODIMP nsDispatchSupport::IsClassMarkedSafeForScripting(const nsCID & cid, PRBool *classExists, PRBool *aResult)
{
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_ARG_POINTER(classExists);
// Test the category the object belongs to
CLSID clsid = XPCDispnsCID2CLSID(cid);
*_retval = ClassImplementsCategory(clsid, CATID_SafeForScripting, *classExists);
*aResult = ClassImplementsCategory(clsid, CATID_SafeForScripting, *classExists);
return NS_OK;
}
/* boolean isObjectSafeForScripting (in voidPtr theObject, in nsIIDRef iid); */
NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, const nsIID & id, PRBool *_retval)
NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, const nsIID & id, PRBool *aResult)
{
NS_ENSURE_ARG_POINTER(theObject);
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_ARG_POINTER(aResult);
// Test if the object implements IObjectSafety and is marked safe for scripting
IUnknown *pObject = (IUnknown *) theObject;
@ -285,7 +278,7 @@ NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, cons
CComQIPtr<IObjectSafety> objectSafety = pObject;
if(!objectSafety)
{
*_retval = PR_FALSE;
*aResult = PR_TRUE;
return NS_OK;
}
@ -297,7 +290,7 @@ NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, cons
iid, &dwSupported, &dwEnabled)))
{
// Interface is not safe or failure.
*_retval = PR_FALSE;
*aResult = PR_FALSE;
return NS_OK;
}
@ -307,19 +300,19 @@ NS_IMETHODIMP nsDispatchSupport::IsObjectSafeForScripting(void * theObject, cons
// Object says it is not set to be safe, but supports unsafe calling,
// try enabling it and asking again.
if (!(dwSupported & INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
if(!(dwSupported & INTERFACESAFE_FOR_UNTRUSTED_CALLER) ||
FAILED(objectSafety->SetInterfaceSafetyOptions(
iid, INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER)) ||
FAILED(objectSafety->GetInterfaceSafetyOptions(
iid, &dwSupported, &dwEnabled)) ||
!(dwEnabled & dwSupported) & INTERFACESAFE_FOR_UNTRUSTED_CALLER)
{
*_retval = PR_FALSE;
*aResult = PR_FALSE;
return NS_OK;
}
}
*_retval = PR_TRUE;
*aResult = PR_TRUE;
return NS_OK;
}
@ -327,42 +320,22 @@ static const PRUint32 kDefaultHostingFlags =
nsIActiveXSecurityPolicy::HOSTING_FLAGS_HOST_NOTHING;
/* unsigned long getHostingFlags (in string aContext); */
NS_IMETHODIMP nsDispatchSupport::GetHostingFlags(const char *aContext, PRUint32 *_retval)
NS_IMETHODIMP nsDispatchSupport::GetHostingFlags(const char *aContext, PRUint32 *aResult)
{
NS_ENSURE_ARG_POINTER(_retval);
NS_ENSURE_ARG_POINTER(aResult);
// Ask the activex security policy what the hosting flags are
nsresult rv;
nsCOMPtr<nsIActiveXSecurityPolicy> securityPolicy =
do_GetService(NS_IACTIVEXSECURITYPOLICY_CONTRACTID, &rv);
if(NS_SUCCEEDED(rv) && securityPolicy)
return securityPolicy->GetHostingFlags(aContext, _retval);
return securityPolicy->GetHostingFlags(aContext, aResult);
// No policy so use the defaults
*_retval = kDefaultHostingFlags;
*aResult = kDefaultHostingFlags;
return NS_OK;
}
/**
* Creates an instance of an COM object, returning it as an IDispatch interface.
* This also allows testing of scriptability.
* @param className prog ID or class ID of COM component, class ID must be in
* the form of {00000000-0000-0000-000000000000}
* @param testScriptability if true this will only succeed if the object is in
* the property category or supports the IObjectSafety interface
* @param result pointer to an IDispatch to receive the pointer to the instance
* @return nsresult
*/
NS_IMETHODIMP nsDispatchSupport::CreateInstance(const nsAString & className,
IDispatch ** result)
{
if (!nsXPConnect::IsIDispatchEnabled())
return NS_ERROR_XPC_IDISPATCH_NOT_ENABLED;
const nsPromiseFlatString & flat = PromiseFlatString(className);
CComBSTR name(flat.Length(), flat.get());
return XPCDispObject::COMCreateInstance(name, PR_TRUE, result);
}
nsDispatchSupport* nsDispatchSupport::GetSingleton()
{
if(!mInstance)

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

@ -219,7 +219,7 @@ AddXPCOMUCStringFinalizer()
sXPCOMUCStringFinalizerIndex =
JS_AddExternalStringFinalizer(FinalizeXPCOMUCString);
if (sXPCOMUCStringFinalizerIndex == -1)
if(sXPCOMUCStringFinalizerIndex == -1)
{
return JS_FALSE;
}

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

@ -582,7 +582,7 @@ void XPCWrappedNativeTearOff::SetJSObject(JSObject* JSObj)
if(IsIDispatch())
{
XPCDispInterface* iface = GetIDispatchInfo();
if (iface)
if(iface)
iface->SetJSObject(JSObj);
}
else

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

@ -52,6 +52,10 @@ const char* XPCJSRuntime::mStrings[] = {
"Object", // IDX_OBJECT
"prototype", // IDX_PROTOTYPE
"createInstance" // IDX_CREATE_INSTANCE
#ifdef XPC_IDISPATCH_SUPPORT
, "ActiveXObject" // IDX_ACTIVEX_OBJECT
, "COMObject" // IDX_COMOBJECT
#endif
};
/***************************************************************************/

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

@ -551,6 +551,10 @@ public:
IDX_OBJECT ,
IDX_PROTOTYPE ,
IDX_CREATE_INSTANCE ,
#ifdef XPC_IDISPATCH_SUPPORT
IDX_ACTIVEX_OBJECT ,
IDX_COM_OBJECT ,
#endif
IDX_TOTAL_COUNT // just a count of the above
};