Bug 379959: Add checks to loadBindingDocument. r/sr=jst
git-svn-id: svn://10.0.0.236/trunk@227915 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -1015,6 +1015,39 @@ public:
|
||||
* FALSE.
|
||||
*/
|
||||
static void NotifyInstalledMenuKeyboardListener(PRBool aInstalling);
|
||||
|
||||
/**
|
||||
* Do security checks before loading a resource. Does the following checks:
|
||||
* nsIScriptSecurityManager::CheckLoadURIWithPrincipal
|
||||
* NS_CheckContentLoadPolicy
|
||||
* nsIScriptSecurityManager::CheckSameOriginURI
|
||||
*
|
||||
* You will still need to do at least SameOrigin checks before on redirects.
|
||||
*
|
||||
* @param aURIToLoad URI that is getting loaded.
|
||||
* @param aLoadingPrincipal Principal of the resource that is initiating
|
||||
* the load
|
||||
* @param aCheckLoadFlags Flags to be passed to
|
||||
* nsIScriptSecurityManager::CheckLoadURIWithPrincipal
|
||||
* NOTE: If this contains ALLOW_CHROME the
|
||||
* CheckSameOriginURI check will be skipped if
|
||||
* aURIToLoad is a chrome uri.
|
||||
* @param aAllowData Set to true to skip CheckSameOriginURI check when
|
||||
aURIToLoad is a data uri.
|
||||
* @param aContentPolicyType Type \
|
||||
* @param aContext Context |- to be passed to
|
||||
* @param aMimeGuess Mimetype | NS_CheckContentLoadPolicy
|
||||
* @param aExtra Extra /
|
||||
*/
|
||||
static nsresult CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
||||
nsIPrincipal* aLoadingPrincipal,
|
||||
PRUint32 aCheckLoadFlags,
|
||||
PRBool aAllowData,
|
||||
PRUint32 aContentPolicyType,
|
||||
nsISupports* aContext,
|
||||
const nsACString& aMimeGuess = EmptyCString(),
|
||||
nsISupports* aExtra = nsnull);
|
||||
|
||||
private:
|
||||
|
||||
static PRBool InitializeEventTable();
|
||||
|
||||
@@ -137,6 +137,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsMutationEvent.h"
|
||||
#include "nsIKBStateControl.h"
|
||||
#include "nsIMEStateManager.h"
|
||||
#include "nsContentErrors.h"
|
||||
|
||||
#ifdef IBMBIDI
|
||||
#include "nsIBidiKeyboard.h"
|
||||
@@ -3552,3 +3553,56 @@ nsContentUtils::NotifyInstalledMenuKeyboardListener(PRBool aInstalling)
|
||||
{
|
||||
nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
|
||||
}
|
||||
|
||||
static PRBool SchemeIs(nsIURI* aURI, const char* aScheme)
|
||||
{
|
||||
nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
|
||||
NS_ENSURE_TRUE(baseURI, PR_FALSE);
|
||||
|
||||
PRBool isScheme = PR_FALSE;
|
||||
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::CheckSecurityBeforeLoad(nsIURI* aURIToLoad,
|
||||
nsIPrincipal* aLoadingPrincipal,
|
||||
PRUint32 aCheckLoadFlags,
|
||||
PRBool aAllowData,
|
||||
PRUint32 aContentPolicyType,
|
||||
nsISupports* aContext,
|
||||
const nsACString& aMimeGuess,
|
||||
nsISupports* aExtra)
|
||||
{
|
||||
nsCOMPtr<nsIURI> loadingURI;
|
||||
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// CheckLoadURIWithPrincipal
|
||||
rv = sSecurityManager->
|
||||
CheckLoadURIWithPrincipal(aLoadingPrincipal, aURIToLoad, aCheckLoadFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Content Policy
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(aContentPolicyType,
|
||||
aURIToLoad,
|
||||
loadingURI,
|
||||
aContext,
|
||||
aMimeGuess,
|
||||
aExtra,
|
||||
&shouldLoad,
|
||||
GetContentPolicy());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
// Same Origin
|
||||
if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
|
||||
((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
|
||||
SchemeIs(aURIToLoad, "chrome"))) {
|
||||
return NS_OK;
|
||||
}
|
||||
return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad);
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
@@ -3430,23 +3431,16 @@ nsDocument::RemoveBinding(nsIDOMElement* aContent, const nsAString& aURI)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::LoadBindingDocument(const nsAString& aURI,
|
||||
nsIDOMDocument** aResult)
|
||||
nsDocument::LoadBindingDocument(const nsAString& aURI)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURI,
|
||||
mCharacterSet.get(),
|
||||
NS_STATIC_CAST(nsIDocument *, this)->GetBaseURI());
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mBindingManager->LoadBindingDocument(this, uri, getter_AddRefs(doc));
|
||||
|
||||
if (doc) {
|
||||
CallQueryInterface(doc, aResult);
|
||||
}
|
||||
|
||||
mBindingManager->LoadBindingDocument(this, uri);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -766,19 +766,11 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL)
|
||||
|
||||
nsresult
|
||||
nsBindingManager::LoadBindingDocument(nsIDocument* aBoundDoc,
|
||||
nsIURI* aURL,
|
||||
nsIDocument** aResult)
|
||||
nsIURI* aURL)
|
||||
{
|
||||
NS_PRECONDITION(aURL, "Must have a URI to load!");
|
||||
|
||||
nsCAutoString otherScheme;
|
||||
aURL->GetScheme(otherScheme);
|
||||
|
||||
nsCAutoString scheme;
|
||||
aBoundDoc->GetDocumentURI()->GetScheme(scheme);
|
||||
|
||||
// First we need to load our binding.
|
||||
*aResult = nsnull;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIXBLService> xblService =
|
||||
do_GetService("@mozilla.org/xbl;1", &rv);
|
||||
@@ -792,11 +784,6 @@ nsBindingManager::LoadBindingDocument(nsIDocument* aBoundDoc,
|
||||
if (!info)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// XXXbz Why is this based on a scheme comparison? Shouldn't this
|
||||
// be a real security check???
|
||||
if (!strcmp(scheme.get(), otherScheme.get()))
|
||||
info->GetDocument(aResult); // Addref happens here.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -156,8 +156,7 @@ public:
|
||||
|
||||
nsresult AddLayeredBinding(nsIContent* aContent, nsIURI* aURL);
|
||||
nsresult RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL);
|
||||
nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL,
|
||||
nsIDocument** aResult);
|
||||
nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL);
|
||||
|
||||
nsresult AddToAttachedQueue(nsXBLBinding* aBinding);
|
||||
void ProcessAttachedQueue();
|
||||
|
||||
@@ -522,42 +522,21 @@ nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFl
|
||||
}
|
||||
}
|
||||
|
||||
// Security check - remote pages can't load local bindings, except from chrome
|
||||
nsIURI *docURI = document->GetDocumentURI();
|
||||
PRBool isChrome = PR_FALSE;
|
||||
rv = docURI->SchemeIs("chrome", &isChrome);
|
||||
|
||||
// Not everything with a chrome URI has a system principal. See bug 160042.
|
||||
if (NS_FAILED(rv) || !isChrome) {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(document->NodePrincipal(), aURL,
|
||||
nsIScriptSecurityManager::ALLOW_CHROME);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Content policy check. We have to be careful to not pass aContent as the
|
||||
// context here. Otherwise, if there is a JS-implemented content policy, we
|
||||
// will attempt to wrap the content node, which will try to load XBL bindings
|
||||
// for it, if any. Since we're not done loading this binding yet, that will
|
||||
// reenter this method and we'll end up creating a binding and then
|
||||
// immediately clobbering it in our table. That makes things very confused,
|
||||
// leading to misbehavior and crashes.
|
||||
PRInt16 decision = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
|
||||
aURL,
|
||||
docURI,
|
||||
document, // context
|
||||
EmptyCString(), // mime guess
|
||||
nsnull, // extra
|
||||
&decision,
|
||||
nsContentUtils::GetContentPolicy());
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !NS_CP_ACCEPTED(decision))
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
// Security check - Enforce same-origin policy, except to chrome.
|
||||
// We have to be careful to not pass aContent as the context here.
|
||||
// Otherwise, if there is a JS-implemented content policy, we will attempt
|
||||
// to wrap the content node, which will try to load XBL bindings for it, if
|
||||
// any. Since we're not done loading this binding yet, that will reenter
|
||||
// this method and we'll end up creating a binding and then immediately
|
||||
// clobbering it in our table. That makes things very confused, leading to
|
||||
// misbehavior and crashes.
|
||||
rv = nsContentUtils::CheckSecurityBeforeLoad(aURL,
|
||||
document->NodePrincipal(),
|
||||
nsIScriptSecurityManager::ALLOW_CHROME,
|
||||
PR_TRUE,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
document);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool ready;
|
||||
nsRefPtr<nsXBLBinding> newBinding;
|
||||
@@ -986,7 +965,16 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
||||
{
|
||||
NS_PRECONDITION(aBindingURI, "Must have a binding URI");
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv;
|
||||
if (aBoundDocument) {
|
||||
rv = nsContentUtils::
|
||||
CheckSecurityBeforeLoad(aBindingURI, aBoundDocument->NodePrincipal(),
|
||||
nsIScriptSecurityManager::ALLOW_CHROME,
|
||||
PR_TRUE,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
aBoundDocument);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIXBLDocumentInfo> info;
|
||||
@@ -1097,6 +1085,43 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsSameOriginChecker : public nsIChannelEventSink,
|
||||
public nsIInterfaceRequestor
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsSameOriginChecker,
|
||||
nsIChannelEventSink,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSameOriginChecker::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);
|
||||
|
||||
return nsContentUtils::GetSecurityManager()->
|
||||
CheckSameOriginURI(oldURI, newURI);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSameOriginChecker::GetInterface(const nsIID & aIID, void **aResult)
|
||||
{
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoundDocument,
|
||||
nsIURI* aDocumentURI, nsIURI* aBindingURI,
|
||||
@@ -1131,6 +1156,11 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), aDocumentURI, nsnull, loadGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> sameOriginChecker = new nsSameOriginChecker;
|
||||
NS_ENSURE_TRUE(sameOriginChecker, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
channel->SetNotificationCallbacks(sameOriginChecker);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
rv = doc->StartDocumentLoad("loadAsInteractiveData",
|
||||
channel,
|
||||
|
||||
@@ -155,9 +155,7 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
|
||||
NS_ASSERTION(xblDoc, "xml document doesn't implement nsIDOMDocumentXBL");
|
||||
NS_ENSURE_TRUE(xblDoc, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> dummy;
|
||||
xblDoc->LoadBindingDocument(NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml"),
|
||||
getter_AddRefs(dummy));
|
||||
xblDoc->LoadBindingDocument(NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml"));
|
||||
|
||||
nsCOMPtr<nsIDOMElement> rootElem;
|
||||
sourceDocument->GetDocumentElement(getter_AddRefs(rootElem));
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(c7c0ae9b-a0ba-4f4e-9f2c-c18deb62ee8b)]
|
||||
[scriptable, uuid(1a38762b-4da5-4f61-80fb-9317e198cb92)]
|
||||
interface nsIDOMDocumentXBL : nsISupports
|
||||
{
|
||||
nsIDOMNodeList getAnonymousNodes(in nsIDOMElement elt);
|
||||
@@ -53,5 +53,5 @@ interface nsIDOMDocumentXBL : nsISupports
|
||||
in DOMString bindingURL);
|
||||
|
||||
nsIDOMElement getBindingParent(in nsIDOMNode node);
|
||||
nsIDOMDocument loadBindingDocument(in DOMString documentURL);
|
||||
void loadBindingDocument(in DOMString documentURL);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user