| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google, Inc. All rights reserved. | 2 * Copyright (C) 2011 Google, Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 static const char sandbox[] = "sandbox"; | 121 static const char sandbox[] = "sandbox"; |
| 122 static const char scriptSrc[] = "script-src"; | 122 static const char scriptSrc[] = "script-src"; |
| 123 static const char styleSrc[] = "style-src"; | 123 static const char styleSrc[] = "style-src"; |
| 124 | 124 |
| 125 // CSP 1.1 Directives | 125 // CSP 1.1 Directives |
| 126 static const char baseURI[] = "base-uri"; | 126 static const char baseURI[] = "base-uri"; |
| 127 static const char formAction[] = "form-action"; | 127 static const char formAction[] = "form-action"; |
| 128 static const char pluginTypes[] = "plugin-types"; | 128 static const char pluginTypes[] = "plugin-types"; |
| 129 static const char reflectedXSS[] = "reflected-xss"; | 129 static const char reflectedXSS[] = "reflected-xss"; |
| 130 | 130 |
| 131 // Experimental Directives (post CSP 1.1) |
| 132 static const char suborigin[] = "suborigin"; |
| 133 |
| 131 bool isDirectiveName(const String& name) | 134 bool isDirectiveName(const String& name) |
| 132 { | 135 { |
| 133 return (equalIgnoringCase(name, connectSrc) | 136 return (equalIgnoringCase(name, connectSrc) |
| 134 || equalIgnoringCase(name, defaultSrc) | 137 || equalIgnoringCase(name, defaultSrc) |
| 135 || equalIgnoringCase(name, fontSrc) | 138 || equalIgnoringCase(name, fontSrc) |
| 136 || equalIgnoringCase(name, frameSrc) | 139 || equalIgnoringCase(name, frameSrc) |
| 137 || equalIgnoringCase(name, imgSrc) | 140 || equalIgnoringCase(name, imgSrc) |
| 138 || equalIgnoringCase(name, mediaSrc) | 141 || equalIgnoringCase(name, mediaSrc) |
| 139 || equalIgnoringCase(name, objectSrc) | 142 || equalIgnoringCase(name, objectSrc) |
| 140 || equalIgnoringCase(name, reportURI) | 143 || equalIgnoringCase(name, reportURI) |
| 141 || equalIgnoringCase(name, sandbox) | 144 || equalIgnoringCase(name, sandbox) |
| 142 || equalIgnoringCase(name, scriptSrc) | 145 || equalIgnoringCase(name, scriptSrc) |
| 146 || equalIgnoringCase(name, suborigin) |
| 143 || equalIgnoringCase(name, styleSrc) | 147 || equalIgnoringCase(name, styleSrc) |
| 144 || equalIgnoringCase(name, baseURI) | 148 || equalIgnoringCase(name, baseURI) |
| 145 || equalIgnoringCase(name, formAction) | 149 || equalIgnoringCase(name, formAction) |
| 146 || equalIgnoringCase(name, pluginTypes) | 150 || equalIgnoringCase(name, pluginTypes) |
| 147 || equalIgnoringCase(name, reflectedXSS) | 151 || equalIgnoringCase(name, reflectedXSS) |
| 148 ); | 152 ); |
| 149 } | 153 } |
| 150 | 154 |
| 151 UseCounter::Feature getUseCounterType(ContentSecurityPolicy::HeaderType type) | 155 UseCounter::Feature getUseCounterType(ContentSecurityPolicy::HeaderType type) |
| 152 { | 156 { |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 | 813 |
| 810 private: | 814 private: |
| 811 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); | 815 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); |
| 812 | 816 |
| 813 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri
ng& value); | 817 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri
ng& value); |
| 814 void parseReportURI(const String& name, const String& value); | 818 void parseReportURI(const String& name, const String& value); |
| 815 void parsePluginTypes(const String& name, const String& value); | 819 void parsePluginTypes(const String& name, const String& value); |
| 816 void parseReflectedXSS(const String& name, const String& value); | 820 void parseReflectedXSS(const String& name, const String& value); |
| 817 void addDirective(const String& name, const String& value); | 821 void addDirective(const String& name, const String& value); |
| 818 void applySandboxPolicy(const String& name, const String& sandboxPolicy); | 822 void applySandboxPolicy(const String& name, const String& sandboxPolicy); |
| 823 void applySuboriginPolicy(const String& name, const String& suboriginPolicy)
; |
| 819 | 824 |
| 820 template <class CSPDirectiveType> | 825 template <class CSPDirectiveType> |
| 821 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire
ctiveType>&); | 826 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire
ctiveType>&); |
| 822 | 827 |
| 823 SourceListDirective* operativeDirective(SourceListDirective*) const; | 828 SourceListDirective* operativeDirective(SourceListDirective*) const; |
| 824 void reportViolation(const String& directiveText, const String& effectiveDir
ective, const String& consoleMessage, const KURL& blockedURL) const; | 829 void reportViolation(const String& directiveText, const String& effectiveDir
ective, const String& consoleMessage, const KURL& blockedURL) const; |
| 825 void reportViolationWithLocation(const String& directiveText, const String&
effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const
String& contextURL, const WTF::OrdinalNumber& contextLine) const; | 830 void reportViolationWithLocation(const String& directiveText, const String&
effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const
String& contextURL, const WTF::OrdinalNumber& contextLine) const; |
| 826 void reportViolationWithState(const String& directiveText, const String& eff
ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta
te*) const; | 831 void reportViolationWithState(const String& directiveText, const String& eff
ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta
te*) const; |
| 827 | 832 |
| 828 bool checkEval(SourceListDirective*) const; | 833 bool checkEval(SourceListDirective*) const; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 841 | 846 |
| 842 bool denyIfEnforcingPolicy() const { return m_reportOnly; } | 847 bool denyIfEnforcingPolicy() const { return m_reportOnly; } |
| 843 | 848 |
| 844 ContentSecurityPolicy* m_policy; | 849 ContentSecurityPolicy* m_policy; |
| 845 | 850 |
| 846 String m_header; | 851 String m_header; |
| 847 ContentSecurityPolicy::HeaderType m_headerType; | 852 ContentSecurityPolicy::HeaderType m_headerType; |
| 848 | 853 |
| 849 bool m_reportOnly; | 854 bool m_reportOnly; |
| 850 bool m_haveSandboxPolicy; | 855 bool m_haveSandboxPolicy; |
| 856 bool m_haveSuboriginPolicy; |
| 851 ReflectedXSSDisposition m_reflectedXSSDisposition; | 857 ReflectedXSSDisposition m_reflectedXSSDisposition; |
| 852 | 858 |
| 853 OwnPtr<MediaListDirective> m_pluginTypes; | 859 OwnPtr<MediaListDirective> m_pluginTypes; |
| 854 OwnPtr<SourceListDirective> m_baseURI; | 860 OwnPtr<SourceListDirective> m_baseURI; |
| 855 OwnPtr<SourceListDirective> m_connectSrc; | 861 OwnPtr<SourceListDirective> m_connectSrc; |
| 856 OwnPtr<SourceListDirective> m_defaultSrc; | 862 OwnPtr<SourceListDirective> m_defaultSrc; |
| 857 OwnPtr<SourceListDirective> m_fontSrc; | 863 OwnPtr<SourceListDirective> m_fontSrc; |
| 858 OwnPtr<SourceListDirective> m_formAction; | 864 OwnPtr<SourceListDirective> m_formAction; |
| 859 OwnPtr<SourceListDirective> m_frameSrc; | 865 OwnPtr<SourceListDirective> m_frameSrc; |
| 860 OwnPtr<SourceListDirective> m_imgSrc; | 866 OwnPtr<SourceListDirective> m_imgSrc; |
| 861 OwnPtr<SourceListDirective> m_mediaSrc; | 867 OwnPtr<SourceListDirective> m_mediaSrc; |
| 862 OwnPtr<SourceListDirective> m_objectSrc; | 868 OwnPtr<SourceListDirective> m_objectSrc; |
| 863 OwnPtr<SourceListDirective> m_scriptSrc; | 869 OwnPtr<SourceListDirective> m_scriptSrc; |
| 864 OwnPtr<SourceListDirective> m_styleSrc; | 870 OwnPtr<SourceListDirective> m_styleSrc; |
| 865 | 871 |
| 866 Vector<KURL> m_reportURIs; | 872 Vector<KURL> m_reportURIs; |
| 867 | 873 |
| 868 String m_evalDisabledErrorMessage; | 874 String m_evalDisabledErrorMessage; |
| 869 }; | 875 }; |
| 870 | 876 |
| 871 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurit
yPolicy::HeaderType type) | 877 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurit
yPolicy::HeaderType type) |
| 872 : m_policy(policy) | 878 : m_policy(policy) |
| 873 , m_headerType(type) | 879 , m_headerType(type) |
| 874 , m_reportOnly(false) | 880 , m_reportOnly(false) |
| 875 , m_haveSandboxPolicy(false) | 881 , m_haveSandboxPolicy(false) |
| 882 , m_haveSuboriginPolicy(false) |
| 876 , m_reflectedXSSDisposition(ReflectedXSSUnset) | 883 , m_reflectedXSSDisposition(ReflectedXSSUnset) |
| 877 { | 884 { |
| 878 m_reportOnly = (type == ContentSecurityPolicy::Report || type == ContentSecu
rityPolicy::PrefixedReport); | 885 m_reportOnly = (type == ContentSecurityPolicy::Report || type == ContentSecu
rityPolicy::PrefixedReport); |
| 879 } | 886 } |
| 880 | 887 |
| 881 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* pol
icy, const UChar* begin, const UChar* end, ContentSecurityPolicy::HeaderType typ
e) | 888 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* pol
icy, const UChar* begin, const UChar* end, ContentSecurityPolicy::HeaderType typ
e) |
| 882 { | 889 { |
| 883 OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy,
type)); | 890 OwnPtr<CSPDirectiveList> directives = adoptPtr(new CSPDirectiveList(policy,
type)); |
| 884 directives->parse(begin, end); | 891 directives->parse(begin, end); |
| 885 | 892 |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 m_policy->reportDuplicateDirective(name); | 1306 m_policy->reportDuplicateDirective(name); |
| 1300 return; | 1307 return; |
| 1301 } | 1308 } |
| 1302 m_haveSandboxPolicy = true; | 1309 m_haveSandboxPolicy = true; |
| 1303 String invalidTokens; | 1310 String invalidTokens; |
| 1304 m_policy->enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPol
icy, invalidTokens)); | 1311 m_policy->enforceSandboxFlags(SecurityContext::parseSandboxPolicy(sandboxPol
icy, invalidTokens)); |
| 1305 if (!invalidTokens.isNull()) | 1312 if (!invalidTokens.isNull()) |
| 1306 m_policy->reportInvalidSandboxFlags(invalidTokens); | 1313 m_policy->reportInvalidSandboxFlags(invalidTokens); |
| 1307 } | 1314 } |
| 1308 | 1315 |
| 1316 void CSPDirectiveList::applySuboriginPolicy(const String& name, const String& su
boriginPolicy) |
| 1317 { |
| 1318 if (m_haveSuboriginPolicy) { |
| 1319 m_policy->reportDuplicateDirective(name); |
| 1320 return; |
| 1321 } |
| 1322 m_haveSuboriginPolicy = true; |
| 1323 String invalidTokens; |
| 1324 m_policy->enforceSuboriginFlags(SecurityContext::parseSuboriginPolicy(subori
ginPolicy, invalidTokens)); |
| 1325 if (!invalidTokens.isNull()) |
| 1326 m_policy->reportInvalidSuboriginFlags(invalidTokens); |
| 1327 } |
| 1328 |
| 1309 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) | 1329 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) |
| 1310 { | 1330 { |
| 1311 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { | 1331 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { |
| 1312 m_policy->reportDuplicateDirective(name); | 1332 m_policy->reportDuplicateDirective(name); |
| 1313 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 1333 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
| 1314 return; | 1334 return; |
| 1315 } | 1335 } |
| 1316 | 1336 |
| 1317 if (value.isEmpty()) { | 1337 if (value.isEmpty()) { |
| 1318 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 1338 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 else if (equalIgnoringCase(name, styleSrc)) | 1391 else if (equalIgnoringCase(name, styleSrc)) |
| 1372 setCSPDirective<SourceListDirective>(name, value, m_styleSrc); | 1392 setCSPDirective<SourceListDirective>(name, value, m_styleSrc); |
| 1373 else if (equalIgnoringCase(name, fontSrc)) | 1393 else if (equalIgnoringCase(name, fontSrc)) |
| 1374 setCSPDirective<SourceListDirective>(name, value, m_fontSrc); | 1394 setCSPDirective<SourceListDirective>(name, value, m_fontSrc); |
| 1375 else if (equalIgnoringCase(name, mediaSrc)) | 1395 else if (equalIgnoringCase(name, mediaSrc)) |
| 1376 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc); | 1396 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc); |
| 1377 else if (equalIgnoringCase(name, connectSrc)) | 1397 else if (equalIgnoringCase(name, connectSrc)) |
| 1378 setCSPDirective<SourceListDirective>(name, value, m_connectSrc); | 1398 setCSPDirective<SourceListDirective>(name, value, m_connectSrc); |
| 1379 else if (equalIgnoringCase(name, sandbox)) | 1399 else if (equalIgnoringCase(name, sandbox)) |
| 1380 applySandboxPolicy(name, value); | 1400 applySandboxPolicy(name, value); |
| 1401 else if (equalIgnoringCase(name, suborigin)) |
| 1402 applySuboriginPolicy(name, value); |
| 1381 else if (equalIgnoringCase(name, reportURI)) | 1403 else if (equalIgnoringCase(name, reportURI)) |
| 1382 parseReportURI(name, value); | 1404 parseReportURI(name, value); |
| 1383 else if (m_policy->experimentalFeaturesEnabled()) { | 1405 else if (m_policy->experimentalFeaturesEnabled()) { |
| 1384 if (equalIgnoringCase(name, baseURI)) | 1406 if (equalIgnoringCase(name, baseURI)) |
| 1385 setCSPDirective<SourceListDirective>(name, value, m_baseURI); | 1407 setCSPDirective<SourceListDirective>(name, value, m_baseURI); |
| 1386 else if (equalIgnoringCase(name, formAction)) | 1408 else if (equalIgnoringCase(name, formAction)) |
| 1387 setCSPDirective<SourceListDirective>(name, value, m_formAction); | 1409 setCSPDirective<SourceListDirective>(name, value, m_formAction); |
| 1388 else if (equalIgnoringCase(name, pluginTypes)) | 1410 else if (equalIgnoringCase(name, pluginTypes)) |
| 1389 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); | 1411 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); |
| 1390 else if (equalIgnoringCase(name, reflectedXSS)) | 1412 else if (equalIgnoringCase(name, reflectedXSS)) |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1676 KURL ContentSecurityPolicy::completeURL(const String& url) const | 1698 KURL ContentSecurityPolicy::completeURL(const String& url) const |
| 1677 { | 1699 { |
| 1678 return m_scriptExecutionContext->completeURL(url); | 1700 return m_scriptExecutionContext->completeURL(url); |
| 1679 } | 1701 } |
| 1680 | 1702 |
| 1681 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const | 1703 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) const |
| 1682 { | 1704 { |
| 1683 m_scriptExecutionContext->enforceSandboxFlags(mask); | 1705 m_scriptExecutionContext->enforceSandboxFlags(mask); |
| 1684 } | 1706 } |
| 1685 | 1707 |
| 1708 void ContentSecurityPolicy::enforceSuboriginFlags(SuboriginFlags mask) const |
| 1709 { |
| 1710 m_scriptExecutionContext->enforceSuboriginFlags(mask); |
| 1711 logToConsole("enforcing suborigin flags."); |
| 1712 } |
| 1713 |
| 1686 static String stripURLForUseInReport(Document* document, const KURL& url) | 1714 static String stripURLForUseInReport(Document* document, const KURL& url) |
| 1687 { | 1715 { |
| 1688 if (!url.isValid()) | 1716 if (!url.isValid()) |
| 1689 return String(); | 1717 return String(); |
| 1690 if (!url.isHierarchical() || url.protocolIs("file")) | 1718 if (!url.isHierarchical() || url.protocolIs("file")) |
| 1691 return url.protocol(); | 1719 return url.protocol(); |
| 1692 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); | 1720 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); |
| 1693 } | 1721 } |
| 1694 | 1722 |
| 1695 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) | 1723 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 else | 1850 else |
| 1823 message = "Invalid plugin type in 'plugin-types' Content Security Policy
directive: '" + pluginType + "'.\n"; | 1851 message = "Invalid plugin type in 'plugin-types' Content Security Policy
directive: '" + pluginType + "'.\n"; |
| 1824 logToConsole(message); | 1852 logToConsole(message); |
| 1825 } | 1853 } |
| 1826 | 1854 |
| 1827 void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags
) const | 1855 void ContentSecurityPolicy::reportInvalidSandboxFlags(const String& invalidFlags
) const |
| 1828 { | 1856 { |
| 1829 logToConsole("Error while parsing the 'sandbox' Content Security Policy dire
ctive: " + invalidFlags); | 1857 logToConsole("Error while parsing the 'sandbox' Content Security Policy dire
ctive: " + invalidFlags); |
| 1830 } | 1858 } |
| 1831 | 1859 |
| 1860 void ContentSecurityPolicy::reportInvalidSuboriginFlags(const String& invalidFla
gs) const |
| 1861 { |
| 1862 logToConsole("Error while parsing the 'suborigin' Content Security Policy di
rective: " + invalidFlags); |
| 1863 } |
| 1864 |
| 1832 void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue
) const | 1865 void ContentSecurityPolicy::reportInvalidReflectedXSS(const String& invalidValue
) const |
| 1833 { | 1866 { |
| 1834 logToConsole("The 'reflected-xss' Content Security Policy directive has the
invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\",
and \"block\"."); | 1867 logToConsole("The 'reflected-xss' Content Security Policy directive has the
invalid value \"" + invalidValue + "\". Valid values are \"allow\", \"filter\",
and \"block\"."); |
| 1835 } | 1868 } |
| 1836 | 1869 |
| 1837 void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& d
irectiveName, const String& value) const | 1870 void ContentSecurityPolicy::reportInvalidDirectiveValueCharacter(const String& d
irectiveName, const String& value) const |
| 1838 { | 1871 { |
| 1839 String message = "The value for Content Security Policy directive '" + direc
tiveName + "' contains an invalid character: '" + value + "'. Non-whitespace cha
racters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 398
6, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; | 1872 String message = "The value for Content Security Policy directive '" + direc
tiveName + "' contains an invalid character: '" + value + "'. Non-whitespace cha
racters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 398
6, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1."; |
| 1840 logToConsole(message); | 1873 logToConsole(message); |
| 1841 } | 1874 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 1933 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
| 1901 return !m_violationReportsSent.contains(report.impl()->hash()); | 1934 return !m_violationReportsSent.contains(report.impl()->hash()); |
| 1902 } | 1935 } |
| 1903 | 1936 |
| 1904 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 1937 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
| 1905 { | 1938 { |
| 1906 m_violationReportsSent.add(report.impl()->hash()); | 1939 m_violationReportsSent.add(report.impl()->hash()); |
| 1907 } | 1940 } |
| 1908 | 1941 |
| 1909 } // namespace WebCore | 1942 } // namespace WebCore |
| OLD | NEW |