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( |
| 49 HashAlgorithm algorithm) { |
| 50 switch (algorithm) { |
| 51 case HashAlgorithmSha1: |
| 52 // Sha1 is not supported. |
| 53 return ContentSecurityPolicyHashAlgorithmNone; |
| 54 case HashAlgorithmSha256: |
| 55 return ContentSecurityPolicyHashAlgorithmSha256; |
| 56 case HashAlgorithmSha384: |
| 57 return ContentSecurityPolicyHashAlgorithmSha384; |
| 58 case HashAlgorithmSha512: |
| 59 return ContentSecurityPolicyHashAlgorithmSha512; |
| 60 } |
| 61 NOTREACHED(); |
| 62 return ContentSecurityPolicyHashAlgorithmNone; |
| 63 } |
| 64 |
| 65 // IntegrityMetadata (from SRI) has base64-encoded digest values, but CSP uses |
| 66 // binary format. This converts from the former to the latter. |
| 67 bool parseBase64Digest(String base64, DigestValue& hash) { |
| 68 Vector<char> hashVector; |
| 69 // We accept base64url-encoded data here by normalizing it to base64. |
| 70 if (!base64Decode(normalizeToBase64(base64), hashVector)) |
| 71 return false; |
| 72 if (hashVector.isEmpty() || hashVector.size() > kMaxDigestSize) |
| 73 return false; |
| 74 hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size()); |
| 75 return true; |
| 76 } |
| 77 |
48 } // namespace | 78 } // namespace |
49 | 79 |
50 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, | 80 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, |
51 ContentSecurityPolicyHeaderType type, | 81 ContentSecurityPolicyHeaderType type, |
52 ContentSecurityPolicyHeaderSource source) | 82 ContentSecurityPolicyHeaderSource source) |
53 : m_policy(policy), | 83 : m_policy(policy), |
54 m_headerType(type), | 84 m_headerType(type), |
55 m_headerSource(source), | 85 m_headerSource(source), |
56 m_hasSandboxPolicy(false), | 86 m_hasSandboxPolicy(false), |
57 m_strictMixedContentCheckingEnforced(false), | 87 m_strictMixedContentCheckingEnforced(false), |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 | 201 |
172 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const { | 202 bool CSPDirectiveList::checkEval(SourceListDirective* directive) const { |
173 return !directive || directive->allowEval(); | 203 return !directive || directive->allowEval(); |
174 } | 204 } |
175 | 205 |
176 bool CSPDirectiveList::isMatchingNoncePresent(SourceListDirective* directive, | 206 bool CSPDirectiveList::isMatchingNoncePresent(SourceListDirective* directive, |
177 const String& nonce) const { | 207 const String& nonce) const { |
178 return directive && directive->allowNonce(nonce); | 208 return directive && directive->allowNonce(nonce); |
179 } | 209 } |
180 | 210 |
| 211 bool CSPDirectiveList::areAllMatchingHashesPresent( |
| 212 SourceListDirective* directive, |
| 213 const IntegrityMetadataSet& hashes) const { |
| 214 if (!directive || hashes.isEmpty()) |
| 215 return false; |
| 216 for (const std::pair<WTF::String, HashAlgorithm>& hash : hashes) { |
| 217 // Convert the hash from integrity metadata format to CSP format. |
| 218 CSPHashValue cspHash; |
| 219 cspHash.first = convertHashAlgorithmToCSPHashAlgorithm(hash.second); |
| 220 if (!parseBase64Digest(hash.first, cspHash.second)) |
| 221 return false; |
| 222 // All integrity hashes must be listed in the CSP. |
| 223 if (!directive->allowHash(cspHash)) |
| 224 return false; |
| 225 } |
| 226 return true; |
| 227 } |
| 228 |
181 bool CSPDirectiveList::checkHash(SourceListDirective* directive, | 229 bool CSPDirectiveList::checkHash(SourceListDirective* directive, |
182 const CSPHashValue& hashValue) const { | 230 const CSPHashValue& hashValue) const { |
183 return !directive || directive->allowHash(hashValue); | 231 return !directive || directive->allowHash(hashValue); |
184 } | 232 } |
185 | 233 |
186 bool CSPDirectiveList::checkHashedAttributes( | 234 bool CSPDirectiveList::checkHashedAttributes( |
187 SourceListDirective* directive) const { | 235 SourceListDirective* directive) const { |
188 return !directive || directive->allowHashedAttributes(); | 236 return !directive || directive->allowHashedAttributes(); |
189 } | 237 } |
190 | 238 |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 "Refused to load '" + url.elidedString() + "' (MIME type '" + | 674 "Refused to load '" + url.elidedString() + "' (MIME type '" + |
627 typeAttribute + | 675 typeAttribute + |
628 "') because it violates the following Content Security " | 676 "') because it violates the following Content Security " |
629 "Policy Directive: ") | 677 "Policy Directive: ") |
630 : checkMediaType(m_pluginTypes.get(), type, typeAttribute); | 678 : checkMediaType(m_pluginTypes.get(), type, typeAttribute); |
631 } | 679 } |
632 | 680 |
633 bool CSPDirectiveList::allowScriptFromSource( | 681 bool CSPDirectiveList::allowScriptFromSource( |
634 const KURL& url, | 682 const KURL& url, |
635 const String& nonce, | 683 const String& nonce, |
| 684 const IntegrityMetadataSet& hashes, |
636 ParserDisposition parserDisposition, | 685 ParserDisposition parserDisposition, |
637 ResourceRequest::RedirectStatus redirectStatus, | 686 ResourceRequest::RedirectStatus redirectStatus, |
638 SecurityViolationReportingPolicy reportingPolicy) const { | 687 SecurityViolationReportingPolicy reportingPolicy) const { |
639 if (isMatchingNoncePresent(operativeDirective(m_scriptSrc.get()), nonce)) | 688 SourceListDirective* directive = operativeDirective(m_scriptSrc.get()); |
| 689 if (isMatchingNoncePresent(directive, nonce)) |
640 return true; | 690 return true; |
641 if (parserDisposition == NotParserInserted && allowDynamic()) | 691 if (parserDisposition == NotParserInserted && allowDynamic()) |
642 return true; | 692 return true; |
| 693 if (areAllMatchingHashesPresent(directive, hashes)) |
| 694 return true; |
643 return reportingPolicy == SecurityViolationReportingPolicy::Report | 695 return reportingPolicy == SecurityViolationReportingPolicy::Report |
644 ? checkSourceAndReportViolation( | 696 ? checkSourceAndReportViolation( |
645 operativeDirective(m_scriptSrc.get()), url, | 697 directive, url, |
646 ContentSecurityPolicy::DirectiveType::ScriptSrc, | 698 ContentSecurityPolicy::DirectiveType::ScriptSrc, |
647 redirectStatus) | 699 redirectStatus) |
648 : checkSource(operativeDirective(m_scriptSrc.get()), url, | 700 : checkSource(directive, url, redirectStatus); |
649 redirectStatus); | |
650 } | 701 } |
651 | 702 |
652 bool CSPDirectiveList::allowObjectFromSource( | 703 bool CSPDirectiveList::allowObjectFromSource( |
653 const KURL& url, | 704 const KURL& url, |
654 ResourceRequest::RedirectStatus redirectStatus, | 705 ResourceRequest::RedirectStatus redirectStatus, |
655 SecurityViolationReportingPolicy reportingPolicy) const { | 706 SecurityViolationReportingPolicy reportingPolicy) const { |
656 if (url.protocolIsAbout()) | 707 if (url.protocolIsAbout()) |
657 return true; | 708 return true; |
658 return reportingPolicy == SecurityViolationReportingPolicy::Report | 709 return reportingPolicy == SecurityViolationReportingPolicy::Report |
659 ? checkSourceAndReportViolation( | 710 ? checkSourceAndReportViolation( |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 visitor->trace(m_imgSrc); | 1414 visitor->trace(m_imgSrc); |
1364 visitor->trace(m_mediaSrc); | 1415 visitor->trace(m_mediaSrc); |
1365 visitor->trace(m_manifestSrc); | 1416 visitor->trace(m_manifestSrc); |
1366 visitor->trace(m_objectSrc); | 1417 visitor->trace(m_objectSrc); |
1367 visitor->trace(m_scriptSrc); | 1418 visitor->trace(m_scriptSrc); |
1368 visitor->trace(m_styleSrc); | 1419 visitor->trace(m_styleSrc); |
1369 visitor->trace(m_workerSrc); | 1420 visitor->trace(m_workerSrc); |
1370 } | 1421 } |
1371 | 1422 |
1372 } // namespace blink | 1423 } // namespace blink |
OLD | NEW |