Title: [94128] trunk/Source/WebCore
Revision
94128
Author
[email protected]
Date
2011-08-30 16:55:52 -0700 (Tue, 30 Aug 2011)

Log Message

This patch makes the XMLHttpRequest method/header validation logic available as
static methods so URL loaders can perform the same checks for untrusted HTTP requests
coming from plugins.
https://bugs.webkit.org/show_bug.cgi?id=66909

Patch by Bill Budge <[email protected]> on 2011-08-30
Reviewed by David Levin.

No new tests. Exposes no new functionality.

* CMakeLists.txt:
* GNUmakefile.list.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.vcproj/WebCore.vcproj:
* platform/network/HTTPValidation.cpp: Added.
(WebCore::isValidHTTPToken):
(WebCore::isValidHTTPHeaderValue):
* platform/network/HTTPValidation.h: Added.
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::isAllowedHTTPMethod):
(WebCore::XMLHttpRequest::uppercaseKnownHTTPMethod):
(WebCore::XMLHttpRequest::isAllowedHTTPHeader):
(WebCore::XMLHttpRequest::open):
(WebCore::XMLHttpRequest::setRequestHeader):
* xml/XMLHttpRequest.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/CMakeLists.txt (94127 => 94128)


--- trunk/Source/WebCore/CMakeLists.txt	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/CMakeLists.txt	2011-08-30 23:55:52 UTC (rev 94128)
@@ -1133,6 +1133,7 @@
     platform/network/FormData.cpp
     platform/network/HTTPHeaderMap.cpp
     platform/network/HTTPParsers.cpp
+    platform/network/HTTPValidation.cpp
     platform/network/MIMEHeader.cpp
     platform/network/NetworkStateNotifier.cpp
     platform/network/ProtectionSpace.cpp

Modified: trunk/Source/WebCore/ChangeLog (94127 => 94128)


--- trunk/Source/WebCore/ChangeLog	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/ChangeLog	2011-08-30 23:55:52 UTC (rev 94128)
@@ -1,3 +1,31 @@
+2011-08-30  Bill Budge  <[email protected]>
+
+        This patch makes the XMLHttpRequest method/header validation logic available as
+        static methods so URL loaders can perform the same checks for untrusted HTTP requests
+        coming from plugins. 
+        https://bugs.webkit.org/show_bug.cgi?id=66909
+
+        Reviewed by David Levin.
+
+        No new tests. Exposes no new functionality.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * platform/network/HTTPValidation.cpp: Added.
+        (WebCore::isValidHTTPToken):
+        (WebCore::isValidHTTPHeaderValue):
+        * platform/network/HTTPValidation.h: Added.
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::isAllowedHTTPMethod):
+        (WebCore::XMLHttpRequest::uppercaseKnownHTTPMethod):
+        (WebCore::XMLHttpRequest::isAllowedHTTPHeader):
+        (WebCore::XMLHttpRequest::open):
+        (WebCore::XMLHttpRequest::setRequestHeader):
+        * xml/XMLHttpRequest.h:
+
 2011-08-30  Chris Rogers  <[email protected]>
 
         Don't allow nodes of one context to be connected to nodes of another context

Modified: trunk/Source/WebCore/GNUmakefile.list.am (94127 => 94128)


--- trunk/Source/WebCore/GNUmakefile.list.am	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2011-08-30 23:55:52 UTC (rev 94128)
@@ -2706,6 +2706,8 @@
 	Source/WebCore/platform/network/HTTPHeaderMap.h \
 	Source/WebCore/platform/network/HTTPParsers.cpp \
 	Source/WebCore/platform/network/HTTPParsers.h \
+	Source/WebCore/platform/network/HTTPValidation.cpp \
+	Source/WebCore/platform/network/HTTPValidation.h \
 	Source/WebCore/platform/network/MIMEHeader.cpp \
 	Source/WebCore/platform/network/MIMEHeader.h \
 	Source/WebCore/platform/network/NetworkingContext.h \

Modified: trunk/Source/WebCore/WebCore.gypi (94127 => 94128)


--- trunk/Source/WebCore/WebCore.gypi	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/WebCore.gypi	2011-08-30 23:55:52 UTC (rev 94128)
@@ -4138,6 +4138,8 @@
             'platform/network/HTTPHeaderMap.cpp',
             'platform/network/HTTPParsers.cpp',
             'platform/network/HTTPParsers.h',
+            'platform/network/HTTPValidation.cpp',
+            'platform/network/HTTPValidation.h',
             'platform/network/MIMEHeader.cpp',
             'platform/network/NetworkStateNotifier.cpp',
             'platform/network/NetworkStateNotifier.h',

Modified: trunk/Source/WebCore/WebCore.pro (94127 => 94128)


--- trunk/Source/WebCore/WebCore.pro	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/WebCore.pro	2011-08-30 23:55:52 UTC (rev 94128)
@@ -1050,6 +1050,7 @@
     platform/network/FormDataBuilder.cpp \
     platform/network/HTTPHeaderMap.cpp \
     platform/network/HTTPParsers.cpp \
+    platform/network/HTTPValidation.cpp \
     platform/network/MIMEHeader.cpp \
     platform/network/NetworkStateNotifier.cpp \
     platform/network/ProtectionSpace.cpp \
@@ -2061,6 +2062,7 @@
     platform/network/FormData.h \
     platform/network/HTTPHeaderMap.h \
     platform/network/HTTPParsers.h \
+    platform/network/HTTPValidation.h \
     platform/network/HTTPStatusCodes.h \
     platform/network/MIMESniffing.h \
     platform/network/NetworkingContext.h \

Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (94127 => 94128)


--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-08-30 23:55:52 UTC (rev 94128)
@@ -30445,6 +30445,14 @@
 					>
 				</File>
 				<File
+					RelativePath="..\platform\network\HTTPValidation.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\platform\network\HTTPValidation.h"
+					>
+				</File>
+				<File
 					RelativePath="..\platform\network\MIMEHeader.cpp"
 					>
 				</File>

Added: trunk/Source/WebCore/platform/network/HTTPValidation.cpp (0 => 94128)


--- trunk/Source/WebCore/platform/network/HTTPValidation.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/network/HTTPValidation.cpp	2011-08-30 23:55:52 UTC (rev 94128)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 Alexey Proskuryakov ([email protected])
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "HTTPValidation.h"
+
+#include "PlatformString.h"
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+// Determines if a string is a valid token, as defined by
+// "token" in section 2.2 of RFC 2616.
+bool isValidHTTPToken(const String& name)
+{
+    unsigned length = name.length();
+    for (unsigned i = 0; i < length; i++) {
+        UChar c = name[i];
+
+        if (c >= 127 || c <= 32)
+            return false;
+
+        if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@'
+            || c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"'
+            || c == '/' || c == '[' || c == ']' || c == '?' || c == '='
+            || c == '{' || c == '}')
+            return false;
+    }
+
+    return length > 0;
+}
+
+bool isValidHTTPHeaderValue(const String& name)
+{
+    // FIXME: This should really match name against
+    // field-value in section 4.2 of RFC 2616.
+
+    return !name.contains('\r') && !name.contains('\n');
+}
+
+}

Added: trunk/Source/WebCore/platform/network/HTTPValidation.h (0 => 94128)


--- trunk/Source/WebCore/platform/network/HTTPValidation.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/network/HTTPValidation.h	2011-08-30 23:55:52 UTC (rev 94128)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 Alexey Proskuryakov ([email protected])
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTTPValidation_h
+#define HTTPValidation_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+bool isValidHTTPToken(const String&);
+bool isValidHTTPHeaderValue(const String&);
+
+}
+
+#endif

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (94127 => 94128)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2011-08-30 23:55:52 UTC (rev 94128)
@@ -2,7 +2,7 @@
  *  Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
  *  Copyright (C) 2005-2007 Alexey Proskuryakov <[email protected]>
  *  Copyright (C) 2007, 2008 Julien Chaffraix <[email protected]>
- *  Copyright (C) 2008 David Levin <[email protected]>
+ *  Copyright (C) 2008, 2011 Google Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -36,6 +36,7 @@
 #include "ExceptionCode.h"
 #include "File.h"
 #include "HTTPParsers.h"
+#include "HTTPValidation.h"
 #include "InspectorInstrumentation.h"
 #include "ResourceError.h"
 #include "ResourceRequest.h"
@@ -104,35 +105,6 @@
     m_forbiddenRequestHeaders.add("via");
 }
 
-// Determines if a string is a valid token, as defined by
-// "token" in section 2.2 of RFC 2616.
-static bool isValidToken(const String& name)
-{
-    unsigned length = name.length();
-    for (unsigned i = 0; i < length; i++) {
-        UChar c = name[i];
-
-        if (c >= 127 || c <= 32)
-            return false;
-
-        if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
-            c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
-            c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
-            c == '{' || c == '}')
-            return false;
-    }
-
-    return length > 0;
-}
-
-static bool isValidHeaderValue(const String& name)
-{
-    // FIXME: This should really match name against
-    // field-value in section 4.2 of RFC 2616.
-
-    return !name.contains('\r') && !name.contains('\n');
-}
-
 static bool isSetCookieHeader(const AtomicString& name)
 {
     return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
@@ -398,6 +370,32 @@
 }
 #endif
 
+bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
+{
+    return !equalIgnoringCase(method, "TRACE")
+        && !equalIgnoringCase(method, "TRACK")
+        && !equalIgnoringCase(method, "CONNECT");
+}
+
+String XMLHttpRequest::uppercaseKnownHTTPMethod(const String& method)
+{
+    if (equalIgnoringCase(method, "COPY") || equalIgnoringCase(method, "DELETE") || equalIgnoringCase(method, "GET")
+        || equalIgnoringCase(method, "HEAD") || equalIgnoringCase(method, "INDEX") || equalIgnoringCase(method, "LOCK")
+        || equalIgnoringCase(method, "M-POST") || equalIgnoringCase(method, "MKCOL") || equalIgnoringCase(method, "MOVE")
+        || equalIgnoringCase(method, "OPTIONS") || equalIgnoringCase(method, "POST") || equalIgnoringCase(method, "PROPFIND")
+        || equalIgnoringCase(method, "PROPPATCH") || equalIgnoringCase(method, "PUT") || equalIgnoringCase(method, "UNLOCK")) {
+        return method.upper();
+    }
+    return method;
+}
+
+bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
+{
+    initializeXMLHttpRequestStaticData();
+    return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
+        && !name.startsWith(staticData->m_secHeaderPrefix, false);
+}
+
 void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionCode& ec)
 {
     open(method, url, true, ec);
@@ -418,29 +416,20 @@
 
     ASSERT(m_state == UNSENT);
 
-    if (!isValidToken(method)) {
+    if (!isValidHTTPToken(method)) {
         ec = SYNTAX_ERR;
         return;
     }
 
-    // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
-    String methodUpper(method.upper());
-
-    if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
+    if (!isAllowedHTTPMethod(method)) {
         ec = SECURITY_ERR;
         return;
     }
 
+    m_method = uppercaseKnownHTTPMethod(method);
+
     m_url = url;
 
-    if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
-        || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
-        || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"
-        || methodUpper == "UNLOCK")
-        m_method = methodUpper;
-    else
-        m_method = method;
-
     m_async = async;
 
     ASSERT(!m_loader);
@@ -835,13 +824,13 @@
         return;
     }
 
-    if (!isValidToken(name) || !isValidHeaderValue(value)) {
+    if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(value)) {
         ec = SYNTAX_ERR;
         return;
     }
 
     // A privileged script (e.g. a Dashboard widget) can set any headers.
-    if (!securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
+    if (!securityOrigin()->canLoadLocalResources() && !isAllowedHTTPHeader(name)) {
         reportUnsafeUsage(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
         return;
     }
@@ -856,12 +845,6 @@
         result.first->second += ", " + value;
 }
 
-bool XMLHttpRequest::isSafeRequestHeader(const String& name) const
-{
-    return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
-        && !name.startsWith(staticData->m_secHeaderPrefix, false);
-}
-
 String XMLHttpRequest::getRequestHeader(const AtomicString& name) const
 {
     return m_requestHeaders.get(name);

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (94127 => 94128)


--- trunk/Source/WebCore/xml/XMLHttpRequest.h	2011-08-30 23:45:53 UTC (rev 94127)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h	2011-08-30 23:55:52 UTC (rev 94128)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
  *  Copyright (C) 2005, 2006 Alexey Proskuryakov <[email protected]>
+ *  Copyright (C) 2011 Google Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -110,6 +111,11 @@
     Blob* optionalResponseBlob() const { return m_responseBlob.get(); }
 #endif
 
+    // Expose HTTP validation methods for other untrusted requests.
+    static bool isAllowedHTTPMethod(const String&);
+    static String uppercaseKnownHTTPMethod(const String&);
+    static bool isAllowedHTTPHeader(const String&);
+
     void setResponseType(const String&, ExceptionCode&);
     String responseType();
     ResponseTypeCode responseTypeCode() const { return m_responseTypeCode; }
@@ -163,7 +169,6 @@
 
     String getRequestHeader(const AtomicString& name) const;
     void setRequestHeaderInternal(const AtomicString& name, const String& value);
-    bool isSafeRequestHeader(const String&) const;
 
     void changeState(State newState);
     void callReadyStateChangeListener();
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to