From 36ecadf8f0b2ec5afc68ac2d0709d2865ef85a2e Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Wed, 1 Dec 2004 23:50:29 +0000 Subject: [PATCH] fixes bug 271411 "Same-origin checking for XForms submission" r=bryner sr=jst --- extensions/xforms/nsXFormsInstanceElement.cpp | 28 +++++++++++++---- extensions/xforms/nsXFormsSetValueElement.cpp | 2 ++ .../xforms/nsXFormsSubmissionElement.cpp | 21 ++++--------- extensions/xforms/nsXFormsUtils.cpp | 31 +++++++++++++++++++ extensions/xforms/nsXFormsUtils.h | 6 ++++ 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/extensions/xforms/nsXFormsInstanceElement.cpp b/extensions/xforms/nsXFormsInstanceElement.cpp index 8be2f6d64c7f..9acfddc91d24 100644 --- a/extensions/xforms/nsXFormsInstanceElement.cpp +++ b/extensions/xforms/nsXFormsInstanceElement.cpp @@ -49,6 +49,7 @@ #include "nsIDOMDOMImplementation.h" #include "nsIXTFGenericElementWrapper.h" #include "nsXFormsUtils.h" +#include "nsNetUtil.h" NS_IMPL_ISUPPORTS_INHERITED3(nsXFormsInstanceElement, nsXFormsStubElement, @@ -253,14 +254,29 @@ nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc) if (NS_FAILED(CreateInstanceDocument())) return; - nsCOMPtr rec = do_QueryInterface(mDocument); - rec->AddEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener)); + nsCOMPtr doc = do_QueryInterface(mDocument); + if (!doc) + return; - nsCOMPtr xmlDoc = do_QueryInterface(mDocument); - NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?"); + nsCOMPtr uri; + NS_NewURI(getter_AddRefs(uri), aSrc, doc->GetDocumentCharacterSet().get(), + doc->GetDocumentURI()); + if (!uri) + return; - PRBool success; - xmlDoc->Load(aSrc, &success); + PRBool success = PR_FALSE; + + if (nsXFormsUtils::CheckSameOrigin(doc->GetDocumentURI(), uri)) { + nsCOMPtr rec = do_QueryInterface(mDocument); + rec->AddEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener)); + + nsCOMPtr xmlDoc = do_QueryInterface(mDocument); + NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?"); + + nsCAutoString spec; + uri->GetSpec(spec); + xmlDoc->Load(NS_ConvertUTF8toUTF16(spec), &success); + } nsCOMPtr model = GetModel(); if (model) { diff --git a/extensions/xforms/nsXFormsSetValueElement.cpp b/extensions/xforms/nsXFormsSetValueElement.cpp index edae752dcfe1..754d181eb1e2 100644 --- a/extensions/xforms/nsXFormsSetValueElement.cpp +++ b/extensions/xforms/nsXFormsSetValueElement.cpp @@ -92,6 +92,8 @@ nsXFormsSetValueElement::HandleAction(nsIDOMEvent* aEvent, nsCOMPtr xpResult = nsXFormsUtils::EvaluateXPath(value, docElement, mElement, nsIDOMXPathResult::STRING_TYPE); + if (!xpResult) + return NS_OK; xpResult->GetStringValue(value); } else { diff --git a/extensions/xforms/nsXFormsSubmissionElement.cpp b/extensions/xforms/nsXFormsSubmissionElement.cpp index a4b0dfeb37c7..04b92beaceb5 100644 --- a/extensions/xforms/nsXFormsSubmissionElement.cpp +++ b/extensions/xforms/nsXFormsSubmissionElement.cpp @@ -1341,24 +1341,15 @@ nsXFormsSubmissionElement::SendData(PRUint32 format, nsresult rv; + // We require same-origin for replace="instance" or XML submission + nsAutoString replace; mElement->GetAttribute(NS_LITERAL_STRING("replace"), replace); - if (replace.IsEmpty() || replace.EqualsLiteral("all")) + if (format & (ENCODING_XML | ENCODING_MULTIPART_RELATED) || + replace.EqualsLiteral("instance")) { - // check to see if we're allowed to load this URI - nsCOMPtr secMan = - do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); - NS_ENSURE_STATE(secMan); - - rv = secMan->CheckConnect(nsnull, uri, "XForms", "submission"); - if (NS_FAILED(rv)) - { - // We need to return success here so that JS will get a proper - // exception thrown later. Native calls should always result in - // CheckConnect() succeeding, but in case JS calls C++ which calls - // this code the exception might be lost. - return NS_OK; - } + if (!nsXFormsUtils::CheckSameOrigin(doc->GetDocumentURI(), uri)) + return NS_ERROR_ABORT; } // wrap the entire upload stream in a buffered input stream, so that diff --git a/extensions/xforms/nsXFormsUtils.cpp b/extensions/xforms/nsXFormsUtils.cpp index 85899b8d62c4..f09356253436 100644 --- a/extensions/xforms/nsXFormsUtils.cpp +++ b/extensions/xforms/nsXFormsUtils.cpp @@ -58,6 +58,10 @@ #include "nsIDOMEventTarget.h" #include "nsDataHashtable.h" +#include "nsIScriptSecurityManager.h" +#include "nsIPermissionManager.h" +#include "nsServiceManagerUtils.h" + struct EventData { const char *name; @@ -835,3 +839,30 @@ nsXFormsUtils::FindParentContext(nsIDOMElement *aElement, return NS_OK; } + +/* static */ PRBool +nsXFormsUtils::CheckSameOrigin(nsIURI *aBaseURI, nsIURI *aTestURI) +{ + nsresult rv; + + // check to see if we're allowed to load this URI + nsCOMPtr secMan = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + if (secMan) { + rv = secMan->CheckSameOriginURI(aBaseURI, aTestURI); + if (NS_SUCCEEDED(rv)) + return PR_TRUE; + } + + // else, check with the permission manager to see if this host is + // permitted to access sites from other domains. + + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + PRUint32 perm; + rv = permMgr->TestPermission(aBaseURI, "xforms-load", &perm); + if (NS_SUCCEEDED(rv) && perm == nsIPermissionManager::ALLOW_ACTION) + return PR_TRUE; + + return PR_FALSE; +} diff --git a/extensions/xforms/nsXFormsUtils.h b/extensions/xforms/nsXFormsUtils.h index 034f9336af71..4bfdb858167b 100644 --- a/extensions/xforms/nsXFormsUtils.h +++ b/extensions/xforms/nsXFormsUtils.h @@ -47,6 +47,7 @@ class nsIDOMNode; class nsIDOMElement; class nsIXFormsModelElement; +class nsIURI; class nsString; #define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms" @@ -292,6 +293,11 @@ public: PRInt32 *aContextPosition, PRInt32 *aContextSize); + /** + * @return true if aTestURI has the same origin as aBaseURI + */ + static NS_HIDDEN_(PRBool) CheckSameOrigin(nsIURI *aBaseURI, + nsIURI *aTestURI); }; #endif