| Index: Source/core/frame/ContentSecurityPolicy.cpp
|
| diff --git a/Source/core/frame/ContentSecurityPolicy.cpp b/Source/core/frame/ContentSecurityPolicy.cpp
|
| index 4c3cbe42472a78353ff0c53ffac601e356ea6179..bfe7b56818084f7f78c92e366a2e1cc35502f0b8 100644
|
| --- a/Source/core/frame/ContentSecurityPolicy.cpp
|
| +++ b/Source/core/frame/ContentSecurityPolicy.cpp
|
| @@ -149,6 +149,7 @@ static const char styleSrc[] = "style-src";
|
| // CSP 1.1 Directives
|
| static const char baseURI[] = "base-uri";
|
| static const char formAction[] = "form-action";
|
| +static const char frameAncestors[] = "frame-ancestors";
|
| static const char pluginTypes[] = "plugin-types";
|
| static const char reflectedXSS[] = "reflected-xss";
|
|
|
| @@ -167,6 +168,7 @@ bool isDirectiveName(const String& name)
|
| || equalIgnoringCase(name, styleSrc)
|
| || equalIgnoringCase(name, baseURI)
|
| || equalIgnoringCase(name, formAction)
|
| + || equalIgnoringCase(name, frameAncestors)
|
| || equalIgnoringCase(name, pluginTypes)
|
| || equalIgnoringCase(name, reflectedXSS)
|
| );
|
| @@ -880,6 +882,7 @@ public:
|
| bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatus) const;
|
| bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) const;
|
| bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const;
|
| + bool allowAncestors(Frame*, ContentSecurityPolicy::ReportingStatus) const;
|
| bool allowScriptNonce(const String&) const;
|
| bool allowStyleNonce(const String&) const;
|
| bool allowScriptHash(const SourceHashValue&) const;
|
| @@ -914,6 +917,7 @@ private:
|
| bool checkHash(SourceListDirective*, const SourceHashValue&) const;
|
| bool checkSource(SourceListDirective*, const KURL&) const;
|
| bool checkMediaType(MediaListDirective*, const String& type, const String& typeAttribute) const;
|
| + bool checkAncestors(SourceListDirective*, Frame*) const;
|
|
|
| void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisabledErrorMessage = errorMessage; }
|
|
|
| @@ -922,6 +926,7 @@ private:
|
|
|
| bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const;
|
| bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& type, const String& typeAttribute, const String& consoleMessage) const;
|
| + bool checkAncestorsAndReportViolation(SourceListDirective*, Frame*) const;
|
|
|
| bool denyIfEnforcingPolicy() const { return m_reportOnly; }
|
|
|
| @@ -940,6 +945,7 @@ private:
|
| OwnPtr<SourceListDirective> m_defaultSrc;
|
| OwnPtr<SourceListDirective> m_fontSrc;
|
| OwnPtr<SourceListDirective> m_formAction;
|
| + OwnPtr<SourceListDirective> m_frameAncestors;
|
| OwnPtr<SourceListDirective> m_frameSrc;
|
| OwnPtr<SourceListDirective> m_imgSrc;
|
| OwnPtr<SourceListDirective> m_mediaSrc;
|
| @@ -1024,6 +1030,18 @@ bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u
|
| return !directive || directive->allows(url);
|
| }
|
|
|
| +bool CSPDirectiveList::checkAncestors(SourceListDirective* directive, Frame* frame) const
|
| +{
|
| + if (!frame || !directive)
|
| + return true;
|
| +
|
| + for (Frame* current = frame->tree().parent(); current; current = current->tree().parent()) {
|
| + if (!directive->allows(current->document()->url()))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const String& type, const String& typeAttribute) const
|
| {
|
| if (!directive)
|
| @@ -1122,6 +1140,15 @@ bool CSPDirectiveList::checkSourceAndReportViolation(SourceListDirective* direct
|
| return denyIfEnforcingPolicy();
|
| }
|
|
|
| +bool CSPDirectiveList::checkAncestorsAndReportViolation(SourceListDirective* directive, Frame* frame) const
|
| +{
|
| + if (checkAncestors(directive, frame))
|
| + return true;
|
| +
|
| + reportViolation(directive->text(), "frame-ancestors", "Refused to display '" + frame->document()->url().elidedString() + " in a frame because an ancestor violates the following Content Security Policy directive: \"" + directive->text() + "\".", frame->document()->url());
|
| + return denyIfEnforcingPolicy();
|
| +}
|
| +
|
| bool CSPDirectiveList::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
|
| {
|
| DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute JavaScript URL because it violates the following Content Security Policy directive: "));
|
| @@ -1251,6 +1278,13 @@ bool CSPDirectiveList::allowBaseURI(const KURL& url, ContentSecurityPolicy::Repo
|
| checkSource(m_baseURI.get(), url);
|
| }
|
|
|
| +bool CSPDirectiveList::allowAncestors(Frame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) const
|
| +{
|
| + return reportingStatus == ContentSecurityPolicy::SendReport ?
|
| + checkAncestorsAndReportViolation(m_frameAncestors.get(), frame) :
|
| + checkAncestors(m_frameAncestors.get(), frame);
|
| +}
|
| +
|
| bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
|
| {
|
| return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
|
| @@ -1477,6 +1511,8 @@ void CSPDirectiveList::addDirective(const String& name, const String& value)
|
| setCSPDirective<SourceListDirective>(name, value, m_baseURI);
|
| else if (equalIgnoringCase(name, formAction))
|
| setCSPDirective<SourceListDirective>(name, value, m_formAction);
|
| + else if (equalIgnoringCase(name, frameAncestors))
|
| + setCSPDirective<SourceListDirective>(name, value, m_frameAncestors);
|
| else if (equalIgnoringCase(name, pluginTypes))
|
| setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
|
| else if (equalIgnoringCase(name, reflectedXSS))
|
| @@ -1643,6 +1679,16 @@ bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u
|
| return true;
|
| }
|
|
|
| +template<bool (CSPDirectiveList::*allowed)(Frame*, ContentSecurityPolicy::ReportingStatus) const>
|
| +bool isAllowedByAllWithFrame(const CSPDirectiveListVector& policies, Frame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus)
|
| +{
|
| + for (size_t i = 0; i < policies.size(); ++i) {
|
| + if (!(policies[i].get()->*allowed)(frame, reportingStatus))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| bool ContentSecurityPolicy::allowJavaScriptURLs(const String& contextURL, const WTF::OrdinalNumber& contextLine, ContentSecurityPolicy::ReportingStatus reportingStatus) const
|
| {
|
| return isAllowedByAllWithContext<&CSPDirectiveList::allowJavaScriptURLs>(m_policies, contextURL, contextLine, reportingStatus);
|
| @@ -1770,6 +1816,11 @@ bool ContentSecurityPolicy::allowBaseURI(const KURL& url, ContentSecurityPolicy:
|
| return isAllowedByAllWithURL<&CSPDirectiveList::allowBaseURI>(m_policies, url, reportingStatus);
|
| }
|
|
|
| +bool ContentSecurityPolicy::allowAncestors(Frame* frame, ContentSecurityPolicy::ReportingStatus reportingStatus) const
|
| +{
|
| + return isAllowedByAllWithFrame<&CSPDirectiveList::allowAncestors>(m_policies, frame, reportingStatus);
|
| +}
|
| +
|
| bool ContentSecurityPolicy::isActive() const
|
| {
|
| return !m_policies.isEmpty();
|
|
|