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 27 matching lines...) Expand all Loading... | |
38 | 38 |
39 return "sha256-" + base64Encode(reinterpret_cast<char*>(digest.data()), | 39 return "sha256-" + base64Encode(reinterpret_cast<char*>(digest.data()), |
40 digest.size(), Base64DoNotInsertLFs); | 40 digest.size(), Base64DoNotInsertLFs); |
41 } | 41 } |
42 | 42 |
43 template <typename CharType> | 43 template <typename CharType> |
44 inline bool isASCIIAlphanumericOrHyphen(CharType c) { | 44 inline bool isASCIIAlphanumericOrHyphen(CharType c) { |
45 return isASCIIAlphanumeric(c) || c == '-'; | 45 return isASCIIAlphanumeric(c) || c == '-'; |
46 } | 46 } |
47 | 47 |
48 ContentSecurityPolicyHashAlgorithm convertHashAlgorithmToCSPHashAlgorithm( | |
Mike West
2017/03/29 13:03:54
Hrm. Can we just make these the same thing? I don'
Marc Treib
2017/03/30 09:48:51
I was wondering that myself :)
The CSP variant has
| |
49 HashAlgorithm algorithm) { | |
50 switch (algorithm) { | |
51 case HashAlgorithmSha1: | |
52 return ContentSecurityPolicyHashAlgorithmSha1; | |
Mike West
2017/03/29 13:03:54
We shouldn't support SHA-1.
Marc Treib
2017/03/30 09:48:51
Done.
| |
53 case HashAlgorithmSha256: | |
54 return ContentSecurityPolicyHashAlgorithmSha256; | |
55 case HashAlgorithmSha384: | |
56 return ContentSecurityPolicyHashAlgorithmSha384; | |
57 case HashAlgorithmSha512: | |
58 return ContentSecurityPolicyHashAlgorithmSha512; | |
59 } | |
60 NOTREACHED(); | |
61 return ContentSecurityPolicyHashAlgorithmNone; | |
62 } | |
63 | |
64 bool parseBase64Digest(String base64, DigestValue& hash) { | |
Mike West
2017/03/29 13:03:54
Can you add some comments noting why this is neces
Marc Treib
2017/03/30 09:48:51
The DigestValue type has a binary digest value, wh
| |
65 Vector<char> hashVector; | |
66 // We accept base64url-encoded data here by normalizing it to base64. | |
67 if (!base64Decode(normalizeToBase64(base64), hashVector)) | |
68 return false; | |
69 if (hashVector.isEmpty() || hashVector.size() > kMaxDigestSize) | |
70 return false; | |
71 hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size()); | |
72 return true; | |
73 } | |
74 | |
48 } // namespace | 75 } // namespace |
49 | 76 |
50 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, | 77 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, |
51 ContentSecurityPolicyHeaderType type, | 78 ContentSecurityPolicyHeaderType type, |
52 ContentSecurityPolicyHeaderSource source) | 79 ContentSecurityPolicyHeaderSource source) |
53 : m_policy(policy), | 80 : m_policy(policy), |
54 m_headerType(type), | 81 m_headerType(type), |
55 m_headerSource(source), | 82 m_headerSource(source), |
56 m_hasSandboxPolicy(false), | 83 m_hasSandboxPolicy(false), |
57 m_strictMixedContentCheckingEnforced(false), | 84 m_strictMixedContentCheckingEnforced(false), |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 | 191 |
165 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const { | 192 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const { |
166 return !directive || directive->allowEval(); | 193 return !directive || directive->allowEval(); |
167 } | 194 } |
168 | 195 |
169 bool CSPDirectiveList::isMatchingNoncePresent(SourceListDirective* directive, | 196 bool CSPDirectiveList::isMatchingNoncePresent(SourceListDirective* directive, |
170 const String& nonce) const { | 197 const String& nonce) const { |
171 return directive && directive->allowNonce(nonce); | 198 return directive && directive->allowNonce(nonce); |
172 } | 199 } |
173 | 200 |
201 bool CSPDirectiveList::areAllMatchingHashesPresent( | |
202 SourceListDirective* directive, | |
203 const IntegrityMetadataSet& hashes) const { | |
204 if (!directive || hashes.isEmpty()) | |
205 return false; | |
206 for (const std::pair<WTF::String, HashAlgorithm>& hash : hashes) { | |
207 // Convert the hash from integrity metadata format to CSP format. | |
208 CSPHashValue cspHash; | |
209 cspHash.first = convertHashAlgorithmToCSPHashAlgorithm(hash.second); | |
210 if (!parseBase64Digest(hash.first, cspHash.second)) | |
211 return false; | |
Mike West
2017/03/29 13:03:54
This appears to replicate much of the logic in `ch
Marc Treib
2017/03/30 09:48:51
I don't think they're all that similar. checkDiges
| |
212 // All integrity hashes must be listed in the CSP. | |
213 if (!directive->allowHash(cspHash)) | |
214 return false; | |
215 } | |
216 return true; | |
217 } | |
218 | |
174 bool CSPDirectiveList::checkHash(SourceListDirective* directive, | 219 bool CSPDirectiveList::checkHash(SourceListDirective* directive, |
175 const CSPHashValue& hashValue) const { | 220 const CSPHashValue& hashValue) const { |
176 return !directive || directive->allowHash(hashValue); | 221 return !directive || directive->allowHash(hashValue); |
177 } | 222 } |
178 | 223 |
179 bool CSPDirectiveList::checkHashedAttributes( | 224 bool CSPDirectiveList::checkHashedAttributes( |
180 SourceListDirective* directive) const { | 225 SourceListDirective* directive) const { |
181 return !directive || directive->allowHashedAttributes(); | 226 return !directive || directive->allowHashedAttributes(); |
182 } | 227 } |
183 | 228 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
617 "Refused to load '" + url.elidedString() + "' (MIME type '" + | 662 "Refused to load '" + url.elidedString() + "' (MIME type '" + |
618 typeAttribute + | 663 typeAttribute + |
619 "') because it violates the following Content Security " | 664 "') because it violates the following Content Security " |
620 "Policy Directive: ") | 665 "Policy Directive: ") |
621 : checkMediaType(m_pluginTypes.get(), type, typeAttribute); | 666 : checkMediaType(m_pluginTypes.get(), type, typeAttribute); |
622 } | 667 } |
623 | 668 |
624 bool CSPDirectiveList::allowScriptFromSource( | 669 bool CSPDirectiveList::allowScriptFromSource( |
625 const KURL& url, | 670 const KURL& url, |
626 const String& nonce, | 671 const String& nonce, |
672 const IntegrityMetadataSet& hashes, | |
627 ParserDisposition parserDisposition, | 673 ParserDisposition parserDisposition, |
628 ResourceRequest::RedirectStatus redirectStatus, | 674 ResourceRequest::RedirectStatus redirectStatus, |
629 SecurityViolationReportingPolicy reportingPolicy) const { | 675 SecurityViolationReportingPolicy reportingPolicy) const { |
630 if (isMatchingNoncePresent(operativeDirective(m_scriptSrc.get()), nonce)) | 676 SourceListDirective* directive = operativeDirective(m_scriptSrc.get()); |
677 if (isMatchingNoncePresent(directive, nonce)) | |
631 return true; | 678 return true; |
632 if (parserDisposition == NotParserInserted && allowDynamic()) | 679 if (parserDisposition == NotParserInserted && allowDynamic()) |
633 return true; | 680 return true; |
681 if (areAllMatchingHashesPresent(directive, hashes)) | |
682 return true; | |
634 return reportingPolicy == SecurityViolationReportingPolicy::Report | 683 return reportingPolicy == SecurityViolationReportingPolicy::Report |
635 ? checkSourceAndReportViolation( | 684 ? checkSourceAndReportViolation( |
636 operativeDirective(m_scriptSrc.get()), url, | 685 directive, url, |
637 ContentSecurityPolicy::DirectiveType::ScriptSrc, | 686 ContentSecurityPolicy::DirectiveType::ScriptSrc, |
638 redirectStatus) | 687 redirectStatus) |
639 : checkSource(operativeDirective(m_scriptSrc.get()), url, | 688 : checkSource(directive, url, redirectStatus); |
640 redirectStatus); | |
641 } | 689 } |
642 | 690 |
643 bool CSPDirectiveList::allowObjectFromSource( | 691 bool CSPDirectiveList::allowObjectFromSource( |
644 const KURL& url, | 692 const KURL& url, |
645 ResourceRequest::RedirectStatus redirectStatus, | 693 ResourceRequest::RedirectStatus redirectStatus, |
646 SecurityViolationReportingPolicy reportingPolicy) const { | 694 SecurityViolationReportingPolicy reportingPolicy) const { |
647 if (url.protocolIsAbout()) | 695 if (url.protocolIsAbout()) |
648 return true; | 696 return true; |
649 return reportingPolicy == SecurityViolationReportingPolicy::Report | 697 return reportingPolicy == SecurityViolationReportingPolicy::Report |
650 ? checkSourceAndReportViolation( | 698 ? checkSourceAndReportViolation( |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1354 visitor->trace(m_imgSrc); | 1402 visitor->trace(m_imgSrc); |
1355 visitor->trace(m_mediaSrc); | 1403 visitor->trace(m_mediaSrc); |
1356 visitor->trace(m_manifestSrc); | 1404 visitor->trace(m_manifestSrc); |
1357 visitor->trace(m_objectSrc); | 1405 visitor->trace(m_objectSrc); |
1358 visitor->trace(m_scriptSrc); | 1406 visitor->trace(m_scriptSrc); |
1359 visitor->trace(m_styleSrc); | 1407 visitor->trace(m_styleSrc); |
1360 visitor->trace(m_workerSrc); | 1408 visitor->trace(m_workerSrc); |
1361 } | 1409 } |
1362 | 1410 |
1363 } // namespace blink | 1411 } // namespace blink |
OLD | NEW |