2011-04-07 Adam Barth <abarth@webkit.org>
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Apr 2011 20:51:22 +0000 (20:51 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Apr 2011 20:51:22 +0000 (20:51 +0000)
        Reviewed by Eric Seidel.

        Implement CSP's options directive
        https://bugs.webkit.org/show_bug.cgi?id=58014

        * http/tests/security/contentSecurityPolicy/inline-script-allowed-expected.txt: Added.
        * http/tests/security/contentSecurityPolicy/inline-script-allowed.html: Added.
        * http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy-expected.txt: Added.
        * http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html: Added.
2011-04-07  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        Implement CSP's options directive
        https://bugs.webkit.org/show_bug.cgi?id=58014

        This patch contains the full options parser, but we only have enough of
        CSP implemented to see the effects of disable-xss-protection.  Will
        need to do some more work before we can see eval-script in action.

        Tests: http/tests/security/contentSecurityPolicy/inline-script-allowed.html
               http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html

        * page/ContentSecurityPolicy.cpp:
        (WebCore::CSPOptions::CSPOptions):
        (WebCore::CSPOptions::disableXSSProtection):
        (WebCore::CSPOptions::evalScript):
        (WebCore::CSPOptions::parse):
        (WebCore::ContentSecurityPolicy::allowJavaScriptURLs):
        (WebCore::ContentSecurityPolicy::allowInlineEventHandlers):
        (WebCore::ContentSecurityPolicy::allowInlineScript):
        (WebCore::ContentSecurityPolicy::addDirective):
        * page/ContentSecurityPolicy.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83205 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed.html [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/ContentSecurityPolicy.cpp
Source/WebCore/page/ContentSecurityPolicy.h

index 1b52658..30e7de0 100644 (file)
@@ -1,3 +1,15 @@
+2011-04-07  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Implement CSP's options directive
+        https://bugs.webkit.org/show_bug.cgi?id=58014
+
+        * http/tests/security/contentSecurityPolicy/inline-script-allowed-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/inline-script-allowed.html: Added.
+        * http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy-expected.txt: Added.
+        * http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html: Added.
+
 2011-04-07  Enrica Casucci  <enrica@apple.com>
 
         Unreviewed.
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed-expected.txt b/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed-expected.txt
new file mode 100644 (file)
index 0000000..276099c
--- /dev/null
@@ -0,0 +1,4 @@
+ALERT: PASS 1 of 3
+ALERT: PASS 2 of 3
+ALERT: PASS 3 of 3
+
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed.html b/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-allowed.html
new file mode 100644 (file)
index 0000000..b07431e
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-WebKit-CSP" content="script-src http://127.0.0.1:*; options disable-xss-protection">
+<script src="resources/dump-as-text.js"></script>
+</head>
+<body onload="alert('PASS 3 of 3')">
+<script>
+alert('PASS 1 of 3');
+</script>
+<iframe src="javascript:alert('PASS 2 of 3')"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy-expected.txt b/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy-expected.txt
new file mode 100644 (file)
index 0000000..d04a3fb
--- /dev/null
@@ -0,0 +1 @@
+This test passes if it doesn't alert fail.  
diff --git a/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html b/LayoutTests/http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html
new file mode 100644 (file)
index 0000000..a67d56f
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="X-WebKit-CSP" content="script-src http://127.0.0.1:*; options goofy">
+<script src="resources/dump-as-text.js"></script>
+</head>
+<body onload="alert('FAIL 3 of 3')">
+This test passes if it doesn't alert fail.
+<script>
+alert('FAIL 1 of 3');
+</script>
+<iframe src="javascript:alert('FAIL 2 of 3')"></iframe>
+</body>
+</html>
index fad5a3c..15e3284 100644 (file)
@@ -1,3 +1,28 @@
+2011-04-07  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        Implement CSP's options directive
+        https://bugs.webkit.org/show_bug.cgi?id=58014
+
+        This patch contains the full options parser, but we only have enough of
+        CSP implemented to see the effects of disable-xss-protection.  Will
+        need to do some more work before we can see eval-script in action.
+
+        Tests: http/tests/security/contentSecurityPolicy/inline-script-allowed.html
+               http/tests/security/contentSecurityPolicy/inline-script-blocked-goofy.html
+
+        * page/ContentSecurityPolicy.cpp:
+        (WebCore::CSPOptions::CSPOptions):
+        (WebCore::CSPOptions::disableXSSProtection):
+        (WebCore::CSPOptions::evalScript):
+        (WebCore::CSPOptions::parse):
+        (WebCore::ContentSecurityPolicy::allowJavaScriptURLs):
+        (WebCore::ContentSecurityPolicy::allowInlineEventHandlers):
+        (WebCore::ContentSecurityPolicy::allowInlineScript):
+        (WebCore::ContentSecurityPolicy::addDirective):
+        * page/ContentSecurityPolicy.h:
+
 2011-04-07  Alexey Proskuryakov  <ap@apple.com>
 
         Reviewed by Anders Carlsson.
index b8989af..a92b428 100644 (file)
@@ -57,6 +57,11 @@ bool isHostCharacter(UChar c)
     return isASCIIAlphanumeric(c) || c == '-';
 }
 
+bool isOptionValueCharacter(UChar c)
+{
+    return isASCIIAlphanumeric(c) || c == '-';
+}
+
 bool isSchemeContinuationCharacter(UChar c)
 {
     return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
@@ -406,6 +411,55 @@ private:
     CSPSourceList m_sourceList;
 };
 
+class CSPOptions {
+public:
+    explicit CSPOptions(const String& value)
+        : m_disableXSSProtection(false)
+        , m_evalScript(false)
+    {
+        parse(value);
+    }
+
+    bool disableXSSProtection() const { return m_disableXSSProtection; }
+    bool evalScript() const { return m_evalScript; }
+
+private:
+    void parse(const String&);
+
+    bool m_disableXSSProtection;
+    bool m_evalScript;
+};
+
+// options           = "options" *( 1*WSP option-value ) *WSP
+// option-value      = 1*( ALPHA / DIGIT / "-" )
+//
+void CSPOptions::parse(const String& value)
+{
+    DEFINE_STATIC_LOCAL(String, disableXSSProtection, ("disable-xss-protection"));
+    DEFINE_STATIC_LOCAL(String, evalScript, ("eval-script"));
+
+    const UChar* position = value.characters();
+    const UChar* end = position + value.length();
+
+    while (position < end) {
+        skipWhile<isASCIISpace>(position, end);
+
+        const UChar* optionsValueBegin = position;
+
+        if (!skipExactly<isOptionValueCharacter>(position, end))
+            return;
+
+        skipWhile<isOptionValueCharacter>(position, end);
+
+        String optionsValue(optionsValueBegin, position - optionsValueBegin);
+
+        if (equalIgnoringCase(optionsValue, disableXSSProtection))
+            m_disableXSSProtection = true;
+        else if (equalIgnoringCase(optionsValue, evalScript))
+            m_evalScript = true;
+    }
+}
+
 ContentSecurityPolicy::ContentSecurityPolicy(SecurityOrigin* origin)
     : m_havePolicy(false)
     , m_origin(origin)
@@ -425,19 +479,24 @@ void ContentSecurityPolicy::didReceiveHeader(const String& header)
     m_havePolicy = true;
 }
 
+bool ContentSecurityPolicy::protectAgainstXSS() const
+{
+    return m_scriptSrc && (!m_options || !m_options->disableXSSProtection());
+}
+
 bool ContentSecurityPolicy::allowJavaScriptURLs() const
 {
-    return !m_scriptSrc;
+    return !protectAgainstXSS();
 }
 
 bool ContentSecurityPolicy::allowInlineEventHandlers() const
 {
-    return !m_scriptSrc;
+    return !protectAgainstXSS();
 }
 
 bool ContentSecurityPolicy::allowInlineScript() const
 {
-    return !m_scriptSrc;
+    return !protectAgainstXSS();
 }
 
 bool ContentSecurityPolicy::allowScriptFromSource(const KURL& url) const
@@ -525,6 +584,7 @@ void ContentSecurityPolicy::addDirective(const String& name, const String& value
 {
     DEFINE_STATIC_LOCAL(String, scriptSrc, ("script-src"));
     DEFINE_STATIC_LOCAL(String, objectSrc, ("object-src"));
+    DEFINE_STATIC_LOCAL(String, options, ("options"));
 
     ASSERT(!name.isEmpty());
 
@@ -532,6 +592,8 @@ void ContentSecurityPolicy::addDirective(const String& name, const String& value
         m_scriptSrc = adoptPtr(new CSPDirective(value, m_origin.get()));
     else if (!m_objectSrc && equalIgnoringCase(name, objectSrc))
         m_objectSrc = adoptPtr(new CSPDirective(value, m_origin.get()));
+    else if (!m_options && equalIgnoringCase(name, options))
+        m_options = adoptPtr(new CSPOptions(value));
 }
 
 }
index 750a443..7ec4ffc 100644 (file)
@@ -32,6 +32,7 @@
 namespace WebCore {
 
 class CSPDirective;
+class CSPOptions;
 class KURL;
 class SecurityOrigin;
 
@@ -54,6 +55,8 @@ public:
 private:
     explicit ContentSecurityPolicy(SecurityOrigin*);
 
+    bool protectAgainstXSS() const;
+
     void parse(const String&);
     bool parseDirective(const UChar* begin, const UChar* end, String& name, String& value);
     void addDirective(const String& name, const String& value);
@@ -62,6 +65,7 @@ private:
     RefPtr<SecurityOrigin> m_origin;
     OwnPtr<CSPDirective> m_scriptSrc;
     OwnPtr<CSPDirective> m_objectSrc;
+    OwnPtr<CSPOptions> m_options;
 };
 
 }