Allow XMLHttpRequest and document.load load files from subdirectories. r/sr=dveditz
Allow XMLHttpRequest and document.load load files from subdirectories. r/sr=dveditz
--- a/caps/idl/nsIScriptSecurityManager.idl
+++ b/caps/idl/nsIScriptSecurityManager.idl
@@ -37,38 +37,30 @@
#include "nsISupports.idl"
#include "nsIPrincipal.idl"
#include "nsIXPCSecurityManager.idl"
interface nsIURI;
interface nsIChannel;
-[scriptable, uuid(3fffd8e8-3fea-442e-a0ed-2ba81ae197d5)]
+[scriptable, uuid(e74487fd-98ef-48d1-b973-3f2938f04e8e)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
///////////////// Security Checks //////////////////
/**
* Checks whether the running script is allowed to access aProperty.
*/
[noscript] void checkPropertyAccess(in JSContextPtr aJSContext,
in JSObjectPtr aJSObject,
in string aClassName,
in JSVal 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 aProperty);
-
- /**
* Check that the script currently running in context "cx" can load "uri".
*
* Will return error code NS_ERROR_DOM_BAD_URI if the load request
* should be denied.
*
* @param cx the JSContext of the script causing the load
* @param uri the URI that is being loaded
*/
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -403,18 +403,17 @@ public:
*/
static PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
static nsresult
ReportError(JSContext* cx, const nsAString& messageTag,
nsIURI* aSource, nsIURI* aTarget);
static nsresult
CheckSameOriginPrincipal(nsIPrincipal* aSubject,
- nsIPrincipal* aObject,
- PRBool aIsCheckConnect);
+ nsIPrincipal* aObject);
static PRBool
GetStrictFileOriginPolicy()
{
return sStrictFileOriginPolicy;
}
private:
@@ -441,26 +440,25 @@ private:
// when this happens -- this means that there was no JS running.
nsIPrincipal*
doGetSubjectPrincipal(nsresult* rv);
nsresult
CheckPropertyAccessImpl(PRUint32 aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
- nsISupports* aObj, nsIURI* aTargetURI,
+ nsISupports* aObj,
nsIClassInfo* aClassInfo,
const char* aClassName, jsval aProperty,
void** aCachedClassPolicy);
nsresult
CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
- PRUint32 aAction,
- PRBool aIsCheckConnect);
+ PRUint32 aAction);
nsresult
LookupPolicy(nsIPrincipal* principal,
ClassInfoData& aClassData, jsval aProperty,
PRUint32 aAction,
ClassPolicy** aCachedClassPolicy,
SecurityLevel* result);
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -286,18 +286,17 @@ nsPrincipal::Equals(nsIPrincipal *aOther
}
// Fall through to the codebase comparison.
}
// Codebases are equal if they have the same origin.
*aResult =
NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
- aOther,
- PR_FALSE));
+ aOther));
return NS_OK;
}
*aResult = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -565,49 +565,21 @@ nsScriptSecurityManager::CheckObjectAcce
NS_IMETHODIMP
nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
JSObject* aJSObject,
const char* aClassName,
jsval aProperty,
PRUint32 aAction)
{
return CheckPropertyAccessImpl(aAction, nsnull, cx, aJSObject,
- nsnull, nsnull, nsnull,
+ nsnull, nsnull,
aClassName, aProperty, nsnull);
}
NS_IMETHODIMP
-nsScriptSecurityManager::CheckConnect(JSContext* cx,
- nsIURI* aTargetURI,
- const char* aClassName,
- const char* aPropertyName)
-{
- // Get a context if necessary
- if (!cx)
- {
- cx = GetCurrentJSContext();
- if (!cx)
- return NS_OK; // No JS context, so allow the load
- }
-
- nsresult rv = CheckLoadURIFromScript(cx, aTargetURI);
- if (NS_FAILED(rv)) return rv;
-
- JSAutoRequest ar(cx);
-
- JSString* propertyName = ::JS_InternString(cx, aPropertyName);
- if (!propertyName)
- return NS_ERROR_OUT_OF_MEMORY;
-
- return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD, nsnull,
- cx, nsnull, nsnull, aTargetURI,
- nsnull, aClassName, STRING_TO_JSVAL(propertyName), nsnull);
-}
-
-NS_IMETHODIMP
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
nsIURI* aTargetURI)
{
nsresult rv;
// Get a context if necessary
if (!cx)
{
@@ -667,17 +639,17 @@ nsScriptSecurityManager::CheckSameOrigin
}
return NS_OK;
}
nsresult
nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
- nsISupports* aObj, nsIURI* aTargetURI,
+ nsISupports* aObj,
nsIClassInfo* aClassInfo,
const char* aClassName, jsval aProperty,
void** aCachedClassPolicy)
{
nsresult rv;
nsIPrincipal* subjectPrincipal = GetSubjectPrincipal(cx, &rv);
if (NS_FAILED(rv))
return rv;
@@ -742,32 +714,24 @@ nsScriptSecurityManager::CheckPropertyAc
nsCOMPtr<nsIPrincipal> principalHolder;
nsIPrincipal *objectPrincipal;
if(aJSObject)
{
objectPrincipal = doGetObjectPrincipal(aJSObject);
if (!objectPrincipal)
rv = NS_ERROR_DOM_SECURITY_ERR;
}
- else if(aTargetURI)
- {
- if (NS_FAILED(GetCodebasePrincipal(
- aTargetURI, getter_AddRefs(principalHolder))))
- return NS_ERROR_FAILURE;
-
- objectPrincipal = principalHolder;
- }
else
{
- NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
+ NS_ERROR("CheckPropertyAccessImpl called without a target object");
return NS_ERROR_FAILURE;
}
if(NS_SUCCEEDED(rv))
rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
- aAction, aTargetURI != nsnull);
+ aAction);
break;
}
default:
#ifdef DEBUG_CAPS_CheckPropertyAccessImpl
printf("ERROR ");
#endif
NS_ERROR("Bad Security Level Value");
return NS_ERROR_FAILURE;
@@ -892,99 +856,72 @@ nsScriptSecurityManager::CheckPropertyAc
}
return rv;
}
/* static */
nsresult
nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
- nsIPrincipal* aObject,
- PRBool aIsCheckConnect)
+ nsIPrincipal* aObject)
{
/*
** Get origin of subject and object and compare.
*/
if (aSubject == aObject)
return NS_OK;
- // These booleans are only used when !aIsCheckConnect. Default
- // them to false, and change if that turns out wrong.
PRBool subjectSetDomain = PR_FALSE;
PRBool objectSetDomain = PR_FALSE;
nsCOMPtr<nsIURI> subjectURI;
nsCOMPtr<nsIURI> objectURI;
- if (aIsCheckConnect)
- {
- // Don't use domain for CheckConnect calls, since that's called for
- // data-only load checks like XMLHTTPRequest (bug 290100).
+ aSubject->GetDomain(getter_AddRefs(subjectURI));
+ if (!subjectURI) {
aSubject->GetURI(getter_AddRefs(subjectURI));
- aObject->GetURI(getter_AddRefs(objectURI));
+ } else {
+ subjectSetDomain = PR_TRUE;
}
- else
- {
- aSubject->GetDomain(getter_AddRefs(subjectURI));
- if (!subjectURI) {
- aSubject->GetURI(getter_AddRefs(subjectURI));
- } else {
- subjectSetDomain = PR_TRUE;
- }
-
- aObject->GetDomain(getter_AddRefs(objectURI));
- if (!objectURI) {
- aObject->GetURI(getter_AddRefs(objectURI));
- } else {
- objectSetDomain = PR_TRUE;
- }
+
+ aObject->GetDomain(getter_AddRefs(objectURI));
+ if (!objectURI) {
+ aObject->GetURI(getter_AddRefs(objectURI));
+ } else {
+ objectSetDomain = PR_TRUE;
}
if (SecurityCompareURIs(subjectURI, objectURI))
{ // If either the subject or the object has changed its principal by
// explicitly setting document.domain then the other must also have
// done so in order to be considered the same origin. This prevents
// DNS spoofing based on document.domain (154930)
- // But this restriction does not apply to CheckConnect calls, since
- // that's called for data-only load checks like XMLHTTPRequest where
- // we ignore domain (bug 290100).
- if (aIsCheckConnect)
- return NS_OK;
-
// If both or neither explicitly set their domain, allow the access
if (subjectSetDomain == objectSetDomain)
return NS_OK;
}
/*
** Access tests failed, so now report error.
*/
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
nsresult
nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
- PRUint32 aAction,
- PRBool aIsCheckConnect)
+ PRUint32 aAction)
{
nsresult rv;
- if (aIsCheckConnect) {
- // Don't do equality compares, just do a same-origin compare,
- // since the object principal isn't a real principal, just a
- // GetCodebasePrincipal() on whatever URI we started with.
- rv = CheckSameOriginPrincipal(aSubject, aObject, aIsCheckConnect);
- } else {
- PRBool subsumes;
- rv = aSubject->Subsumes(aObject, &subsumes);
- if (NS_SUCCEEDED(rv) && !subsumes) {
- rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
- }
+ PRBool subsumes;
+ rv = aSubject->Subsumes(aObject, &subsumes);
+ if (NS_SUCCEEDED(rv) && !subsumes) {
+ rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
if (NS_SUCCEEDED(rv))
return NS_OK;
/*
* Content can't ever touch chrome (we check for UniversalXPConnect later)
*/
@@ -3105,17 +3042,17 @@ nsScriptSecurityManager::CanAccess(PRUin
JSContext* cx,
JSObject* aJSObject,
nsISupports* aObj,
nsIClassInfo* aClassInfo,
jsval aPropertyName,
void** aPolicy)
{
return CheckPropertyAccessImpl(aAction, aCallContext, cx,
- aJSObject, aObj, nsnull, aClassInfo,
+ aJSObject, aObj, aClassInfo,
nsnull, aPropertyName, aPolicy);
}
nsresult
nsScriptSecurityManager::CheckXPCPermissions(nsISupports* aObj,
const char* aObjectSecurityLevel)
{
//-- Check for the all-powerful UniversalXPConnect privilege
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1264,33 +1264,23 @@ nsXMLHttpRequest::Open(const nsACString&
rv = NS_NewURI(getter_AddRefs(targetURI), url, nsnull, GetBaseURI());
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
if (!secMan) {
return NS_ERROR_FAILURE;
}
- rv = secMan->CheckConnect(cx, targetURI, "XMLHttpRequest", "open");
- if (NS_FAILED(rv))
- {
- // Security check failed.
- return NS_OK;
- }
-
// Find out if UniversalBrowserRead privileges are enabled
- // we will need this in case of a redirect
- PRBool crossSiteAccessEnabled;
- rv = secMan->IsCapabilityEnabled("UniversalBrowserRead",
- &crossSiteAccessEnabled);
- if (NS_FAILED(rv)) return rv;
- if (crossSiteAccessEnabled) {
+ if (nsContentUtils::IsCallerTrustedForRead()) {
mState |= XML_HTTP_REQUEST_XSITEENABLED;
} else {
mState &= ~XML_HTTP_REQUEST_XSITEENABLED;
+ rv = mPrincipal->CheckMayLoad(targetURI, PR_TRUE);
+ NS_ENSURE_SUCCESS(rv, NS_OK);
}
if (argc > 2) {
JSAutoRequest ar(cx);
JSBool asyncBool;
::JS_ValueToBoolean(cx, argv[2], &asyncBool);
async = (PRBool)asyncBool;
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -85,16 +85,18 @@
#include "nsCRT.h"
#include "nsIAuthPrompt.h"
#include "nsIScriptGlobalObjectOwner.h"
#include "nsIJSContextStack.h"
#include "nsContentCreatorFunctions.h"
#include "nsIDOMUserDataHandler.h"
#include "nsEventDispatcher.h"
#include "nsNodeUtils.h"
+#include "nsIConsoleService.h"
+#include "nsIScriptError.h"
// ==================================================================
// =
// ==================================================================
nsresult
@@ -338,51 +340,58 @@ nsXMLDocument::Load(const nsAString& aUr
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
nsCOMPtr<nsIURI> codebase;
principal->GetURI(getter_AddRefs(codebase));
- // Get security manager, check to see whether the current document
- // is allowed to load this URI. It's important to use the current
- // document's principal for this check so that we don't end up in a
- // case where code with elevated privileges is calling us and
- // changing the principal of this document.
- nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
+ // Check to see whether the current document is allowed to load this URI.
+ // It's important to use the current document's principal for this check so
+ // that we don't end up in a case where code with elevated privileges is
+ // calling us and changing the principal of this document.
// Enforce same-origin even for chrome loaders to avoid someone accidentally
// using a document that content has a reference to and turn that into a
// chrome document.
if (codebase) {
- rv = secMan->CheckSameOriginURI(codebase, uri, PR_FALSE);
-
- if (NS_FAILED(rv)) {
- return rv;
- }
+ rv = principal->CheckMayLoad(uri, PR_FALSE);
+ NS_ENSURE_SUCCESS(rv, rv);
} else {
// We're called from chrome, check to make sure the URI we're
// about to load is also chrome.
PRBool isChrome = PR_FALSE;
if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
+ nsCAutoString spec;
+ if (mDocumentURI)
+ mDocumentURI->GetSpec(spec);
+
+ nsAutoString error;
+ error.AssignLiteral("Cross site loading using document.load is no "
+ "longer supported. Use XMLHttpRequest instead.");
+ nsCOMPtr<nsIScriptError> errorObject =
+ do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = errorObject->Init(error.get(), NS_ConvertUTF8toUTF16(spec).get(),
+ nsnull, 0, 0, nsIScriptError::warningFlag,
+ "DOM");
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIConsoleService> consoleService =
+ do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+ if (consoleService) {
+ consoleService->LogMessage(errorObject);
+ }
+
return NS_ERROR_DOM_SECURITY_ERR;
}
}
- rv = secMan->CheckConnect(nsnull, uri, "XMLDocument", "load");
- if (NS_FAILED(rv)) {
- // We need to return success here so that JS will get a proper
- // exception thrown later. Native calls should always result in
- // CheckConnect() succeeding, but in case JS calls C++ which calls
- // this code the exception might be lost.
- return NS_OK;
- }
-
// Partial Reset, need to restore principal for security reasons and
// event listener manager so that load listeners etc. will
// remain. This should be done before the security check is done to
// ensure that the document is reset even if the new document can't
// be loaded. Note that we need to hold a strong ref to |principal|
// here, because ResetToURI will null out our node principal before
// setting the new one.
nsCOMPtr<nsIEventListenerManager> elm(mListenerManager);
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -997,24 +997,16 @@ NS_IMETHODIMP
FullTrustSecMan::CheckPropertyAccess(JSContext * aJSContext,
JSObject * aJSObject,
const char *aClassName,
jsval aProperty, PRUint32 aAction)
{
return NS_OK;
}
-/* [noscript] void checkConnect (in JSContextPtr aJSContext, in nsIURI aTargetURI, in string aClassName, in string aProperty); */
-NS_IMETHODIMP
-FullTrustSecMan::CheckConnect(JSContext * aJSContext, nsIURI *aTargetURI,
- const char *aClassName, const char *aProperty)
-{
- return NS_OK;
-}
-
/* [noscript] void checkLoadURIFromScript (in JSContextPtr cx, in nsIURI uri); */
NS_IMETHODIMP
FullTrustSecMan::CheckLoadURIFromScript(JSContext * cx, nsIURI *uri)
{
return NS_OK;
}
/* void checkLoadURIWithPrincipal (in nsIPrincipal aPrincipal, in nsIURI uri, in unsigned long flags); */