Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(666)

Side by Side Diff: third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp

Issue 2264503002: Clean up SecurityOrigin handling around CrossOriginAccessControl::handleRedirect() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 "cache-control", 49 "cache-control",
50 "content-language", 50 "content-language",
51 "content-type", 51 "content-type",
52 "expires", 52 "expires",
53 "last-modified", 53 "last-modified",
54 "pragma", 54 "pragma",
55 }))); 55 })));
56 return allowedCrossOriginResponseHeaders.contains(name); 56 return allowedCrossOriginResponseHeaders.contains(name);
57 } 57 }
58 58
59 void updateRequestForAccessControl(ResourceRequest& request, SecurityOrigin* sec urityOrigin, StoredCredentials allowCredentials) 59 void updateRequestForAccessControl(ResourceRequest& request, const SecurityOrigi n* securityOrigin, StoredCredentials allowCredentials)
60 { 60 {
61 request.removeCredentials(); 61 request.removeCredentials();
62 request.setAllowStoredCredentials(allowCredentials == AllowStoredCredentials ); 62 request.setAllowStoredCredentials(allowCredentials == AllowStoredCredentials );
63 63
64 if (securityOrigin) 64 if (securityOrigin)
65 request.setHTTPOrigin(securityOrigin); 65 request.setHTTPOrigin(securityOrigin);
66 } 66 }
67 67
68 ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& reque st, SecurityOrigin* securityOrigin) 68 ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& reque st, const SecurityOrigin* securityOrigin)
69 { 69 {
70 ResourceRequest preflightRequest(request.url()); 70 ResourceRequest preflightRequest(request.url());
71 updateRequestForAccessControl(preflightRequest, securityOrigin, DoNotAllowSt oredCredentials); 71 updateRequestForAccessControl(preflightRequest, securityOrigin, DoNotAllowSt oredCredentials);
72 preflightRequest.setHTTPMethod(HTTPNames::OPTIONS); 72 preflightRequest.setHTTPMethod(HTTPNames::OPTIONS);
73 preflightRequest.setHTTPHeaderField(HTTPNames::Access_Control_Request_Method , AtomicString(request.httpMethod())); 73 preflightRequest.setHTTPHeaderField(HTTPNames::Access_Control_Request_Method , AtomicString(request.httpMethod()));
74 preflightRequest.setPriority(request.priority()); 74 preflightRequest.setPriority(request.priority());
75 preflightRequest.setRequestContext(request.requestContext()); 75 preflightRequest.setRequestContext(request.requestContext());
76 preflightRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All) ; 76 preflightRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All) ;
77 77
78 if (request.isExternalRequest()) 78 if (request.isExternalRequest())
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 117 }
118 118
119 static bool isInterestingStatusCode(int statusCode) 119 static bool isInterestingStatusCode(int statusCode)
120 { 120 {
121 // Predicate that gates what status codes should be included in 121 // Predicate that gates what status codes should be included in
122 // console error messages for responses containing no access 122 // console error messages for responses containing no access
123 // control headers. 123 // control headers.
124 return statusCode >= 400; 124 return statusCode >= 400;
125 } 125 }
126 126
127 static String buildAccessControlFailureMessage(const String& detail, SecurityOri gin* securityOrigin) 127 static String buildAccessControlFailureMessage(const String& detail, const Secur ityOrigin* securityOrigin)
128 { 128 {
129 return detail + " Origin '" + securityOrigin->toString() + "' is therefore n ot allowed access."; 129 return detail + " Origin '" + securityOrigin->toString() + "' is therefore n ot allowed access.";
130 } 130 }
131 131
132 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential s includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription, WebURLRequest::RequestContext context) 132 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential s includeCredentials, const SecurityOrigin* securityOrigin, String& errorDescrip tion, WebURLRequest::RequestContext context)
133 { 133 {
134 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowOriginHeaderName, (new At omicString("access-control-allow-origin"))); 134 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowOriginHeaderName, (new At omicString("access-control-allow-origin")));
135 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowCredentialsHeaderName, (n ew AtomicString("access-control-allow-credentials"))); 135 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowCredentialsHeaderName, (n ew AtomicString("access-control-allow-credentials")));
136 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowSuboriginHeaderName, (new AtomicString("access-control-allow-suborigin"))); 136 DEFINE_THREAD_SAFE_STATIC_LOCAL(AtomicString, allowSuboriginHeaderName, (new AtomicString("access-control-allow-suborigin")));
137 137
138 // TODO(esprehn): This code is using String::append extremely inefficiently 138 // TODO(esprehn): This code is using String::append extremely inefficiently
139 // causing tons of copies. It should pass around a StringBuilder instead. 139 // causing tons of copies. It should pass around a StringBuilder instead.
140 140
141 int statusCode = response.httpStatusCode(); 141 int statusCode = response.httpStatusCode();
142 142
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 if (response.wasFetchedViaServiceWorker()) { 265 if (response.wasFetchedViaServiceWorker()) {
266 for (const auto& header : response.corsExposedHeaderNames()) 266 for (const auto& header : response.corsExposedHeaderNames())
267 headerSet.add(header); 267 headerSet.add(header);
268 return; 268 return;
269 } 269 }
270 parseAccessControlExposeHeadersAllowList(response.httpHeaderField(HTTPNames: :Access_Control_Expose_Headers), headerSet); 270 parseAccessControlExposeHeadersAllowList(response.httpHeaderField(HTTPNames: :Access_Control_Expose_Headers), headerSet);
271 } 271 }
272 272
273 bool CrossOriginAccessControl::isLegalRedirectLocation(const KURL& requestURL, S tring& errorDescription) 273 bool CrossOriginAccessControl::isLegalRedirectLocation(const KURL& requestURL, S tring& errorDescription)
274 { 274 {
275 // CORS restrictions imposed on Location: URL -- http://www.w3.org/TR/cors/# redirect-steps (steps 2 + 3.) 275 // Block non HTTP(S) schemes as specified in the step 4 in
276 // https://fetch.spec.whatwg.org/#http-redirect-fetch. Chromium also allows
277 // the data scheme.
278 //
279 // TODO(tyoshino): This check should be performed regardless of the CORS
280 // flag and request's mode.
276 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(requestURL.protocol() )) { 281 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(requestURL.protocol() )) {
277 errorDescription = "Redirect location '" + requestURL.getString() + "' h as a disallowed scheme for cross-origin requests."; 282 errorDescription = "Redirect location '" + requestURL.getString() + "' h as a disallowed scheme for cross-origin requests.";
278 return false; 283 return false;
279 } 284 }
280 285
286 // Block URLs including credentials as specified in the step 9 in
287 // https://fetch.spec.whatwg.org/#http-redirect-fetch.
288 //
289 // TODO(tyoshino): This check should be performed also when request's
290 // origin is not same origin with the redirect destination's origin.
281 if (!(requestURL.user().isEmpty() && requestURL.pass().isEmpty())) { 291 if (!(requestURL.user().isEmpty() && requestURL.pass().isEmpty())) {
282 errorDescription = "Redirect location '" + requestURL.getString() + "' c ontains userinfo, which is disallowed for cross-origin requests."; 292 errorDescription = "Redirect location '" + requestURL.getString() + "' c ontains userinfo, which is disallowed for cross-origin requests.";
283 return false; 293 return false;
284 } 294 }
285 295
286 return true; 296 return true;
287 } 297 }
288 298
289 bool CrossOriginAccessControl::handleRedirect(SecurityOrigin* securityOrigin, Re sourceRequest& newRequest, const ResourceResponse& redirectResponse, StoredCrede ntials withCredentials, ResourceLoaderOptions& options, String& errorMessage) 299 bool CrossOriginAccessControl::handleRedirect(const SecurityOrigin* securityOrig in, ResourceRequest& newRequest, const ResourceResponse& redirectResponse, Store dCredentials withCredentials, ResourceLoaderOptions& options, String& errorMessa ge)
290 { 300 {
291 // http://www.w3.org/TR/cors/#redirect-steps terminology: 301 // http://www.w3.org/TR/cors/#redirect-steps terminology:
292 const KURL& originalURL = redirectResponse.url(); 302 const KURL& lastURL = redirectResponse.url();
293 const KURL& newURL = newRequest.url(); 303 const KURL& newURL = newRequest.url();
294 304
295 bool redirectCrossOrigin = !securityOrigin->canRequest(newURL); 305 const SecurityOrigin* securityOriginForHeader = securityOrigin;
296 306
297 // Same-origin request URLs that redirect are allowed without checking acces s. 307 // TODO(tyoshino): This should be fixed to check not only the last one but
298 if (!securityOrigin->canRequest(originalURL)) { 308 // all redirect responses.
309 if (!securityOrigin->canRequest(lastURL)) {
299 // Follow http://www.w3.org/TR/cors/#redirect-steps 310 // Follow http://www.w3.org/TR/cors/#redirect-steps
300 String errorDescription; 311 String errorDescription;
301 312
302 // Steps 3 & 4 - check if scheme and other URL restrictions hold.
303 if (!isLegalRedirectLocation(newURL, errorDescription)) { 313 if (!isLegalRedirectLocation(newURL, errorDescription)) {
304 errorMessage = "Redirect from '" + originalURL.getString() + "' has been blocked by CORS policy: " + errorDescription; 314 errorMessage = "Redirect from '" + lastURL.getString() + "' has been blocked by CORS policy: " + errorDescription;
305 return false; 315 return false;
306 } 316 }
307 317
308 // Step 5: perform resource sharing access check. 318 // Step 5: perform resource sharing access check.
309 if (!passesAccessControlCheck(redirectResponse, withCredentials, securit yOrigin, errorDescription, newRequest.requestContext())) { 319 if (!passesAccessControlCheck(redirectResponse, withCredentials, securit yOrigin, errorDescription, newRequest.requestContext())) {
310 errorMessage = "Redirect from '" + originalURL.getString() + "' has been blocked by CORS policy: " + errorDescription; 320 errorMessage = "Redirect from '" + lastURL.getString() + "' has been blocked by CORS policy: " + errorDescription;
311 return false; 321 return false;
312 } 322 }
313 323
314 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(originalU RL); 324 RefPtr<SecurityOrigin> lastOrigin = SecurityOrigin::create(lastURL);
315 // Step 6: if the request URL origin is not same origin as the original URL's, 325 // Set request's origin to a globally unique identifier as specified in
316 // set the source origin to a globally unique identifier. 326 // the step 10 in https://fetch.spec.whatwg.org/#http-redirect-fetch.
317 if (!originalOrigin->canRequest(newURL)) { 327 if (!lastOrigin->canRequest(newURL)) {
318 options.securityOrigin = SecurityOrigin::createUnique(); 328 options.securityOrigin = SecurityOrigin::createUnique();
319 securityOrigin = options.securityOrigin.get(); 329 securityOriginForHeader = options.securityOrigin.get();
320 } 330 }
321 } 331 }
322 if (redirectCrossOrigin) { 332
323 // If now to a different origin, update/set Origin:. 333 if (!securityOrigin->canRequest(newURL)) {
324 newRequest.clearHTTPOrigin(); 334 newRequest.clearHTTPOrigin();
325 newRequest.setHTTPOrigin(securityOrigin); 335 newRequest.setHTTPOrigin(securityOriginForHeader);
326 // If the user didn't request credentials in the first place, update our 336
327 // state so we neither request them nor expect they must be allowed. 337 // Unset credentials flag if request's credentials mode is
338 // "same-origin" as request's response tainting becomes "cors".
339 //
340 // This is equivalent to the step 2 in
341 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
328 if (options.credentialsRequested == ClientDidNotRequestCredentials) 342 if (options.credentialsRequested == ClientDidNotRequestCredentials)
329 options.allowCredentials = DoNotAllowStoredCredentials; 343 options.allowCredentials = DoNotAllowStoredCredentials;
330 } 344 }
331 return true; 345 return true;
332 } 346 }
333 347
334 } // namespace blink 348 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698