crossorigin element resource loading should check HTTP redirection
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 11:17:09 +0000 (11:17 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 11:17:09 +0000 (11:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=130578

Reviewed by Daniel Bates and Brent Fulgham.

Source/WebCore:

Moved part of DocumentThreadableLoader redirection cross origin control code
into functions in CrossOriginAccessControl.cpp. Added cross origin control for
redirections in SubResourceLoader when policy is set to PotentiallyCrossOriginEnabled
using CrossOriginAccessControl.cpp new functions. Added a new test that checks that
cross-origin redirections are checked against CORS.

Test: http/tests/security/shape-image-cors-redirect.html

* loader/CrossOriginAccessControl.cpp:
(WebCore::isValidCrossOriginRedirectionURL): Returns true if the redirected URL is a valid URL for cross-origin requests.
(WebCore::cleanRedirectedRequestForAccessControl): Removes all headers added by the network backend that may cause the response CORS validation to fail.
* loader/CrossOriginAccessControl.h: Added above function prototypes.
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::redirectReceived): Used new CORS redirection methods of CrossOriginAccessControl.cpp.
* loader/SubresourceLoader.cpp:
(WebCore::SubresourceLoader::init): Initialize the SecurityOrigin to be used for loading the resource.
(WebCore::SubresourceLoader::willSendRequest): Added cross-origin redirection response check.
(WebCore::SubresourceLoader::checkCrossOriginAccessControl): Checks CORS and update request if needed. Returns true if control checks passed.
* loader/SubresourceLoader.h: Added checkCrossOriginAccessControl declaration and m_origin declaration.

LayoutTests:

shape-image-cors-redirect.html checks that cross-origin redirections are checked against CORS.
It also checks that same-origin redirections are not checked against CORS.

* http/tests/security/resources/redirect-allow-star.php: Added.
* http/tests/security/shape-image-cors-redirect-expected.html: Added.
* http/tests/security/shape-image-cors-redirect.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@198395 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/tests/security/resources/redirect-allow-star.php [new file with mode: 0755]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1.html [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2.html [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3.html [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4.html [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect-expected.html [new file with mode: 0644]
LayoutTests/http/tests/security/shape-image-cors-redirect.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/CrossOriginAccessControl.cpp
Source/WebCore/loader/CrossOriginAccessControl.h
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/SubresourceLoader.cpp
Source/WebCore/loader/SubresourceLoader.h

index c7abcff..c6d385b 100644 (file)
@@ -1,5 +1,19 @@
 2016-03-18  Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
+        crossorigin element resource loading should check HTTP redirection
+        https://bugs.webkit.org/show_bug.cgi?id=130578
+
+        Reviewed by Daniel Bates and Brent Fulgham.
+
+        shape-image-cors-redirect.html checks that cross-origin redirections are checked against CORS.
+        It also checks that same-origin redirections are not checked against CORS.
+
+        * http/tests/security/resources/redirect-allow-star.php: Added.
+        * http/tests/security/shape-image-cors-redirect-expected.html: Added.
+        * http/tests/security/shape-image-cors-redirect.html: Added.
+
+2016-03-18  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
         Move IndexedDB regular test to web-platform-tests
         https://bugs.webkit.org/show_bug.cgi?id=155581
 
index 9ef7a90..4ad6b84 100644 (file)
@@ -805,6 +805,11 @@ webkit.org/b/154687 streams/pipe-to.html [ Slow ]
 
 webkit.org/b/52185 fast/css/vertical-align-baseline-rowspan-010.html [ ImageOnlyFailure ]
 
+webkit.org/b/155634 http/tests/security/shape-image-cors-redirect-error-message-logging-1.html [ Pass Failure ]
+webkit.org/b/155634 http/tests/security/shape-image-cors-redirect-error-message-logging-2.html [ Pass Failure ]
+webkit.org/b/155634 http/tests/security/shape-image-cors-redirect-error-message-logging-3.html [ Pass Failure ]
+webkit.org/b/155634 http/tests/security/shape-image-cors-redirect-error-message-logging-4.html [ Pass Failure ]
+
 # Content Security Policy failures
 webkit.org/b/85558 http/tests/security/contentSecurityPolicy/1.1
 http/tests/security/contentSecurityPolicy/1.1/child-src [ Pass ]
diff --git a/LayoutTests/http/tests/security/resources/redirect-allow-star.php b/LayoutTests/http/tests/security/resources/redirect-allow-star.php
new file mode 100755 (executable)
index 0000000..c465a06
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+    $url = $_GET["url"];
+
+    $code = isset($_GET["code"]) ? $_GET["code"] : 302;
+
+    header("HTTP/1.1 $code");
+    header("Location: $url");
+    header("Access-Control-Allow-Origin: *");
+
+    # Workaround for https://bugs.webkit.org/show_bug.cgi?id=77538
+    # Caching redirects results in flakiness in tests that dump loader delegates.
+    header("Cache-Control: no-store");
+?>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1-expected.txt b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1-expected.txt
new file mode 100644 (file)
index 0000000..3649143
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Unsafe attempt to load URL http://127.0.0.1:8000/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse.
+Verify the error message in console in case of CORS failing checks.
+
+
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1.html b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-1.html
new file mode 100644 (file)
index 0000000..7d86a12
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Triggering message logging in case of failing CORS check</title>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+<style>
+    /* Not OK Tests: image resource loading should fail */
+    /* Cross-origin request is not OK because the HTTP header "Access-Control-Allow-Origin:" header is not returned for the final resource when the redirection was initiated from the same origin as the page. */
+    #notok-shape-outside-same-origin-redirection-disallow-url {
+        float: left;
+        width: 200px;
+        height: 20px;
+        -webkit-shape-outside: url("/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse");
+    }
+</style>
+</head>
+<body>
+    <p>Verify the error message in console in case of CORS failing checks.</p>
+    <div id="notok-shape-outside-same-origin-redirection-disallow-url"></div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2-expected.txt b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2-expected.txt
new file mode 100644 (file)
index 0000000..ff2d5a8
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Unsafe attempt to load URL http://localhost:8080/security/resources/redirect-allow-star.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse.
+Verify the error message in console in case of CORS failing checks.
+
+
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2.html b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-2.html
new file mode 100644 (file)
index 0000000..7b4ffe7
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Triggering message logging in case of failing CORS check</title>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+<style>
+    /* Cross-origin request is not OK because a "Access-Control-Allow-Origin:" header is not returned for the final resource. */
+    #notok-shape-outside-allow-redirection-disallow-url {
+        float: left;
+        width: 200px;
+        height: 20px;
+        -webkit-shape-outside: url("http://localhost:8080/security/resources/redirect-allow-star.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse");
+    }
+</style>
+</head>
+<body>
+    <p>Verify the error message in console in case of CORS failing checks.</p>
+    <div id="notok-shape-outside-allow-redirection-disallow-url"></div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3-expected.txt b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3-expected.txt
new file mode 100644 (file)
index 0000000..422339e
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Cross-origin redirection denied by Cross-Origin Resource Sharing policy: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
+Verify the error message in console in case of CORS failing checks.
+
+
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3.html b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-3.html
new file mode 100644 (file)
index 0000000..813e134
--- /dev/null
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Triggering message logging in case of failing CORS check</title>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+<style>
+    /* Cross-origin request is not OK because the "Access-Control-Allow-Origin: *" is not returned for the redirection */
+    #notok-shape-outside-disallow-redirection-allow-url {
+        float: left;
+        width: 200px;
+        height: 20px;
+        -webkit-shape-outside: url("http://localhost:8080/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dtrue");
+    }
+
+</style>
+</head>
+<body>
+    <p>Verify the error message in console in case of CORS failing checks.</p>
+    <div id="notok-shape-outside-disallow-redirection-allow-url"></div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4-expected.txt b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4-expected.txt
new file mode 100644 (file)
index 0000000..dd30606
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: Cross-origin redirection denied by Cross-Origin Resource Sharing policy: Redirected to either a non-HTTP URL or a URL that contains credentials.
+Verify the error message in console in case of CORS failing checks.
+
+
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4.html b/LayoutTests/http/tests/security/shape-image-cors-redirect-error-message-logging-4.html
new file mode 100644 (file)
index 0000000..276c7a4
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Triggering message logging in case of failing CORS check</title>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+<style>
+    /* Cross-origin request is not OK because redirection URL is not a http URL */
+    #notok-shape-outside-disallow-redirection-not-http-url {
+        float: left;
+        width: 200px;
+        height: 20px;
+        -webkit-shape-outside: url("http://localhost:8080/security/resources/redirect-allow-star.php?url=mailto%3A%2F%2Fuser%40example.com");
+    }
+</style>
+</head>
+<body>
+    <p>Verify the error message in console in case of CORS failing checks.</p>
+    <div id="notok-shape-outside-disallow-redirection-not-http-url"></div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect-expected.html b/LayoutTests/http/tests/security/shape-image-cors-redirect-expected.html
new file mode 100644 (file)
index 0000000..5fd0d4b
--- /dev/null
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+    #clear-left {
+        clear: left;
+        font: 20px/1 Ahem, sans-serif;
+        color: green;
+    }
+
+    #clear-left > div {
+        float: left;
+        height: 20px;
+    }
+
+    /* OK Tests: image resource loading should succeed */
+    #ok-shape-outside-allow-url {
+        width: 100px;
+    }
+
+    #ok-shape-outside-same-origin-redirection-allow-url {
+        width: 100px;
+    }
+
+    #ok-shape-outside-allow-redirection-allow-url {
+        width: 100px;
+    }
+
+    /* Not OK Tests: image resource loading should fail */
+    #notok-shape-outside-same-origin-redirection-disallow-url {
+        width: 200px;
+    }
+
+    #notok-shape-outside-allow-redirection-disallow-url {
+        width: 200px;
+    }
+
+    #notok-shape-outside-disallow-redirection-allow-url {
+        width: 200px;
+    }
+</style>
+</head>
+<body>
+    <p>Verify that images not allowed by CORS don't affect the layout and that images (and any redirection) with a "Access-Control-Allow-Origin: *" header do define the layout.</p>
+    <div id="clear-left"><div id="ok-shape-outside-allow-url"></div>X</div>
+    <div id="clear-left"><div id="ok-shape-outside-same-origin-redirection-allow-url"></div>X</div>
+    <div id="clear-left"><div id="ok-shape-outside-allow-redirection-allow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-same-origin-redirection-disallow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-allow-redirection-disallow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-disallow-redirection-allow-url"></div>X</div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/shape-image-cors-redirect.html b/LayoutTests/http/tests/security/shape-image-cors-redirect.html
new file mode 100644 (file)
index 0000000..b4d342c
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+    #clear-left {
+        clear: left;
+        font: 20px/1 Ahem, sans-serif;
+        color: green;
+    }
+
+    #clear-left > div {
+        float: left;
+        width: 200px;
+        height: 20px;
+    }
+
+    /* OK Tests: image resource loading should succeed */
+    /* Cross-origin request is OK because the "Access-Control-Allow-Origin: *" is returned for the resource (no redirection). */
+    #ok-shape-outside-allow-url {
+        -webkit-shape-outside: url("http://localhost:8080/security/resources/image-access-control.php?file=../../resources/square100.png&allow=true");
+    }
+
+    /* Cross-origin request is OK because the "Access-Control-Allow-Origin: *" is returned for the final resource and the redirection is same origin. */
+    #ok-shape-outside-same-origin-redirection-allow-url {
+        -webkit-shape-outside: url("/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dtrue");
+    }
+
+    /* Cross-origin request is OK because the "Access-Control-Allow-Origin: *" is returned for both redirection and final resource. */
+    #ok-shape-outside-allow-redirection-allow-url {
+        -webkit-shape-outside: url("http://localhost:8080/security/resources/redirect-allow-star.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dtrue");
+    }
+
+    /* Not OK Tests: image resource loading should fail */
+    /* Cross-origin request is not OK because the HTTP header "Access-Control-Allow-Origin:" header is not returned for the final resource when the redirection was initiated from the same origin as the page. */
+    #notok-shape-outside-same-origin-redirection-disallow-url {
+        -webkit-shape-outside: url("/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse");
+    }
+
+    /* Cross-origin request is not OK because a "Access-Control-Allow-Origin:" header is not returned for the final resource. */
+    #notok-shape-outside-allow-redirection-disallow-url {
+        -webkit-shape-outside: url("http://localhost:8080/security/resources/redirect-allow-star.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dfalse");
+    }
+
+    /* Cross-origin request is not OK because the "Access-Control-Allow-Origin: *" is not returned for the redirection */
+    #notok-shape-outside-disallow-redirection-allow-url {
+        -webkit-shape-outside: url("http://localhost:8080/resources/redirect.php?url=http%3A%2F%2Flocalhost%3A8080%2Fsecurity%2Fresources%2Fimage-access-control.php%3Ffile%3D..%2F..%2Fresources%2Fsquare100.png%26allow%3Dtrue");
+    }
+</style>
+</head>
+<body>
+    <p>Verify that images not allowed by CORS don't affect the layout and that images (and any redirection) with a "Access-Control-Allow-Origin: *" header do define the layout.</p>
+    <div id="clear-left"><div id="ok-shape-outside-allow-url"></div>X</div>
+    <div id="clear-left"><div id="ok-shape-outside-same-origin-redirection-allow-url"></div>X</div>
+    <div id="clear-left"><div id="ok-shape-outside-allow-redirection-allow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-same-origin-redirection-disallow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-allow-redirection-disallow-url"></div>X</div>
+    <div id="clear-left"><div id="notok-shape-outside-disallow-redirection-allow-url"></div>X</div>
+</body>
+</html>
index 6c99c57..9c40da1 100644 (file)
@@ -1,3 +1,30 @@
+2016-03-18  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        crossorigin element resource loading should check HTTP redirection
+        https://bugs.webkit.org/show_bug.cgi?id=130578
+
+        Reviewed by Daniel Bates and Brent Fulgham.
+
+        Moved part of DocumentThreadableLoader redirection cross origin control code
+        into functions in CrossOriginAccessControl.cpp. Added cross origin control for
+        redirections in SubResourceLoader when policy is set to PotentiallyCrossOriginEnabled 
+        using CrossOriginAccessControl.cpp new functions. Added a new test that checks that 
+        cross-origin redirections are checked against CORS.
+
+        Test: http/tests/security/shape-image-cors-redirect.html
+
+        * loader/CrossOriginAccessControl.cpp:
+        (WebCore::isValidCrossOriginRedirectionURL): Returns true if the redirected URL is a valid URL for cross-origin requests.
+        (WebCore::cleanRedirectedRequestForAccessControl): Removes all headers added by the network backend that may cause the response CORS validation to fail.
+        * loader/CrossOriginAccessControl.h: Added above function prototypes.
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::redirectReceived): Used new CORS redirection methods of CrossOriginAccessControl.cpp.
+        * loader/SubresourceLoader.cpp:
+        (WebCore::SubresourceLoader::init): Initialize the SecurityOrigin to be used for loading the resource.
+        (WebCore::SubresourceLoader::willSendRequest): Added cross-origin redirection response check.
+        (WebCore::SubresourceLoader::checkCrossOriginAccessControl): Checks CORS and update request if needed. Returns true if control checks passed.
+        * loader/SubresourceLoader.h: Added checkCrossOriginAccessControl declaration and m_origin declaration.
+
 2016-03-18  Darin Adler  <darin@apple.com>
 
         Disable Caches in Safari's Develop menu does not disable caches.
index 01a4d6f..ad0cf1d 100644 (file)
@@ -31,6 +31,7 @@
 #include "HTTPParsers.h"
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
+#include "SchemeRegistry.h"
 #include "SecurityOrigin.h"
 #include <mutex>
 #include <wtf/NeverDestroyed.h>
@@ -133,6 +134,24 @@ ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& reque
     return preflightRequest;
 }
 
+bool isValidCrossOriginRedirectionURL(const URL& redirectURL)
+{
+    return SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(redirectURL.protocol())
+        && redirectURL.user().isEmpty()
+        && redirectURL.pass().isEmpty();
+}
+
+void cleanRedirectedRequestForAccessControl(ResourceRequest& request)
+{
+    // Remove headers that may have been added by the network layer that cause access control to fail.
+    request.clearHTTPContentType();
+    request.clearHTTPReferrer();
+    request.clearHTTPOrigin();
+    request.clearHTTPUserAgent();
+    request.clearHTTPAccept();
+    request.clearHTTPAcceptEncoding();
+}
+
 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription)
 {
     // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent,
index 7438c03..c5524b0 100644 (file)
@@ -41,6 +41,7 @@ enum class HTTPHeaderName;
 class ResourceRequest;
 class ResourceResponse;
 class SecurityOrigin;
+class URL;
 
 bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&);
 bool isOnAccessControlSimpleRequestMethodWhitelist(const String&);
@@ -50,6 +51,9 @@ bool isOnAccessControlResponseHeaderWhitelist(const String&);
 void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin*, StoredCredentials);
 ResourceRequest createAccessControlPreflightRequest(const ResourceRequest&, SecurityOrigin*);
 
+bool isValidCrossOriginRedirectionURL(const URL&);
+void cleanRedirectedRequestForAccessControl(ResourceRequest&);
+
 bool passesAccessControlCheck(const ResourceResponse&, StoredCredentials, SecurityOrigin*, String& errorDescription);
 void parseAccessControlExposeHeadersAllowList(const String& headerValue, HTTPHeaderSet&);
 
index 1e582a4..6b2ef89 100644 (file)
@@ -208,9 +208,7 @@ void DocumentThreadableLoader::redirectReceived(CachedResource* resource, Resour
         bool allowRedirect = false;
         if (m_simpleRequest) {
             String accessControlErrorDescription;
-            allowRedirect = SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())
-                            && request.url().user().isEmpty()
-                            && request.url().pass().isEmpty()
+            allowRedirect = isValidCrossOriginRedirectionURL(request.url())
                             && (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, m_options.allowCredentials(), securityOrigin(), accessControlErrorDescription));
         }
 
@@ -233,13 +231,8 @@ void DocumentThreadableLoader::redirectReceived(CachedResource* resource, Resour
             if (m_options.credentialRequest() == ClientDidNotRequestCredentials)
                 m_options.setAllowCredentials(DoNotAllowStoredCredentials);
 
-            // Remove any headers that may have been added by the network layer that cause access control to fail.
-            request.clearHTTPContentType();
-            request.clearHTTPReferrer();
-            request.clearHTTPOrigin();
-            request.clearHTTPUserAgent();
-            request.clearHTTPAccept();
-            request.clearHTTPAcceptEncoding();
+            cleanRedirectedRequestForAccessControl(request);
+
             makeCrossOriginAccessRequest(request);
             return;
         }
index db7c634..da3edb2 100644 (file)
@@ -30,6 +30,7 @@
 #include "SubresourceLoader.h"
 
 #include "CachedResourceLoader.h"
+#include "CrossOriginAccessControl.h"
 #include "DiagnosticLoggingClient.h"
 #include "DiagnosticLoggingKeys.h"
 #include "Document.h"
@@ -146,6 +147,13 @@ bool SubresourceLoader::init(const ResourceRequest& request)
     ASSERT(!reachedTerminalState());
     m_state = Initialized;
     m_documentLoader->addSubresourceLoader(this);
+
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=155633.
+    // SubresourceLoader could use the document origin as a default and set PotentiallyCrossOriginEnabled requests accordingly.
+    // This would simplify resource loader users as they would only need to set the policy to PotentiallyCrossOriginEnabled.
+    if (options().requestOriginPolicy() == PotentiallyCrossOriginEnabled)
+        m_origin = SecurityOrigin::createFromString(request.httpOrigin());
+
     return true;
 }
 
@@ -182,6 +190,12 @@ void SubresourceLoader::willSendRequestInternal(ResourceRequest& newRequest, con
             cancel();
             return;
         }
+
+        if (options().requestOriginPolicy() == PotentiallyCrossOriginEnabled && !checkCrossOriginAccessControl(request(), redirectResponse, newRequest)) {
+            cancel();
+            return;
+        }
+
         if (m_resource->isImage() && m_documentLoader->cachedResourceLoader().shouldDeferImageLoad(newRequest.url())) {
             cancel();
             return;
@@ -370,6 +384,31 @@ static void logResourceLoaded(Frame* frame, CachedResource::Type type)
     frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceKey(), DiagnosticLoggingKeys::loadedKey(), resourceType, ShouldSample::Yes);
 }
 
+bool SubresourceLoader::checkCrossOriginAccessControl(const ResourceRequest& previousRequest, const ResourceResponse& redirectResponse, ResourceRequest& newRequest)
+{
+    if (m_origin->canRequest(newRequest.url()))
+        return true;
+
+    String errorDescription;
+    bool responsePassesCORS = m_origin->canRequest(previousRequest.url())
+        || passesAccessControlCheck(redirectResponse, options().allowCredentials(), m_origin.get(), errorDescription);
+    if (!responsePassesCORS || !isValidCrossOriginRedirectionURL(newRequest.url())) {
+        if (m_frame && m_frame->document()) {
+            String errorMessage = "Cross-origin redirection denied by Cross-Origin Resource Sharing policy: " +
+                (!responsePassesCORS ? errorDescription : "Redirected to either a non-HTTP URL or a URL that contains credentials.");
+            m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, errorMessage);
+        }
+        return false;
+    }
+
+    // If the request URL origin is not the same as the original origin, the request origin should be set to a globally unique identifier.
+    m_origin = SecurityOrigin::createUnique();
+    cleanRedirectedRequestForAccessControl(newRequest);
+    updateRequestForAccessControl(newRequest, m_origin.get(), options().allowCredentials());
+
+    return true;
+}
+
 void SubresourceLoader::didFinishLoading(double finishTime)
 {
     if (m_state != Initialized)
index 083eff4..d2bc2ec 100644 (file)
@@ -40,6 +40,7 @@ class CachedResource;
 class CachedResourceLoader;
 class Document;
 class ResourceRequest;
+class SecurityOrigin;
 
 class SubresourceLoader final : public ResourceLoader {
 public:
@@ -91,6 +92,7 @@ private:
 #endif
 
     bool checkForHTTPStatusCodeError();
+    bool checkCrossOriginAccessControl(const ResourceRequest&, const ResourceResponse&, ResourceRequest& newRequest);
 
     void didReceiveDataOrBuffer(const char*, int, PassRefPtr<SharedBuffer>, long long encodedDataLength, DataPayloadType);
 
@@ -124,6 +126,7 @@ private:
     bool m_loadingMultipartContent;
     SubresourceLoaderState m_state;
     std::unique_ptr<RequestCountTracker> m_requestCountTracker;
+    RefPtr<SecurityOrigin> m_origin;
 };
 
 }