зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1320201 - When an XHR is made with an expanded principal, use the expanded principal for CORS security checks; r=bzbarsky
We should only ensure that the resulting document doesn't end up inheriting the expanded principal.
This commit is contained in:
Родитель
2c794979ff
Коммит
d67534c9f0
|
@ -2500,27 +2500,6 @@ XMLHttpRequestMainThread::CreateChannel()
|
|||
secFlags |= nsILoadInfo::SEC_COOKIES_OMIT;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(mPrincipal);
|
||||
if (ep) {
|
||||
// If we have an expanded principal, instead of using that, select the
|
||||
// principal in the whitelist which can load our URL, and use that instead.
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>>* whitelist = nullptr;
|
||||
ep->GetWhiteList(&whitelist);
|
||||
if (!whitelist) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(!(secFlags & nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS));
|
||||
bool dataInherits = (secFlags &
|
||||
(nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) != 0;
|
||||
for (const auto& principal : *whitelist) {
|
||||
if (NS_SUCCEEDED(principal->CheckMayLoad(mRequestURL, false, dataInherits))) {
|
||||
mPrincipal = principal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the responsibleDocument if we have it, except for dedicated workers
|
||||
// where it will be the parent document, which is not the one we want to use.
|
||||
nsresult rv;
|
||||
|
@ -2559,6 +2538,35 @@ XMLHttpRequestMainThread::CreateChannel()
|
|||
}
|
||||
}
|
||||
|
||||
// Using the provided principal as the triggeringPrincipal is fine, since we
|
||||
// want to be able to access any of the origins that the principal has access
|
||||
// to during the security checks, but we don't want a document to inherit an
|
||||
// expanded principal, so in that case we need to select the principal in the
|
||||
// expanded principal's whitelist that can load our URL as principalToInherit.
|
||||
nsCOMPtr<nsIPrincipal> resultingDocumentPrincipal(mPrincipal);
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(mPrincipal);
|
||||
if (ep) {
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>>* whitelist = nullptr;
|
||||
ep->GetWhiteList(&whitelist);
|
||||
if (!whitelist) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(!(secFlags & nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS));
|
||||
bool dataInherits = (secFlags &
|
||||
(nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) != 0;
|
||||
for (const auto& principal : *whitelist) {
|
||||
if (NS_SUCCEEDED(principal->CheckMayLoad(mRequestURL, false, dataInherits))) {
|
||||
resultingDocumentPrincipal = principal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
|
||||
rv = loadInfo->SetPrincipalToInherit(resultingDocumentPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,16 @@ cu.import("resource://testing-common/httpd.js");
|
|||
|
||||
var httpserver = new HttpServer();
|
||||
var httpserver2 = new HttpServer();
|
||||
var httpserver3 = new HttpServer();
|
||||
var testpath = "/simple";
|
||||
var redirectpath = "/redirect";
|
||||
var negativetestpath = "/negative";
|
||||
var httpbody = "<?xml version='1.0' ?><root>0123456789</root>";
|
||||
|
||||
var sb = cu.Sandbox(["http://www.example.com",
|
||||
"http://localhost:4444/simple"],
|
||||
"http://localhost:4444/redirect",
|
||||
"http://localhost:4444/simple",
|
||||
"http://localhost:4446/redirect"],
|
||||
{ wantGlobalProperties: ["XMLHttpRequest"] });
|
||||
|
||||
function createXHR(loc, async)
|
||||
|
@ -35,7 +39,7 @@ function checkResults(xhr)
|
|||
var httpServersClosed = 0;
|
||||
function finishIfDone()
|
||||
{
|
||||
if (++httpServersClosed == 2)
|
||||
if (++httpServersClosed == 3)
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
|
@ -44,11 +48,15 @@ function run_test()
|
|||
do_test_pending();
|
||||
|
||||
httpserver.registerPathHandler(testpath, serverHandler);
|
||||
httpserver.registerPathHandler(redirectpath, redirectHandler1);
|
||||
httpserver.start(4444);
|
||||
|
||||
httpserver2.registerPathHandler(negativetestpath, serverHandler);
|
||||
httpserver2.start(4445);
|
||||
|
||||
httpserver3.registerPathHandler(redirectpath, redirectHandler2);
|
||||
httpserver3.start(4446);
|
||||
|
||||
// Test sync XHR sending
|
||||
cu.evalInSandbox('var createXHR = ' + createXHR.toString(), sb);
|
||||
var res = cu.evalInSandbox('var sync = createXHR("4444/simple"); sync.send(null); sync', sb);
|
||||
|
@ -68,7 +76,21 @@ function run_test()
|
|||
do_check_true(true);
|
||||
}
|
||||
|
||||
// Test redirect handling.
|
||||
// This request bounces to server 2 and then back to server 1. Neither of
|
||||
// these servers support CORS, but if the expanded principal is used as the
|
||||
// triggering principal, this should work.
|
||||
cu.evalInSandbox('var createXHR = ' + createXHR.toString(), sb);
|
||||
var res = cu.evalInSandbox('var sync = createXHR("4444/redirect"); sync.send(null); sync', sb);
|
||||
do_check_true(checkResults(res));
|
||||
|
||||
var principal = res.responseXML.nodePrincipal;
|
||||
do_check_true(principal.isCodebasePrincipal);
|
||||
var requestURL = "http://localhost:4444/simple";
|
||||
do_check_eq(principal.URI.spec, requestURL);
|
||||
|
||||
httpserver2.stop(finishIfDone);
|
||||
httpserver3.stop(finishIfDone);
|
||||
|
||||
// Test async XHR sending
|
||||
sb.finish = function(){
|
||||
|
@ -95,8 +117,20 @@ function run_test()
|
|||
async.send(null);
|
||||
}
|
||||
|
||||
function serverHandler(metadata, response)
|
||||
function serverHandler(request, response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/xml", false);
|
||||
response.bodyOutputStream.write(httpbody, httpbody.length);
|
||||
}
|
||||
|
||||
function redirectHandler1(request, response)
|
||||
{
|
||||
response.setStatusLine(request.httpVersion, 302, "Found");
|
||||
response.setHeader("Location", "http://localhost:4446/redirect", false);
|
||||
}
|
||||
|
||||
function redirectHandler2(request, response)
|
||||
{
|
||||
response.setStatusLine(request.httpVersion, 302, "Found");
|
||||
response.setHeader("Location", "http://localhost:4444/simple", false);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче