--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -46,17 +46,17 @@ struct JSContext;
struct JSPrincipals;
%}
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
{
/**
* Values of capabilities for each principal. Order is
* significant: if an operation is performed on a set
* of capabilities, the minimum is computed.
*/
const short ENABLE_DENIED = 1;
@@ -199,16 +199,39 @@ interface nsIPrincipal : nsISerializable
* Note for the future: Perhaps we should consider a certificate principal
* for a given URI subsuming a codebase principal for the same URI? Not
* sure what the immediate benefit would be, but I think the setup could
* make some code (e.g. MaybeDowngradeToCodebase) clearer.
*/
[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
* mean much to a typical user on its own (e.g. it may have a number of
* different names all concatenated together with some information on what
* they mean in between).
*
* Throws if there is no certificate associated with this principal.
*/
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -390,16 +390,28 @@ public:
static nsSystemPrincipal*
SystemPrincipalSingletonConstructor();
JSContext* GetCurrentJSContext();
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
nsScriptSecurityManager();
virtual ~nsScriptSecurityManager();
static JSBool JS_DLL_CALLBACK
CheckObjectAccess(JSContext *cx, JSObject *obj,
@@ -415,20 +427,16 @@ private:
#endif
);
// Returns null if a principal cannot be found. Note that rv can be NS_OK
// when this happens -- this means that there was no JS running.
nsIPrincipal*
doGetSubjectPrincipal(nsresult* rv);
- static nsresult
- ReportError(JSContext* cx, const nsAString& messageTag,
- nsIURI* aSource, nsIURI* aTarget);
-
nsresult
CheckPropertyAccessImpl(PRUint32 aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
nsISupports* aObj, nsIURI* aTargetURI,
nsIClassInfo* aClassInfo,
const char* aClassName, jsval aProperty,
void** aCachedClassPolicy);
@@ -535,26 +543,19 @@ private:
InitDomainPolicy(JSContext* cx, const char* aPolicyName,
DomainPolicy* aDomainPolicy);
nsresult
InitPrincipals(PRUint32 prefCount, const char** prefNames,
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
// referenced so this should be fine.
nsresult
CheckComponentPermissions(JSContext *cx, const nsCID &aCID);
#endif
#ifdef DEBUG_CAPS_HACKER
@@ -585,17 +586,18 @@ private:
PRPackedBool mIsJavaScriptEnabled;
PRPackedBool mIsMailJavaScriptEnabled;
PRPackedBool mIsWritingPrefs;
PRPackedBool mPolicyPrefsChanged;
#ifdef XPC_IDISPATCH_SUPPORT
PRPackedBool mXPCDefaultGrantAll;
static const char sXPCDefaultGrantAllName[];
#endif
- PRInt32 mFileURIOriginPolicy;
+
+ static PRInt32 sFileURIOriginPolicy;
static nsIIOService *sIOService;
static nsIXPConnect *sXPConnect;
static nsIStringBundle *sStrBundle;
static JSRuntime *sRuntime;
};
// Levels for file: URI same-origin policy:
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -44,16 +44,18 @@
#include "nsNullPrincipal.h"
#include "nsMemory.h"
#include "nsIUUIDGenerator.h"
#include "nsID.h"
#include "nsNetUtil.h"
#include "nsIClassInfoImpl.h"
#include "nsNetCID.h"
+#include "nsDOMError.h"
+#include "nsScriptSecurityManager.h"
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
nsIPrincipal,
nsISerializable)
NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
nsIPrincipal,
@@ -311,16 +313,27 @@ nsNullPrincipal::Subsumes(nsIPrincipal *
{
// We don't subsume anything except ourselves. Note that nsPrincipal::Equals
// will return false for us, since we're not about:blank and not Equals to
// reasonable nsPrincipals.
*aResult = (aOther == this);
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)
{
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsNullPrincipal::GetCertificate(nsISupports** aCertificate)
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -49,16 +49,17 @@
#include "nsJSPrincipals.h"
#include "nsVoidArray.h"
#include "nsHashtable.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"
#include "nsIClassInfoImpl.h"
+#include "nsDOMError.h"
#include "nsPrincipal.h"
static PRBool URIIsImmutable(nsIURI* aURI)
{
nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
PRBool isMutable;
return
@@ -302,16 +303,31 @@ nsPrincipal::Equals(nsIPrincipal *aOther
NS_IMETHODIMP
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)
{
// If this principal is marked invalid, can't enable any capabilities
if (mCapabilities) {
nsCStringKey invalidKey(sInvalid);
if (mCapabilities->Exists(&invalidKey)) {
*result = nsIPrincipal::ENABLE_DENIED;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -93,16 +93,17 @@
#include "nsCDefaultURIFixup.h"
static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
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
// time when doing security checks.
static const JSClass *sXPCWrappedNativeJSClass;
static JSGetObjectOps sXPCWrappedNativeGetObjOps1;
static JSGetObjectOps sXPCWrappedNativeGetObjOps2;
@@ -272,16 +273,17 @@ nsScriptSecurityManager::GetSafeJSContex
}
JSContext *cx;
if (NS_FAILED(mJSContextStack->GetSafeJSContext(&cx)))
return nsnull;
return cx;
}
+/* static */
PRBool
nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
nsIURI* aTargetURI)
{
// Note that this is not an Equals() test on purpose -- for URIs that don't
// support host/port, we want equality to basically be object identity, for
// security purposes. Otherwise, for example, two javascript: URIs that
// are otherwise unrelated could end up "same origin", which would be
@@ -373,26 +375,26 @@ nsScriptSecurityManager::SecurityCompare
}
// helper function for SecurityCompareURIs
PRBool
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;
// Check simplest and default FILEURI_SOP_SELF case first:
// If they're equal or if the policy says they must be, we're done
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;
// disallow access to directory listings (bug 209234)
PRBool targetIsDir = PR_TRUE;
nsCOMPtr<nsIFile> targetFile;
nsCOMPtr<nsIFileURL> targetFileURL( do_QueryInterface(aTargetURI) );
@@ -401,17 +403,17 @@ nsScriptSecurityManager::SecurityCompare
NS_FAILED( targetFile->IsDirectory(&targetIsDir) ) ||
targetIsDir)
{
return PR_FALSE;
}
// For policy ANYFILE we're done
- if (mFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
+ if (sFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
return PR_TRUE;
// source parent directory is needed for remaining policies
nsCOMPtr<nsIFile> sourceFile;
nsCOMPtr<nsIFile> sourceParent;
nsCOMPtr<nsIFileURL> sourceFileURL( do_QueryInterface(aSourceURI) );
@@ -420,28 +422,28 @@ nsScriptSecurityManager::SecurityCompare
NS_FAILED( sourceFile->GetParent(getter_AddRefs(sourceParent)) ) ||
!sourceParent)
{
// unexpected error
return PR_FALSE;
}
// 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;
nsCOMPtr<nsIFile> targetParent;
if (NS_FAILED( targetFile->GetParent(getter_AddRefs(targetParent)) ) ||
NS_FAILED( sourceParent->Equals(targetParent, &sameParent) ))
return PR_FALSE;
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;
if (NS_FAILED( sourceParent->Contains(targetFile, PR_TRUE, &isChild) ))
return PR_FALSE;
return isChild;
}
@@ -3254,21 +3256,20 @@ nsScriptSecurityManager::Observe(nsISupp
/////////////////////////////////////////////
nsScriptSecurityManager::nsScriptSecurityManager(void)
: mOriginToPolicyMap(nsnull),
mDefaultPolicy(nsnull),
mCapabilities(nsnull),
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);
}
nsresult nsScriptSecurityManager::Init()
{
@@ -3872,17 +3873,17 @@ nsScriptSecurityManager::ScriptSecurityP
mIsJavaScriptEnabled = NS_FAILED(rv) || temp;
rv = mSecurityPref->SecurityGetBoolPref(sJSMailEnabledPrefName, &temp);
// JavaScript in Mail defaults to disabled in failure cases.
mIsMailJavaScriptEnabled = NS_SUCCEEDED(rv) && temp;
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);
// Granting XPC Priveleges defaults to disabled in failure cases.
mXPCDefaultGrantAll = NS_SUCCEEDED(rv) && temp;
#endif
}
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -111,16 +111,22 @@ nsSystemPrincipal::Equals(nsIPrincipal *
NS_IMETHODIMP
nsSystemPrincipal::Subsumes(nsIPrincipal *other, PRBool *result)
{
*result = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
+nsSystemPrincipal::CheckMayLoad(nsIURI* uri, PRBool aReport)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
nsSystemPrincipal::GetHashValue(PRUint32 *result)
{
*result = NS_PTR_TO_INT32(this);
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::CanEnableCapability(const char *capability,
--- a/content/base/public/nsISyncLoadDOMService.idl
+++ b/content/base/public/nsISyncLoadDOMService.idl
@@ -34,60 +34,66 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIURI;
+interface nsIPrincipal;
interface nsIDOMDocument;
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!! *
* *
* *
************************************************************************/
/**
* The nsISyncDOMLoadService interface can be used to synchronously load
* 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);
};
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -861,18 +861,17 @@ nsContentSink::ProcessOfflineManifest(ns
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
manifestSpec, mDocument,
mDocumentURI);
if (!manifestURI) {
return;
}
// 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;
}
// Start the update
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3829,20 +3829,17 @@ nsContentUtils::CheckSecurityBeforeLoad(
// Same Origin
if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
SchemeIs(aURIToLoad, "chrome"))) {
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 */
void
nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
nsIURI *aLinkURI, const nsString &aTargetSpec,
PRBool aClick, PRBool aIsUserTriggered)
{
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -46,28 +46,39 @@
#include "nsParserCIID.h"
#include "nsICharsetAlias.h"
#include "nsMimeTypes.h"
#include "nsIStreamConverterService.h"
#include "nsStringStream.h"
#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
nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
{
if (mHasForwardedRequest) {
return NS_OK;
}
@@ -78,41 +89,42 @@ nsCrossSiteListenerProxy::ForwardRequest
mParser->Terminate();
mParser = nsnull;
mParserListener = nsnull;
}
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.
mStoredData.Truncate();
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()) {
nsCOMPtr<nsIInputStream> stream;
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);
}
return NS_OK;
}
NS_IMETHODIMP
nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
@@ -132,19 +144,18 @@ nsCrossSiteListenerProxy::OnStartRequest
// Check if this was actually a cross domain request
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
if (!channel) {
return NS_ERROR_DOM_BAD_URI;
}
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);
}
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel);
if (http) {
PRBool succeeded;
rv = http->GetRequestSucceeded(&succeeded);
@@ -242,17 +253,17 @@ nsCrossSiteListenerProxy::OnStartRequest
}
NS_IMETHODIMP
nsCrossSiteListenerProxy::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aStatusCode)
{
if (mHasForwardedRequest) {
- return mOuter->OnStopRequest(aRequest, aContext, aStatusCode);
+ return mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
}
mAcceptState = eDeny;
return ForwardRequest(PR_TRUE);
}
NS_METHOD
StringSegmentWriter(nsIInputStream *aInStream,
@@ -276,18 +287,18 @@ nsCrossSiteListenerProxy::OnDataAvailabl
nsIInputStream* aInputStream,
PRUint32 aOffset,
PRUint32 aCount)
{
if (mHasForwardedRequest) {
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,
"Stored wrong amount of data");
PRUint32 read;
nsresult rv = aInputStream->ReadSegments(StringSegmentWriter, &mStoredData,
aCount, &read);
@@ -861,47 +872,98 @@ nsCrossSiteListenerProxy::VerifyAndMatch
// Only matches if we've matched all of pattern and, if there is a wildcard, there
// is at least one more entry in mReqSubdomains.
return patternPos == 0 &&
(!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();
+
+ return NS_OK;
+ }
+
+ return mOuterNotificationCallbacks ?
+ mOuterNotificationCallbacks->GetInterface(aIID, aResult) :
+ NS_ERROR_NO_INTERFACE;
+}
- // Work out the requesting URI
+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);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = uri->GetAsciiHost(host);
+ // Check that the uri is ok to load
+ rv = nsContentUtils::GetSecurityManager()->
+ CheckLoadURIWithPrincipal(mRequestingPrincipal, uri,
+ nsIScriptSecurityManager::STANDARD);
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 (!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);
+
+ 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);
NS_ENSURE_TRUE(http, NS_ERROR_FAILURE);
return http->SetRequestHeader(NS_LITERAL_CSTRING("Access-Control-Origin"),
root, PR_FALSE);
}
--- a/content/base/src/nsCrossSiteListenerProxy.h
+++ b/content/base/src/nsCrossSiteListenerProxy.h
@@ -39,62 +39,71 @@
#include "nsIInterfaceRequestor.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIURI.h"
#include "nsTArray.h"
#include "nsIContentSink.h"
#include "nsIXMLContentSink.h"
#include "nsIExpatSink.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIChannelEventSink.h"
class nsIURI;
class nsIParser;
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; }
NS_IMETHOD WillBuildModel(void);
NS_IMETHOD DidBuildModel() { return NS_OK; }
NS_IMETHOD WillInterrupt(void) { return NS_OK; }
NS_IMETHOD WillResume(void) { return NS_OK; }
NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; }
virtual void FlushPendingNotifications(mozFlushType aType) { }
NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; }
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 {
eAccept,
eDeny,
eNotSet
} mAcceptState;
PRBool mHasForwardedRequest;
+ PRBool mHasBeenCrossSite;
};
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -54,32 +54,33 @@
#include "nsIPrivateDOMImplementation.h"
#include "nsIScriptSecurityManager.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
#include "nsAutoPtr.h"
#include "nsLoadListenerProxy.h"
#include "nsStreamUtils.h"
+#include "nsCrossSiteListenerProxy.h"
/**
* This class manages loading a single XML document
*/
class nsSyncLoader : public nsIDOMLoadListener,
public nsIChannelEventSink,
public nsIInterfaceRequestor,
public nsSupportsWeakReference
{
public:
virtual ~nsSyncLoader();
NS_DECL_ISUPPORTS
- nsresult LoadDocument(nsIChannel* aChannel, nsIURI *aLoaderURI,
+ nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
PRBool aChannelIsSync, PRBool aForceToXML,
nsIDOMDocument** aResult);
NS_DECL_NSIDOMEVENTLISTENER
// nsIDOMLoadListener
NS_IMETHOD Load(nsIDOMEvent* aEvent);
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
@@ -157,51 +158,45 @@ nsSyncLoader::~nsSyncLoader()
NS_IMPL_ISUPPORTS4(nsSyncLoader,
nsIDOMLoadListener,
nsIChannelEventSink,
nsIInterfaceRequestor,
nsISupportsWeakReference)
nsresult
nsSyncLoader::LoadDocument(nsIChannel* aChannel,
- nsIURI *aLoaderURI,
+ nsIPrincipal *aLoaderPrincipal,
PRBool aChannelIsSync,
PRBool aForceToXML,
nsIDOMDocument **aResult)
{
NS_ENSURE_ARG_POINTER(aResult);
*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;
rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(rv, rv);
// Create document
nsCOMPtr<nsIDocument> document;
@@ -218,16 +213,23 @@ nsSyncLoader::LoadDocument(nsIChannel* a
NS_ENSURE_SUCCESS(rv, rv);
if (aForceToXML) {
nsCOMPtr<nsIStreamListener> forceListener =
new nsForceXMLListener(listener);
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);
nsWeakPtr requestWeak = do_GetWeakReference(static_cast<nsIDOMLoadListener*>(this));
nsLoadListenerProxy* proxy = new nsLoadListenerProxy(requestWeak);
NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
@@ -265,19 +267,16 @@ nsSyncLoader::LoadDocument(nsIChannel* a
NS_ENSURE_TRUE(document->GetRootContent(), NS_ERROR_FAILURE);
return CallQueryInterface(document, aResult);
}
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);
if (NS_SUCCEEDED(rv)) {
// process events until we're finished.
mLoading = PR_TRUE;
nsIThread *thread = NS_GetCurrentThread();
while (mLoading && NS_SUCCEEDED(rv)) {
@@ -362,82 +361,75 @@ nsSyncLoader::Error(nsIDOMEvent* aEvent)
NS_IMETHODIMP
nsSyncLoader::OnChannelRedirect(nsIChannel *aOldChannel,
nsIChannel *aNewChannel,
PRUint32 aFlags)
{
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;
}
NS_IMETHODIMP
nsSyncLoader::GetInterface(const nsIID & aIID,
void **aResult)
{
return QueryInterface(aIID, aResult);
}
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)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv = NS_NewChannel(getter_AddRefs(channel), aURI, nsnull,
aLoadGroup);
NS_ENSURE_SUCCESS(rv, rv);
@@ -446,17 +438,18 @@ nsSyncLoadService::LoadDocument(nsIURI *
}
PRBool isChrome = PR_FALSE, isResource = PR_FALSE;
PRBool isSync = (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
isChrome) ||
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
isResource);
- return LoadFromChannel(channel, aLoaderURI, isSync, aForceToXML, aResult);
+ return LoadFromChannel(channel, aLoaderPrincipal, isSync, aForceToXML,
+ aResult);
}
/* static */
nsresult
nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
nsIStreamListener* aListener,
nsIChannel* aChannel)
{
--- a/content/base/src/nsSyncLoadService.h
+++ b/content/base/src/nsSyncLoadService.h
@@ -55,25 +55,25 @@ class nsSyncLoadService : public nsISync
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISYNCLOADDOMSERVICE
/**
* 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);
/**
* Read input stream aIn in chunks and deliver synchronously to aListener.
*
* @param aIn The stream to be read.
* @param aListener The listener that will receive
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1411,37 +1411,27 @@ nsXMLHttpRequest::CheckChannelForCrossSi
return NS_OK;
}
// This is a cross-site request
// 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;
for (i = 0; i < mExtraRequestHeaders.Length(); ++i) {
http->SetRequestHeader(mExtraRequestHeaders[i], EmptyCString(), PR_FALSE);
}
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); */
NS_IMETHODIMP
nsXMLHttpRequest::OpenRequest(const nsACString& method,
const nsACString& url,
PRBool async,
const nsAString& user,
@@ -1585,18 +1575,16 @@ nsXMLHttpRequest::OpenRequest(const nsAC
if (expiration <= PR_Now()) {
// Either it wasn't cached or the cached result has expired. Build a
// channel for the OPTIONS request.
rv = NS_NewChannel(getter_AddRefs(mACGetChannel), uri, nsnull, loadGroup,
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!");
rv = acHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
NS_ENSURE_SUCCESS(rv, rv);
}
}
@@ -2285,18 +2273,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
if (!listener) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
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:
// 1) Multipart responses are very large and would likely be doomed by the
// cache once they grow too large, so they are not worth caching.
// 2) POST responses are always unique, and we provide no API that would
// allow our consumers to specify a "cache key" to access old POST
// responses, so they are not worth caching.
@@ -2323,18 +2313,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
// If we're doing a cross-site non-GET request we need to first do
// a GET request to the same URI. Set that up if needed
if (mACGetChannel) {
nsCOMPtr<nsIStreamListener> acListener =
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);
}
else {
// Start reading from the channel
rv = mChannel->AsyncOpen(listener, nsnull);
}
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -766,19 +766,16 @@ nsXMLContentSink::ProcessStyleLink(nsICo
// Do security check
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
rv = secMan->
CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
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,
url,
mDocument->NodePrincipal(),
aElement,
type,
nsnull,
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -373,16 +373,19 @@ nsXMLDocument::Load(const nsAString& aUr
// 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();
+ // 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;
}
} else {
// We're called from chrome, check to make sure the URI we're
--- a/content/xslt/src/xml/txXMLParser.cpp
+++ b/content/xslt/src/xml/txXMLParser.cpp
@@ -95,28 +95,25 @@ txParseDocumentFromURI(const nsAString&
nsCOMPtr<nsIURI> documentURI;
nsresult rv = NS_NewURI(getter_AddRefs(documentURI), aHref);
NS_ENSURE_SUCCESS(rv, rv);
nsIDocument* loaderDocument = txXPathNativeNode::getDocument(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 ") +
aHref + NS_LITERAL_STRING(" failed."));
return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
}
*aResult = txXPathNativeNode::createXPathNode(theDocument);
--- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
+++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
@@ -65,16 +65,18 @@
#include "txAtoms.h"
#include "txLog.h"
#include "txMozillaXSLTProcessor.h"
#include "txStylesheetCompiler.h"
#include "txXMLUtils.h"
#include "nsAttrName.h"
#include "nsIScriptError.h"
#include "nsIURL.h"
+#include "nsCrossSiteListenerProxy.h"
+#include "nsDOMError.h"
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
static void
getSpec(nsIChannel* aChannel, nsAString& aSpec)
{
if (!aChannel) {
return;
@@ -89,27 +91,25 @@ getSpec(nsIChannel* aChannel, nsAString&
nsCAutoString spec;
uri->GetSpec(spec);
AppendUTF8toUTF16(spec, aSpec);
}
class txStylesheetSink : public nsIXMLContentSink,
public nsIExpatSink,
public nsIStreamListener,
- public nsIChannelEventSink,
public nsIInterfaceRequestor
{
public:
txStylesheetSink(txStylesheetCompiler* aCompiler, nsIParser* aParser);
NS_DECL_ISUPPORTS
NS_DECL_NSIEXPATSINK
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
- NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
// nsIContentSink
NS_IMETHOD WillTokenize(void) { return NS_OK; }
NS_IMETHOD WillBuildModel(void) { return NS_OK; }
NS_IMETHOD DidBuildModel();
NS_IMETHOD WillInterrupt(void) { return NS_OK; }
NS_IMETHOD WillResume(void) { return NS_OK; }
@@ -131,23 +131,22 @@ protected:
txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler,
nsIParser* aParser)
: mCompiler(aCompiler),
mCheckedForXML(PR_FALSE)
{
mListener = do_QueryInterface(aParser);
}
-NS_IMPL_ISUPPORTS7(txStylesheetSink,
+NS_IMPL_ISUPPORTS6(txStylesheetSink,
nsIXMLContentSink,
nsIContentSink,
nsIExpatSink,
nsIStreamListener,
nsIRequestObserver,
- nsIChannelEventSink,
nsIInterfaceRequestor)
NS_IMETHODIMP
txStylesheetSink::HandleStartElement(const PRUnichar *aName,
const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRInt32 aIndex,
PRUint32 aLineNumber)
@@ -370,39 +369,16 @@ txStylesheetSink::OnStopRequest(nsIReque
}
nsresult rv = mListener->OnStopRequest(aRequest, aContext, aStatusCode);
mListener = nsnull;
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)
{
if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
NS_ENSURE_ARG(aResult);
*aResult = nsnull;
nsresult rv;
nsCOMPtr<nsIWindowWatcher> wwatcher =
@@ -415,17 +391,17 @@ txStylesheetSink::GetInterface(const nsI
nsIAuthPrompt* rawPtr = nsnull;
prompt.swap(rawPtr);
*aResult = rawPtr;
return NS_OK;
}
- return QueryInterface(aIID, aResult);
+ return NS_ERROR_NO_INTERFACE;
}
class txCompileObserver : public txACompileObserver
{
public:
txCompileObserver(txMozillaXSLTProcessor* aProcessor,
nsILoadGroup* aLoadGroup);
@@ -488,23 +464,29 @@ txCompileObserver::loadURI(const nsAStri
rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> referrerPrincipal;
rv = nsContentUtils::GetSecurityManager()->
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);
}
void
txCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
nsresult aResult,
const PRUnichar *aErrorText,
@@ -550,35 +532,47 @@ txCompileObserver::startLoad(nsIURI* aUr
NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY);
channel->SetNotificationCallbacks(sink);
parser->SetCommand(kLoadAsData);
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);
}
nsresult
TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
nsILoadGroup* aLoadGroup, nsIPrincipal* aCallerPrincipal)
{
nsCAutoString spec;
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);
NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<txStylesheetCompiler> compiler =
new txStylesheetCompiler(NS_ConvertUTF8toUTF16(spec), observer);
NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
@@ -710,28 +704,35 @@ txSyncCompileObserver::loadURI(const nsA
rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> referrerPrincipal;
rv = nsContentUtils::GetSecurityManager()->
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);
rv = handleNode(doc, aCompiler);
if (NS_FAILED(rv)) {
nsCAutoString spec;
uri->GetSpec(spec);
aCompiler->cancel(rv, nsnull, NS_ConvertUTF8toUTF16(spec).get());
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -2600,26 +2600,23 @@ nsXULDocument::LoadOverlayInternal(nsIUR
PR_LOG(gXULLog, PR_LOG_DEBUG,
("xul: loading overlay %s", urlspec.get()));
}
#endif
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;
}
}
// Look in the prototype cache for the prototype document with
// the specified overlay URI.
--- a/dom/tests/mochitest/bugs/test_bug317448.html
+++ b/dom/tests/mochitest/bugs/test_bug317448.html
@@ -18,22 +18,21 @@ https://bugzilla.mozilla.org/show_bug.cg
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 317448 **/
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) {
return Components.interfacesByID[id].toString();
});
isnot(interfaces.indexOf("nsIInterfaceRequestor"), "-1",
"Must have interface requestor classinfo");
</script>
--- a/extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
+++ b/extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
@@ -708,40 +708,26 @@ nsCanvasRenderingContextGLPrivate::DoDra
fprintf (stderr, "DoDrawImageSecuritycheck this 3: %p\n", this);
if (forceWriteOnly) {
mCanvasElement->SetWriteOnly();
return;
}
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
}
nsCanvasRenderingContextGLPrivate::nsCanvasRenderingContextGLPrivate()
: mGLPbuffer(nsnull), mWidth(0), mHeight(0), mCanvasElement(nsnull)
{