OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 11 matching lines...) Expand all Loading... |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 * | 24 * |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "core/fetch/CrossOriginAccessControl.h" | 28 #include "core/fetch/CrossOriginAccessControl.h" |
29 | 29 |
30 #include "core/fetch/Resource.h" | 30 #include "core/fetch/Resource.h" |
31 #include "core/fetch/ResourceLoaderOptions.h" | 31 #include "core/fetch/ResourceLoaderOptions.h" |
| 32 #include "core/frame/UseCounter.h" |
32 #include "platform/network/HTTPParsers.h" | 33 #include "platform/network/HTTPParsers.h" |
33 #include "platform/network/ResourceRequest.h" | 34 #include "platform/network/ResourceRequest.h" |
34 #include "platform/network/ResourceResponse.h" | 35 #include "platform/network/ResourceResponse.h" |
35 #include "platform/weborigin/SchemeRegistry.h" | 36 #include "platform/weborigin/SchemeRegistry.h" |
36 #include "platform/weborigin/SecurityOrigin.h" | 37 #include "platform/weborigin/SecurityOrigin.h" |
37 #include "wtf/Threading.h" | 38 #include "wtf/Threading.h" |
38 #include "wtf/text/AtomicString.h" | 39 #include "wtf/text/AtomicString.h" |
39 #include "wtf/text/StringBuilder.h" | 40 #include "wtf/text/StringBuilder.h" |
40 | 41 |
41 namespace blink { | 42 namespace blink { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 } | 108 } |
108 | 109 |
109 static bool isInterestingStatusCode(int statusCode) | 110 static bool isInterestingStatusCode(int statusCode) |
110 { | 111 { |
111 // Predicate that gates what status codes should be included in | 112 // Predicate that gates what status codes should be included in |
112 // console error messages for responses containing no access | 113 // console error messages for responses containing no access |
113 // control headers. | 114 // control headers. |
114 return statusCode >= 400; | 115 return statusCode >= 400; |
115 } | 116 } |
116 | 117 |
117 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential
s includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription) | 118 bool passesAccessControlCheck(ExecutionContext* context, const ResourceResponse&
response, StoredCredentials includeCredentials, SecurityOrigin* securityOrigin,
String& errorDescription) |
118 { | 119 { |
119 AtomicallyInitializedStatic(AtomicString&, accessControlAllowOrigin = *new A
tomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)); | 120 AtomicallyInitializedStatic(AtomicString&, accessControlAllowOrigin = *new A
tomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)); |
120 AtomicallyInitializedStatic(AtomicString&, accessControlAllowCredentials = *
new AtomicString("access-control-allow-credentials", AtomicString::ConstructFrom
Literal)); | 121 AtomicallyInitializedStatic(AtomicString&, accessControlAllowCredentials = *
new AtomicString("access-control-allow-credentials", AtomicString::ConstructFrom
Literal)); |
121 | 122 |
122 if (!response.httpStatusCode()) { | 123 if (!response.httpStatusCode()) { |
123 errorDescription = "Received an invalid response. Origin '" + securityOr
igin->toString() + "' is therefore not allowed access."; | 124 errorDescription = "Received an invalid response. Origin '" + securityOr
igin->toString() + "' is therefore not allowed access."; |
124 return false; | 125 return false; |
125 } | 126 } |
126 | 127 |
127 const AtomicString& accessControlOriginString = response.httpHeaderField(acc
essControlAllowOrigin); | 128 const AtomicString& accessControlOriginString = response.httpHeaderField(acc
essControlAllowOrigin); |
(...skipping 23 matching lines...) Expand all Loading... |
151 } | 152 } |
152 return false; | 153 return false; |
153 } | 154 } |
154 | 155 |
155 if (includeCredentials == AllowStoredCredentials) { | 156 if (includeCredentials == AllowStoredCredentials) { |
156 const AtomicString& accessControlCredentialsString = response.httpHeader
Field(accessControlAllowCredentials); | 157 const AtomicString& accessControlCredentialsString = response.httpHeader
Field(accessControlAllowCredentials); |
157 if (accessControlCredentialsString != "true") { | 158 if (accessControlCredentialsString != "true") { |
158 errorDescription = "Credentials flag is 'true', but the 'Access-Cont
rol-Allow-Credentials' header is '" + accessControlCredentialsString + "'. It mu
st be 'true' to allow credentials."; | 159 errorDescription = "Credentials flag is 'true', but the 'Access-Cont
rol-Allow-Credentials' header is '" + accessControlCredentialsString + "'. It mu
st be 'true' to allow credentials."; |
159 return false; | 160 return false; |
160 } | 161 } |
| 162 if (accessControlOriginString == "null") |
| 163 UseCounter::count(context, UseCounter::CORSCredentialedNullOriginAcc
essAllowed); |
161 } | 164 } |
162 | 165 |
163 return true; | 166 return true; |
164 } | 167 } |
165 | 168 |
166 bool passesPreflightStatusCheck(const ResourceResponse& response, String& errorD
escription) | 169 bool passesPreflightStatusCheck(const ResourceResponse& response, String& errorD
escription) |
167 { | 170 { |
168 if (response.httpStatusCode() < 200 || response.httpStatusCode() >= 400) { | 171 if (response.httpStatusCode() < 200 || response.httpStatusCode() >= 400) { |
169 errorDescription = "Invalid HTTP status code " + String::number(response
.httpStatusCode()); | 172 errorDescription = "Invalid HTTP status code " + String::number(response
.httpStatusCode()); |
170 return false; | 173 return false; |
(...skipping 22 matching lines...) Expand all Loading... |
193 } | 196 } |
194 | 197 |
195 if (!(requestURL.user().isEmpty() && requestURL.pass().isEmpty())) { | 198 if (!(requestURL.user().isEmpty() && requestURL.pass().isEmpty())) { |
196 errorDescription = "The request was redirected to a URL ('" + requestURL
.string() + "') containing userinfo, which is disallowed for cross-origin reques
ts."; | 199 errorDescription = "The request was redirected to a URL ('" + requestURL
.string() + "') containing userinfo, which is disallowed for cross-origin reques
ts."; |
197 return false; | 200 return false; |
198 } | 201 } |
199 | 202 |
200 return true; | 203 return true; |
201 } | 204 } |
202 | 205 |
203 bool CrossOriginAccessControl::handleRedirect(Resource* resource, SecurityOrigin
* securityOrigin, ResourceRequest& request, const ResourceResponse& redirectResp
onse, ResourceLoaderOptions& options, String& errorMessage) | 206 bool CrossOriginAccessControl::handleRedirect(ExecutionContext* context, Resourc
e* resource, SecurityOrigin* securityOrigin, ResourceRequest& request, const Res
ourceResponse& redirectResponse, ResourceLoaderOptions& options, String& errorMe
ssage) |
204 { | 207 { |
205 // http://www.w3.org/TR/cors/#redirect-steps terminology: | 208 // http://www.w3.org/TR/cors/#redirect-steps terminology: |
206 const KURL& originalURL = redirectResponse.url(); | 209 const KURL& originalURL = redirectResponse.url(); |
207 const KURL& requestURL = request.url(); | 210 const KURL& requestURL = request.url(); |
208 | 211 |
209 bool redirectCrossOrigin = !securityOrigin->canRequest(requestURL); | 212 bool redirectCrossOrigin = !securityOrigin->canRequest(requestURL); |
210 | 213 |
211 // Same-origin request URLs that redirect are allowed without checking acces
s. | 214 // Same-origin request URLs that redirect are allowed without checking acces
s. |
212 if (!securityOrigin->canRequest(originalURL)) { | 215 if (!securityOrigin->canRequest(originalURL)) { |
213 // Follow http://www.w3.org/TR/cors/#redirect-steps | 216 // Follow http://www.w3.org/TR/cors/#redirect-steps |
214 String errorDescription; | 217 String errorDescription; |
215 | 218 |
216 // Steps 3 & 4 - check if scheme and other URL restrictions hold. | 219 // Steps 3 & 4 - check if scheme and other URL restrictions hold. |
217 bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescriptio
n); | 220 bool allowRedirect = isLegalRedirectLocation(requestURL, errorDescriptio
n); |
218 if (allowRedirect) { | 221 if (allowRedirect) { |
219 // Step 5: perform resource sharing access check. | 222 // Step 5: perform resource sharing access check. |
220 StoredCredentials withCredentials = resource->lastResourceRequest().
allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials; | 223 StoredCredentials withCredentials = resource->lastResourceRequest().
allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials; |
221 allowRedirect = passesAccessControlCheck(redirectResponse, withCrede
ntials, securityOrigin, errorDescription); | 224 allowRedirect = passesAccessControlCheck(context, redirectResponse,
withCredentials, securityOrigin, errorDescription); |
222 if (allowRedirect) { | 225 if (allowRedirect) { |
223 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(o
riginalURL); | 226 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(o
riginalURL); |
224 // Step 6: if the request URL origin is not same origin as the o
riginal URL's, | 227 // Step 6: if the request URL origin is not same origin as the o
riginal URL's, |
225 // set the source origin to a globally unique identifier. | 228 // set the source origin to a globally unique identifier. |
226 if (!originalOrigin->canRequest(requestURL)) { | 229 if (!originalOrigin->canRequest(requestURL)) { |
227 options.securityOrigin = SecurityOrigin::createUnique(); | 230 options.securityOrigin = SecurityOrigin::createUnique(); |
228 securityOrigin = options.securityOrigin.get(); | 231 securityOrigin = options.securityOrigin.get(); |
229 } | 232 } |
230 } | 233 } |
231 } | 234 } |
232 if (!allowRedirect) { | 235 if (!allowRedirect) { |
233 const String& originalOrigin = SecurityOrigin::create(originalURL)->
toString(); | 236 const String& originalOrigin = SecurityOrigin::create(originalURL)->
toString(); |
234 errorMessage = "Redirect at origin '" + originalOrigin + "' has been
blocked from loading by Cross-Origin Resource Sharing policy: " + errorDescript
ion; | 237 errorMessage = "Redirect at origin '" + originalOrigin + "' has been
blocked from loading by Cross-Origin Resource Sharing policy: " + errorDescript
ion; |
235 return false; | 238 return false; |
236 } | 239 } |
237 } | 240 } |
238 if (redirectCrossOrigin) { | 241 if (redirectCrossOrigin) { |
239 // If now to a different origin, update/set Origin:. | 242 // If now to a different origin, update/set Origin:. |
240 request.clearHTTPOrigin(); | 243 request.clearHTTPOrigin(); |
241 request.setHTTPOrigin(securityOrigin->toAtomicString()); | 244 request.setHTTPOrigin(securityOrigin->toAtomicString()); |
242 // If the user didn't request credentials in the first place, update our | 245 // If the user didn't request credentials in the first place, update our |
243 // state so we neither request them nor expect they must be allowed. | 246 // state so we neither request them nor expect they must be allowed. |
244 if (options.credentialsRequested == ClientDidNotRequestCredentials) | 247 if (options.credentialsRequested == ClientDidNotRequestCredentials) |
245 options.allowCredentials = DoNotAllowStoredCredentials; | 248 options.allowCredentials = DoNotAllowStoredCredentials; |
246 } | 249 } |
247 return true; | 250 return true; |
248 } | 251 } |
249 | 252 |
250 } // namespace blink | 253 } // namespace blink |
OLD | NEW |