mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 416534: Clean up cross-site xmlhttprequest security checks. With fixes to tests this time. r/sr=peterv
This commit is contained in:
parent
7aff03fc46
commit
28ea51311b
@ -51,7 +51,7 @@ interface nsIURI;
|
||||
[ptr] native JSContext(JSContext);
|
||||
[ptr] native JSPrincipals(JSPrincipals);
|
||||
|
||||
[scriptable, uuid(635c413b-47c3-4ee1-87c8-e7919cc65f5a)]
|
||||
[scriptable, uuid(7292475e-2821-4602-9d00-228476696428)]
|
||||
interface nsIPrincipal : nsISerializable
|
||||
{
|
||||
/**
|
||||
@ -203,6 +203,29 @@ interface nsIPrincipal : nsISerializable
|
||||
*/
|
||||
[noscript] boolean subsumes(in nsIPrincipal other);
|
||||
|
||||
/**
|
||||
* Checks whether this principal is allowed to load the network resource
|
||||
* located at the given URI under the same-origin policy. This means that
|
||||
* codebase principals are only allowed to load resources from the same
|
||||
* domain, the system principal is allowed to load anything, and null
|
||||
* principals are not allowed to load anything.
|
||||
*
|
||||
* If the load is allowed this function does nothing. If the load is not
|
||||
* allowed the function throws NS_ERROR_DOM_BAD_URI.
|
||||
*
|
||||
* NOTE: Other policies might override this, such as the Access-Control
|
||||
* specification.
|
||||
* NOTE: The 'domain' attribute has no effect on the behaviour of this
|
||||
* function.
|
||||
*
|
||||
*
|
||||
* @param uri The URI about to be loaded.
|
||||
* @param report If true, will report a warning to the console service
|
||||
* if the load is not allowed.
|
||||
* @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
|
||||
*/
|
||||
[noscript] void checkMayLoad(in nsIUri uri, in boolean report);
|
||||
|
||||
/**
|
||||
* The subject name for the certificate. This actually identifies the
|
||||
* subject of the certificate. This may well not be a string that would
|
||||
|
@ -395,6 +395,18 @@ public:
|
||||
|
||||
JSContext* GetSafeJSContext();
|
||||
|
||||
/**
|
||||
* Utility method for comparing two URIs. For security purposes, two URIs
|
||||
* are equivalent if their schemes, hosts, and ports (if any) match. This
|
||||
* method returns true if aSubjectURI and aObjectURI have the same origin,
|
||||
* false otherwise.
|
||||
*/
|
||||
static PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
|
||||
|
||||
static nsresult
|
||||
ReportError(JSContext* cx, const nsAString& messageTag,
|
||||
nsIURI* aSource, nsIURI* aTarget);
|
||||
|
||||
private:
|
||||
|
||||
// GetScriptSecurityManager is the only call that can make one
|
||||
@ -420,10 +432,6 @@ private:
|
||||
nsIPrincipal*
|
||||
doGetSubjectPrincipal(nsresult* rv);
|
||||
|
||||
static nsresult
|
||||
ReportError(JSContext* cx, const nsAString& messageTag,
|
||||
nsIURI* aSource, nsIURI* aTarget);
|
||||
|
||||
nsresult
|
||||
CheckPropertyAccessImpl(PRUint32 aAction,
|
||||
nsAXPCNativeCallContext* aCallContext,
|
||||
@ -540,16 +548,9 @@ private:
|
||||
nsISecurityPref* securityPref);
|
||||
|
||||
|
||||
/**
|
||||
* Utility method for comparing two URIs. For security purposes, two URIs
|
||||
* are equivalent if their schemes, hosts, and ports (if any) match. This
|
||||
* method returns true if aSubjectURI and aObjectURI have the same origin,
|
||||
* false otherwise.
|
||||
*/
|
||||
PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
|
||||
|
||||
/* encapsulate the file comparison rules */
|
||||
PRBool SecurityCompareFileURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
|
||||
static PRBool SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI);
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
// While this header is included outside of caps, this class isn't
|
||||
@ -590,7 +591,8 @@ private:
|
||||
PRPackedBool mXPCDefaultGrantAll;
|
||||
static const char sXPCDefaultGrantAllName[];
|
||||
#endif
|
||||
PRInt32 mFileURIOriginPolicy;
|
||||
|
||||
static PRInt32 sFileURIOriginPolicy;
|
||||
|
||||
static nsIIOService *sIOService;
|
||||
static nsIXPConnect *sXPConnect;
|
||||
|
@ -49,6 +49,8 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
|
||||
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
|
||||
|
||||
@ -316,6 +318,17 @@ nsNullPrincipal::Subsumes(nsIPrincipal *aOther, PRBool *aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::CheckMayLoad(nsIURI* aURI, PRBool aReport)
|
||||
{
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNullPrincipal::GetSubjectName(nsACString& aName)
|
||||
{
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
#include "nsPrincipal.h"
|
||||
|
||||
@ -306,6 +307,21 @@ nsPrincipal::Subsumes(nsIPrincipal *aOther, PRBool *aResult)
|
||||
return Equals(aOther, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CheckMayLoad(nsIURI* aURI, PRBool aReport)
|
||||
{
|
||||
if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
|
||||
if (aReport) {
|
||||
nsScriptSecurityManager::ReportError(
|
||||
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
|
||||
{
|
||||
|
@ -98,6 +98,7 @@ nsIIOService *nsScriptSecurityManager::sIOService = nsnull;
|
||||
nsIXPConnect *nsScriptSecurityManager::sXPConnect = nsnull;
|
||||
nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
|
||||
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
|
||||
PRInt32 nsScriptSecurityManager::sFileURIOriginPolicy = FILEURI_SOP_SELF;
|
||||
|
||||
// Info we need about the JSClasses used by XPConnects wrapped
|
||||
// natives, to avoid having to QI to nsIXPConnectWrappedNative all the
|
||||
@ -277,6 +278,7 @@ nsScriptSecurityManager::GetSafeJSContext()
|
||||
return cx;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PRBool
|
||||
nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI)
|
||||
@ -378,7 +380,7 @@ nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
nsIURI* aTargetURI)
|
||||
{
|
||||
// in traditional unsafe behavior all files are the same origin
|
||||
if (mFileURIOriginPolicy == FILEURI_SOP_TRADITIONAL)
|
||||
if (sFileURIOriginPolicy == FILEURI_SOP_TRADITIONAL)
|
||||
return PR_TRUE;
|
||||
|
||||
|
||||
@ -387,7 +389,7 @@ nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
PRBool filesAreEqual = PR_FALSE;
|
||||
if (NS_FAILED( aSourceURI->Equals(aTargetURI, &filesAreEqual) ))
|
||||
return PR_FALSE;
|
||||
if (filesAreEqual || mFileURIOriginPolicy == FILEURI_SOP_SELF)
|
||||
if (filesAreEqual || sFileURIOriginPolicy == FILEURI_SOP_SELF)
|
||||
return filesAreEqual;
|
||||
|
||||
|
||||
@ -406,7 +408,7 @@ nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
|
||||
|
||||
// For policy ANYFILE we're done
|
||||
if (mFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
|
||||
if (sFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
|
||||
return PR_TRUE;
|
||||
|
||||
|
||||
@ -425,7 +427,7 @@ nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
}
|
||||
|
||||
// check remaining policies
|
||||
if (mFileURIOriginPolicy == FILEURI_SOP_SAMEDIR)
|
||||
if (sFileURIOriginPolicy == FILEURI_SOP_SAMEDIR)
|
||||
{
|
||||
// file: URIs in the same directory have the same origin
|
||||
PRBool sameParent = PR_FALSE;
|
||||
@ -436,7 +438,7 @@ nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
|
||||
return sameParent;
|
||||
}
|
||||
|
||||
if (mFileURIOriginPolicy == FILEURI_SOP_SUBDIR)
|
||||
if (sFileURIOriginPolicy == FILEURI_SOP_SUBDIR)
|
||||
{
|
||||
// file: URIs can access files in the same or lower directories
|
||||
PRBool isChild = PR_FALSE;
|
||||
@ -3259,11 +3261,10 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
|
||||
mIsJavaScriptEnabled(PR_FALSE),
|
||||
mIsMailJavaScriptEnabled(PR_FALSE),
|
||||
mIsWritingPrefs(PR_FALSE),
|
||||
mPolicyPrefsChanged(PR_TRUE),
|
||||
mPolicyPrefsChanged(PR_TRUE)
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
mXPCDefaultGrantAll(PR_FALSE),
|
||||
, mXPCDefaultGrantAll(PR_FALSE)
|
||||
#endif
|
||||
mFileURIOriginPolicy(FILEURI_SOP_SELF)
|
||||
{
|
||||
NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure.");
|
||||
mPrincipals.Init(31);
|
||||
@ -3877,7 +3878,7 @@ nsScriptSecurityManager::ScriptSecurityPrefChanged()
|
||||
|
||||
PRInt32 policy;
|
||||
rv = mSecurityPref->SecurityGetIntPref(sFileOriginPolicyPrefName, &policy);
|
||||
mFileURIOriginPolicy = NS_SUCCEEDED(rv) ? policy : FILEURI_SOP_SELF;
|
||||
sFileURIOriginPolicy = NS_SUCCEEDED(rv) ? policy : FILEURI_SOP_SELF;
|
||||
|
||||
#ifdef XPC_IDISPATCH_SUPPORT
|
||||
rv = mSecurityPref->SecurityGetBoolPref(sXPCDefaultGrantAllName, &temp);
|
||||
|
@ -115,6 +115,12 @@ nsSystemPrincipal::Subsumes(nsIPrincipal *other, PRBool *result)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::CheckMayLoad(nsIURI* uri, PRBool aReport)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemPrincipal::GetHashValue(PRUint32 *result)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIPrincipal;
|
||||
interface nsIDOMDocument;
|
||||
interface nsIChannel;
|
||||
|
||||
@ -46,10 +47,14 @@ interface nsIChannel;
|
||||
* *
|
||||
* **** NOTICE **** *
|
||||
* *
|
||||
* nsISyncLoadDOMService defines synchronous methods to download *
|
||||
* data from the network. Any delays from the server will *
|
||||
* appear as a hang in the mozilla UI. Therefore, this interface *
|
||||
* should be avoided as much as possible. *
|
||||
* *
|
||||
* This interface is DEPRECATED! *
|
||||
* You should instead use XMLHttpRequest which now works both from *
|
||||
* Javascript and C++. *
|
||||
* *
|
||||
* Additionally, synchronous network loads are evil. Any delays *
|
||||
* from the server will appear as a hang in the mozilla UI. *
|
||||
* Therefore, they should be avoided as much as possible. *
|
||||
* *
|
||||
* Don't make me come over there!! *
|
||||
* *
|
||||
@ -61,33 +66,34 @@ interface nsIChannel;
|
||||
* a document.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(2ae03836-0704-45c9-a545-4169548c0669)]
|
||||
[scriptable, uuid(8095998d-ae1c-4cfa-9b43-0973e5d77eb0)]
|
||||
interface nsISyncLoadDOMService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Synchronously load the document from the specified channel.
|
||||
*
|
||||
* @param aChannel The channel to load the document from.
|
||||
* @param aLoaderURI URI of loading document. For security checks
|
||||
* null if no securitychecks should be done
|
||||
* @param aLoaderPrincipal Principal of loading document. For security
|
||||
* checks null if no securitychecks should be done
|
||||
*
|
||||
* @returns The document loaded from the URI.
|
||||
*/
|
||||
nsIDOMDocument loadDocument(in nsIChannel aChannel, in nsIURI aLoaderURI);
|
||||
nsIDOMDocument loadDocument(in nsIChannel aChannel,
|
||||
in nsIPrincipal aLoaderPrincipal);
|
||||
|
||||
nsIDOMDocument loadDocumentAsXML(in nsIChannel aChannel,
|
||||
in nsIURI aLoaderURI);
|
||||
in nsIPrincipal aLoaderPrincipal);
|
||||
|
||||
/**
|
||||
* Synchronously load an XML document from the specified
|
||||
* channel. The channel must be possible to open synchronously.
|
||||
*
|
||||
* @param aChannel The channel to load the document from.
|
||||
* @param aLoaderURI URI of loading document. For security checks
|
||||
* null if no securitychecks should be done
|
||||
* @param aLoaderPrincipal Principal of loading document. For security
|
||||
* checks null if no securitychecks should be done
|
||||
*
|
||||
* @returns The document loaded from the URI.
|
||||
*/
|
||||
nsIDOMDocument loadLocalDocument(in nsIChannel aChannel,
|
||||
in nsIURI aLoaderURI);
|
||||
in nsIPrincipal aLoaderPrincipal);
|
||||
};
|
||||
|
@ -866,8 +866,7 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
|
||||
}
|
||||
|
||||
// Documents must list a manifest from the same origin
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckSameOriginURI(manifestURI, mDocumentURI, PR_TRUE);
|
||||
nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -3834,10 +3834,7 @@ nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> loadingURI;
|
||||
rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad, PR_TRUE);
|
||||
return aLoadingPrincipal->CheckMayLoad(aURIToLoad, PR_TRUE);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -51,18 +51,29 @@
|
||||
#include "nsParserUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsCrossSiteListenerProxy, nsIStreamListener,
|
||||
NS_IMPL_ISUPPORTS7(nsCrossSiteListenerProxy, nsIStreamListener,
|
||||
nsIRequestObserver, nsIContentSink, nsIXMLContentSink,
|
||||
nsIExpatSink)
|
||||
nsIExpatSink, nsIChannelEventSink, nsIInterfaceRequestor)
|
||||
|
||||
nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal)
|
||||
: mOuter(aOuter), mAcceptState(eNotSet), mHasForwardedRequest(PR_FALSE)
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsresult* aResult)
|
||||
: mOuterListener(aOuter),
|
||||
mRequestingPrincipal(aRequestingPrincipal),
|
||||
mAcceptState(eNotSet),
|
||||
mHasForwardedRequest(PR_FALSE),
|
||||
mHasBeenCrossSite(PR_FALSE)
|
||||
{
|
||||
aRequestingPrincipal->GetURI(getter_AddRefs(mRequestingURI));
|
||||
aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
|
||||
aChannel->SetNotificationCallbacks(this);
|
||||
|
||||
*aResult = UpdateChannel(aChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -83,13 +94,14 @@ nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
|
||||
if (mAcceptState != eAccept) {
|
||||
mAcceptState = eDeny;
|
||||
mOuterRequest->Cancel(NS_ERROR_DOM_BAD_URI);
|
||||
mOuter->OnStartRequest(mOuterRequest, mOuterContext);
|
||||
mOuterListener->OnStartRequest(mOuterRequest, mOuterContext);
|
||||
|
||||
// Only call OnStopRequest here if we were called from OnStopRequest.
|
||||
// Otherwise the call to Cancel will make us get an OnStopRequest later
|
||||
// so we'll forward OnStopRequest then.
|
||||
if (aFromStop) {
|
||||
mOuter->OnStopRequest(mOuterRequest, mOuterContext, NS_ERROR_DOM_BAD_URI);
|
||||
mOuterListener->OnStopRequest(mOuterRequest, mOuterContext,
|
||||
NS_ERROR_DOM_BAD_URI);
|
||||
}
|
||||
|
||||
// Clear this data just in case since it should never be forwarded.
|
||||
@ -98,7 +110,7 @@ nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
nsresult rv = mOuter->OnStartRequest(mOuterRequest, mOuterContext);
|
||||
nsresult rv = mOuterListener->OnStartRequest(mOuterRequest, mOuterContext);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mStoredData.IsEmpty()) {
|
||||
@ -106,8 +118,8 @@ nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
|
||||
rv = NS_NewCStringInputStream(getter_AddRefs(stream), mStoredData);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOuter->OnDataAvailable(mOuterRequest, mOuterContext, stream, 0,
|
||||
mStoredData.Length());
|
||||
rv = mOuterListener->OnDataAvailable(mOuterRequest, mOuterContext, stream,
|
||||
0, mStoredData.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -137,9 +149,8 @@ nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
|
||||
}
|
||||
nsCOMPtr<nsIURI> finalURI;
|
||||
channel->GetURI(getter_AddRefs(finalURI));
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckSameOriginURI(mRequestingURI, finalURI, PR_FALSE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
if (!mHasBeenCrossSite) {
|
||||
mAcceptState = eAccept;
|
||||
return ForwardRequest(PR_FALSE);
|
||||
}
|
||||
@ -247,7 +258,7 @@ nsCrossSiteListenerProxy::OnStopRequest(nsIRequest* aRequest,
|
||||
nsresult aStatusCode)
|
||||
{
|
||||
if (mHasForwardedRequest) {
|
||||
return mOuter->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
return mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
}
|
||||
|
||||
mAcceptState = eDeny;
|
||||
@ -281,8 +292,8 @@ nsCrossSiteListenerProxy::OnDataAvailable(nsIRequest* aRequest,
|
||||
if (mAcceptState != eAccept) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
return mOuter->OnDataAvailable(aRequest, aContext, aInputStream, aOffset,
|
||||
aCount);
|
||||
return mOuterListener->OnDataAvailable(aRequest, aContext, aInputStream,
|
||||
aOffset, aCount);
|
||||
}
|
||||
|
||||
NS_ASSERTION(mStoredData.Length() == aOffset,
|
||||
@ -866,37 +877,88 @@ nsCrossSiteListenerProxy::VerifyAndMatchDomainPattern(const nsACString& aPattern
|
||||
(!patternHasWild || reqPos >= 1);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::AddRequestHeaders(nsIChannel* aChannel,
|
||||
nsIPrincipal* aRequestingPrincipal)
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
// Once bug 386823 is fixed this could just be an assertion.
|
||||
NS_ENSURE_TRUE(aRequestingPrincipal, NS_ERROR_FAILURE);
|
||||
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
|
||||
*aResult = static_cast<nsIChannelEventSink*>(this);
|
||||
NS_ADDREF_THIS();
|
||||
|
||||
// Work out the requesting URI
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mOuterNotificationCallbacks ?
|
||||
mOuterNotificationCallbacks->GetInterface(aIID, aResult) :
|
||||
NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCrossSiteListenerProxy::OnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIChannelEventSink> outer =
|
||||
do_GetInterface(mOuterNotificationCallbacks);
|
||||
if (outer) {
|
||||
rv = outer->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return UpdateChannel(aNewChannel);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aRequestingPrincipal->GetURI(getter_AddRefs(uri));
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString scheme, host;
|
||||
rv = uri->GetScheme(scheme);
|
||||
// Check that the uri is ok to load
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(mRequestingPrincipal, uri,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = uri->GetAsciiHost(host);
|
||||
if (!mHasBeenCrossSite &&
|
||||
NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, PR_FALSE))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCString userpass;
|
||||
uri->GetUserPass(userpass);
|
||||
NS_ENSURE_TRUE(userpass.IsEmpty(), NS_ERROR_DOM_BAD_URI);
|
||||
|
||||
// It's a cross site load
|
||||
mHasBeenCrossSite = PR_TRUE;
|
||||
|
||||
// Work out the Referer-Root header
|
||||
nsCString root, host;
|
||||
rv = mRequestingURI->GetAsciiHost(host);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString root = scheme + NS_LITERAL_CSTRING("://") + host;
|
||||
// Append the port
|
||||
PRInt32 port;
|
||||
uri->GetPort(&port);
|
||||
if (port != -1) {
|
||||
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
||||
if (port != defaultPort) {
|
||||
root.Append(":");
|
||||
root.AppendInt(port);
|
||||
if (!host.IsEmpty()) {
|
||||
nsCString scheme;
|
||||
rv = mRequestingURI->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
root = scheme + NS_LITERAL_CSTRING("://") + host;
|
||||
|
||||
// If needed, append the port
|
||||
PRInt32 port;
|
||||
mRequestingURI->GetPort(&port);
|
||||
if (port != -1) {
|
||||
PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
|
||||
if (port != defaultPort) {
|
||||
root.Append(":");
|
||||
root.AppendInt(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
root.AssignLiteral("null");
|
||||
}
|
||||
|
||||
// Now add the access-control-origin header
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "nsIContentSink.h"
|
||||
#include "nsIXMLContentSink.h"
|
||||
#include "nsIExpatSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsIParser;
|
||||
@ -51,19 +53,22 @@ class nsIPrincipal;
|
||||
|
||||
class nsCrossSiteListenerProxy : public nsIStreamListener,
|
||||
public nsIXMLContentSink,
|
||||
public nsIExpatSink
|
||||
public nsIExpatSink,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink
|
||||
{
|
||||
public:
|
||||
nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
|
||||
nsIPrincipal* aRequestingPrincipal);
|
||||
|
||||
nsIPrincipal* aRequestingPrincipal,
|
||||
nsIChannel* aChannel,
|
||||
nsresult* aResult);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIEXPATSINK
|
||||
|
||||
static nsresult AddRequestHeaders(nsIChannel* aChannel,
|
||||
nsIPrincipal* aRequestingPrincipal);
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
// nsIContentSink
|
||||
NS_IMETHOD WillTokenize(void) { return NS_OK; }
|
||||
@ -77,18 +82,21 @@ public:
|
||||
virtual nsISupports *GetTarget() { return nsnull; }
|
||||
|
||||
private:
|
||||
nsresult UpdateChannel(nsIChannel* aChannel);
|
||||
|
||||
nsresult ForwardRequest(PRBool aCallStop);
|
||||
PRBool MatchPatternList(const char*& aIter, const char* aEnd);
|
||||
void CheckHeader(const nsCString& aHeader);
|
||||
PRBool VerifyAndMatchDomainPattern(const nsACString& aDomainPattern);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> mOuter;
|
||||
nsCOMPtr<nsIStreamListener> mOuterListener;
|
||||
nsCOMPtr<nsIRequest> mOuterRequest;
|
||||
nsCOMPtr<nsISupports> mOuterContext;
|
||||
nsCOMPtr<nsIStreamListener> mParserListener;
|
||||
nsCOMPtr<nsIParser> mParser;
|
||||
nsCOMPtr<nsIURI> mRequestingURI;
|
||||
nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
|
||||
nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
|
||||
nsTArray<nsCString> mReqSubdomains;
|
||||
nsCString mStoredData;
|
||||
enum {
|
||||
@ -97,4 +105,5 @@ private:
|
||||
eNotSet
|
||||
} mAcceptState;
|
||||
PRBool mHasForwardedRequest;
|
||||
PRBool mHasBeenCrossSite;
|
||||
};
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsLoadListenerProxy.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsCrossSiteListenerProxy.h"
|
||||
|
||||
/**
|
||||
* This class manages loading a single XML document
|
||||
@ -74,7 +75,7 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsresult LoadDocument(nsIChannel* aChannel, nsIURI *aLoaderURI,
|
||||
nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
|
||||
PRBool aChannelIsSync, PRBool aForceToXML,
|
||||
nsIDOMDocument** aResult);
|
||||
|
||||
@ -162,7 +163,7 @@ NS_IMPL_ISUPPORTS4(nsSyncLoader,
|
||||
|
||||
nsresult
|
||||
nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||
nsIURI *aLoaderURI,
|
||||
nsIPrincipal *aLoaderPrincipal,
|
||||
PRBool aChannelIsSync,
|
||||
PRBool aForceToXML,
|
||||
nsIDOMDocument **aResult)
|
||||
@ -171,32 +172,26 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||
*aResult = nsnull;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIURI> loaderUri;
|
||||
if (aLoaderPrincipal) {
|
||||
aLoaderPrincipal->GetURI(getter_AddRefs(loaderUri));
|
||||
}
|
||||
|
||||
mChannel = aChannel;
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
|
||||
if (http) {
|
||||
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
|
||||
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
|
||||
PR_FALSE);
|
||||
if (aLoaderURI) {
|
||||
http->SetReferrer(aLoaderURI);
|
||||
if (loaderUri) {
|
||||
http->SetReferrer(loaderUri);
|
||||
}
|
||||
}
|
||||
|
||||
if (aLoaderURI) {
|
||||
nsCOMPtr<nsIURI> docURI;
|
||||
rv = aChannel->GetOriginalURI(getter_AddRefs(docURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
rv = securityManager->CheckLoadURI(aLoaderURI, docURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = securityManager->CheckSameOriginURI(aLoaderURI, docURI, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// Hook us up to listen to redirects and the like.
|
||||
// Do this before setting up the cross-site proxy since
|
||||
// that installs its own proxies.
|
||||
mChannel->SetNotificationCallbacks(this);
|
||||
|
||||
// Get the loadgroup of the channel
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
@ -223,6 +218,13 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||
listener.swap(forceListener);
|
||||
}
|
||||
|
||||
if (aLoaderPrincipal) {
|
||||
listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
|
||||
mChannel, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Register as a load listener on the document
|
||||
nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(document);
|
||||
NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
|
||||
@ -270,9 +272,6 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
|
||||
nsresult
|
||||
nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener)
|
||||
{
|
||||
// Hook us up to listen to redirects and the like
|
||||
mChannel->SetNotificationCallbacks(this);
|
||||
|
||||
// Start reading from the channel
|
||||
nsresult rv = mChannel->AsyncOpen(aListener, nsnull);
|
||||
|
||||
@ -367,20 +366,6 @@ nsSyncLoader::OnChannelRedirect(nsIChannel *aOldChannel,
|
||||
{
|
||||
NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
nsresult rv = aOldChannel->GetURI(getter_AddRefs(oldURI)); // The original URI
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = aNewChannel->GetURI(getter_AddRefs(newURI)); // The new URI
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
rv = securityManager->CheckSameOriginURI(oldURI, newURI, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mChannel = aNewChannel;
|
||||
|
||||
return NS_OK;
|
||||
@ -397,42 +382,49 @@ NS_IMPL_ISUPPORTS1(nsSyncLoadService,
|
||||
nsISyncLoadDOMService)
|
||||
|
||||
static nsresult
|
||||
LoadFromChannel(nsIChannel* aChannel, nsIURI *aLoaderURI, PRBool aChannelIsSync,
|
||||
PRBool aForceToXML, nsIDOMDocument** aResult)
|
||||
LoadFromChannel(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
|
||||
PRBool aChannelIsSync, PRBool aForceToXML,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
nsRefPtr<nsSyncLoader> loader = new nsSyncLoader();
|
||||
if (!loader) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return loader->LoadDocument(aChannel, aLoaderURI, aChannelIsSync,
|
||||
return loader->LoadDocument(aChannel, aLoaderPrincipal, aChannelIsSync,
|
||||
aForceToXML, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncLoadService::LoadDocument(nsIChannel* aChannel, nsIURI* aLoaderURI,
|
||||
nsSyncLoadService::LoadDocument(nsIChannel* aChannel,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
return LoadFromChannel(aChannel, aLoaderURI, PR_FALSE, PR_FALSE, aResult);
|
||||
return LoadFromChannel(aChannel, aLoaderPrincipal, PR_FALSE, PR_FALSE,
|
||||
aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncLoadService::LoadDocumentAsXML(nsIChannel* aChannel, nsIURI* aLoaderURI,
|
||||
nsSyncLoadService::LoadDocumentAsXML(nsIChannel* aChannel,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
return LoadFromChannel(aChannel, aLoaderURI, PR_FALSE, PR_TRUE, aResult);
|
||||
return LoadFromChannel(aChannel, aLoaderPrincipal, PR_FALSE, PR_TRUE,
|
||||
aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSyncLoadService::LoadLocalDocument(nsIChannel* aChannel, nsIURI* aLoaderURI,
|
||||
nsSyncLoadService::LoadLocalDocument(nsIChannel* aChannel,
|
||||
nsIPrincipal* aLoaderPrincipal,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
return LoadFromChannel(aChannel, aLoaderURI, PR_TRUE, PR_TRUE, aResult);
|
||||
return LoadFromChannel(aChannel, aLoaderPrincipal, PR_TRUE, PR_TRUE,
|
||||
aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIURI *aLoaderURI,
|
||||
nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
||||
nsILoadGroup *aLoadGroup, PRBool aForceToXML,
|
||||
nsIDOMDocument** aResult)
|
||||
{
|
||||
@ -451,7 +443,8 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIURI *aLoaderURI,
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
|
||||
isResource);
|
||||
|
||||
return LoadFromChannel(channel, aLoaderURI, isSync, aForceToXML, aResult);
|
||||
return LoadFromChannel(channel, aLoaderPrincipal, isSync, aForceToXML,
|
||||
aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
@ -60,15 +60,15 @@ public:
|
||||
* Synchronously load the document from the specified URI.
|
||||
*
|
||||
* @param aURI URI to load the document from.
|
||||
* @param aLoaderURI URI of loading document. For security checks and
|
||||
* referrer header. May be null if no security checks
|
||||
* should be done.
|
||||
* @param aLoaderPrincipal Principal of loading document. For security
|
||||
* checks and referrer header. May be null if no
|
||||
* security checks should be done.
|
||||
* @param aLoadGroup The loadgroup to use for loading the document.
|
||||
* @param aForceToXML Whether to parse the document as XML, regardless of
|
||||
* content type.
|
||||
* @param aResult [out] The document loaded from the URI.
|
||||
*/
|
||||
static nsresult LoadDocument(nsIURI *aURI, nsIURI *aLoaderURI,
|
||||
static nsresult LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
|
||||
nsILoadGroup *aLoadGroup, PRBool aForceToXML,
|
||||
nsIDOMDocument** aResult);
|
||||
|
||||
|
@ -1416,7 +1416,7 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest()
|
||||
// The request is now cross-site, so update flag.
|
||||
mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
|
||||
|
||||
// Remove dangerous headers and set XMLHttpRequest-Security-Check
|
||||
// Remove dangerous headers
|
||||
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
|
||||
if (http) {
|
||||
PRUint32 i;
|
||||
@ -1426,17 +1426,7 @@ nsXMLHttpRequest::CheckChannelForCrossSiteRequest()
|
||||
mExtraRequestHeaders.Clear();
|
||||
}
|
||||
|
||||
// Cancel if username/password is supplied to avoid brute-force password
|
||||
// hacking
|
||||
nsCOMPtr<nsIURI> channelURI;
|
||||
nsresult rv = mChannel->GetURI(getter_AddRefs(channelURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString userpass;
|
||||
channelURI->GetUserPass(userpass);
|
||||
NS_ENSURE_TRUE(userpass.IsEmpty(), NS_ERROR_DOM_BAD_URI);
|
||||
|
||||
return nsCrossSiteListenerProxy::AddRequestHeaders(mChannel, mPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* noscript void openRequest (in AUTF8String method, in AUTF8String url, in boolean async, in AString user, in AString password); */
|
||||
@ -1590,8 +1580,6 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method,
|
||||
nsnull, loadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsCrossSiteListenerProxy::AddRequestHeaders(mACGetChannel, mPrincipal);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> acHttp = do_QueryInterface(mACGetChannel);
|
||||
NS_ASSERTION(acHttp, "Failed to QI to nsIHttpChannel!");
|
||||
|
||||
@ -2290,8 +2278,10 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
if (!(mState & XML_HTTP_REQUEST_XSITEENABLED)) {
|
||||
// Always create a nsCrossSiteListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal);
|
||||
listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
|
||||
&rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Bypass the network cache in cases where it makes no sense:
|
||||
@ -2328,8 +2318,10 @@ nsXMLHttpRequest::Send(nsIVariant *aBody)
|
||||
new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method);
|
||||
NS_ENSURE_TRUE(acListener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
listener = new nsCrossSiteListenerProxy(acListener, mPrincipal);
|
||||
listener = new nsCrossSiteListenerProxy(acListener, mPrincipal,
|
||||
mACGetChannel, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mACGetChannel->AsyncOpen(listener, nsnull);
|
||||
}
|
||||
|
@ -771,9 +771,6 @@ nsXMLContentSink::ProcessStyleLink(nsIContent* aElement,
|
||||
nsIScriptSecurityManager::ALLOW_CHROME);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
rv = secMan->CheckSameOriginURI(mDocumentURI, url, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
// Do content policy check
|
||||
PRInt16 decision = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
|
@ -378,6 +378,9 @@ nsXMLDocument::Load(const nsAString& aUrl, PRBool *aReturn)
|
||||
// changing the principal of this document.
|
||||
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -100,18 +100,15 @@ txParseDocumentFromURI(const nsAString& aHref, const txXPathNode& aLoader,
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = loaderDocument->GetDocumentLoadGroup();
|
||||
|
||||
nsCOMPtr<nsIURI> loaderUri;
|
||||
rv = loaderDocument->NodePrincipal()->GetURI(getter_AddRefs(loaderUri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// For the system principal loaderUri will be null here, which is good
|
||||
// since that means that chrome documents can load any uri.
|
||||
|
||||
// Raw pointer, we want the resulting txXPathNode to hold a reference to
|
||||
// the document.
|
||||
nsIDOMDocument* theDocument = nsnull;
|
||||
rv = nsSyncLoadService::LoadDocument(documentURI, loaderUri, loadGroup,
|
||||
PR_TRUE, &theDocument);
|
||||
rv = nsSyncLoadService::LoadDocument(documentURI,
|
||||
loaderDocument->NodePrincipal(),
|
||||
loadGroup, PR_TRUE, &theDocument);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aErrMsg.Append(NS_LITERAL_STRING("Document load of ") +
|
||||
|
@ -70,6 +70,8 @@
|
||||
#include "nsAttrName.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsCrossSiteListenerProxy.h"
|
||||
#include "nsDOMError.h"
|
||||
|
||||
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
|
||||
|
||||
@ -94,7 +96,6 @@ getSpec(nsIChannel* aChannel, nsAString& aSpec)
|
||||
class txStylesheetSink : public nsIXMLContentSink,
|
||||
public nsIExpatSink,
|
||||
public nsIStreamListener,
|
||||
public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
@ -104,7 +105,6 @@ public:
|
||||
NS_DECL_NSIEXPATSINK
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
// nsIContentSink
|
||||
@ -136,13 +136,12 @@ txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler,
|
||||
mListener = do_QueryInterface(aParser);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS7(txStylesheetSink,
|
||||
NS_IMPL_ISUPPORTS6(txStylesheetSink,
|
||||
nsIXMLContentSink,
|
||||
nsIContentSink,
|
||||
nsIExpatSink,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIChannelEventSink,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -374,29 +373,6 @@ txStylesheetSink::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
txStylesheetSink::OnChannelRedirect(nsIChannel *aOldChannel,
|
||||
nsIChannel *aNewChannel,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
rv = aOldChannel->GetURI(getter_AddRefs(oldURI)); // The original URI
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
rv = aNewChannel->GetURI(getter_AddRefs(newURI)); // The new URI
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return secMan->CheckSameOriginURI(oldURI, newURI, PR_TRUE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
txStylesheetSink::GetInterface(const nsIID& aIID, void** aResult)
|
||||
{
|
||||
@ -420,7 +396,7 @@ txStylesheetSink::GetInterface(const nsIID& aIID, void** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return QueryInterface(aIID, aResult);
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
class txCompileObserver : public txACompileObserver
|
||||
@ -493,13 +469,19 @@ txCompileObserver::loadURI(const nsAString& aUri,
|
||||
GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Do security check.
|
||||
rv = nsContentUtils::
|
||||
CheckSecurityBeforeLoad(uri, referrerPrincipal,
|
||||
nsIScriptSecurityManager::STANDARD, PR_FALSE,
|
||||
nsIContentPolicy::TYPE_STYLESHEET,
|
||||
nsnull, NS_LITERAL_CSTRING("application/xml"));
|
||||
// Content Policy
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
uri,
|
||||
referrerPrincipal,
|
||||
nsnull,
|
||||
NS_LITERAL_CSTRING("application/xml"),
|
||||
nsnull,
|
||||
&shouldLoad);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
return startLoad(uri, aCompiler, referrerPrincipal);
|
||||
}
|
||||
@ -555,6 +537,12 @@ txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
|
||||
parser->SetContentSink(sink);
|
||||
parser->Parse(aUri);
|
||||
|
||||
// Always install in case of redirects
|
||||
nsCOMPtr<nsIStreamListener> listener =
|
||||
new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel, &rv);
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return channel->AsyncOpen(sink, parser);
|
||||
}
|
||||
|
||||
@ -566,14 +554,20 @@ TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
|
||||
aUri->GetSpec(spec);
|
||||
PR_LOG(txLog::xslt, PR_LOG_ALWAYS, ("TX_LoadSheet: %s\n", spec.get()));
|
||||
|
||||
// Pass source document as the context
|
||||
nsresult rv = nsContentUtils::
|
||||
CheckSecurityBeforeLoad(aUri, aCallerPrincipal,
|
||||
nsIScriptSecurityManager::STANDARD, PR_FALSE,
|
||||
nsIContentPolicy::TYPE_STYLESHEET,
|
||||
aProcessor->GetSourceContentModel(),
|
||||
NS_LITERAL_CSTRING("application/xml"));
|
||||
// Content Policy
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv =
|
||||
NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
aUri,
|
||||
aCallerPrincipal,
|
||||
aProcessor->GetSourceContentModel(),
|
||||
NS_LITERAL_CSTRING("application/xml"),
|
||||
nsnull,
|
||||
&shouldLoad);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
nsRefPtr<txCompileObserver> observer =
|
||||
new txCompileObserver(aProcessor, aLoadGroup);
|
||||
@ -715,18 +709,25 @@ txSyncCompileObserver::loadURI(const nsAString& aUri,
|
||||
GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = nsContentUtils::
|
||||
CheckSecurityBeforeLoad(uri, referrerPrincipal,
|
||||
nsIScriptSecurityManager::STANDARD,
|
||||
PR_FALSE, nsIContentPolicy::TYPE_STYLESHEET,
|
||||
nsnull, NS_LITERAL_CSTRING("application/xml"));
|
||||
// Content Policy
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
|
||||
uri,
|
||||
referrerPrincipal,
|
||||
nsnull,
|
||||
NS_LITERAL_CSTRING("application/xml"),
|
||||
nsnull,
|
||||
&shouldLoad);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_DOM_BAD_URI;
|
||||
}
|
||||
|
||||
// This is probably called by js, a loadGroup for the channel doesn't
|
||||
// make sense.
|
||||
nsCOMPtr<nsIDOMDocument> document;
|
||||
rv = nsSyncLoadService::LoadDocument(uri, referrerUri, nsnull, PR_FALSE,
|
||||
getter_AddRefs(document));
|
||||
rv = nsSyncLoadService::LoadDocument(uri, referrerPrincipal, nsnull,
|
||||
PR_FALSE, getter_AddRefs(document));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
|
||||
|
@ -2605,16 +2605,13 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, PRBool aIsDynamic,
|
||||
if (aIsDynamic)
|
||||
mResolutionPhase = nsForwardReference::eStart;
|
||||
|
||||
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
|
||||
NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// Chrome documents are allowed to load overlays from anywhere.
|
||||
// In all other cases, the overlay is only allowed to load if
|
||||
// the master document and prototype document have the same origin.
|
||||
|
||||
if (!IsChromeURI(mDocumentURI)) {
|
||||
// Make sure we're allowed to load this overlay.
|
||||
rv = secMan->CheckSameOriginURI(mDocumentURI, aURI, PR_TRUE);
|
||||
rv = NodePrincipal()->CheckMayLoad(aURI, PR_TRUE);
|
||||
if (NS_FAILED(rv)) {
|
||||
*aFailureFromContent = PR_TRUE;
|
||||
return rv;
|
||||
|
@ -23,12 +23,11 @@ var x = new XMLHttpRequest();
|
||||
x.open("GET", document.location.href);
|
||||
x.send("");
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(x.channel.notificationCallbacks instanceof
|
||||
Components.interfaces.nsIInterfaceRequestor,
|
||||
is(x instanceof Components.interfaces.nsIInterfaceRequestor,
|
||||
true, "Must be interface requestor");
|
||||
|
||||
var count = {};
|
||||
var interfaces = x.channel.notificationCallbacks.
|
||||
var interfaces = x.
|
||||
QueryInterface(Components.interfaces.nsIClassInfo).
|
||||
getInterfaces(count).
|
||||
map(function(id) {
|
||||
|
@ -713,30 +713,16 @@ nsCanvasRenderingContextGLPrivate::DoDrawImageSecurityCheck(nsIURI* aURI, PRBool
|
||||
}
|
||||
|
||||
fprintf (stderr, "DoDrawImageSecuritycheck this 4: %p\n", this);
|
||||
nsCOMPtr<nsIScriptSecurityManager> ssm =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
|
||||
if (!ssm) {
|
||||
mCanvasElement->SetWriteOnly();
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (stderr, "DoDrawImageSecuritycheck this 5: %p\n", this);
|
||||
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
|
||||
if (elem && ssm) {
|
||||
nsCOMPtr<nsIPrincipal> uriPrincipal;
|
||||
ssm->GetCodebasePrincipal(aURI, getter_AddRefs(uriPrincipal));
|
||||
|
||||
if (uriPrincipal) {
|
||||
nsresult rv = ssm->CheckSameOriginPrincipal(elem->NodePrincipal(),
|
||||
uriPrincipal);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Same origin
|
||||
return;
|
||||
}
|
||||
if (elem) {
|
||||
rv = elem->NodePrincipal()->CheckMayLoad(aURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Same origin
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (stderr, "DoDrawImageSecuritycheck this 6: %p\n", this); fflush(stderr);
|
||||
fprintf (stderr, "DoDrawImageSecuritycheck this 5: %p\n", this); fflush(stderr);
|
||||
mCanvasElement->SetWriteOnly();
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user