Chromium Code Reviews| 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 "platform/RuntimeEnabledFeatures.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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 97 } | 98 } |
| 98 | 99 |
| 99 return preflightRequest; | 100 return preflightRequest; |
| 100 } | 101 } |
| 101 | 102 |
| 102 static bool isOriginSeparator(UChar ch) | 103 static bool isOriginSeparator(UChar ch) |
| 103 { | 104 { |
| 104 return isASCIISpace(ch) || ch == ','; | 105 return isASCIISpace(ch) || ch == ','; |
| 105 } | 106 } |
| 106 | 107 |
| 108 static bool experimentalContentSecurityPolicyFeaturesEnabled() | |
| 109 { | |
| 110 return RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnab led(); | |
|
Mike West
2014/10/23 12:59:19
For clarity, I'd suggest adding a RuntimeEnabledFe
jww
2015/03/20 22:50:02
Done.
| |
| 111 } | |
| 112 | |
| 107 static bool isInterestingStatusCode(int statusCode) | 113 static bool isInterestingStatusCode(int statusCode) |
| 108 { | 114 { |
| 109 // Predicate that gates what status codes should be included in | 115 // Predicate that gates what status codes should be included in |
| 110 // console error messages for responses containing no access | 116 // console error messages for responses containing no access |
| 111 // control headers. | 117 // control headers. |
| 112 return statusCode >= 400; | 118 return statusCode >= 400; |
| 113 } | 119 } |
| 114 | 120 |
| 115 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential s includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription) | 121 bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential s includeCredentials, SecurityOrigin* securityOrigin, String& errorDescription) |
| 116 { | 122 { |
| 117 AtomicallyInitializedStatic(AtomicString&, accessControlAllowOrigin = *new A tomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)); | 123 AtomicallyInitializedStatic(AtomicString&, accessControlAllowOrigin = *new A tomicString("access-control-allow-origin", AtomicString::ConstructFromLiteral)); |
| 118 AtomicallyInitializedStatic(AtomicString&, accessControlAllowCredentials = * new AtomicString("access-control-allow-credentials", AtomicString::ConstructFrom Literal)); | 124 AtomicallyInitializedStatic(AtomicString&, accessControlAllowCredentials = * new AtomicString("access-control-allow-credentials", AtomicString::ConstructFrom Literal)); |
| 125 AtomicallyInitializedStatic(AtomicString&, accessControlAllowFinerOrigin = * new AtomicString("access-control-allow-finer-origin", AtomicString::ConstructFro mLiteral)); | |
|
Mike West
2014/10/23 12:59:18
"finer-origin"? Why not "suborigin"?
This is a sp
jww
2015/03/20 22:50:02
I'll leave this for now since it's what I've said
| |
| 119 | 126 |
| 120 if (!response.httpStatusCode()) { | 127 if (!response.httpStatusCode()) { |
| 121 errorDescription = "Received an invalid response. Origin '" + securityOr igin->toString() + "' is therefore not allowed access."; | 128 errorDescription = "Received an invalid response. Origin '" + securityOr igin->toString() + "' is therefore not allowed access."; |
| 122 return false; | 129 return false; |
| 123 } | 130 } |
| 124 | 131 |
| 125 const AtomicString& accessControlOriginString = response.httpHeaderField(acc essControlAllowOrigin); | 132 const AtomicString& accessControlOriginString = response.httpHeaderField(acc essControlAllowOrigin); |
| 126 if (accessControlOriginString == starAtom) { | 133 const AtomicString& accessControlFinerOriginString = response.httpHeaderFiel d(accessControlAllowFinerOrigin); |
| 134 if (accessControlOriginString == starAtom || accessControlAllowFinerOrigin = = starAtom) { | |
|
Mike West
2014/10/23 12:59:18
This seems wrong: as written, either `a-c-allow-or
jww
2015/03/20 22:50:02
This is on purpose, and I've tried to explain in t
| |
| 127 // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent, | 135 // A wildcard Access-Control-Allow-Origin can not be used if credentials are to be sent, |
| 128 // even with Access-Control-Allow-Credentials set to true. | 136 // even with Access-Control-Allow-Credentials set to true. |
| 129 if (includeCredentials == DoNotAllowStoredCredentials) | 137 if (includeCredentials == DoNotAllowStoredCredentials) |
| 130 return true; | 138 return true; |
| 131 if (response.isHTTP()) { | 139 if (response.isHTTP()) { |
| 132 errorDescription = "A wildcard '*' cannot be used in the 'Access-Con trol-Allow-Origin' header when the credentials flag is true. Origin '" + securit yOrigin->toString() + "' is therefore not allowed access."; | 140 if (!experimentalContentSecurityPolicyFeaturesEnabled()) |
| 133 return false; | 141 errorDescription = "A wildcard '*' cannot be used in the 'Access -Control-Allow-Origin' header when the credentials flag is true. Origin '" + sec urityOrigin->toString() + "' is therefore not allowed access."; |
| 142 else | |
| 143 errorDescription = "A wildcard '*' cannot be used in the 'Access -Control-Allow-Origin' or 'Access-Control-Allow-Finer-Origin' header when the cr edentials flag is true. Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; | |
| 134 } | 144 } |
| 135 } else if (accessControlOriginString != securityOrigin->toAtomicString()) { | 145 } else if (accessControlOriginString != securityOrigin->toAtomicString() && accessControlFinerOriginString != securityOrigin->toRawAtomicString()) { |
| 136 if (accessControlOriginString.isEmpty()) { | 146 if (accessControlOriginString.isEmpty() && accessControlFinerOriginStrin g.isEmpty()) { |
| 137 errorDescription = "No 'Access-Control-Allow-Origin' header is prese nt on the requested resource. Origin '" + securityOrigin->toString() + "' is the refore not allowed access."; | 147 if (!experimentalContentSecurityPolicyFeaturesEnabled()) |
| 138 | 148 errorDescription = "No 'Access-Control-Allow-Origin' header is p resent on the requested resource. Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; |
| 149 else | |
| 150 errorDescription = "No 'Access-Control-Allow-Origin' or 'Access- Control-Allow-accessControlFinerOriginString' header is present on the requested resource. Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; | |
| 139 if (isInterestingStatusCode(response.httpStatusCode())) | 151 if (isInterestingStatusCode(response.httpStatusCode())) |
| 140 errorDescription.append(" The response had HTTP status code " + String::number(response.httpStatusCode()) + "."); | 152 errorDescription.append(" The response had HTTP status code " + String::number(response.httpStatusCode()) + "."); |
| 141 } else if (accessControlOriginString.string().find(isOriginSeparator, 0) != kNotFound) { | 153 } else if (accessControlOriginString.string().find(isOriginSeparator, 0) != kNotFound || accessControlFinerOriginString.string().find(isOriginSeparator, 0) != kNotFound) { |
| 142 errorDescription = "The 'Access-Control-Allow-Origin' header contain s multiple values '" + accessControlOriginString + "', but only one is allowed. Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; | 154 if (!experimentalContentSecurityPolicyFeaturesEnabled()) |
| 155 errorDescription = "The 'Access-Control-Allow-Origin' header con tains multiple values '" + accessControlOriginString + "', but only one is allow ed. Origin '" + securityOrigin->toString() + "' is therefore not allowed access. "; | |
| 156 else | |
| 157 errorDescription = "The 'Access-Control-Allow-Origin' or 'Access -Control-Allow-Finer-Origin' header contains multiple values '" + accessControlO riginString + "', but only one is allowed. Origin '" + securityOrigin->toString( ) + "' is therefore not allowed access."; | |
| 143 } else { | 158 } else { |
| 144 KURL headerOrigin(KURL(), accessControlOriginString); | 159 KURL headerOrigin(KURL(), accessControlOriginString); |
| 145 if (!headerOrigin.isValid()) | 160 KURL headerFinerOrigin(KURL(), accessControlFinerOriginString); |
| 161 if (!headerOrigin.isValid()) { | |
| 146 errorDescription = "The 'Access-Control-Allow-Origin' header con tains the invalid value '" + accessControlOriginString + "'. Origin '" + securit yOrigin->toString() + "' is therefore not allowed access."; | 162 errorDescription = "The 'Access-Control-Allow-Origin' header con tains the invalid value '" + accessControlOriginString + "'. Origin '" + securit yOrigin->toString() + "' is therefore not allowed access."; |
| 147 else | 163 } else if (experimentalContentSecurityPolicyFeaturesEnabled() && !he aderFinerOrigin.isValid()) { |
| 148 errorDescription = "The 'Access-Control-Allow-Origin' header has a value '" + accessControlOriginString + "' that is not equal to the supplied o rigin. Origin '" + securityOrigin->toString() + "' is therefore not allowed acce ss."; | 164 errorDescription = "The 'Access-Control-Allow-Finer-Origin' head er contains the invalid value '" + accessControlOriginString + "'. Origin '" + s ecurityOrigin->toString() + "' is therefore not allowed access."; |
| 165 } else { | |
| 166 if (!experimentalContentSecurityPolicyFeaturesEnabled()) | |
| 167 errorDescription = "The 'Access-Control-Allow-Origin' header has a value '" + accessControlOriginString + "' that is not equal to the suppli ed origin. Origin '" + securityOrigin->toString() + "' is therefore not allowed access."; | |
| 168 else | |
| 169 errorDescription = "The 'Access-Control-Allow-Origin' or 'Ac cess-Control-Allow-Finer-Origin' header has a value '" + accessControlOriginStri ng + "' that is not equal to the supplied origin. Origin '" + securityOrigin->to String() + "' is therefore not allowed access."; | |
|
Mike West
2014/10/23 12:59:19
I'd suggest moving all the occurrences of these er
jww
2015/03/20 22:50:02
Done. It's still a bit ugly, though, so any other
| |
| 170 } | |
| 149 } | 171 } |
| 150 return false; | 172 return false; |
| 151 } | 173 } |
| 152 | 174 |
| 153 if (includeCredentials == AllowStoredCredentials) { | 175 if (includeCredentials == AllowStoredCredentials) { |
| 154 const AtomicString& accessControlCredentialsString = response.httpHeader Field(accessControlAllowCredentials); | 176 const AtomicString& accessControlCredentialsString = response.httpHeader Field(accessControlAllowCredentials); |
| 155 if (accessControlCredentialsString != "true") { | 177 if (accessControlCredentialsString != "true") { |
| 156 errorDescription = "Credentials flag is 'true', but the 'Access-Cont rol-Allow-Credentials' header is '" + accessControlCredentialsString + "'. It mu st be 'true' to allow credentials."; | 178 errorDescription = "Credentials flag is 'true', but the 'Access-Cont rol-Allow-Credentials' header is '" + accessControlCredentialsString + "'. It mu st be 'true' to allow credentials."; |
| 157 return false; | 179 return false; |
| 158 } | 180 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 request.setHTTPOrigin(securityOrigin->toAtomicString()); | 261 request.setHTTPOrigin(securityOrigin->toAtomicString()); |
| 240 // If the user didn't request credentials in the first place, update our | 262 // If the user didn't request credentials in the first place, update our |
| 241 // state so we neither request them nor expect they must be allowed. | 263 // state so we neither request them nor expect they must be allowed. |
| 242 if (options.credentialsRequested == ClientDidNotRequestCredentials) | 264 if (options.credentialsRequested == ClientDidNotRequestCredentials) |
| 243 options.allowCredentials = DoNotAllowStoredCredentials; | 265 options.allowCredentials = DoNotAllowStoredCredentials; |
| 244 } | 266 } |
| 245 return true; | 267 return true; |
| 246 } | 268 } |
| 247 | 269 |
| 248 } // namespace blink | 270 } // namespace blink |
| OLD | NEW |