| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 #include "platform/weborigin/KnownPorts.h" | 55 #include "platform/weborigin/KnownPorts.h" |
| 56 #include "platform/weborigin/SchemeRegistry.h" | 56 #include "platform/weborigin/SchemeRegistry.h" |
| 57 #include "platform/weborigin/SecurityOrigin.h" | 57 #include "platform/weborigin/SecurityOrigin.h" |
| 58 #include "public/platform/Platform.h" | 58 #include "public/platform/Platform.h" |
| 59 #include "wtf/StringHasher.h" | 59 #include "wtf/StringHasher.h" |
| 60 #include "wtf/text/StringBuilder.h" | 60 #include "wtf/text/StringBuilder.h" |
| 61 #include "wtf/text/StringUTF8Adaptor.h" | 61 #include "wtf/text/StringUTF8Adaptor.h" |
| 62 | 62 |
| 63 namespace blink { | 63 namespace blink { |
| 64 | 64 |
| 65 // CSP 1.0 Directives | 65 // CSP Level 1 Directives |
| 66 const char ContentSecurityPolicy::ConnectSrc[] = "connect-src"; | 66 const char ContentSecurityPolicy::ConnectSrc[] = "connect-src"; |
| 67 const char ContentSecurityPolicy::DefaultSrc[] = "default-src"; | 67 const char ContentSecurityPolicy::DefaultSrc[] = "default-src"; |
| 68 const char ContentSecurityPolicy::FontSrc[] = "font-src"; | 68 const char ContentSecurityPolicy::FontSrc[] = "font-src"; |
| 69 const char ContentSecurityPolicy::FrameSrc[] = "frame-src"; | 69 const char ContentSecurityPolicy::FrameSrc[] = "frame-src"; |
| 70 const char ContentSecurityPolicy::ImgSrc[] = "img-src"; | 70 const char ContentSecurityPolicy::ImgSrc[] = "img-src"; |
| 71 const char ContentSecurityPolicy::MediaSrc[] = "media-src"; | 71 const char ContentSecurityPolicy::MediaSrc[] = "media-src"; |
| 72 const char ContentSecurityPolicy::ObjectSrc[] = "object-src"; | 72 const char ContentSecurityPolicy::ObjectSrc[] = "object-src"; |
| 73 const char ContentSecurityPolicy::ReportURI[] = "report-uri"; | 73 const char ContentSecurityPolicy::ReportURI[] = "report-uri"; |
| 74 const char ContentSecurityPolicy::Sandbox[] = "sandbox"; | 74 const char ContentSecurityPolicy::Sandbox[] = "sandbox"; |
| 75 const char ContentSecurityPolicy::ScriptSrc[] = "script-src"; | 75 const char ContentSecurityPolicy::ScriptSrc[] = "script-src"; |
| 76 const char ContentSecurityPolicy::StyleSrc[] = "style-src"; | 76 const char ContentSecurityPolicy::StyleSrc[] = "style-src"; |
| 77 | 77 |
| 78 // CSP 1.1 Directives | 78 // CSP Level 2 Directives |
| 79 const char ContentSecurityPolicy::BaseURI[] = "base-uri"; | 79 const char ContentSecurityPolicy::BaseURI[] = "base-uri"; |
| 80 const char ContentSecurityPolicy::ChildSrc[] = "child-src"; | 80 const char ContentSecurityPolicy::ChildSrc[] = "child-src"; |
| 81 const char ContentSecurityPolicy::FormAction[] = "form-action"; | 81 const char ContentSecurityPolicy::FormAction[] = "form-action"; |
| 82 const char ContentSecurityPolicy::FrameAncestors[] = "frame-ancestors"; | 82 const char ContentSecurityPolicy::FrameAncestors[] = "frame-ancestors"; |
| 83 const char ContentSecurityPolicy::PluginTypes[] = "plugin-types"; | 83 const char ContentSecurityPolicy::PluginTypes[] = "plugin-types"; |
| 84 const char ContentSecurityPolicy::ReflectedXSS[] = "reflected-xss"; | 84 const char ContentSecurityPolicy::ReflectedXSS[] = "reflected-xss"; |
| 85 const char ContentSecurityPolicy::Referrer[] = "referrer"; | 85 const char ContentSecurityPolicy::Referrer[] = "referrer"; |
| 86 | 86 |
| 87 // Manifest Directives | 87 // Manifest Directives |
| 88 // https://w3c.github.io/manifest/#content-security-policy | 88 // https://w3c.github.io/manifest/#content-security-policy |
| 89 const char ContentSecurityPolicy::ManifestSrc[] = "manifest-src"; | 89 const char ContentSecurityPolicy::ManifestSrc[] = "manifest-src"; |
| 90 | 90 |
| 91 // Mixed Content Directive |
| 92 // https://w3c.github.io/webappsec/specs/mixedcontent/#strict-mode |
| 93 const char ContentSecurityPolicy::StrictMixedContentChecking[] = "strict-mixed-c
ontent-checking"; |
| 94 |
| 91 bool ContentSecurityPolicy::isDirectiveName(const String& name) | 95 bool ContentSecurityPolicy::isDirectiveName(const String& name) |
| 92 { | 96 { |
| 93 return (equalIgnoringCase(name, ConnectSrc) | 97 return (equalIgnoringCase(name, ConnectSrc) |
| 94 || equalIgnoringCase(name, DefaultSrc) | 98 || equalIgnoringCase(name, DefaultSrc) |
| 95 || equalIgnoringCase(name, FontSrc) | 99 || equalIgnoringCase(name, FontSrc) |
| 96 || equalIgnoringCase(name, FrameSrc) | 100 || equalIgnoringCase(name, FrameSrc) |
| 97 || equalIgnoringCase(name, ImgSrc) | 101 || equalIgnoringCase(name, ImgSrc) |
| 98 || equalIgnoringCase(name, MediaSrc) | 102 || equalIgnoringCase(name, MediaSrc) |
| 99 || equalIgnoringCase(name, ObjectSrc) | 103 || equalIgnoringCase(name, ObjectSrc) |
| 100 || equalIgnoringCase(name, ReportURI) | 104 || equalIgnoringCase(name, ReportURI) |
| 101 || equalIgnoringCase(name, Sandbox) | 105 || equalIgnoringCase(name, Sandbox) |
| 102 || equalIgnoringCase(name, ScriptSrc) | 106 || equalIgnoringCase(name, ScriptSrc) |
| 103 || equalIgnoringCase(name, StyleSrc) | 107 || equalIgnoringCase(name, StyleSrc) |
| 104 || equalIgnoringCase(name, BaseURI) | 108 || equalIgnoringCase(name, BaseURI) |
| 105 || equalIgnoringCase(name, ChildSrc) | 109 || equalIgnoringCase(name, ChildSrc) |
| 106 || equalIgnoringCase(name, FormAction) | 110 || equalIgnoringCase(name, FormAction) |
| 107 || equalIgnoringCase(name, FrameAncestors) | 111 || equalIgnoringCase(name, FrameAncestors) |
| 108 || equalIgnoringCase(name, PluginTypes) | 112 || equalIgnoringCase(name, PluginTypes) |
| 109 || equalIgnoringCase(name, ReflectedXSS) | 113 || equalIgnoringCase(name, ReflectedXSS) |
| 110 || equalIgnoringCase(name, Referrer) | 114 || equalIgnoringCase(name, Referrer) |
| 111 || equalIgnoringCase(name, ManifestSrc) | 115 || equalIgnoringCase(name, ManifestSrc) |
| 112 ); | 116 || equalIgnoringCase(name, StrictMixedContentChecking)); |
| 113 } | 117 } |
| 114 | 118 |
| 115 static UseCounter::Feature getUseCounterType(ContentSecurityPolicyHeaderType typ
e) | 119 static UseCounter::Feature getUseCounterType(ContentSecurityPolicyHeaderType typ
e) |
| 116 { | 120 { |
| 117 switch (type) { | 121 switch (type) { |
| 118 case ContentSecurityPolicyHeaderTypeEnforce: | 122 case ContentSecurityPolicyHeaderTypeEnforce: |
| 119 return UseCounter::ContentSecurityPolicy; | 123 return UseCounter::ContentSecurityPolicy; |
| 120 case ContentSecurityPolicyHeaderTypeReport: | 124 case ContentSecurityPolicyHeaderTypeReport: |
| 121 return UseCounter::ContentSecurityPolicyReportOnly; | 125 return UseCounter::ContentSecurityPolicyReportOnly; |
| 122 } | 126 } |
| 123 ASSERT_NOT_REACHED(); | 127 ASSERT_NOT_REACHED(); |
| 124 return UseCounter::NumberOfFeatures; | 128 return UseCounter::NumberOfFeatures; |
| 125 } | 129 } |
| 126 | 130 |
| 127 static ReferrerPolicy mergeReferrerPolicies(ReferrerPolicy a, ReferrerPolicy b) | 131 static ReferrerPolicy mergeReferrerPolicies(ReferrerPolicy a, ReferrerPolicy b) |
| 128 { | 132 { |
| 129 if (a != b) | 133 if (a != b) |
| 130 return ReferrerPolicyNever; | 134 return ReferrerPolicyNever; |
| 131 return a; | 135 return a; |
| 132 } | 136 } |
| 133 | 137 |
| 134 ContentSecurityPolicy::ContentSecurityPolicy() | 138 ContentSecurityPolicy::ContentSecurityPolicy() |
| 135 : m_executionContext(nullptr) | 139 : m_executionContext(nullptr) |
| 136 , m_overrideInlineStyleAllowed(false) | 140 , m_overrideInlineStyleAllowed(false) |
| 137 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 141 , m_scriptHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
| 138 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) | 142 , m_styleHashAlgorithmsUsed(ContentSecurityPolicyHashAlgorithmNone) |
| 139 , m_sandboxMask(0) | 143 , m_sandboxMask(0) |
| 144 , m_enforceStrictMixedContentChecking(false) |
| 140 , m_referrerPolicy(ReferrerPolicyDefault) | 145 , m_referrerPolicy(ReferrerPolicyDefault) |
| 141 { | 146 { |
| 142 } | 147 } |
| 143 | 148 |
| 144 void ContentSecurityPolicy::bindToExecutionContext(ExecutionContext* executionCo
ntext) | 149 void ContentSecurityPolicy::bindToExecutionContext(ExecutionContext* executionCo
ntext) |
| 145 { | 150 { |
| 146 m_executionContext = executionContext; | 151 m_executionContext = executionContext; |
| 147 applyPolicySideEffectsToExecutionContext(); | 152 applyPolicySideEffectsToExecutionContext(); |
| 148 } | 153 } |
| 149 | 154 |
| 150 void ContentSecurityPolicy::applyPolicySideEffectsToExecutionContext() | 155 void ContentSecurityPolicy::applyPolicySideEffectsToExecutionContext() |
| 151 { | 156 { |
| 152 ASSERT(m_executionContext); | 157 ASSERT(m_executionContext); |
| 153 // Ensure that 'self' processes correctly. | 158 // Ensure that 'self' processes correctly. |
| 154 m_selfProtocol = securityOrigin()->protocol(); | 159 m_selfProtocol = securityOrigin()->protocol(); |
| 155 m_selfSource = adoptPtr(new CSPSource(this, m_selfProtocol, securityOrigin()
->host(), securityOrigin()->port(), String(), CSPSource::NoWildcard, CSPSource::
NoWildcard)); | 160 m_selfSource = adoptPtr(new CSPSource(this, m_selfProtocol, securityOrigin()
->host(), securityOrigin()->port(), String(), CSPSource::NoWildcard, CSPSource::
NoWildcard)); |
| 156 | 161 |
| 157 // If we're in a Document, set the referrer policy and sandbox flags, then d
ump all the | 162 // If we're in a Document, set the referrer policy, mixed content checking,
and sandbox |
| 158 // parsing error messages, then poke at histograms. | 163 // flags, then dump all the parsing error messages, then poke at histograms. |
| 159 if (Document* document = this->document()) { | 164 if (Document* document = this->document()) { |
| 160 document->enforceSandboxFlags(m_sandboxMask); | 165 document->enforceSandboxFlags(m_sandboxMask); |
| 166 if (m_enforceStrictMixedContentChecking) |
| 167 document->enforceStrictMixedContentChecking(); |
| 161 if (didSetReferrerPolicy()) | 168 if (didSetReferrerPolicy()) |
| 162 document->setReferrerPolicy(m_referrerPolicy); | 169 document->setReferrerPolicy(m_referrerPolicy); |
| 163 | 170 |
| 164 for (const auto& consoleMessage : m_consoleMessages) | 171 for (const auto& consoleMessage : m_consoleMessages) |
| 165 m_executionContext->addConsoleMessage(consoleMessage); | 172 m_executionContext->addConsoleMessage(consoleMessage); |
| 166 m_consoleMessages.clear(); | 173 m_consoleMessages.clear(); |
| 167 | 174 |
| 168 for (const auto& policy : m_policies) | 175 for (const auto& policy : m_policies) |
| 169 UseCounter::count(*document, getUseCounterType(policy->headerType())
); | 176 UseCounter::count(*document, getUseCounterType(policy->headerType())
); |
| 170 } | 177 } |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 KURL ContentSecurityPolicy::completeURL(const String& url) const | 599 KURL ContentSecurityPolicy::completeURL(const String& url) const |
| 593 { | 600 { |
| 594 return m_executionContext->contextCompleteURL(url); | 601 return m_executionContext->contextCompleteURL(url); |
| 595 } | 602 } |
| 596 | 603 |
| 597 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) | 604 void ContentSecurityPolicy::enforceSandboxFlags(SandboxFlags mask) |
| 598 { | 605 { |
| 599 m_sandboxMask |= mask; | 606 m_sandboxMask |= mask; |
| 600 } | 607 } |
| 601 | 608 |
| 609 void ContentSecurityPolicy::enforceStrictMixedContentChecking() |
| 610 { |
| 611 m_enforceStrictMixedContentChecking = true; |
| 612 } |
| 613 |
| 602 static String stripURLForUseInReport(Document* document, const KURL& url) | 614 static String stripURLForUseInReport(Document* document, const KURL& url) |
| 603 { | 615 { |
| 604 if (!url.isValid()) | 616 if (!url.isValid()) |
| 605 return String(); | 617 return String(); |
| 606 if (!url.isHierarchical() || url.protocolIs("file")) | 618 if (!url.isHierarchical() || url.protocolIs("file")) |
| 607 return url.protocol(); | 619 return url.protocol(); |
| 608 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); | 620 return document->securityOrigin()->canRequest(url) ? url.strippedForUseAsRef
errer() : SecurityOrigin::create(url)->toString(); |
| 609 } | 621 } |
| 610 | 622 |
| 611 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) | 623 static void gatherSecurityPolicyViolationEventData(SecurityPolicyViolationEventI
nit& init, Document* document, const String& directiveText, const String& effect
iveDirective, const KURL& blockedURL, const String& header) |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) | 733 void ContentSecurityPolicy::reportReportOnlyInMeta(const String& header) |
| 722 { | 734 { |
| 723 logToConsole("The report-only Content Security Policy '" + header + "' was d
elivered via a <meta> element, which is disallowed. The policy has been ignored.
"); | 735 logToConsole("The report-only Content Security Policy '" + header + "' was d
elivered via a <meta> element, which is disallowed. The policy has been ignored.
"); |
| 724 } | 736 } |
| 725 | 737 |
| 726 void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) | 738 void ContentSecurityPolicy::reportMetaOutsideHead(const String& header) |
| 727 { | 739 { |
| 728 logToConsole("The Content Security Policy '" + header + "' was delivered via
a <meta> element outside the document's <head>, which is disallowed. The policy
has been ignored."); | 740 logToConsole("The Content Security Policy '" + header + "' was delivered via
a <meta> element outside the document's <head>, which is disallowed. The policy
has been ignored."); |
| 729 } | 741 } |
| 730 | 742 |
| 743 void ContentSecurityPolicy::reportValueForEmptyDirective(const String& name, con
st String& value) |
| 744 { |
| 745 logToConsole("The Content Security Policy directive '" + name + "' should be
empty, but was delivered with a value of '" + value + "'. The directive has bee
n applied, and the value ignored."); |
| 746 } |
| 747 |
| 731 void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) | 748 void ContentSecurityPolicy::reportInvalidInReportOnly(const String& name) |
| 732 { | 749 { |
| 733 logToConsole("The Content Security Policy directive '" + name + "' is ignore
d when delivered in a report-only policy."); | 750 logToConsole("The Content Security Policy directive '" + name + "' is ignore
d when delivered in a report-only policy."); |
| 734 } | 751 } |
| 735 | 752 |
| 736 void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) | 753 void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) |
| 737 { | 754 { |
| 738 DEFINE_STATIC_LOCAL(String, allow, ("allow")); | 755 DEFINE_STATIC_LOCAL(String, allow, ("allow")); |
| 739 DEFINE_STATIC_LOCAL(String, options, ("options")); | 756 DEFINE_STATIC_LOCAL(String, options, ("options")); |
| 740 DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); | 757 DEFINE_STATIC_LOCAL(String, policyURI, ("policy-uri")); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. | 889 // Collisions have no security impact, so we can save space by storing only
the string's hash rather than the whole report. |
| 873 return !m_violationReportsSent.contains(report.impl()->hash()); | 890 return !m_violationReportsSent.contains(report.impl()->hash()); |
| 874 } | 891 } |
| 875 | 892 |
| 876 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 893 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
| 877 { | 894 { |
| 878 m_violationReportsSent.add(report.impl()->hash()); | 895 m_violationReportsSent.add(report.impl()->hash()); |
| 879 } | 896 } |
| 880 | 897 |
| 881 } // namespace blink | 898 } // namespace blink |
| OLD | NEW |