diff --git a/caps/idl/nsIScriptSecurityManager.idl b/caps/idl/nsIScriptSecurityManager.idl index 44e9569a34de..37f7bb0e1ce6 100644 --- a/caps/idl/nsIScriptSecurityManager.idl +++ b/caps/idl/nsIScriptSecurityManager.idl @@ -34,13 +34,19 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager /** * Checks whether the running script is allowed to access aProperty. */ - [noscript] void checkPropertyAccess(in PRUint32 aAction, - in JSContextPtr aJSContext, + [noscript] void checkPropertyAccess(in JSContextPtr aJSContext, in JSObjectPtr aJSObject, - in nsISupports aObj, - in nsIClassInfo aClassInfo, in string aClassName, - in string aProperty); + in string aProperty, + in PRUint32 aAction); + + /** + * Checks whether the running script is allowed to connect to aTargetURI + */ + [noscript] void checkConnect(in JSContextPtr aJSContext, + in nsIURI aTargetURI, + in string aClassName, + in string aPropertyName); /** * Check that the script currently running in context "cx" can load "uri". diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index 400d2b03f2b2..0f43dbc0ef89 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -112,7 +112,8 @@ private: nsresult CheckPropertyAccessImpl(PRUint32 aAction, nsIXPCNativeCallContext* aCallContext, JSContext* aJSContext, JSObject* aJSObject, - nsISupports* aObj, nsIClassInfo* aClassInfo, + nsISupports* aObj, nsIURI* aTargetURI, + nsIClassInfo* aClassInfo, jsval aName, const char* aClassName, const char* aProperty, void** aPolicy); @@ -122,7 +123,7 @@ private: PRInt32 GetSecurityLevel(JSContext* aCx, nsIPrincipal *principal, - nsIClassInfo* aClassInfo, + PRBool aIsDOM, const char* aClassName, const char* aProperty, PRUint32 aAction, nsCString &capability, void** aPolicy); diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 16926b28e6fa..e7ef4ca68f4f 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -137,23 +137,34 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptSecurityManager, ///////////////// Security Checks ///////////////// NS_IMETHODIMP -nsScriptSecurityManager::CheckPropertyAccess(PRUint32 aAction, - JSContext* aJSContext, +nsScriptSecurityManager::CheckPropertyAccess(JSContext* aJSContext, JSObject* aJSObject, - nsISupports* aObj, - nsIClassInfo* aClassInfo, const char* aClassName, - const char* aProperty) + const char* aPropertyName, + PRUint32 aAction) { - return CheckPropertyAccessImpl(aAction, nsnull, aJSContext, aJSObject, aObj, - aClassInfo, nsnull, aClassName, aProperty, nsnull); + return CheckPropertyAccessImpl(aAction, nsnull, aJSContext, aJSObject, + nsnull, nsnull, nsnull, nsnull, + aClassName, aPropertyName, nsnull); +} + +NS_IMETHODIMP +nsScriptSecurityManager::CheckConnect(JSContext* aJSContext, + nsIURI* aTargetURI, + const char* aClassName, + const char* aPropertyName) +{ + return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_GET_PROPERTY, nsnull, + aJSContext, nsnull, nsnull, aTargetURI, + nsnull, nsnull, aClassName, aPropertyName, nsnull); } nsresult nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, nsIXPCNativeCallContext* aCallContext, JSContext* aJSContext, JSObject* aJSObject, - nsISupports* aObj, nsIClassInfo* aClassInfo, + nsISupports* aObj, nsIURI* aTargetURI, + nsIClassInfo* aClassInfo, jsval aName, const char* aClassName, const char* aProperty, void** aPolicy) { @@ -214,8 +225,11 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, propertyName.AssignWithConversion((PRUnichar*)JSValIDToString(aJSContext, aName)); } - secLevel = GetSecurityLevel(aJSContext, subjectPrincipal, aClassInfo, className, - propertyName, aAction, capability, aPolicy); + // if (aPropertyStr), we were called from CheckPropertyAccess or checkConnect, + // so we can assume this is a DOM class. Otherwise, we ask the ClassInfo. + secLevel = GetSecurityLevel(aJSContext, subjectPrincipal, + (aProperty || IsDOMClass(aClassInfo)), + className, propertyName, aAction, capability, aPolicy); } nsresult rv; @@ -232,18 +246,27 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction, #ifdef DEBUG_mstoltz printf("Level: SameOrigin "); #endif + nsCOMPtr objectPrincipal; if(aJSObject) { - nsCOMPtr objectPrincipal; if (NS_FAILED(GetObjectPrincipal(aJSContext, NS_REINTERPRET_CAST(JSObject*, aJSObject), getter_AddRefs(objectPrincipal)))) return NS_ERROR_FAILURE; - rv = CheckSameOrigin(aJSContext, subjectPrincipal, objectPrincipal, - aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY); + } + else if(aTargetURI) + { + if (NS_FAILED(GetCodebasePrincipal(aTargetURI, getter_AddRefs(objectPrincipal)))) + return NS_ERROR_FAILURE; } else + { rv = NS_ERROR_DOM_SECURITY_ERR; + break; + } + rv = CheckSameOrigin(aJSContext, subjectPrincipal, objectPrincipal, + aAction == nsIXPCSecurityManager::ACCESS_SET_PROPERTY); + break; } case SCRIPT_SECURITY_CAPABILITY_ONLY: @@ -383,7 +406,7 @@ nsScriptSecurityManager::IsDOMClass(nsIClassInfo* aClassInfo) PRInt32 nsScriptSecurityManager::GetSecurityLevel(JSContext* aJSContext, nsIPrincipal *principal, - nsIClassInfo* aClassInfo, + PRBool aIsDOM, const char* aClassName, const char* aPropertyName, PRUint32 aAction, @@ -447,7 +470,7 @@ nsScriptSecurityManager::GetSecurityLevel(JSContext* aJSContext, } //-- No policy for this property. // Use the default policy: sameOrigin for DOM, noAccess for everything else - if(IsDOMClass(aClassInfo)) + if(aIsDOM) secLevel = SCRIPT_SECURITY_SAME_ORIGIN_ACCESS; if (!classPolicy && aPolicy) //-- If there's no stored policy for this property, @@ -1688,8 +1711,9 @@ nsScriptSecurityManager::CanAccess(PRUint32 aAction, jsval aName, void** aPolicy) { - return CheckPropertyAccessImpl(aAction, aCallContext, aJSContext, aJSObject, - aObj, aClassInfo, aName, nsnull, nsnull, aPolicy); + return CheckPropertyAccessImpl(aAction, aCallContext, aJSContext, + aJSObject, aObj, nsnull, aClassInfo, + aName, nsnull, nsnull, aPolicy); } nsresult @@ -1951,12 +1975,10 @@ nsScriptSecurityManager::InitPolicies(PRUint32 aPrefCount, const char** aPrefNam else if (count > 3) { // capability.policy...[.(get|set)] // Store the class name so we know this class has a policy set on it - const char* className = dots[2] + 1; - PRInt32 classNameLen = dots[3] - className; - char* classNameNullTerm = PL_strndup(className, classNameLen); - if (!classNameNullTerm) - return NS_ERROR_OUT_OF_MEMORY; - nsCStringKey classNameKey(classNameNullTerm); + // Shoving a null into the pref anme string is unorthodox + // but it saves a malloc & copy - hash keys require null-terminated strings + *(char*)dots[3] = '\0'; + nsCStringKey classNameKey(dots[2] + 1); if (!(mClassPolicies)) mClassPolicies = new nsHashtable(31); // We don't actually have to store the class name as data in the hashtable, @@ -1966,7 +1988,6 @@ nsScriptSecurityManager::InitPolicies(PRUint32 aPrefCount, const char** aPrefNam mClassPolicies->Put(&classNameKey, (void*)CLASS_POLICY_DEFAULT); else if (!isDefault && classPolicy != (void*)CLASS_POLICY_SITE) mClassPolicies->Put(&classNameKey, (void*)CLASS_POLICY_SITE); - PR_Free(classNameNullTerm); } } return NS_OK; diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index c1d45cfa7ac4..5670c46cb7a6 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -981,11 +981,9 @@ nsEventListenerManager::RegisterScriptEventListener(nsIScriptContext *aContext, if (NS_FAILED(rv)) return rv; - nsCOMPtr classInfo = do_QueryInterface(aObject); - - if (NS_FAILED(rv = securityManager->CheckPropertyAccess( - nsIXPCSecurityManager::ACCESS_SET_PROPERTY, cx, jsobj, aObject, classInfo, - "EventTarget","addEventListener"))) { + if (NS_FAILED(rv = securityManager->CheckPropertyAccess(cx, jsobj, + "EventTarget","addEventListener", + nsIXPCSecurityManager::ACCESS_SET_PROPERTY))) { // XXX set pending exception on the native call context? return rv; } diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index 04c198cad3f0..7a0e5f05c85b 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -1108,9 +1108,9 @@ nsWindowSH::doCheckWriteAccess(JSContext *cx, JSObject *obj, jsval id, PRBool isLocation = JSVAL_IS_STRING(id) && JSVAL_TO_STRING(id) == sLocation_id; - rv = sSecMan->CheckPropertyAccess(nsIXPCSecurityManager::ACCESS_SET_PROPERTY, - cx, obj, native, this, "Window", - isLocation ? "location" : "scriptglobals"); + rv = sSecMan->CheckPropertyAccess(cx, obj, "Window", + isLocation ? "location" : "scriptglobals", + nsIXPCSecurityManager::ACCESS_SET_PROPERTY); if (NS_SUCCEEDED(rv)) { return rv; @@ -1146,9 +1146,9 @@ nsWindowSH::doCheckReadAccess(JSContext *cx, JSObject *obj, jsval id, PRBool isLocation = JSVAL_IS_STRING(id) && JSVAL_TO_STRING(id) == sLocation_id; - rv = sSecMan->CheckPropertyAccess(nsIXPCSecurityManager::ACCESS_GET_PROPERTY, - cx, obj, native, this, "Window", - isLocation ? "location" : "scriptglobals"); + rv = sSecMan->CheckPropertyAccess(cx, obj, "Window", + isLocation ? "location" : "scriptglobals", + nsIXPCSecurityManager::ACCESS_GET_PROPERTY); if (NS_SUCCEEDED(rv)) { return rv; diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index d7605fc9191d..50632697ec34 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -4123,8 +4123,8 @@ NavigatorImpl::Preference() action = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; else action = nsIXPCSecurityManager::ACCESS_SET_PROPERTY; - rv = secMan->CheckPropertyAccess(action, cx, nsnull, nsnull, nsnull, - "Navigator", "preferenceinternal"); + rv = secMan->CheckPropertyAccess(cx, nsnull, + "Navigator", "preferenceinternal", action); if (NS_FAILED(rv)) { //-- XXX doing the right thing here? Does the exception propagate? diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index dc22826442b1..ab7195721952 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -630,17 +630,22 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent, nsCOMPtr newDocShell(do_QueryInterface(newDocShellItem)); if (uriToLoad) { // Get script principal and pass to docshell - nsCOMPtr principal; - if (NS_FAILED(secMan->GetSubjectPrincipal(getter_AddRefs(principal)))) - return NS_ERROR_FAILURE; - nsCOMPtr loadInfo; - newDocShell->CreateLoadInfo(getter_AddRefs(loadInfo)); - NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE); - if (principal) { - nsCOMPtr owner(do_QueryInterface(principal)); - loadInfo->SetOwner(owner); + PRBool isChrome = PR_FALSE; + rv = uriToLoad->SchemeIs("chrome", &isChrome); + if (NS_FAILED(rv) || !isChrome) { + nsCOMPtr principal; + if (NS_FAILED(secMan->GetSubjectPrincipal(getter_AddRefs(principal)))) + return NS_ERROR_FAILURE; + + newDocShell->CreateLoadInfo(getter_AddRefs(loadInfo)); + NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE); + + if (principal) { + nsCOMPtr owner(do_QueryInterface(principal)); + loadInfo->SetOwner(owner); + } } // Get the calling context off the JS context stack diff --git a/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp b/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp index 40c8e6b86c1d..db949c17472d 100644 --- a/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp +++ b/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp @@ -922,10 +922,26 @@ nsXMLHttpRequest::Open(const char *method, const char *url) NS_WITH_SERVICE(nsIScriptSecurityManager, secMan, NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - /* - rv = secMan->CheckScriptAccessToURL(cx, url, NS_DOM_PROP_XMLHTTPREQUEST_OPEN, PR_FALSE); - if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - */ + + nsCOMPtr targetURI; + rv = NS_NewURI(getter_AddRefs(targetURI), url, nsnull); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + rv = secMan->CheckConnect(cx, targetURI, "XMLHttpRequest","open"); + if (NS_FAILED(rv)) + { + // Security check failed. The above call set a JS exception. The + // following lines ensure that the exception is propagated. + + NS_WITH_SERVICE(nsIXPConnect, xpc, nsIXPConnect::GetCID(), &rv); + nsCOMPtr cc; + if(NS_SUCCEEDED(rv)) + xpc->GetCurrentNativeCallContext(getter_AddRefs(cc)); + if (cc) + cc->SetExceptionWasThrown(PR_TRUE); + return NS_OK; + } + nsCOMPtr principal; rv = secMan->GetSubjectPrincipal(getter_AddRefs(principal)); if (NS_SUCCEEDED(rv)) {