| Index: Source/core/frame/ContentSecurityPolicy.cpp
|
| diff --git a/Source/core/frame/ContentSecurityPolicy.cpp b/Source/core/frame/ContentSecurityPolicy.cpp
|
| index e4b9eb18c21379dec8d909be260a627ac9d22e7e..dbcd2d3d318896d52ed07ba3d47d5d75506f6faf 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";
|
| static const char referrer[] = "referrer";
|
| @@ -168,6 +169,7 @@ bool isDirectiveName(const String& name)
|
| || equalIgnoringCase(name, styleSrc)
|
| || equalIgnoringCase(name, baseURI)
|
| || equalIgnoringCase(name, formAction)
|
| + || equalIgnoringCase(name, frameAncestors)
|
| || equalIgnoringCase(name, pluginTypes)
|
| || equalIgnoringCase(name, reflectedXSS)
|
| || equalIgnoringCase(name, referrer)
|
| @@ -893,6 +895,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;
|
| @@ -930,6 +933,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; }
|
|
|
| @@ -938,6 +942,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; }
|
|
|
| @@ -960,6 +965,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;
|
| @@ -1047,6 +1053,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)
|
| @@ -1151,6 +1169,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: "));
|
| @@ -1274,6 +1301,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);
|
| @@ -1563,6 +1597,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))
|
| @@ -1746,6 +1782,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);
|
| @@ -1894,6 +1940,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();
|
|
|