| 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 |