Changeset 94128 in webkit


Ignore:
Timestamp:
Aug 30, 2011, 4:55:52 PM (14 years ago)
Author:
commit-queue@webkit.org
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 <bbudge@chromium.org> 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:
Location:
trunk/Source/WebCore
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/CMakeLists.txt

    r94089 r94128  
    11341134    platform/network/HTTPHeaderMap.cpp
    11351135    platform/network/HTTPParsers.cpp
     1136    platform/network/HTTPValidation.cpp
    11361137    platform/network/MIMEHeader.cpp
    11371138    platform/network/NetworkStateNotifier.cpp
  • trunk/Source/WebCore/ChangeLog

    r94127 r94128  
     12011-08-30  Bill Budge  <bbudge@chromium.org>
     2
     3        This patch makes the XMLHttpRequest method/header validation logic available as
     4        static methods so URL loaders can perform the same checks for untrusted HTTP requests
     5        coming from plugins.
     6        https://bugs.webkit.org/show_bug.cgi?id=66909
     7
     8        Reviewed by David Levin.
     9
     10        No new tests. Exposes no new functionality.
     11
     12        * CMakeLists.txt:
     13        * GNUmakefile.list.am:
     14        * WebCore.gypi:
     15        * WebCore.pro:
     16        * WebCore.vcproj/WebCore.vcproj:
     17        * platform/network/HTTPValidation.cpp: Added.
     18        (WebCore::isValidHTTPToken):
     19        (WebCore::isValidHTTPHeaderValue):
     20        * platform/network/HTTPValidation.h: Added.
     21        * xml/XMLHttpRequest.cpp:
     22        (WebCore::XMLHttpRequest::isAllowedHTTPMethod):
     23        (WebCore::XMLHttpRequest::uppercaseKnownHTTPMethod):
     24        (WebCore::XMLHttpRequest::isAllowedHTTPHeader):
     25        (WebCore::XMLHttpRequest::open):
     26        (WebCore::XMLHttpRequest::setRequestHeader):
     27        * xml/XMLHttpRequest.h:
     28
    1292011-08-30  Chris Rogers  <crogers@google.com>
    230
  • trunk/Source/WebCore/GNUmakefile.list.am

    r94119 r94128  
    27072707        Source/WebCore/platform/network/HTTPParsers.cpp \
    27082708        Source/WebCore/platform/network/HTTPParsers.h \
     2709        Source/WebCore/platform/network/HTTPValidation.cpp \
     2710        Source/WebCore/platform/network/HTTPValidation.h \
    27092711        Source/WebCore/platform/network/MIMEHeader.cpp \
    27102712        Source/WebCore/platform/network/MIMEHeader.h \
  • trunk/Source/WebCore/WebCore.gypi

    r94119 r94128  
    41394139            'platform/network/HTTPParsers.cpp',
    41404140            'platform/network/HTTPParsers.h',
     4141            'platform/network/HTTPValidation.cpp',
     4142            'platform/network/HTTPValidation.h',
    41414143            'platform/network/MIMEHeader.cpp',
    41424144            'platform/network/NetworkStateNotifier.cpp',
  • trunk/Source/WebCore/WebCore.pro

    r94119 r94128  
    10511051    platform/network/HTTPHeaderMap.cpp \
    10521052    platform/network/HTTPParsers.cpp \
     1053    platform/network/HTTPValidation.cpp \
    10531054    platform/network/MIMEHeader.cpp \
    10541055    platform/network/NetworkStateNotifier.cpp \
     
    20622063    platform/network/HTTPHeaderMap.h \
    20632064    platform/network/HTTPParsers.h \
     2065    platform/network/HTTPValidation.h \
    20642066    platform/network/HTTPStatusCodes.h \
    20652067    platform/network/MIMESniffing.h \
  • trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj

    r94119 r94128  
    3044630446                                </File>
    3044730447                                <File
     30448                                        RelativePath="..\platform\network\HTTPValidation.cpp"
     30449                                        >
     30450                                </File>
     30451                                <File
     30452                                        RelativePath="..\platform\network\HTTPValidation.h"
     30453                                        >
     30454                                </File>
     30455                                <File
    3044830456                                        RelativePath="..\platform\network\MIMEHeader.cpp"
    3044930457                                        >
  • trunk/Source/WebCore/xml/XMLHttpRequest.cpp

    r93886 r94128  
    33 *  Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
    44 *  Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org>
    5  *  Copyright (C) 2008 David Levin <levin@chromium.org>
     5 *  Copyright (C) 2008, 2011 Google Inc. All rights reserved.
    66 *
    77 *  This library is free software; you can redistribute it and/or
     
    3737#include "File.h"
    3838#include "HTTPParsers.h"
     39#include "HTTPValidation.h"
    3940#include "InspectorInstrumentation.h"
    4041#include "ResourceError.h"
     
    105106}
    106107
    107 // Determines if a string is a valid token, as defined by
    108 // "token" in section 2.2 of RFC 2616.
    109 static bool isValidToken(const String& name)
    110 {
    111     unsigned length = name.length();
    112     for (unsigned i = 0; i < length; i++) {
    113         UChar c = name[i];
    114 
    115         if (c >= 127 || c <= 32)
    116             return false;
    117 
    118         if (c == '(' || c == ')' || c == '<' || c == '>' || c == '@' ||
    119             c == ',' || c == ';' || c == ':' || c == '\\' || c == '\"' ||
    120             c == '/' || c == '[' || c == ']' || c == '?' || c == '=' ||
    121             c == '{' || c == '}')
    122             return false;
    123     }
    124 
    125     return length > 0;
    126 }
    127 
    128 static bool isValidHeaderValue(const String& name)
    129 {
    130     // FIXME: This should really match name against
    131     // field-value in section 4.2 of RFC 2616.
    132 
    133     return !name.contains('\r') && !name.contains('\n');
    134 }
    135 
    136108static bool isSetCookieHeader(const AtomicString& name)
    137109{
     
    399371#endif
    400372
     373bool XMLHttpRequest::isAllowedHTTPMethod(const String& method)
     374{
     375    return !equalIgnoringCase(method, "TRACE")
     376        && !equalIgnoringCase(method, "TRACK")
     377        && !equalIgnoringCase(method, "CONNECT");
     378}
     379
     380String XMLHttpRequest::uppercaseKnownHTTPMethod(const String& method)
     381{
     382    if (equalIgnoringCase(method, "COPY") || equalIgnoringCase(method, "DELETE") || equalIgnoringCase(method, "GET")
     383        || equalIgnoringCase(method, "HEAD") || equalIgnoringCase(method, "INDEX") || equalIgnoringCase(method, "LOCK")
     384        || equalIgnoringCase(method, "M-POST") || equalIgnoringCase(method, "MKCOL") || equalIgnoringCase(method, "MOVE")
     385        || equalIgnoringCase(method, "OPTIONS") || equalIgnoringCase(method, "POST") || equalIgnoringCase(method, "PROPFIND")
     386        || equalIgnoringCase(method, "PROPPATCH") || equalIgnoringCase(method, "PUT") || equalIgnoringCase(method, "UNLOCK")) {
     387        return method.upper();
     388    }
     389    return method;
     390}
     391
     392bool XMLHttpRequest::isAllowedHTTPHeader(const String& name)
     393{
     394    initializeXMLHttpRequestStaticData();
     395    return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
     396        && !name.startsWith(staticData->m_secHeaderPrefix, false);
     397}
     398
    401399void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionCode& ec)
    402400{
     
    419417    ASSERT(m_state == UNSENT);
    420418
    421     if (!isValidToken(method)) {
     419    if (!isValidHTTPToken(method)) {
    422420        ec = SYNTAX_ERR;
    423421        return;
    424422    }
    425423
    426     // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.
    427     String methodUpper(method.upper());
    428 
    429     if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {
     424    if (!isAllowedHTTPMethod(method)) {
    430425        ec = SECURITY_ERR;
    431426        return;
    432427    }
    433428
     429    m_method = uppercaseKnownHTTPMethod(method);
     430
    434431    m_url = url;
    435 
    436     if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"
    437         || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"
    438         || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"
    439         || methodUpper == "UNLOCK")
    440         m_method = methodUpper;
    441     else
    442         m_method = method;
    443432
    444433    m_async = async;
     
    836825    }
    837826
    838     if (!isValidToken(name) || !isValidHeaderValue(value)) {
     827    if (!isValidHTTPToken(name) || !isValidHTTPHeaderValue(value)) {
    839828        ec = SYNTAX_ERR;
    840829        return;
     
    842831
    843832    // A privileged script (e.g. a Dashboard widget) can set any headers.
    844     if (!securityOrigin()->canLoadLocalResources() && !isSafeRequestHeader(name)) {
     833    if (!securityOrigin()->canLoadLocalResources() && !isAllowedHTTPHeader(name)) {
    845834        reportUnsafeUsage(scriptExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
    846835        return;
     
    855844    if (!result.second)
    856845        result.first->second += ", " + value;
    857 }
    858 
    859 bool XMLHttpRequest::isSafeRequestHeader(const String& name) const
    860 {
    861     return !staticData->m_forbiddenRequestHeaders.contains(name) && !name.startsWith(staticData->m_proxyHeaderPrefix, false)
    862         && !name.startsWith(staticData->m_secHeaderPrefix, false);
    863846}
    864847
  • trunk/Source/WebCore/xml/XMLHttpRequest.h

    r92691 r94128  
    22 *  Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
    33 *  Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@nypop.com>
     4 *  Copyright (C) 2011 Google Inc. All rights reserved.
    45 *
    56 *  This library is free software; you can redistribute it and/or
     
    111112#endif
    112113
     114    // Expose HTTP validation methods for other untrusted requests.
     115    static bool isAllowedHTTPMethod(const String&);
     116    static String uppercaseKnownHTTPMethod(const String&);
     117    static bool isAllowedHTTPHeader(const String&);
     118
    113119    void setResponseType(const String&, ExceptionCode&);
    114120    String responseType();
     
    164170    String getRequestHeader(const AtomicString& name) const;
    165171    void setRequestHeaderInternal(const AtomicString& name, const String& value);
    166     bool isSafeRequestHeader(const String&) const;
    167172
    168173    void changeState(State newState);
Note: See TracChangeset for help on using the changeset viewer.