Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1241)

Side by Side Diff: third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp

Issue 2784753003: CSP: Enable whitelisting of external JavaScript via hashes (Closed)
Patch Set: webkit_unit_tests builds Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698