Commit 5ace159f authored by jchaffraix@webkit.org's avatar jchaffraix@webkit.org
Browse files

[XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR

https://bugs.webkit.org/show_bug.cgi?id=37781
<rdar://problem/7905150>

Reviewed by Alexey Proskuryakov.

WebCore:

Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html
       http/tests/xmlhttprequest/access-control-preflight-credential-sync.html

Rolling the patch in as I could not reproduce Qt results locally.

* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the
credential from the request here to avoid forgetting to do so in the different code path.
(WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the
"Origin" header.
(WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have
been removed so that we don't leak them. Also tweaked a comment to make it clear that
the URL check has issue when credential is involved.

LayoutTests:

Test that doing a cross-origin request with a preflight check does
not raise a NETWORK_ERR exception and does not send the credentials.

* http/tests/xmlhttprequest/access-control-preflight-credential-async-expected.txt: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-async.html: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-sync-expected.txt: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-sync.html: Added.
* http/tests/xmlhttprequest/resources/basic-auth/access-control-auth-basic.php: Added.

* platform/mac-tiger/Skipped:
* platform/qt/Skipped:
Added those 2 tests to the Skipped lists.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@58409 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f3f07304
2010-04-28 Julien Chaffraix <jchaffraix@webkit.org>
Reviewed by Alexey Proskuryakov.
[XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR
https://bugs.webkit.org/show_bug.cgi?id=37781
<rdar://problem/7905150>
Test that doing a cross-origin request with a preflight check does
not raise a NETWORK_ERR exception and does not send the credentials.
* http/tests/xmlhttprequest/access-control-preflight-credential-async-expected.txt: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-async.html: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-sync-expected.txt: Added.
* http/tests/xmlhttprequest/access-control-preflight-credential-sync.html: Added.
* http/tests/xmlhttprequest/resources/basic-auth/access-control-auth-basic.php: Added.
* platform/mac-tiger/Skipped:
* platform/qt/Skipped:
Added those 2 tests to the Skipped lists.
2010-04-28 Marcus Bulach <bulach@chromium.org>
 
Reviewed by Jeremy Orlow.
......
Test case for bug 37781: [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR
PASSED
<html>
<body>
<p>Test case for bug <a href="https://bugs.webkit.org/show_bug.cgi?id=37781">37781</a>: [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR</p>
<pre id='console'></pre>
<script type="text/javascript">
function log(message)
{
document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
}
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
try {
var xhr = new XMLHttpRequest;
xhr.open("PUT", "http://localhost:8000/xmlhttprequest/resources/basic-auth/access-control-auth-basic.php?uid=fooUser", false, "fooUser", "barPass");
xhr.onerror = function (e) {
log("FAILED: received error");
if (window.layoutTestController)
layoutTestController.notifyDone();
};
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
log((xhr.status == 401) ? "PASSED" : "FAILED: credential send!");
if (window.layoutTestController)
layoutTestController.notifyDone();
}
};
xhr.send();
} catch(e) {
log("FAILED: got exception " + e.message);
}
</script>
</body>
</html>
Test case for bug 37781: [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR
PASSED
<html>
<body>
<p>Test case for bug <a href="https://bugs.webkit.org/show_bug.cgi?id=37781">37781</a>: [XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR</p>
<pre id='console'></pre>
<script type="text/javascript">
function log(message)
{
document.getElementById('console').appendChild(document.createTextNode(message + "\n"));
}
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
try {
var xhr = new XMLHttpRequest;
xhr.open("PUT", "http://localhost:8000/xmlhttprequest/resources/basic-auth/access-control-auth-basic.php?uid=fooUser", false, "fooUser", "barPass");
xhr.onerror = function (e) {
log("FAILED: received error");
if (window.layoutTestController)
layoutTestController.notifyDone();
};
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
log((xhr.status == 401) ? "PASSED" : "FAILED: credential send!");
if (window.layoutTestController)
layoutTestController.notifyDone();
}
};
xhr.send();
} catch(e) {
log("FAILED: got exception " + e.message);
}
</script>
</body>
</html>
<?php
header("Access-Control-Allow-Origin: http://127.0.0.1:8000/");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: PUT");
if ($_SERVER['REQUEST_METHOD'] != "OPTIONS") {
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_REQUEST['uid']) || ($_REQUEST['uid'] != $_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="WebKit Test Realm/Cross Origin"');
header('HTTP/1.0 401 Unauthorized');
echo 'Authentication canceled';
exit;
} else {
echo "User: {$_SERVER['PHP_AUTH_USER']}, password: {$_SERVER['PHP_AUTH_PW']}.";
}
}
?>
......@@ -141,3 +141,8 @@ platform/mac/fonts/color-bitmap.html
# https://bugs.webkit.org/show_bug.cgi?id=38000 - r58107 causes video-play-stall and video-play-stall-seek to fail
http/tests/media/video-play-stall.html
http/tests/media/video-play-stall-seek.html
# https://bugs.webkit.org/show_bug.cgi?id=38265
# LayoutTests/http/tests/xmlhttprequest/access-control-preflight-credential-[a]sync.html fails on Tiger
http/tests/xmlhttprequest/access-control-preflight-credential-async.html
http/tests/xmlhttprequest/access-control-preflight-credential-sync.html
......@@ -4985,6 +4985,8 @@ http/tests/xmlhttprequest/access-control-basic-post-fail-non-simple-content-type
http/tests/xmlhttprequest/access-control-basic-whitelist-request-headers.html
http/tests/xmlhttprequest/access-control-preflight-async-header-denied.html
http/tests/xmlhttprequest/access-control-preflight-async-method-denied.html
http/tests/xmlhttprequest/access-control-preflight-credential-async.html
http/tests/xmlhttprequest/access-control-preflight-credential-sync.html
http/tests/xmlhttprequest/access-control-preflight-headers-async.html
http/tests/xmlhttprequest/access-control-preflight-headers-sync.html
http/tests/xmlhttprequest/access-control-preflight-sync-header-denied.html
......
2010-04-28 Julien Chaffraix <jchaffraix@webkit.org>
Reviewed by Alexey Proskuryakov.
[XHR] Cross-Origin synchronous request with credential raises NETWORK_ERR
https://bugs.webkit.org/show_bug.cgi?id=37781
<rdar://problem/7905150>
Tests: http/tests/xmlhttprequest/access-control-preflight-credential-async.html
http/tests/xmlhttprequest/access-control-preflight-credential-sync.html
Rolling the patch in as I could not reproduce Qt results locally.
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::DocumentThreadableLoader): Now we remove the
credential from the request here to avoid forgetting to do so in the different code path.
(WebCore::DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest): Just add the
"Origin" header.
(WebCore::DocumentThreadableLoader::loadRequest): Check here the the credential have
been removed so that we don't leak them. Also tweaked a comment to make it clear that
the URL check has issue when credential is involved.
2010-04-28 Noam Rosenthal <noam.rosenthal@nokia.com>
 
Reviewed by Kenneth Rohde Christiansen.
......@@ -81,16 +81,19 @@ DocumentThreadableLoader::DocumentThreadableLoader(Document* document, Threadabl
ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()))
makeSimpleCrossOriginAccessRequest(request);
OwnPtr<ResourceRequest> crossOriginRequest(new ResourceRequest(request));
crossOriginRequest->removeCredentials();
crossOriginRequest->setAllowCookies(m_options.allowCredentials);
if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields()))
makeSimpleCrossOriginAccessRequest(*crossOriginRequest);
else {
m_actualRequest.set(new ResourceRequest(request));
m_actualRequest->setAllowCookies(m_options.allowCredentials);
m_actualRequest.set(crossOriginRequest.release());
if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields()))
if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields()))
preflightSuccess();
else
makeCrossOriginAccessRequestWithPreflight(request);
makeCrossOriginAccessRequestWithPreflight(*m_actualRequest);
}
}
......@@ -106,8 +109,6 @@ void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const Resource
// Make a copy of the passed request so that we can modify some details.
ResourceRequest crossOriginRequest(request);
crossOriginRequest.removeCredentials();
crossOriginRequest.setAllowCookies(m_options.allowCredentials);
crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString());
loadRequest(crossOriginRequest, DoSecurityCheck);
......@@ -297,6 +298,11 @@ void DocumentThreadableLoader::preflightFailure()
void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, SecurityCheckPolicy securityCheck)
{
// Any credential should have been removed from the cross-site requests.
const KURL& requestURL = request.url();
ASSERT(m_sameOriginRequest || requestURL.user().isEmpty());
ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty());
if (m_async) {
// Don't sniff content or send load callbacks for the preflight request.
bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest;
......@@ -320,15 +326,15 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur
// No exception for file:/// resources, see <rdar://problem/4962298>.
// Also, if we have an HTTP response, then it wasn't a network error in fact.
if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) {
if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode() <= 0) {
m_client->didFail(error);
return;
}
// FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the
// request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was
// requested.
if (request.url() != response.url() && !isAllowedRedirect(response.url())) {
// requested. Also comparing the request and response URLs as strings will fail if the requestURL still has its credentials.
if (requestURL != response.url() && !isAllowedRedirect(response.url())) {
m_client->didFailRedirectCheck();
return;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment