Followup patch to bug 425201. Make sure to throw if xhr.open is called with an illegal uri. Also restore the nsIScriptSecurityManager.CheckConnect API as soap still uses it

This commit is contained in:
jonas@sicking.cc 2008-04-18 10:35:55 -07:00
Родитель 4d1513544b
Коммит 3cbf219992
8 изменённых файлов: 168 добавлений и 28 удалений

Просмотреть файл

@ -51,6 +51,15 @@ interface nsIURI;
[ptr] native JSContext(JSContext);
[ptr] native JSPrincipals(JSPrincipals);
/**
* WARNING!! The JEP needs to call GetOrigin() to support
* JavaScript-to-Java LiveConnect. So every change to the nsIPrincipal
* interface (big enough to change its IID) also breaks JavaScript-to-Java
* LiveConnect on mac.
*
* If you REALLY have to change this interface, please mark your bug as
* blocking bug 293973.
*/
[scriptable, uuid(b8268b9a-2403-44ed-81e3-614075c92034)]
interface nsIPrincipal : nsISerializable
{

Просмотреть файл

@ -41,8 +41,16 @@
interface nsIURI;
interface nsIChannel;
[scriptable, uuid(e74487fd-98ef-48d1-b973-3f2938f04e8e)]
/**
* WARNING!! The JEP needs to call GetSubjectPrincipal()
* to support JavaScript-to-Java LiveConnect. So every change to the
* nsIScriptSecurityManager interface (big enough to change its IID) also
* breaks JavaScript-to-Java LiveConnect on mac.
*
* If you REALLY have to change this interface, please mark your bug as
* blocking bug 293973.
*/
[scriptable, uuid(3fffd8e8-3fea-442e-a0ed-2ba81ae197d5)]
interface nsIScriptSecurityManager : nsIXPCSecurityManager
{
///////////////// Security Checks //////////////////
@ -55,6 +63,14 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
in JSVal aProperty,
in PRUint32 aAction);
/**
* Checks whether the running script is allowed to connect to aTargetURI
*/
[noscript] void checkConnect(in JSContextPtr aJSContext,
in nsIURI aTargetURI,
in string aClassName,
in string aProperty);
/**
* Check that the script currently running in context "cx" can load "uri".
*

Просмотреть файл

@ -408,7 +408,8 @@ public:
nsIURI* aSource, nsIURI* aTarget);
static nsresult
CheckSameOriginPrincipal(nsIPrincipal* aSubject,
nsIPrincipal* aObject);
nsIPrincipal* aObject,
PRBool aIsCheckConnect);
static PRBool
GetStrictFileOriginPolicy()
@ -445,7 +446,7 @@ private:
CheckPropertyAccessImpl(PRUint32 aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
nsISupports* aObj,
nsISupports* aObj, nsIURI* aTargetURI,
nsIClassInfo* aClassInfo,
const char* aClassName, jsval aProperty,
void** aCachedClassPolicy);
@ -453,7 +454,8 @@ private:
nsresult
CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
PRUint32 aAction);
PRUint32 aAction,
PRBool aIsCheckConnect);
nsresult
LookupPolicy(nsIPrincipal* principal,

Просмотреть файл

@ -291,7 +291,8 @@ nsPrincipal::Equals(nsIPrincipal *aOther, PRBool *aResult)
// Codebases are equal if they have the same origin.
*aResult =
NS_SUCCEEDED(nsScriptSecurityManager::CheckSameOriginPrincipal(this,
aOther));
aOther,
PR_FALSE));
return NS_OK;
}

Просмотреть файл

@ -571,10 +571,38 @@ nsScriptSecurityManager::CheckPropertyAccess(JSContext* cx,
PRUint32 aAction)
{
return CheckPropertyAccessImpl(aAction, nsnull, cx, aJSObject,
nsnull, nsnull,
nsnull, nsnull, nsnull,
aClassName, aProperty, nsnull);
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckConnect(JSContext* cx,
nsIURI* aTargetURI,
const char* aClassName,
const char* aPropertyName)
{
// Get a context if necessary
if (!cx)
{
cx = GetCurrentJSContext();
if (!cx)
return NS_OK; // No JS context, so allow the load
}
nsresult rv = CheckLoadURIFromScript(cx, aTargetURI);
if (NS_FAILED(rv)) return rv;
JSAutoRequest ar(cx);
JSString* propertyName = ::JS_InternString(cx, aPropertyName);
if (!propertyName)
return NS_ERROR_OUT_OF_MEMORY;
return CheckPropertyAccessImpl(nsIXPCSecurityManager::ACCESS_CALL_METHOD, nsnull,
cx, nsnull, nsnull, aTargetURI,
nsnull, aClassName, STRING_TO_JSVAL(propertyName), nsnull);
}
NS_IMETHODIMP
nsScriptSecurityManager::CheckSameOrigin(JSContext* cx,
nsIURI* aTargetURI)
@ -645,7 +673,7 @@ nsresult
nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
nsAXPCNativeCallContext* aCallContext,
JSContext* cx, JSObject* aJSObject,
nsISupports* aObj,
nsISupports* aObj, nsIURI* aTargetURI,
nsIClassInfo* aClassInfo,
const char* aClassName, jsval aProperty,
void** aCachedClassPolicy)
@ -720,14 +748,22 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
if (!objectPrincipal)
rv = NS_ERROR_DOM_SECURITY_ERR;
}
else if(aTargetURI)
{
if (NS_FAILED(GetCodebasePrincipal(
aTargetURI, getter_AddRefs(principalHolder))))
return NS_ERROR_FAILURE;
objectPrincipal = principalHolder;
}
else
{
NS_ERROR("CheckPropertyAccessImpl called without a target object");
NS_ERROR("CheckPropertyAccessImpl called without a target object or URL");
return NS_ERROR_FAILURE;
}
if(NS_SUCCEEDED(rv))
rv = CheckSameOriginDOMProp(subjectPrincipal, objectPrincipal,
aAction);
aAction, aTargetURI != nsnull);
break;
}
default:
@ -862,7 +898,8 @@ nsScriptSecurityManager::CheckPropertyAccessImpl(PRUint32 aAction,
/* static */
nsresult
nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
nsIPrincipal* aObject)
nsIPrincipal* aObject,
PRBool aIsCheckConnect)
{
/*
** Get origin of subject and object and compare.
@ -870,24 +907,36 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
if (aSubject == aObject)
return NS_OK;
// These booleans are only used when !aIsCheckConnect. Default
// them to false, and change if that turns out wrong.
PRBool subjectSetDomain = PR_FALSE;
PRBool objectSetDomain = PR_FALSE;
nsCOMPtr<nsIURI> subjectURI;
nsCOMPtr<nsIURI> objectURI;
aSubject->GetDomain(getter_AddRefs(subjectURI));
if (!subjectURI) {
if (aIsCheckConnect)
{
// Don't use domain for CheckConnect calls, since that's called for
// data-only load checks like XMLHTTPRequest (bug 290100).
aSubject->GetURI(getter_AddRefs(subjectURI));
} else {
subjectSetDomain = PR_TRUE;
}
aObject->GetDomain(getter_AddRefs(objectURI));
if (!objectURI) {
aObject->GetURI(getter_AddRefs(objectURI));
} else {
objectSetDomain = PR_TRUE;
}
else
{
aSubject->GetDomain(getter_AddRefs(subjectURI));
if (!subjectURI) {
aSubject->GetURI(getter_AddRefs(subjectURI));
} else {
subjectSetDomain = PR_TRUE;
}
aObject->GetDomain(getter_AddRefs(objectURI));
if (!objectURI) {
aObject->GetURI(getter_AddRefs(objectURI));
} else {
objectSetDomain = PR_TRUE;
}
}
if (SecurityCompareURIs(subjectURI, objectURI))
@ -896,6 +945,12 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
// done so in order to be considered the same origin. This prevents
// DNS spoofing based on document.domain (154930)
// But this restriction does not apply to CheckConnect calls, since
// that's called for data-only load checks like XMLHTTPRequest where
// we ignore domain (bug 290100).
if (aIsCheckConnect)
return NS_OK;
// If both or neither explicitly set their domain, allow the access
if (subjectSetDomain == objectSetDomain)
return NS_OK;
@ -911,13 +966,21 @@ nsScriptSecurityManager::CheckSameOriginPrincipal(nsIPrincipal* aSubject,
nsresult
nsScriptSecurityManager::CheckSameOriginDOMProp(nsIPrincipal* aSubject,
nsIPrincipal* aObject,
PRUint32 aAction)
PRUint32 aAction,
PRBool aIsCheckConnect)
{
nsresult rv;
PRBool subsumes;
rv = aSubject->Subsumes(aObject, &subsumes);
if (NS_SUCCEEDED(rv) && !subsumes) {
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
if (aIsCheckConnect) {
// Don't do equality compares, just do a same-origin compare,
// since the object principal isn't a real principal, just a
// GetCodebasePrincipal() on whatever URI we started with.
rv = CheckSameOriginPrincipal(aSubject, aObject, aIsCheckConnect);
} else {
PRBool subsumes;
rv = aSubject->Subsumes(aObject, &subsumes);
if (NS_SUCCEEDED(rv) && !subsumes) {
rv = NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
}
if (NS_SUCCEEDED(rv))
@ -3062,7 +3125,7 @@ nsScriptSecurityManager::CanAccess(PRUint32 aAction,
void** aPolicy)
{
return CheckPropertyAccessImpl(aAction, aCallContext, cx,
aJSObject, aObj, aClassInfo,
aJSObject, aObj, nsnull, aClassInfo,
nsnull, aPropertyName, aPolicy);
}

Просмотреть файл

@ -1275,7 +1275,7 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url)
} else {
mState &= ~XML_HTTP_REQUEST_XSITEENABLED;
rv = mPrincipal->CheckMayLoad(targetURI, PR_TRUE);
NS_ENSURE_SUCCESS(rv, NS_OK);
NS_ENSURE_SUCCESS(rv, rv);
}
if (argc > 2) {

Просмотреть файл

@ -174,6 +174,7 @@ _TEST_FILES = test_bug5141.html \
test_bug428847.html \
file_bug428847-1.xhtml \
file_bug428847-2.xhtml \
test_bug425201.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=425201
-->
<head>
<title>Test for Bug 425201</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=425201">Mozilla Bug 425201</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 425201 **/
var req = new XMLHttpRequest();
var threw = false;
try {
req.open("GET", "http://www.example.com/", false);
}
catch (e) {
threw = true;
}
ok(threw, "Open should have thrown");
threw = false;
try {
req.send(null);
}
catch (e) {
threw = true;
}
ok(threw, "Send should have thrown");
</script>
</pre>
</body>
</html>