Chromium Code Reviews| 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 |