+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.
return isASCIIAlphanumeric(c) || c == '-';
}
+bool isOptionValueCharacter(UChar c)
+{
+ return isASCIIAlphanumeric(c) || c == '-';
+}
+
bool isSchemeContinuationCharacter(UChar c)
{
return isASCIIAlphanumeric(c) || c == '+' || c == '-' || c == '.';
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)
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
{
DEFINE_STATIC_LOCAL(String, scriptSrc, ("script-src"));
DEFINE_STATIC_LOCAL(String, objectSrc, ("object-src"));
+ DEFINE_STATIC_LOCAL(String, options, ("options"));
ASSERT(!name.isEmpty());
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));
}
}