OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/frame/csp/CSPDirectiveList.h" | 5 #include "core/frame/csp/CSPDirectiveList.h" |
6 | 6 |
7 #include "bindings/core/v8/SourceLocation.h" | 7 #include "bindings/core/v8/SourceLocation.h" |
8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
9 #include "core/dom/SecurityContext.h" | 9 #include "core/dom/SecurityContext.h" |
10 #include "core/dom/SpaceSplitString.h" | 10 #include "core/dom/SpaceSplitString.h" |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 // | 166 // |
167 // TODO(mkwst): Move this check up into the browser process. See | 167 // TODO(mkwst): Move this check up into the browser process. See |
168 // https://crbug.com/555418. | 168 // https://crbug.com/555418. |
169 KURL url(KURL(), current->securityContext()->getSecurityOrigin()->toStri ng()); | 169 KURL url(KURL(), current->securityContext()->getSecurityOrigin()->toStri ng()); |
170 if (!directive->allows(url, ResourceRequest::RedirectStatus::NoRedirect) ) | 170 if (!directive->allows(url, ResourceRequest::RedirectStatus::NoRedirect) ) |
171 return false; | 171 return false; |
172 } | 172 } |
173 return true; | 173 return true; |
174 } | 174 } |
175 | 175 |
176 bool CSPDirectiveList::checkIntegrityPresence(WebURLRequest::RequestContext cont ext, const IntegrityMetadataSet& integrityMetadata) const | |
177 { | |
178 if (!integrityMetadata.isEmpty()) | |
179 return true; | |
180 | |
181 if (m_requireSRIFor.isEmpty()) | |
182 return true; | |
183 | |
184 for (const auto& token : m_requireSRIFor) { | |
185 if (equalIgnoringCase(token, "script")) { | |
186 if (context == WebURLRequest::RequestContextScript || context == Web URLRequest::RequestContextImport) { | |
187 if (integrityMetadata.isEmpty()) | |
188 return false; | |
189 } | |
190 } else if (equalIgnoringCase(token, "style")) { | |
191 if (context == WebURLRequest::RequestContextStyle) { | |
192 if (integrityMetadata.isEmpty()) | |
193 return false; | |
194 } | |
195 } | |
196 } | |
197 return true; | |
198 } | |
199 | |
200 bool CSPDirectiveList::checkIntegrityPresenceAndReportViolation(WebURLRequest::R equestContext context, const KURL& url, const IntegrityMetadataSet& integrityMet adata) const | |
201 { | |
202 if (checkIntegrityPresence(context, integrityMetadata)) | |
203 return true; | |
204 String resourceType; | |
205 if (context == WebURLRequest::RequestContextScript || context == WebURLReque st::RequestContextImport) | |
jww
2016/06/11 22:45:12
Treating RequestContextImport as guaranteed to be
Sergey Shekyan
2016/06/20 07:12:00
I inherited the logic that RequestContextImport is
Mike West
2016/06/20 08:11:37
Right. Contexts are from an earlier version of Fet
| |
206 resourceType = "script"; | |
207 else if (context == WebURLRequest::RequestContextStyle) | |
208 resourceType = "stylesheet"; | |
209 reportViolation(ContentSecurityPolicy::RequireSRIFor, ContentSecurityPolicy: :RequireSRIFor, "Refused to load the " + resourceType + " '" + url.elidedString( ) + "' because 'require-sri-for' directive requires integrity attribute be prese nt for all " + resourceType + "s.", url, ResourceRequest::RedirectStatus::NoRedi rect); | |
Mike West
2016/06/10 09:25:15
`NoRedirect` probably isn't correct here, as I thi
Sergey Shekyan
2016/06/20 07:11:59
Acknowledged.
| |
210 return denyIfEnforcingPolicy(); | |
211 } | |
212 | |
213 bool CSPDirectiveList::allowRequestWithoutMetadata(WebURLRequest::RequestContext context, const KURL& url, const IntegrityMetadataSet& integrityMetadata, Conten tSecurityPolicy::ReportingStatus reportingStatus) const | |
214 { | |
215 if (reportingStatus == ContentSecurityPolicy::SendReport) { | |
216 return checkIntegrityPresenceAndReportViolation(context, url, integrityM etadata); | |
217 } | |
218 return checkIntegrityPresence(context, integrityMetadata); | |
219 } | |
220 | |
176 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const | 221 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const |
177 { | 222 { |
178 if (!directive) | 223 if (!directive) |
179 return true; | 224 return true; |
180 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) | 225 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) |
181 return false; | 226 return false; |
182 return directive->allows(type); | 227 return directive->allows(type); |
183 } | 228 } |
184 | 229 |
185 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* d irective) const | 230 SourceListDirective* CSPDirectiveList::operativeDirective(SourceListDirective* d irective) const |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
544 } | 589 } |
545 | 590 |
546 // The directive-value may be empty. | 591 // The directive-value may be empty. |
547 if (valueBegin == position) | 592 if (valueBegin == position) |
548 return true; | 593 return true; |
549 | 594 |
550 value = String(valueBegin, position - valueBegin); | 595 value = String(valueBegin, position - valueBegin); |
551 return true; | 596 return true; |
552 } | 597 } |
553 | 598 |
599 void CSPDirectiveList::parseRequireSRIFor(const String& name, const String& valu e) | |
600 { | |
601 if (!m_requireSRIFor.isEmpty()) { | |
602 m_policy->reportDuplicateDirective(name); | |
603 return; | |
604 } | |
605 StringBuilder tokenErrors; | |
606 StringBuilder validTokens; | |
607 unsigned numberOfTokenErrors = 0; | |
608 Vector<UChar> characters; | |
609 value.appendTo(characters); | |
610 | |
611 const UChar* position = characters.data(); | |
612 const UChar* end = position + characters.size(); | |
613 | |
614 while (position < end) { | |
615 skipWhile<UChar, isASCIISpace>(position, end); | |
616 | |
617 const UChar* tokenBegin = position; | |
618 skipWhile<UChar, isNotASCIISpace>(position, end); | |
619 | |
620 if (tokenBegin < position) { | |
621 String token = String(tokenBegin, position - tokenBegin); | |
622 if (equalIgnoringCase(token, "script") || equalIgnoringCase(token, " style")) { | |
623 m_requireSRIFor.append(token); | |
624 if (!validTokens.isEmpty()) | |
625 validTokens.append(' '); | |
626 validTokens.append(token); | |
627 } else { | |
628 if (numberOfTokenErrors) | |
629 tokenErrors.append(", \'"); | |
630 else | |
631 tokenErrors.append('\''); | |
632 tokenErrors.append(token); | |
633 tokenErrors.append('\''); | |
634 numberOfTokenErrors++; | |
635 } | |
636 } | |
637 } | |
638 | |
639 if (numberOfTokenErrors == 0) | |
640 return; | |
641 | |
642 String invalidTokensErrorMessage; | |
643 if (numberOfTokenErrors > 1) | |
644 tokenErrors.append(" are invalid 'require-sri-for' tokens."); | |
645 else | |
646 tokenErrors.append(" is an invalid 'require-sri-for' token."); | |
647 | |
648 invalidTokensErrorMessage = tokenErrors.toString(); | |
649 | |
650 if (!invalidTokensErrorMessage.isEmpty()) { | |
jww
2016/06/11 22:45:12
I think inavildTokensErrorMessage cannot be empty
Sergey Shekyan
2016/06/20 07:12:00
Acknowledged.
| |
651 m_policy->reportInvalidRequireSRIForTokens(invalidTokensErrorMessage); | |
652 } | |
653 } | |
654 | |
554 void CSPDirectiveList::parseReportURI(const String& name, const String& value) | 655 void CSPDirectiveList::parseReportURI(const String& name, const String& value) |
555 { | 656 { |
556 if (!m_reportEndpoints.isEmpty()) { | 657 if (!m_reportEndpoints.isEmpty()) { |
557 m_policy->reportDuplicateDirective(name); | 658 m_policy->reportDuplicateDirective(name); |
558 return; | 659 return; |
559 } | 660 } |
560 | 661 |
561 // Remove report-uri in meta policies, per https://www.w3.org/TR/CSP2/#deliv ery-html-meta-element. | 662 // Remove report-uri in meta policies, per https://www.w3.org/TR/CSP2/#deliv ery-html-meta-element. |
562 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { | 663 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { |
563 UseCounter::count(m_policy->document(), UseCounter::InvalidReportUriDire ctiveInMetaCSP); | 664 UseCounter::count(m_policy->document(), UseCounter::InvalidReportUriDire ctiveInMetaCSP); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
817 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { | 918 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { |
818 parseReferrer(name, value); | 919 parseReferrer(name, value); |
819 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq uests)) { | 920 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq uests)) { |
820 enableInsecureRequestsUpgrade(name, value); | 921 enableInsecureRequestsUpgrade(name, value); |
821 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte nt)) { | 922 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte nt)) { |
822 enforceStrictMixedContentChecking(name, value); | 923 enforceStrictMixedContentChecking(name, value); |
823 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) { | 924 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) { |
824 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); | 925 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); |
825 } else if (equalIgnoringCase(name, ContentSecurityPolicy::TreatAsPublicAddre ss)) { | 926 } else if (equalIgnoringCase(name, ContentSecurityPolicy::TreatAsPublicAddre ss)) { |
826 treatAsPublicAddress(name, value); | 927 treatAsPublicAddress(name, value); |
928 } else if (equalIgnoringCase(name, ContentSecurityPolicy::RequireSRIFor)) { | |
929 parseRequireSRIFor(name, value); | |
Mike West
2016/06/10 09:25:15
This functionality should be hidden behind the exp
Sergey Shekyan
2016/06/20 07:12:00
Acknowledged.
| |
827 } else { | 930 } else { |
828 m_policy->reportUnsupportedDirective(name); | 931 m_policy->reportUnsupportedDirective(name); |
829 } | 932 } |
830 } | 933 } |
831 | 934 |
832 DEFINE_TRACE(CSPDirectiveList) | 935 DEFINE_TRACE(CSPDirectiveList) |
833 { | 936 { |
834 visitor->trace(m_policy); | 937 visitor->trace(m_policy); |
835 visitor->trace(m_pluginTypes); | 938 visitor->trace(m_pluginTypes); |
836 visitor->trace(m_baseURI); | 939 visitor->trace(m_baseURI); |
837 visitor->trace(m_childSrc); | 940 visitor->trace(m_childSrc); |
838 visitor->trace(m_connectSrc); | 941 visitor->trace(m_connectSrc); |
839 visitor->trace(m_defaultSrc); | 942 visitor->trace(m_defaultSrc); |
840 visitor->trace(m_fontSrc); | 943 visitor->trace(m_fontSrc); |
841 visitor->trace(m_formAction); | 944 visitor->trace(m_formAction); |
842 visitor->trace(m_frameAncestors); | 945 visitor->trace(m_frameAncestors); |
843 visitor->trace(m_frameSrc); | 946 visitor->trace(m_frameSrc); |
844 visitor->trace(m_imgSrc); | 947 visitor->trace(m_imgSrc); |
845 visitor->trace(m_mediaSrc); | 948 visitor->trace(m_mediaSrc); |
846 visitor->trace(m_manifestSrc); | 949 visitor->trace(m_manifestSrc); |
847 visitor->trace(m_objectSrc); | 950 visitor->trace(m_objectSrc); |
848 visitor->trace(m_scriptSrc); | 951 visitor->trace(m_scriptSrc); |
849 visitor->trace(m_styleSrc); | 952 visitor->trace(m_styleSrc); |
850 } | 953 } |
851 | 954 |
852 | 955 |
853 } // namespace blink | 956 } // namespace blink |
OLD | NEW |