summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/CrossOriginAccessControl.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-05-24 08:28:08 +0000
commita4e969f4965059196ca948db781e52f7cfebf19e (patch)
tree6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/WebCore/loader/CrossOriginAccessControl.cpp
parent41386e9cb918eed93b3f13648cbef387e371e451 (diff)
downloadWebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/WebCore/loader/CrossOriginAccessControl.cpp')
-rw-r--r--Source/WebCore/loader/CrossOriginAccessControl.cpp104
1 files changed, 60 insertions, 44 deletions
diff --git a/Source/WebCore/loader/CrossOriginAccessControl.cpp b/Source/WebCore/loader/CrossOriginAccessControl.cpp
index 257b43ed8..ad0cf1db7 100644
--- a/Source/WebCore/loader/CrossOriginAccessControl.cpp
+++ b/Source/WebCore/loader/CrossOriginAccessControl.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -27,11 +27,14 @@
#include "config.h"
#include "CrossOriginAccessControl.h"
+#include "HTTPHeaderNames.h"
#include "HTTPParsers.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
+#include "SchemeRegistry.h"
#include "SecurityOrigin.h"
#include <mutex>
+#include <wtf/NeverDestroyed.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/StringBuilder.h>
@@ -42,24 +45,25 @@ bool isOnAccessControlSimpleRequestMethodWhitelist(const String& method)
return method == "GET" || method == "HEAD" || method == "POST";
}
-bool isOnAccessControlSimpleRequestHeaderWhitelist(const String& name, const String& value)
+bool isOnAccessControlSimpleRequestHeaderWhitelist(HTTPHeaderName name, const String& value)
{
- if (equalIgnoringCase(name, "accept")
- || equalIgnoringCase(name, "accept-language")
- || equalIgnoringCase(name, "content-language")
- || equalIgnoringCase(name, "origin")
- || equalIgnoringCase(name, "referer"))
+ switch (name) {
+ case HTTPHeaderName::Accept:
+ case HTTPHeaderName::AcceptLanguage:
+ case HTTPHeaderName::ContentLanguage:
+ case HTTPHeaderName::Origin:
+ case HTTPHeaderName::Referer:
return true;
-
- // Preflight is required for MIME types that can not be sent via form submission.
- if (equalIgnoringCase(name, "content-type")) {
+ case HTTPHeaderName::ContentType: {
+ // Preflight is required for MIME types that can not be sent via form submission.
String mimeType = extractMIMETypeFromMediaType(value);
- return equalIgnoringCase(mimeType, "application/x-www-form-urlencoded")
- || equalIgnoringCase(mimeType, "multipart/form-data")
- || equalIgnoringCase(mimeType, "text/plain");
+ return equalIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded")
+ || equalIgnoringASCIICase(mimeType, "multipart/form-data")
+ || equalIgnoringASCIICase(mimeType, "text/plain");
+ }
+ default:
+ return false;
}
-
- return false;
}
bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap& headerMap)
@@ -67,9 +71,8 @@ bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&
if (!isOnAccessControlSimpleRequestMethodWhitelist(method))
return false;
- HTTPHeaderMap::const_iterator end = headerMap.end();
- for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) {
- if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value))
+ for (const auto& header : headerMap) {
+ if (!header.keyAsHTTPHeaderName || !isOnAccessControlSimpleRequestHeaderWhitelist(header.keyAsHTTPHeaderName.value(), header.value))
return false;
}
@@ -79,20 +82,20 @@ bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&
bool isOnAccessControlResponseHeaderWhitelist(const String& name)
{
static std::once_flag onceFlag;
- static HTTPHeaderSet* allowedCrossOriginResponseHeaders;
+ static LazyNeverDestroyed<HTTPHeaderSet> allowedCrossOriginResponseHeaders;
std::call_once(onceFlag, []{
- allowedCrossOriginResponseHeaders = std::make_unique<HTTPHeaderSet, std::initializer_list<String>>({
+ allowedCrossOriginResponseHeaders.construct<std::initializer_list<String>>({
"cache-control",
"content-language",
"content-type",
"expires",
"last-modified",
"pragma"
- }).release();
+ });
});
- return allowedCrossOriginResponseHeaders->contains(name);
+ return allowedCrossOriginResponseHeaders.get().contains(name);
}
void updateRequestForAccessControl(ResourceRequest& request, SecurityOrigin* securityOrigin, StoredCredentials allowCredentials)
@@ -107,43 +110,56 @@ ResourceRequest createAccessControlPreflightRequest(const ResourceRequest& reque
ResourceRequest preflightRequest(request.url());
updateRequestForAccessControl(preflightRequest, securityOrigin, DoNotAllowStoredCredentials);
preflightRequest.setHTTPMethod("OPTIONS");
- preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod());
+ preflightRequest.setHTTPHeaderField(HTTPHeaderName::AccessControlRequestMethod, request.httpMethod());
preflightRequest.setPriority(request.priority());
const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields();
- if (requestHeaderFields.size() > 0) {
+ if (!requestHeaderFields.isEmpty()) {
StringBuilder headerBuffer;
- HTTPHeaderMap::const_iterator it = requestHeaderFields.begin();
- headerBuffer.append(it->key);
- ++it;
-
- HTTPHeaderMap::const_iterator end = requestHeaderFields.end();
- for (; it != end; ++it) {
- headerBuffer.append(',');
- headerBuffer.append(' ');
- headerBuffer.append(it->key);
+
+ bool appendComma = false;
+ for (const auto& headerField : requestHeaderFields) {
+ if (appendComma)
+ headerBuffer.appendLiteral(", ");
+ else
+ appendComma = true;
+
+ headerBuffer.append(headerField.key);
}
- preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", headerBuffer.toString().lower());
+ preflightRequest.setHTTPHeaderField(HTTPHeaderName::AccessControlRequestHeaders, headerBuffer.toString().convertToASCIILowercase());
}
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,
// even with Access-Control-Allow-Credentials set to true.
- const String& accessControlOriginString = response.httpHeaderField("access-control-allow-origin");
+ const String& accessControlOriginString = response.httpHeaderField(HTTPHeaderName::AccessControlAllowOrigin);
if (accessControlOriginString == "*" && includeCredentials == DoNotAllowStoredCredentials)
return true;
- if (securityOrigin->isUnique()) {
- errorDescription = "Cannot make any requests from " + securityOrigin->toString() + ".";
- return false;
- }
-
// FIXME: Access-Control-Allow-Origin can contain a list of origins.
if (accessControlOriginString != securityOrigin->toString()) {
if (accessControlOriginString == "*")
@@ -154,7 +170,7 @@ bool passesAccessControlCheck(const ResourceResponse& response, StoredCredential
}
if (includeCredentials == AllowStoredCredentials) {
- const String& accessControlCredentialsString = response.httpHeaderField("access-control-allow-credentials");
+ const String& accessControlCredentialsString = response.httpHeaderField(HTTPHeaderName::AccessControlAllowCredentials);
if (accessControlCredentialsString != "true") {
errorDescription = "Credentials flag is true, but Access-Control-Allow-Credentials is not \"true\".";
return false;
@@ -168,8 +184,8 @@ void parseAccessControlExposeHeadersAllowList(const String& headerValue, HTTPHea
{
Vector<String> headers;
headerValue.split(',', false, headers);
- for (unsigned headerCount = 0; headerCount < headers.size(); headerCount++) {
- String strippedHeader = headers[headerCount].stripWhiteSpace();
+ for (auto& header : headers) {
+ String strippedHeader = header.stripWhiteSpace();
if (!strippedHeader.isEmpty())
headerSet.add(strippedHeader);
}