Changeset 82028 in webkit


Ignore:
Timestamp:
Mar 26, 2011 4:59:34 AM (13 years ago)
Author:
abarth@webkit.org
Message:

2011-03-26 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

Teach Content Security Policy how to parse source-list
https://bugs.webkit.org/show_bug.cgi?id=54799

Test a variety of source-list parsing cases. There's a bunch more
cases we could be testing. We'll add more over time.

  • http/tests/security/contentSecurityPolicy/source-list-parsing-expected.txt: Added.
  • http/tests/security/contentSecurityPolicy/source-list-parsing.html: Added.

2011-03-26 Adam Barth <abarth@webkit.org>

Reviewed by Eric Seidel.

Teach Content Security Policy how to parse source-list
https://bugs.webkit.org/show_bug.cgi?id=54799

This patch is larger than I would like, but I wasn't sure how to make
it any smaller while still being reasonably testable. I've left out
some features (such as host wildcarding and 'self') so I can add them
in later patches with tests.

Test: http/tests/security/contentSecurityPolicy/source-list-parsing.html

  • bindings/ScriptControllerBase.cpp:
  • dom/ScriptElement.cpp:
  • html/parser/HTMLDocumentParser.cpp:
  • loader/FrameLoader.cpp:
    • Add include explicitly now that we're not spamming the include everywhere.
  • dom/Document.cpp: (WebCore::Document::initSecurityContext):
    • We need to pass the SecurityOrigin object to ContentSecurityPolicy so that it can resolve implicit parts of source patterns, such as the scheme.
  • dom/Document.h:
    • Forward declare ContentSecurityPolicy rather than including the header. Technically this could be a separate change, but I was getting annoyed at the world re-builds.
  • page/ContentSecurityPolicy.cpp: (WebCore::skipExactly): (WebCore::skipUtil): (WebCore::skipWhile):
    • Clean up these parser helper functions. We might consider moving them to a more general location. They're very helpful for writing secure HTTP header parsers.

(WebCore::CSPSource::CSPSource):

  • New class to represent one source in a source-list.

(WebCore::CSPSource::matches):
(WebCore::CSPSource::schemeMatches):
(WebCore::CSPSource::hostMatches):
(WebCore::CSPSource::portMatches):
(WebCore::CSPSource::isSchemeOnly):

  • Currently we represent scheme-only sources using with an empty m_host. Another approach I considered was using another bool, but that seemed slighly messier.

(WebCore::CSPSourceList::CSPSourceList):

  • CSPSourceList doesn't need to ref SecurityOrigin because CSPSourceList is owned by ContentSecurityPolicy, which holds a ref.

(WebCore::CSPSourceList::parse):
(WebCore::CSPSourceList::matches):
(WebCore::CSPSourceList::parseSource):
(WebCore::CSPSourceList::parseScheme):
(WebCore::CSPSourceList::parseHost):
(WebCore::CSPSourceList::parsePort):

  • A basic "segment and recurse" parser. This parser causes us to take more branches than we need, but I don't think we need to squeeze every last ouch of performance out of this parser. This approach is more simple than some of the other approaches I tried.

(WebCore::CSPSourceList::addSourceSelf):
(WebCore::CSPDirective::CSPDirective):
(WebCore::CSPDirective::allows):
(WebCore::ContentSecurityPolicy::ContentSecurityPolicy):
(WebCore::ContentSecurityPolicy::parse):
(WebCore::ContentSecurityPolicy::parseDirective):
(WebCore::ContentSecurityPolicy::addDirective):

  • I couldn't resist re-writing this parser to use the helper functions and to match the style of the source-list parser.
  • page/ContentSecurityPolicy.h: (WebCore::ContentSecurityPolicy::create):
    • Accept a SecurityOrigin context object.
Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r82026 r82028  
     12011-03-26  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Teach Content Security Policy how to parse source-list
     6        https://bugs.webkit.org/show_bug.cgi?id=54799
     7
     8        Test a variety of source-list parsing cases.  There's a bunch more
     9        cases we could be testing.  We'll add more over time.
     10
     11        * http/tests/security/contentSecurityPolicy/source-list-parsing-expected.txt: Added.
     12        * http/tests/security/contentSecurityPolicy/source-list-parsing.html: Added.
     13
    1142011-03-26  Dan Bernstein  <mitz@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r82027 r82028  
     12011-03-26  Adam Barth  <abarth@webkit.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Teach Content Security Policy how to parse source-list
     6        https://bugs.webkit.org/show_bug.cgi?id=54799
     7
     8        This patch is larger than I would like, but I wasn't sure how to make
     9        it any smaller while still being reasonably testable.  I've left out
     10        some features (such as host wildcarding and 'self') so I can add them
     11        in later patches with tests.
     12
     13        Test: http/tests/security/contentSecurityPolicy/source-list-parsing.html
     14
     15        * bindings/ScriptControllerBase.cpp:
     16        * dom/ScriptElement.cpp:
     17        * html/parser/HTMLDocumentParser.cpp:
     18        * loader/FrameLoader.cpp:
     19            - Add include explicitly now that we're not spamming the include
     20              everywhere.
     21        * dom/Document.cpp:
     22        (WebCore::Document::initSecurityContext):
     23            - We need to pass the SecurityOrigin object to
     24              ContentSecurityPolicy so that it can resolve implicit parts of
     25              source patterns, such as the scheme.
     26        * dom/Document.h:
     27            - Forward declare ContentSecurityPolicy rather than including the
     28              header.  Technically this could be a separate change, but I was
     29              getting annoyed at the world re-builds.
     30        * page/ContentSecurityPolicy.cpp:
     31        (WebCore::skipExactly):
     32        (WebCore::skipUtil):
     33        (WebCore::skipWhile):
     34            - Clean up these parser helper functions.  We might consider moving
     35              them to a more general location.  They're very helpful for
     36              writing secure HTTP header parsers.
     37        (WebCore::CSPSource::CSPSource):
     38            - New class to represent one source in a source-list.
     39        (WebCore::CSPSource::matches):
     40        (WebCore::CSPSource::schemeMatches):
     41        (WebCore::CSPSource::hostMatches):
     42        (WebCore::CSPSource::portMatches):
     43        (WebCore::CSPSource::isSchemeOnly):
     44            - Currently we represent scheme-only sources using with an empty
     45              m_host.  Another approach I considered was using another bool,
     46              but that seemed slighly messier.
     47        (WebCore::CSPSourceList::CSPSourceList):
     48            - CSPSourceList doesn't need to ref SecurityOrigin because
     49              CSPSourceList is owned by ContentSecurityPolicy, which holds a
     50              ref.
     51        (WebCore::CSPSourceList::parse):
     52        (WebCore::CSPSourceList::matches):
     53        (WebCore::CSPSourceList::parseSource):
     54        (WebCore::CSPSourceList::parseScheme):
     55        (WebCore::CSPSourceList::parseHost):
     56        (WebCore::CSPSourceList::parsePort):
     57            - A basic "segment and recurse" parser.  This parser causes us to
     58              take more branches than we need, but I don't think we need to
     59              squeeze every last ouch of performance out of this parser.  This
     60              approach is more simple than some of the other approaches I
     61              tried.
     62        (WebCore::CSPSourceList::addSourceSelf):
     63        (WebCore::CSPDirective::CSPDirective):
     64        (WebCore::CSPDirective::allows):
     65        (WebCore::ContentSecurityPolicy::ContentSecurityPolicy):
     66        (WebCore::ContentSecurityPolicy::parse):
     67        (WebCore::ContentSecurityPolicy::parseDirective):
     68        (WebCore::ContentSecurityPolicy::addDirective):
     69            - I couldn't resist re-writing this parser to use the helper
     70              functions and to match the style of the source-list parser.
     71        * page/ContentSecurityPolicy.h:
     72        (WebCore::ContentSecurityPolicy::create):
     73            - Accept a SecurityOrigin context object.
     74
    1752011-03-26  Patrick Gansterer  <paroga@webkit.org>
    276
  • trunk/Source/WebCore/bindings/ScriptControllerBase.cpp

    r79547 r82028  
    2222#include "ScriptController.h"
    2323
     24#include "ContentSecurityPolicy.h"
    2425#include "DocumentLoader.h"
    2526#include "Frame.h"
  • trunk/Source/WebCore/dom/Document.cpp

    r81965 r82028  
    4343#include "Comment.h"
    4444#include "Console.h"
     45#include "ContentSecurityPolicy.h"
    4546#include "CookieJar.h"
    4647#include "CustomEvent.h"
     
    45014502    m_cookieURL = m_url;
    45024503    ScriptExecutionContext::setSecurityOrigin(SecurityOrigin::create(m_url, m_frame->loader()->sandboxFlags()));
    4503     m_contentSecurityPolicy = ContentSecurityPolicy::create();
     4504    m_contentSecurityPolicy = ContentSecurityPolicy::create(securityOrigin());
    45044505
    45054506    if (SecurityOrigin::allowSubstituteDataAccessToLocal()) {
  • trunk/Source/WebCore/dom/Document.h

    r81220 r82028  
    3333#include "Color.h"
    3434#include "ContainerNode.h"
    35 #include "ContentSecurityPolicy.h"
    3635#include "DOMTimeStamp.h"
    3736#include "DocumentOrderedMap.h"
     
    5251namespace WebCore {
    5352
     53class AXObjectCache;
    5454class Attr;
    55 class AXObjectCache;
    5655class CDATASection;
     56class CSSPrimitiveValueCache;
     57class CSSStyleDeclaration;
     58class CSSStyleSelector;
     59class CSSStyleSheet;
    5760class CachedCSSStyleSheet;
    5861class CachedResourceLoader;
     
    6063class CanvasRenderingContext;
    6164class CharacterData;
    62 class CSSPrimitiveValueCache;
    63 class CSSStyleDeclaration;
    64 class CSSStyleSelector;
    65 class CSSStyleSheet;
    6665class Comment;
     66class ContentSecurityPolicy;
    6767class DOMImplementation;
    6868class DOMSelection;
  • trunk/Source/WebCore/dom/ScriptElement.cpp

    r81198 r82028  
    2727#include "CachedScript.h"
    2828#include "CachedResourceLoader.h"
     29#include "ContentSecurityPolicy.h"
    2930#include "Document.h"
    3031#include "DocumentParser.h"
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp

    r80861 r82028  
    2727#include "HTMLDocumentParser.h"
    2828
     29#include "ContentSecurityPolicy.h"
    2930#include "DocumentFragment.h"
    3031#include "Element.h"
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r82010 r82028  
    4242#include "CachedResourceLoader.h"
    4343#include "Chrome.h"
     44#include "ContentSecurityPolicy.h"
    4445#include "DOMImplementation.h"
    4546#include "DOMWindow.h"
  • trunk/Source/WebCore/page/ContentSecurityPolicy.cpp

    r81425 r82028  
    2626#include "config.h"
    2727#include "ContentSecurityPolicy.h"
     28
    2829#include "Document.h"
     30#include "NotImplemented.h"
     31#include "SecurityOrigin.h"
    2932
    3033namespace WebCore {
    3134
    32 static bool isDirectiveNameCharacter(UChar c)
    33 {
    34     return isASCIIAlpha(c) || isASCIIDigit(c) || c == '-';
    35 }
    36 
    37 static bool isDirectiveValueCharacter(UChar c)
     35// Normally WebKit uses "static" for internal linkage, but using "static" for
     36// these functions causes a compile error because these functions are used as
     37// template parameters.
     38namespace {
     39
     40bool isDirectiveNameCharacter(UChar c)
     41{
     42    return isASCIIAlphanumeric(c) || c == '-';
     43}
     44
     45bool isDirectiveValueCharacter(UChar c)
    3846{
    3947    return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
    4048}
    4149
    42 static void advanceUntil(const UChar*& pos, const UChar* end, UChar delimiter)
    43 {
    44     while (pos < end) {
    45         if (*pos++ == delimiter)
    46             return;
    47     }
     50bool isSourceCharacter(UChar c)
     51{
     52    return !isASCIISpace(c);
     53}
     54
     55bool isHostCharacter(UChar c)
     56{
     57    return isASCIIAlphanumeric(c) || c == '-';
     58}
     59
     60bool isSchemeContinuationCharacter(UChar c)
     61{
     62    return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
     63}
     64
     65} // namespace
     66
     67static bool skipExactly(const UChar*& position, const UChar* end, UChar delimiter)
     68{
     69    if (position < end && *position == delimiter) {
     70        ++position;
     71        return true;
     72    }
     73    return false;
     74}
     75
     76template<bool characterPredicate(UChar)>
     77static bool skipExactly(const UChar*& position, const UChar* end)
     78{
     79    if (position < end && characterPredicate(*position)) {
     80        ++position;
     81        return true;
     82    }
     83    return false;
     84}
     85
     86static void skipUtil(const UChar*& position, const UChar* end, UChar delimiter)
     87{
     88    while (position < end && *position != delimiter)
     89        ++position;
     90}
     91
     92template<bool characterPredicate(UChar)>
     93static void skipWhile(const UChar*& position, const UChar* end)
     94{
     95    while (position < end && characterPredicate(*position))
     96        ++position;
     97}
     98
     99class CSPSource {
     100public:
     101    CSPSource(const String& scheme, const String& host, int port, bool hostHasWildcard, bool portHasWildcard)
     102        : m_scheme(scheme)
     103        , m_host(host)
     104        , m_port(port)
     105        , m_hostHasWildcard(hostHasWildcard)
     106        , m_portHasWildcard(portHasWildcard)
     107    {
     108    }
     109
     110    bool matches(const KURL& url) const
     111    {
     112        if (!schemeMatches(url))
     113            return false;
     114        if (isSchemeOnly())
     115            return true;
     116        return hostMatches(url) && portMatches(url);
     117    }
     118
     119private:
     120    bool schemeMatches(const KURL& url) const
     121    {
     122        return equalIgnoringCase(url.protocol(), m_scheme);
     123    }
     124
     125    bool hostMatches(const KURL& url) const
     126    {
     127        if (m_hostHasWildcard)
     128            notImplemented();
     129
     130        return equalIgnoringCase(url.host(), m_host);
     131    }
     132
     133    bool portMatches(const KURL& url) const
     134    {
     135        if (m_portHasWildcard)
     136            return true;
     137
     138        // FIXME: Handle explicit default ports correctly.
     139        return url.port() == m_port;
     140    }
     141
     142    bool isSchemeOnly() const { return m_host.isEmpty(); }
     143
     144    String m_scheme;
     145    String m_host;
     146    int m_port;
     147
     148    bool m_hostHasWildcard;
     149    bool m_portHasWildcard;
     150};
     151
     152class CSPSourceList {
     153public:
     154    explicit CSPSourceList(SecurityOrigin*);
     155
     156    void parse(const String&);
     157    bool matches(const KURL&);
     158
     159private:
     160    void parse(const UChar* begin, const UChar* end);
     161
     162    bool parseSource(const UChar* begin, const UChar* end, String& scheme, String& host, int& port, bool& hostHasWildcard, bool& portHasWildcard);
     163    bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
     164    bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard);
     165    bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard);
     166
     167    void addSourceSelf();
     168
     169    SecurityOrigin* m_origin;
     170    Vector<CSPSource> m_list;
     171};
     172
     173CSPSourceList::CSPSourceList(SecurityOrigin* origin)
     174    : m_origin(origin)
     175{
     176}
     177
     178void CSPSourceList::parse(const String& value)
     179{
     180    parse(value.characters(), value.characters() + value.length());
     181}
     182
     183bool CSPSourceList::matches(const KURL& url)
     184{
     185    for (size_t i = 0; i < m_list.size(); ++i) {
     186        if (m_list[i].matches(url))
     187            return true;
     188    }
     189    return false;
     190}
     191
     192// source-list       = *WSP [ source *( 1*WSP source ) *WSP ]
     193//                   / *WSP "'none'" *WSP
     194//
     195void CSPSourceList::parse(const UChar* begin, const UChar* end)
     196{
     197    const UChar* position = begin;
     198
     199    bool isFirstSourceInList = true;
     200    while (position < end) {
     201        skipWhile<isASCIISpace>(position, end);
     202        const UChar* beginSource = position;
     203        skipWhile<isSourceCharacter>(position, end);
     204
     205        if (isFirstSourceInList && equalIgnoringCase("'none'", beginSource, position - beginSource))
     206            return; // We represent 'none' as an empty m_list.
     207        isFirstSourceInList = false;
     208
     209        String scheme, host;
     210        int port = 0;
     211        bool hostHasWildcard = false;
     212        bool portHasWildcard = false;
     213
     214        if (parseSource(beginSource, position, scheme, host, port, hostHasWildcard, portHasWildcard)) {
     215            if (scheme.isEmpty())
     216                scheme = m_origin->protocol();
     217            m_list.append(CSPSource(scheme, host, port, hostHasWildcard, portHasWildcard));
     218        }
     219
     220        ASSERT(position == end || isASCIISpace(*position));
     221     }
     222}
     223
     224// source            = scheme ":"
     225//                   / ( [ scheme "://" ] host [ port ] )
     226//                   / "'self'"
     227//
     228bool CSPSourceList::parseSource(const UChar* begin, const UChar* end,
     229                                String& scheme, String& host, int& port,
     230                                bool& hostHasWildcard, bool& portHasWildcard)
     231{
     232    if (begin == end)
     233        return false;
     234
     235    if (equalIgnoringCase("'self'", begin, end - begin)) {
     236        addSourceSelf();
     237        return false;
     238    }
     239
     240    const UChar* position = begin;
     241
     242    const UChar* beginHost = begin;
     243    skipUtil(position, end, ':');
     244
     245    if (position == end) {
     246        // This must be a host-only source.
     247        if (!parseHost(beginHost, position, host, hostHasWildcard))
     248            return false;
     249        return true;
     250    }
     251
     252    if (end - position == 1) {
     253        ASSERT(*position == ':');
     254        // This must be a scheme-only source.
     255        if (!parseScheme(begin, position, scheme))
     256            return false;
     257        return true;
     258    }
     259
     260    ASSERT(end - position >= 2);
     261    if (position[1] == '/') {
     262        if (!parseScheme(begin, position, scheme)
     263            || !skipExactly(position, end, ':')
     264            || !skipExactly(position, end, '/')
     265            || !skipExactly(position, end, '/'))
     266            return false;
     267        beginHost = position;
     268        skipUtil(position, end, ':');
     269    }
     270
     271    if (position == beginHost)
     272        return false;
     273
     274    if (!parseHost(beginHost, position, host, hostHasWildcard))
     275        return false;
     276
     277    if (position == end) {
     278        port = 0;
     279        return true;
     280    }
     281
     282    if (!skipExactly(position, end, ':'))
     283        ASSERT_NOT_REACHED();
     284
     285    if (!parsePort(position, end, port, portHasWildcard))
     286        return false;
     287
     288    return true;
     289}
     290
     291//                     ; <scheme> production from RFC 3986
     292// scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
     293//
     294bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& scheme)
     295{
     296    ASSERT(begin <= end);
     297    ASSERT(scheme.isEmpty());
     298
     299    if (begin == end)
     300        return false;
     301
     302    const UChar* position = begin;
     303
     304    if (!skipExactly<isASCIIAlpha>(position, end))
     305        return false;
     306
     307    skipWhile<isSchemeContinuationCharacter>(position, end);
     308
     309    if (position != end)
     310        return false;
     311
     312    scheme = String(begin, end - begin);
     313    return true;
     314}
     315
     316// host              = [ "*." ] 1*host-char *( "." 1*host-char )
     317//                   / "*"
     318// host-char         = ALPHA / DIGIT / "-"
     319//
     320bool CSPSourceList::parseHost(const UChar* begin, const UChar* end, String& host, bool& hostHasWildcard)
     321{
     322    ASSERT(begin <= end);
     323    ASSERT(host.isEmpty());
     324    ASSERT(!hostHasWildcard);
     325
     326    if (begin == end)
     327        return false;
     328
     329    const UChar* position = begin;
     330
     331    if (skipExactly(position, end, '*')) {
     332        hostHasWildcard = true;
     333
     334        if (position == end)
     335            return true;
     336
     337        if (!skipExactly(position, end, '.'))
     338            return false;
     339    }
     340
     341    const UChar* hostBegin = position;
     342
     343    while (position < end) {
     344        if (!skipExactly<isHostCharacter>(position, end))
     345            return false;
     346
     347        skipWhile<isHostCharacter>(position, end);
     348
     349        if (position < end && !skipExactly(position, end, '.'))
     350            return false;
     351    }
     352
     353    ASSERT(position == end);
     354    host = String(hostBegin, end - hostBegin);
     355    return true;
     356}
     357
     358// port              = ":" ( 1*DIGIT / "*" )
     359//
     360bool CSPSourceList::parsePort(const UChar* begin, const UChar* end, int& port, bool& portHasWildcard)
     361{
     362    ASSERT(begin <= end);
     363    ASSERT(!port);
     364    ASSERT(!portHasWildcard);
     365
     366    if (begin == end)
     367        return false;
     368
     369    if (end - begin == 1 && *begin == '*') {
     370        port = 0;
     371        portHasWildcard = true;
     372        return true;
     373    }
     374
     375    const UChar* position = begin;
     376    skipWhile<isASCIIDigit>(position, end);
     377
     378    if (position != end)
     379        return false;
     380
     381    bool ok;
     382    port = charactersToIntStrict(begin, end - begin, &ok);
     383    return ok;
     384}
     385
     386void CSPSourceList::addSourceSelf()
     387{
     388    // FIXME: Inherit the scheme, host, and port from the current URL.
     389    notImplemented();
    48390}
    49391
    50392class CSPDirective {
    51393public:
    52     explicit CSPDirective(const String& value)
    53         : m_value(value)
    54     {
    55     }
    56 
    57     bool allows(const KURL&)
    58     {
    59         return false;
     394    CSPDirective(const String& value, SecurityOrigin* origin)
     395        : m_sourceList(origin)
     396    {
     397        m_sourceList.parse(value);
     398    }
     399
     400    bool allows(const KURL& url)
     401    {
     402        return m_sourceList.matches(url);
    60403    }
    61404
    62405private:
    63     String m_value;
     406    CSPSourceList m_sourceList;
    64407};
    65408
    66 ContentSecurityPolicy::ContentSecurityPolicy()
     409ContentSecurityPolicy::ContentSecurityPolicy(SecurityOrigin* origin)
    67410    : m_havePolicy(false)
     411    , m_origin(origin)
    68412{
    69413}
     
    92436}
    93437
     438// policy            = directive-list
     439// directive-list    = [ directive *( ";" [ directive ] ) ]
     440//
    94441void ContentSecurityPolicy::parse(const String& policy)
    95442{
     
    99446        return;
    100447
    101     const UChar* pos = policy.characters();
    102     const UChar* end = pos + policy.length();
    103 
    104     while (pos < end) {
    105         Vector<UChar, 32> name;
    106         Vector<UChar, 64> value;
    107 
    108         if (!parseDirective(pos, end, name, value))
    109             continue;
    110         if (name.isEmpty())
    111             continue;
    112 
    113         // We use a copy here instead of String::adopt because we expect
    114         // the name and the value to be relatively short, so the copy will
    115         // be cheaper than the extra malloc.
    116         emitDirective(String(name), String(value));
    117     }
    118 }
    119 
    120 bool ContentSecurityPolicy::parseDirective(const UChar*& pos, const UChar* end, Vector<UChar, 32>& name, Vector<UChar, 64>& value)
    121 {
    122     ASSERT(pos < end);
     448    const UChar* position = policy.characters();
     449    const UChar* end = position + policy.length();
     450
     451    while (position < end) {
     452        const UChar* directiveBegin = position;
     453        skipUtil(position, end, ';');
     454
     455        String name, value;
     456        if (parseDirective(directiveBegin, position, name, value)) {
     457            ASSERT(!name.isEmpty());
     458            addDirective(name, value);
     459        }
     460
     461        ASSERT(position == end || *position == ';');
     462        skipExactly(position, end, ';');
     463    }
     464}
     465
     466// directive         = *WSP [ directive-name [ WSP directive-value ] ]
     467// directive-name    = 1*( ALPHA / DIGIT / "-" )
     468// directive-value   = *( WSP / <VCHAR except ";"> )
     469//
     470bool ContentSecurityPolicy::parseDirective(const UChar* begin, const UChar* end, String& name, String& value)
     471{
    123472    ASSERT(name.isEmpty());
    124473    ASSERT(value.isEmpty());
    125474
    126     while (pos < end && isASCIISpace(*pos))
    127         pos++;
    128 
    129     while (pos < end) {
    130         UChar currentCharacter = *pos;
    131         if (currentCharacter == ';')
    132             break;
    133         if (isASCIISpace(currentCharacter))
    134             break;
    135         if (!isDirectiveNameCharacter(currentCharacter)) {
    136             advanceUntil(pos, end, ';');
    137             return false;
    138         }
    139         name.append(currentCharacter);
    140         pos++;
    141     }
    142 
    143     while (pos < end && isASCIISpace(*pos))
    144         pos++;
    145 
    146     if (pos < end && *pos == ';') {
    147         pos++;
    148         return true;
    149     }
    150 
    151     while (pos < end) {
    152         UChar currentCharacter = *pos;
    153         if (currentCharacter == ';')
    154             break;
    155         if (!isDirectiveValueCharacter(currentCharacter)) {
    156             advanceUntil(pos, end, ';');
    157             return false;
    158         }
    159         value.append(currentCharacter);
    160         pos++;
    161     }
    162 
    163     if (pos < end && *pos == ';') {
    164         pos++;
    165         return true;
    166     }
    167 
     475    const UChar* position = begin;
     476    skipWhile<isASCIISpace>(position, end);
     477
     478    const UChar* nameBegin = position;
     479    skipWhile<isDirectiveNameCharacter>(position, end);
     480
     481    // The directive-name must be non-empty.
     482    if (nameBegin == position)
     483        return false;
     484
     485    name = String(nameBegin, position - nameBegin);
     486
     487    if (position == end)
     488        return true;
     489
     490    if (!skipExactly<isASCIISpace>(position, end))
     491        return false;
     492
     493    skipWhile<isASCIISpace>(position, end);
     494
     495    const UChar* valueBegin = position;
     496    skipWhile<isDirectiveValueCharacter>(position, end);
     497
     498    if (position != end)
     499        return false;
     500
     501    // The directive-value may be empty.
     502    if (valueBegin == position)
     503        return true;
     504
     505    value = String(valueBegin, position - valueBegin);
    168506    return true;
    169507}
    170508
    171 void ContentSecurityPolicy::emitDirective(const String& name, const String& value)
     509void ContentSecurityPolicy::addDirective(const String& name, const String& value)
    172510{
    173511    DEFINE_STATIC_LOCAL(String, scriptSrc, ("script-src"));
     
    176514
    177515    if (!m_scriptSrc && equalIgnoringCase(name, scriptSrc))
    178         m_scriptSrc = adoptPtr(new CSPDirective(value));
    179 }
    180 
    181 }
     516        m_scriptSrc = adoptPtr(new CSPDirective(value, m_origin.get()));
     517}
     518
     519}
  • trunk/Source/WebCore/page/ContentSecurityPolicy.h

    r81425 r82028  
    3333
    3434class CSPDirective;
     35class SecurityOrigin;
    3536
    3637class ContentSecurityPolicy : public RefCounted<ContentSecurityPolicy> {
    3738public:
    38     static PassRefPtr<ContentSecurityPolicy> create() { return adoptRef(new ContentSecurityPolicy); }
     39    static PassRefPtr<ContentSecurityPolicy> create(SecurityOrigin* origin = 0)
     40    {
     41        return adoptRef(new ContentSecurityPolicy(origin));
     42    }
    3943    ~ContentSecurityPolicy();
    4044
     
    4650
    4751private:
    48     ContentSecurityPolicy();
     52    explicit ContentSecurityPolicy(SecurityOrigin*);
    4953
    5054    void parse(const String&);
    51     bool parseDirective(const UChar*& pos, const UChar* end, Vector<UChar, 32>& name, Vector<UChar, 64>& value);
    52     void emitDirective(const String& name, const String& value);
     55    bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
     56    void addDirective(const String& name, const String& value);
    5357
    5458    bool m_havePolicy;
     59    RefPtr<SecurityOrigin> m_origin;
    5560    OwnPtr<CSPDirective> m_scriptSrc;
    5661};
Note: See TracChangeset for help on using the changeset viewer.