From 17bc6e66e4deb8088b77ed9428e7a7caa55031d7 Mon Sep 17 00:00:00 2001 From: "sicking%bigfoot.com" Date: Tue, 16 Jul 2002 13:09:15 +0000 Subject: [PATCH] Add same-origin checks in a few DOM methods. Patch by me and jst. b=156452, r=jst/me, sr=bz, a=pending --- content/base/public/nsContentUtils.h | 3 + content/base/src/nsContentUtils.cpp | 94 ++++++++++++------- content/base/src/nsDOMAttributeMap.cpp | 12 +++ content/base/src/nsDocument.cpp | 33 +++++++ content/base/src/nsGenericElement.cpp | 20 ++-- content/base/src/nsRange.cpp | 41 ++++++++ content/xml/content/src/nsXMLNamedNodeMap.cpp | 2 + content/xul/content/src/nsXULElement.cpp | 8 +- .../document/src/nsXULCommandDispatcher.cpp | 7 +- content/xul/document/src/nsXULDocument.cpp | 10 ++ extensions/transformiix/build/makefile.win | 1 + .../transformiix/source/base/Makefile.in | 3 + .../transformiix/source/base/makefile.win | 3 + .../transformiix/source/base/txURIUtils.cpp | 48 +++++++++- .../transformiix/source/base/txURIUtils.h | 12 ++- .../source/xpath/nsXPathEvaluator.cpp | 6 ++ .../source/xpath/nsXPathExpression.cpp | 6 ++ .../source/xslt/XSLTProcessor.cpp | 8 +- 18 files changed, 270 insertions(+), 47 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 6c38759d8104..602d229974c0 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -170,6 +170,9 @@ public: // Checks if two nodes live in document coming from the same origin static nsresult CheckSameOrigin(nsIDOMNode* aNode1, nsIDOMNode* aNode2); + // Check if the (JS) caller can access aNode. + static PRBool CanCallerAccess(nsIDOMNode *aNode); + private: static nsresult doReparentContentWrapper(nsIContent *aChild, nsIDocument *aNewDocument, diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 847db2f7e15c..a7c3a4b5b464 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -356,7 +356,7 @@ nsContentUtils::GetClassInfoInstance(nsDOMClassInfoID aID) // static nsresult -nsContentUtils::CheckSameOrigin(nsIDOMNode* aNode1, nsIDOMNode* aNode2) +nsContentUtils::CheckSameOrigin(nsIDOMNode *aNode1, nsIDOMNode *aNode2) { nsCOMPtr doc1 = do_QueryInterface(aNode1); if (!doc1) { @@ -368,10 +368,12 @@ nsContentUtils::CheckSameOrigin(nsIDOMNode* aNode1, nsIDOMNode* aNode2) nsCOMPtr domDoc1; aNode1->GetOwnerDocument(getter_AddRefs(domDoc1)); - doc1 = do_QueryInterface(domDoc1); - if (!doc1) { - return NS_ERROR_FAILURE; + if (!domDoc1) { + // aNode1 is not part of a document, let any caller access it. + return NS_OK; } + doc1 = do_QueryInterface(domDoc1); + NS_ASSERTION(doc1, "QI to nsIDocument failed"); } nsCOMPtr doc2 = do_QueryInterface(aNode2); @@ -384,10 +386,12 @@ nsContentUtils::CheckSameOrigin(nsIDOMNode* aNode1, nsIDOMNode* aNode2) nsCOMPtr domDoc2; aNode2->GetOwnerDocument(getter_AddRefs(domDoc2)); - doc2 = do_QueryInterface(domDoc2); - if (!doc2) { - return NS_ERROR_FAILURE; + if (!domDoc2) { + // aNode2 is not part of a document, let any caller access it. + return NS_OK; } + doc2 = do_QueryInterface(domDoc2); + NS_ASSERTION(doc2, "QI to nsIDocument failed"); } if (doc1 == doc2) @@ -400,12 +404,52 @@ nsContentUtils::CheckSameOrigin(nsIDOMNode* aNode1, nsIDOMNode* aNode2) nsresult rv = NS_OK; nsCOMPtr securityManager = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); return securityManager->CheckSameOriginURI(uri1, uri2); } +// static +PRBool +nsContentUtils::CanCallerAccess(nsIDOMNode *aNode) +{ + nsCOMPtr doc(do_QueryInterface(aNode)); + + if (!doc) { + // Make sure that this is a real node. + nsCOMPtr content(do_QueryInterface(aNode)); + if (!content) { + return PR_FALSE; + } + + nsCOMPtr domDoc; + aNode->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!domDoc) { + // aNode is not part of a document, let any caller access it. + return PR_TRUE; + } + doc = do_QueryInterface(domDoc); + NS_ASSERTION(doc, "QI to nsIDocument failed"); + } + + nsCOMPtr uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + + nsresult rv = NS_OK; + nsCOMPtr securityManager = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + + // If we can't get the security manager service we'll assume that's + // because it's not installed, if that's the case then the installer + // didn't care about security in the first place. + NS_ENSURE_SUCCESS(rv, PR_TRUE); + + rv = securityManager->CheckSameOrigin(nsnull, uri); + + return NS_SUCCEEDED(rv); +} + // static nsresult nsContentUtils::doReparentContentWrapper(nsIContent *aChild, @@ -583,34 +627,18 @@ nsContentUtils::ReparentContentWrapper(nsIContent *aContent, PRBool nsContentUtils::IsCallerChrome() { - nsCOMPtr docShell; - nsCOMPtr stack(do_GetService(sJSStackContractID)); + nsresult rv = NS_OK; + nsCOMPtr securityManager = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); - if (stack) { - JSContext *cx = nsnull; - stack->Peek(&cx); - - if (cx) { - nsCOMPtr sgo; - nsContentUtils::GetDynamicScriptGlobal(cx, getter_AddRefs(sgo)); - - if (sgo) { - sgo->GetDocShell(getter_AddRefs(docShell)); - } - } + PRBool is_caller_chrome = PR_FALSE; + rv = securityManager->SubjectPrincipalIsSystem(&is_caller_chrome); + if (NS_FAILED(rv)) { + return PR_FALSE; } - nsCOMPtr item(do_QueryInterface(docShell)); - if (item) { - PRInt32 callerType = nsIDocShellTreeItem::typeChrome; - item->GetItemType(&callerType); - - if (callerType != nsIDocShellTreeItem::typeChrome) { - return PR_FALSE; - } - } - - return PR_TRUE; + return is_caller_chrome; } // static diff --git a/content/base/src/nsDOMAttributeMap.cpp b/content/base/src/nsDOMAttributeMap.cpp index 58c159658e5a..ab6f9dae1862 100644 --- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -125,6 +125,12 @@ nsDOMAttributeMap::SetNamedItem(nsIDOMNode *aNode, nsIDOMNode **aReturn) *aReturn = nsnull; if (mContent) { + nsCOMPtr contNode = do_QueryInterface(mContent); + rv = nsContentUtils::CheckSameOrigin(contNode, aNode); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr attribute(do_QueryInterface(aNode)); if (!attribute) { @@ -335,6 +341,12 @@ nsDOMAttributeMap::SetNamedItemNS(nsIDOMNode* aArg, nsIDOMNode** aReturn) *aReturn = nsnull; if (mContent) { + nsCOMPtr contNode = do_QueryInterface(mContent); + rv = nsContentUtils::CheckSameOrigin(contNode, aArg); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr attribute(do_QueryInterface(aArg)); if (!attribute) { diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index c0812cc987af..2c1e7897fa78 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -372,6 +372,14 @@ nsDOMImplementation::CreateDocument(const nsAString& aNamespaceURI, NS_ENSURE_ARG_POINTER(aReturn); *aReturn = nsnull; + + if (aDoctype) { + nsCOMPtr owner; + aDoctype->GetOwnerDocument(getter_AddRefs(owner)); + if (owner) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; + } + } return NS_NewDOMDocument(aReturn, aNamespaceURI, aQualifiedName, aDoctype, mBaseURI); @@ -2541,6 +2549,11 @@ nsDocument::ImportNode(nsIDOMNode* aImportedNode, { NS_ENSURE_ARG(aImportedNode); NS_ENSURE_ARG_POINTER(aReturn); + + nsresult rv = nsContentUtils::CheckSameOrigin(this, aImportedNode); + if (NS_FAILED(rv)) { + return rv; + } return aImportedNode->CloneNode(aDeep, aReturn); } @@ -2548,6 +2561,11 @@ nsDocument::ImportNode(nsIDOMNode* aImportedNode, NS_IMETHODIMP nsDocument::AddBinding(nsIDOMElement* aContent, const nsAString& aURL) { + nsresult rv = nsContentUtils::CheckSameOrigin(this, aContent); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr bm; GetBindingManager(getter_AddRefs(bm)); nsCOMPtr content(do_QueryInterface(aContent)); @@ -2558,6 +2576,11 @@ nsDocument::AddBinding(nsIDOMElement* aContent, const nsAString& aURL) NS_IMETHODIMP nsDocument::RemoveBinding(nsIDOMElement* aContent, const nsAString& aURL) { + nsresult rv = nsContentUtils::CheckSameOrigin(this, aContent); + if (NS_FAILED(rv)) { + return rv; + } + if (mBindingManager) { nsCOMPtr content(do_QueryInterface(aContent)); return mBindingManager->RemoveLayeredBinding(content, aURL); @@ -3148,6 +3171,11 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, return NS_ERROR_NULL_POINTER; } + nsresult rv = nsContentUtils::CheckSameOrigin(this, aNewChild); + if (NS_FAILED(rv)) { + return rv; + } + // If it's a child type we can't handle (per DOM spec), or if it's an // element and we already have a root (our addition to DOM spec), throw // HIERARCHY_REQUEST_ERR. @@ -3217,6 +3245,11 @@ nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNod return NS_ERROR_NULL_POINTER; } + result = nsContentUtils::CheckSameOrigin(this, aNewChild); + if (NS_FAILED(result)) { + return result; + } + aNewChild->GetNodeType(&nodeType); if ((COMMENT_NODE != nodeType) && diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index b17efdf17ba0..d4104a9677da 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2334,6 +2334,12 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } + nsCOMPtr old_doc; + newContent->GetDocument(*getter_AddRefs(old_doc)); + if (old_doc != mDocument && !nsContentUtils::CanCallerAccess(aNewChild)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + /* * Make sure the new child is not "this" node or one of this nodes * ancestors. Doing this check here should be safe even if newContent @@ -2410,10 +2416,6 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, return res; } - nsCOMPtr old_doc; - - newContent->GetDocument(*getter_AddRefs(old_doc)); - /* * Remove the element from the old parent if one exists, since oldParent * is a nsIDOMNode this will do the right thing even if the parent of @@ -2548,6 +2550,12 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } + nsCOMPtr old_doc; + newContent->GetDocument(*getter_AddRefs(old_doc)); + if (old_doc != mDocument && !nsContentUtils::CanCallerAccess(aNewChild)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + nsCOMPtr document; GetDocument(*getter_AddRefs(document)); @@ -2610,10 +2618,6 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, return res; } - nsCOMPtr old_doc; - - newContent->GetDocument(*getter_AddRefs(old_doc)); - /* * Remove the element from the old parent if one exists, since oldParent * is a nsIDOMNode this will do the right thing even if the parent of diff --git a/content/base/src/nsRange.cpp b/content/base/src/nsRange.cpp index 0f55c4b51631..445938493e2a 100644 --- a/content/base/src/nsRange.cpp +++ b/content/base/src/nsRange.cpp @@ -985,6 +985,11 @@ nsresult nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent) nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset) { NS_ENSURE_ARG_POINTER(aParent); + + if (!nsContentUtils::CanCallerAccess(aParent)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; @@ -1009,6 +1014,10 @@ nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset) nsresult nsRange::SetStartBefore(nsIDOMNode* aSibling) { + if (!nsContentUtils::CanCallerAccess(aSibling)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; if (nsnull == aSibling)// Not the correct one to throw, but spec doesn't say what is @@ -1023,6 +1032,10 @@ nsresult nsRange::SetStartBefore(nsIDOMNode* aSibling) nsresult nsRange::SetStartAfter(nsIDOMNode* aSibling) { + if (!nsContentUtils::CanCallerAccess(aSibling)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; if (nsnull == aSibling)// Not the correct one to throw, but spec doesn't say what is @@ -1037,6 +1050,10 @@ nsresult nsRange::SetStartAfter(nsIDOMNode* aSibling) nsresult nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset) { + if (!nsContentUtils::CanCallerAccess(aParent)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; @@ -1065,6 +1082,10 @@ nsresult nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset) nsresult nsRange::SetEndBefore(nsIDOMNode* aSibling) { + if (!nsContentUtils::CanCallerAccess(aSibling)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; if (nsnull == aSibling)// Not the correct one to throw, but spec doesn't say what is @@ -1079,6 +1100,10 @@ nsresult nsRange::SetEndBefore(nsIDOMNode* aSibling) nsresult nsRange::SetEndAfter(nsIDOMNode* aSibling) { + if (!nsContentUtils::CanCallerAccess(aSibling)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; if (nsnull == aSibling)// Not the correct one to throw, but spec doesn't say what is @@ -1112,6 +1137,10 @@ nsresult nsRange::Unposition() nsresult nsRange::SelectNode(nsIDOMNode* aN) { + if (!nsContentUtils::CanCallerAccess(aN)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; @@ -1160,6 +1189,10 @@ nsresult nsRange::SelectNode(nsIDOMNode* aN) nsresult nsRange::SelectNodeContents(nsIDOMNode* aN) { + if (!nsContentUtils::CanCallerAccess(aN)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; NS_ENSURE_ARG_POINTER(aN); @@ -2026,6 +2059,10 @@ nsresult nsRange::CloneRange(nsIDOMRange** aReturn) nsresult nsRange::InsertNode(nsIDOMNode* aN) { + if (!nsContentUtils::CanCallerAccess(aN)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; @@ -2078,6 +2115,10 @@ nsresult nsRange::InsertNode(nsIDOMNode* aN) nsresult nsRange::SurroundContents(nsIDOMNode* aN) { + if (!nsContentUtils::CanCallerAccess(aN)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + if(IsDetached()) return NS_ERROR_DOM_INVALID_STATE_ERR; diff --git a/content/xml/content/src/nsXMLNamedNodeMap.cpp b/content/xml/content/src/nsXMLNamedNodeMap.cpp index 55903ab2c259..4d623484866b 100644 --- a/content/xml/content/src/nsXMLNamedNodeMap.cpp +++ b/content/xml/content/src/nsXMLNamedNodeMap.cpp @@ -171,6 +171,8 @@ nsXMLNamedNodeMap::SetNamedItem(nsIDOMNode* aArg, nsIDOMNode** aReturn) return NS_ERROR_NULL_POINTER; *aReturn = 0; + + // XXX, do same-origin check here once we know what to do with this class nsAutoString argName; aArg->GetNodeName(argName); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 969f87ab4b61..5fea4d1869e9 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -987,7 +987,9 @@ nsXULElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, // aRefChild may be null; that means "append". - nsresult rv; + nsresult rv = nsContentUtils::CheckSameOrigin(this, aNewChild); + if (NS_FAILED(rv)) + return rv; nsCOMPtr newcontent = do_QueryInterface(aNewChild); NS_ASSERTION(newcontent != nsnull, "not an nsIContent"); @@ -1065,7 +1067,9 @@ nsXULElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, if (! aOldChild) return NS_ERROR_NULL_POINTER; - nsresult rv; + nsresult rv = nsContentUtils::CheckSameOrigin(this, aNewChild); + if (NS_FAILED(rv)) + return rv; nsCOMPtr oldelement = do_QueryInterface(aOldChild); NS_ASSERTION(oldelement != nsnull, "not an nsIContent"); diff --git a/content/xul/document/src/nsXULCommandDispatcher.cpp b/content/xul/document/src/nsXULCommandDispatcher.cpp index bf91b2c0fc7b..604a109ca544 100644 --- a/content/xul/document/src/nsXULCommandDispatcher.cpp +++ b/content/xul/document/src/nsXULCommandDispatcher.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * @@ -68,6 +68,7 @@ #include "nsContentUtils.h" #include "nsReadableUtils.h" #include "nsCRT.h" +#include "nsDOMError.h" #ifdef PR_LOGGING static PRLogModuleInfo* gLog; @@ -216,6 +217,10 @@ nsXULCommandDispatcher::AddCommandUpdater(nsIDOMElement* aElement, if (! aElement) return NS_ERROR_NULL_POINTER; + if (!nsContentUtils::CanCallerAccess(aElement)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + Updater* updater = mUpdaters; Updater** link = &mUpdaters; diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 2fc03ef537f2..fca525ac2eb8 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1937,6 +1937,11 @@ nsXULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, nsIDOMElement* aListener, const nsAString& aAttr) { + if (!nsContentUtils::CanCallerAccess(aBroadcaster) || + !nsContentUtils::CanCallerAccess(aListener)) { + return NS_ERROR_DOM_SECURITY_ERR; + } + static PLDHashTableOps gOps = { PL_DHashAllocTable, PL_DHashFreeTable, @@ -3375,6 +3380,11 @@ NS_IMETHODIMP nsXULDocument::AddBinding(nsIDOMElement* aContent, const nsAString& aURL) { + nsresult rv = nsContentUtils::CheckSameOrigin(this, aContent); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr bm; GetBindingManager(getter_AddRefs(bm)); nsCOMPtr content(do_QueryInterface(aContent)); diff --git a/extensions/transformiix/build/makefile.win b/extensions/transformiix/build/makefile.win index e11252682162..6915521e9c93 100644 --- a/extensions/transformiix/build/makefile.win +++ b/extensions/transformiix/build/makefile.win @@ -33,6 +33,7 @@ REQUIRES = xpcom \ htmlparser \ webshell \ docshell \ + caps \ $(NULL) include <$(DEPTH)/config/config.mak> diff --git a/extensions/transformiix/source/base/Makefile.in b/extensions/transformiix/source/base/Makefile.in index 605c67b31ed5..f44bf8bc4ad3 100644 --- a/extensions/transformiix/source/base/Makefile.in +++ b/extensions/transformiix/source/base/Makefile.in @@ -35,6 +35,9 @@ REQUIRES = string \ content \ widget \ necko \ + caps \ + xpconnect \ + js \ $(NULL) endif diff --git a/extensions/transformiix/source/base/makefile.win b/extensions/transformiix/source/base/makefile.win index c7251c9cdb5d..a32c373507dd 100644 --- a/extensions/transformiix/source/base/makefile.win +++ b/extensions/transformiix/source/base/makefile.win @@ -28,6 +28,9 @@ REQUIRES = string \ content \ widget \ necko \ + caps \ + xpconnect \ + js \ $(NULL) include <$(DEPTH)/config/config.mak> diff --git a/extensions/transformiix/source/base/txURIUtils.cpp b/extensions/transformiix/source/base/txURIUtils.cpp index 683a0095890d..bd0c0cd607e9 100644 --- a/extensions/transformiix/source/base/txURIUtils.cpp +++ b/extensions/transformiix/source/base/txURIUtils.cpp @@ -34,6 +34,10 @@ #ifndef TX_EXE #include "nsNetUtil.h" +#include "nsIScriptSecurityManager.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIContent.h" #endif /** @@ -311,4 +315,46 @@ URIUtils::ParsedURI* URIUtils::parseURI(const String& uri) { return uriTokens; } //-- parseURI -#endif +#else /* TX_EXE */ + +// static +MBool URIUtils::CanCallerAccess(nsIDOMNode *aNode) +{ + nsCOMPtr doc(do_QueryInterface(aNode)); + + if (!doc) { + // Make sure that this is a real node. + nsCOMPtr content(do_QueryInterface(aNode)); + if (!content) { + return MB_FALSE; + } + + nsCOMPtr domDoc; + aNode->GetOwnerDocument(getter_AddRefs(domDoc)); + if (!domDoc) { + // aNode is not part of a document, let any caller access it. + return PR_TRUE; + } + doc = do_QueryInterface(domDoc); + NS_ASSERTION(doc, "QI to nsIDocument failed"); + } + + nsCOMPtr uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + + nsresult rv = NS_OK; + nsCOMPtr securityManager = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + + // If we can't get the security manager service we'll assume that's + // because it's not installed, if that's the case then the installer + // didn't care about security in the first place. + NS_ENSURE_SUCCESS(rv, PR_TRUE); + + rv = securityManager->CheckSameOrigin(nsnull, uri); + + return NS_SUCCEEDED(rv); +} + + +#endif /* TX_EXE */ diff --git a/extensions/transformiix/source/base/txURIUtils.h b/extensions/transformiix/source/base/txURIUtils.h index 24dabf40ea9c..4189ff7b368a 100644 --- a/extensions/transformiix/source/base/txURIUtils.h +++ b/extensions/transformiix/source/base/txURIUtils.h @@ -40,6 +40,8 @@ #include "baseutils.h" #ifdef TX_EXE #include +#else +#include "nsIDOMNode.h" #endif @@ -86,7 +88,15 @@ public: * The document base will be appended to the given dest String **/ static void getDocumentBase(const String& href, String& dest); -#endif + +#else /* TX_EXE */ + + /* + * Checks if a caller is allowed to access a given node + */ + static MBool CanCallerAccess(nsIDOMNode *aNode); + +#endif /* TX_EXE */ /** * Resolves the given href argument, using the given documentBase diff --git a/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp b/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp index edbad45cd1a5..2e9a74e0ff75 100644 --- a/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp +++ b/extensions/transformiix/source/xpath/nsXPathEvaluator.cpp @@ -47,6 +47,9 @@ #include "ProcessorState.h" #include "nsContentCID.h" #include "ExprParser.h" +#include "nsDOMError.h" +#include "txURIUtils.h" + NS_IMPL_ADDREF(nsXPathEvaluator) NS_IMPL_RELEASE(nsXPathEvaluator) @@ -91,6 +94,9 @@ nsXPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, nsIDOMXPathNSResolver **aResult) { NS_ENSURE_ARG(aNodeResolver); + if (!URIUtils::CanCallerAccess(aNodeResolver)) + return NS_ERROR_DOM_SECURITY_ERR; + *aResult = new nsXPathNSResolver(aNodeResolver); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); diff --git a/extensions/transformiix/source/xpath/nsXPathExpression.cpp b/extensions/transformiix/source/xpath/nsXPathExpression.cpp index 735b210d2c1f..97116e9bbd20 100644 --- a/extensions/transformiix/source/xpath/nsXPathExpression.cpp +++ b/extensions/transformiix/source/xpath/nsXPathExpression.cpp @@ -43,6 +43,9 @@ #include "nsIDOMClassInfo.h" #include "nsIDOMXPathNamespace.h" #include "nsXPathResult.h" +#include "nsDOMError.h" +#include "txURIUtils.h" + NS_IMPL_ADDREF(nsXPathExpression) NS_IMPL_RELEASE(nsXPathExpression) @@ -70,6 +73,9 @@ nsXPathExpression::Evaluate(nsIDOMNode *aContextNode, { NS_ENSURE_ARG(aContextNode); + if (!URIUtils::CanCallerAccess(aContextNode)) + return NS_ERROR_DOM_SECURITY_ERR; + nsresult rv; PRUint16 nodeType; rv = aContextNode->GetNodeType(&nodeType); diff --git a/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/extensions/transformiix/source/xslt/XSLTProcessor.cpp index 1d638737e4a1..366fd5da9f98 100644 --- a/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ b/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -67,6 +67,7 @@ #include "nsNetUtil.h" #include "nsIDOMClassInfo.h" #include "nsIConsoleService.h" +#include "nsDOMError.h" #else #include "txHTMLOutput.h" #include "txTextOutput.h" @@ -2329,9 +2330,14 @@ XSLTProcessor::TransformDocument(nsIDOMNode* aSourceDOM, nsIDOMDocument* aOutputDoc, nsITransformObserver* aObserver) { - // We need source and result documents but no stylesheet. NS_ENSURE_ARG(aSourceDOM); + NS_ENSURE_ARG(aStyleDOM); NS_ENSURE_ARG(aOutputDoc); + + if (!URIUtils::CanCallerAccess(aSourceDOM) || + !URIUtils::CanCallerAccess(aStyleDOM) || + !URIUtils::CanCallerAccess(aOutputDoc)) + return NS_ERROR_DOM_SECURITY_ERR; // Create wrapper for the source document. nsCOMPtr sourceDOMDocument;