Title: [204693] trunk
Revision
204693
Author
[email protected]
Date
2016-08-21 06:36:48 -0700 (Sun, 21 Aug 2016)

Log Message

cross-origin requests redirected fail or drop author requested headers
https://bugs.webkit.org/show_bug.cgi?id=112471

Patch by Youenn Fablet <[email protected]> on 2016-08-21
Reviewed by Alex Christensen.

Source/WebCore:

Test: http/tests/xmlhttprequest/redirections-and-user-headers.html

Storing original headers in DocumentThreadableLoader.
In case of cross-origin redirection in CORS mode, set the new request headers to the original headers.
Add a special handling to Authorization header that should not be used when it is already removed by the network layer.

* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::redirectReceived):
(WebCore::DocumentThreadableLoader::loadRequest):
* loader/DocumentThreadableLoader.h:

LayoutTests:

* http/tests/xmlhttprequest/redirections-and-user-headers-expected.txt: Added.
* http/tests/xmlhttprequest/redirections-and-user-headers.html: Added.
* http/tests/xmlhttprequest/resources/access-control-preflight-redirect.php: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (204692 => 204693)


--- trunk/LayoutTests/ChangeLog	2016-08-21 12:18:43 UTC (rev 204692)
+++ trunk/LayoutTests/ChangeLog	2016-08-21 13:36:48 UTC (rev 204693)
@@ -1,3 +1,14 @@
+2016-08-21  Youenn Fablet  <[email protected]>
+
+        cross-origin requests redirected fail or drop author requested headers
+        https://bugs.webkit.org/show_bug.cgi?id=112471
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/xmlhttprequest/redirections-and-user-headers-expected.txt: Added.
+        * http/tests/xmlhttprequest/redirections-and-user-headers.html: Added.
+        * http/tests/xmlhttprequest/resources/access-control-preflight-redirect.php: Added.
+
 2016-08-19  Sam Weinig  <[email protected]>
 
         Location.ancestorOrigins should return a FrozenArray<USVString>

Added: trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers-expected.txt (0 => 204693)


--- trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers-expected.txt	2016-08-21 13:36:48 UTC (rev 204693)
@@ -0,0 +1,12 @@
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url="" Cross-origin redirection denied by Cross-Origin Resource Sharing policy.
+CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url="" Cross-origin redirection denied by Cross-Origin Resource Sharing policy.
+
+PASS Check headers after same-origin redirection to same-origin resource (simple request) 
+PASS Check headers after same-origin redirection to same-origin resource (not simple request) 
+PASS Check headers after same origin redirection to cross-origin resource (simple request) 
+PASS Check headers after same origin redirection to cross-origin resource (not simple request) 
+PASS Check headers after cross-origin redirection to same-origin resource (simple request) 
+FAIL Check headers after cross-origin redirection to same-origin resource (not simple request) promise_test: Unhandled rejection with value: "Loading failure"
+PASS Check headers after cross-origin redirection to cross-origin resource (simple request) 
+FAIL Check headers after cross-origin redirection to cross-origin resource (not simple request) promise_test: Unhandled rejection with value: "Loading failure"
+

Added: trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers.html (0 => 204693)


--- trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/redirections-and-user-headers.html	2016-08-21 13:36:48 UTC (rev 204693)
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>XMLHttpRequest: ensure user script headers do not get dropped during cross-origin redirections</title>
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script type="text/_javascript_">
+function doTest(testName, testURL, simpleRequest, changeOrigin)
+{
+  promise_test(function(test) {
+    var resolvePromise, rejectPromise;
+    var promise = new Promise((resolve, reject) => {
+        resolvePromise = resolve;
+        rejectPromise = reject;
+    });
+
+    var xhr = new XMLHttpRequest;
+    xhr.open("GET", testURL);
+    xhr.setRequestHeader("accept", "groovy");
+
+    if (!simpleRequest) {
+        xhr.setRequestHeader("x-webkit", "funky");
+        xhr.setRequestHeader("content-type", "rocky");
+        xhr.setRequestHeader("authorization", "Basic QXV0aG9yaXphdGlvbi1IZWFkZXI6QXV0aG9yaXphdGlvbi1IZWFkZXI=");
+    }
+
+    xhr._onload_ = (test) => {
+        assert_true(xhr.responseText.indexOf("accept header found: groovy") !== -1, "xhr final request should have an accept=groovy header");
+        if (!simpleRequest) {
+            assert_true(xhr.responseText.indexOf("x-webkit header found: funky") !== -1, "xhr final request should have a x-webkit=funky header");
+            assert_true(xhr.responseText.indexOf("content-type header found: rocky") !== -1, "xhr final request should have a content-type=groovy header");
+            assert_true(xhr.responseText.indexOf("not found any authorization header") !== -1, "xhr final request should not have an authorization header");
+        }
+        testPassed = true;
+    }
+
+    xhr._onerror_ = (e) => {
+        rejectPromise("Loading failure");
+    }
+
+    var testPassed = false;
+    xhr._onloadend_ = () => {
+        testPassed ? resolvePromise() : rejectPromise("testPassed is not true");
+    }
+    xhr.send();
+    return promise;
+  }, testName);
+}
+
+var simpleRequest = true;
+
+doTest("Check headers after same-origin redirection to same-origin resource (simple request)",
+        "resources/access-control-preflight-redirect.php?redirect=true&url=""
+        simpleRequest);
+
+doTest("Check headers after same-origin redirection to same-origin resource (not simple request)",
+        "resources/access-control-preflight-redirect.php?redirect=true&url=""
+        !simpleRequest);
+
+doTest("Check headers after same origin redirection to cross-origin resource (simple request)",
+        "resources/access-control-preflight-redirect.php?redirect=true&url=""
+        simpleRequest);
+
+doTest("Check headers after same origin redirection to cross-origin resource (not simple request)",
+        "resources/access-control-preflight-redirect.php?redirect=true&url=""
+        !simpleRequest);
+
+doTest("Check headers after cross-origin redirection to same-origin resource (simple request)",
+        "http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url=""
+        simpleRequest);
+
+// FIXME: Thistest will not pass as long as not-simple cross origin requests are not allowed to redirect. See https://bugs.webkit.org/show_bug.cgi?id=159056.
+doTest("Check headers after cross-origin redirection to same-origin resource (not simple request)",
+        "http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url=""
+        !simpleRequest);
+
+doTest("Check headers after cross-origin redirection to cross-origin resource (simple request)",
+        "http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url=""
+        simpleRequest);
+
+// FIXME: Thistest will not pass as long as not-simple cross origin requests are not allowed to redirect. See https://bugs.webkit.org/show_bug.cgi?id=159056.
+doTest("Check headers after cross-origin redirection to cross-origin resource (not simple request)",
+        "http://localhost:8080/xmlhttprequest/resources/access-control-preflight-redirect.php?redirect=true&url=""
+        !simpleRequest);
+
+    </script>
+  </body>
+</html>
+

Added: trunk/LayoutTests/http/tests/xmlhttprequest/resources/access-control-preflight-redirect.php (0 => 204693)


--- trunk/LayoutTests/http/tests/xmlhttprequest/resources/access-control-preflight-redirect.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/xmlhttprequest/resources/access-control-preflight-redirect.php	2016-08-21 13:36:48 UTC (rev 204693)
@@ -0,0 +1,47 @@
+<?php
+
+header("Access-Control-Allow-Origin: *");
+header("Access-Control-Allow-Methods: GET");
+header("Access-Control-Allow-Headers: authorization, x-webkit, content-type");
+
+if ($_SERVER['REQUEST_METHOD'] == "OPTIONS") {
+    header("HTTP/1.1 200");
+    return;
+}
+
+$redirect = $_GET['redirect'];
+$url = ""
+
+if (isset($redirect)) {
+    header("HTTP/1.1 302");
+    header("Location: $url");
+    return;
+}
+
+header("HTTP/1.1 200");
+
+if (!isset($_SERVER["HTTP_X_WEBKIT"])) {
+    echo "not found any x-webkit header found";
+} else {
+    echo "x-webkit header found: " . $_SERVER["HTTP_X_WEBKIT"];
+}
+echo "\n";
+if (!isset($_SERVER["HTTP_ACCEPT"])) {
+    echo "not found any accept header found";
+} else {
+    echo "accept header found: " . $_SERVER["HTTP_ACCEPT"];
+}
+echo "\n";
+if (!isset($_SERVER["CONTENT_TYPE"])) {
+    echo "not found any content-type header";
+} else {
+    echo "content-type header found: " . $_SERVER["CONTENT_TYPE"];
+}
+echo "\n";
+if (!isset($_SERVER['PHP_AUTH_USER'])) {
+    echo "not found any authorization header";
+} else {
+    echo "authorization header found";
+}
+
+?>

Modified: trunk/Source/WebCore/ChangeLog (204692 => 204693)


--- trunk/Source/WebCore/ChangeLog	2016-08-21 12:18:43 UTC (rev 204692)
+++ trunk/Source/WebCore/ChangeLog	2016-08-21 13:36:48 UTC (rev 204693)
@@ -1,3 +1,21 @@
+2016-08-21  Youenn Fablet  <[email protected]>
+
+        cross-origin requests redirected fail or drop author requested headers
+        https://bugs.webkit.org/show_bug.cgi?id=112471
+
+        Reviewed by Alex Christensen.
+
+        Test: http/tests/xmlhttprequest/redirections-and-user-headers.html
+
+        Storing original headers in DocumentThreadableLoader.
+        In case of cross-origin redirection in CORS mode, set the new request headers to the original headers.
+        Add a special handling to Authorization header that should not be used when it is already removed by the network layer.
+
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::redirectReceived):
+        (WebCore::DocumentThreadableLoader::loadRequest):
+        * loader/DocumentThreadableLoader.h:
+
 2016-08-21  Frederic Wang  <[email protected]>
 
         Introduce a MathMLAnnotationElement class for the annotation/annotation-xml elements

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp (204692 => 204693)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2016-08-21 12:18:43 UTC (rev 204692)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2016-08-21 13:36:48 UTC (rev 204693)
@@ -99,6 +99,12 @@
 
     m_options.allowCredentials = (m_options.credentials == FetchOptions::Credentials::Include || (m_options.credentials == FetchOptions::Credentials::SameOrigin && m_sameOriginRequest)) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
 
+    ASSERT(!request.httpHeaderFields().contains(HTTPHeaderName::Origin));
+
+    // Copy headers if we need to replay the request after a redirection.
+    if (m_async && m_options.mode == FetchOptions::Mode::Cors)
+        m_originalHeaders = request.httpHeaderFields();
+
     if (m_sameOriginRequest || m_options.mode == FetchOptions::Mode::NoCors) {
         loadRequest(WTFMove(request), DoSecurityCheck);
         return;
@@ -246,9 +252,13 @@
 
     clearResource();
 
-    // We need to clean the request again as SubresourceLoader may not always do the cleaning,
-    // especially in the case of a cross-origin load but redirection sticking to the same origin.
-    cleanRedirectedRequestForAccessControl(request);
+    ASSERT(m_originalHeaders);
+    // Let's fetch the request with the original headers (equivalent to request cloning specified by fetch algorithm).
+    // Do not copy the Authorization header if removed by the network layer.
+    if (!request.httpHeaderFields().contains(HTTPHeaderName::Authorization))
+        m_originalHeaders->remove(HTTPHeaderName::Authorization);
+    request.setHTTPHeaderFields(*m_originalHeaders);
+
     makeCrossOriginAccessRequest(ResourceRequest(request));
 }
 

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.h (204692 => 204693)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.h	2016-08-21 12:18:43 UTC (rev 204692)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.h	2016-08-21 13:36:48 UTC (rev 204693)
@@ -117,6 +117,7 @@
         bool m_async;
         std::unique_ptr<ContentSecurityPolicy> m_contentSecurityPolicy;
         Optional<CrossOriginPreflightChecker> m_preflightChecker;
+        Optional<HTTPHeaderMap> m_originalHeaders;
     };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to