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

Side by Side Diff: Source/core/frame/ContentSecurityPolicy.cpp

Issue 26481005: Implementation of script hashes for CSP. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase on tip of tree Created 7 years, 1 month 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
« no previous file with comments | « Source/core/frame/ContentSecurityPolicy.h ('k') | Source/wtf/text/Base64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google, Inc. All rights reserved. 2 * Copyright (C) 2011 Google, Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 24 matching lines...) Expand all
35 #include "core/events/SecurityPolicyViolationEvent.h" 35 #include "core/events/SecurityPolicyViolationEvent.h"
36 #include "core/frame/ContentSecurityPolicyResponseHeaders.h" 36 #include "core/frame/ContentSecurityPolicyResponseHeaders.h"
37 #include "core/frame/DOMWindow.h" 37 #include "core/frame/DOMWindow.h"
38 #include "core/frame/Frame.h" 38 #include "core/frame/Frame.h"
39 #include "core/inspector/InspectorInstrumentation.h" 39 #include "core/inspector/InspectorInstrumentation.h"
40 #include "core/inspector/ScriptCallStack.h" 40 #include "core/inspector/ScriptCallStack.h"
41 #include "core/loader/DocumentLoader.h" 41 #include "core/loader/DocumentLoader.h"
42 #include "core/loader/PingLoader.h" 42 #include "core/loader/PingLoader.h"
43 #include "core/page/UseCounter.h" 43 #include "core/page/UseCounter.h"
44 #include "platform/JSONValues.h" 44 #include "platform/JSONValues.h"
45 #include "platform/NotImplemented.h"
45 #include "platform/ParsingUtilities.h" 46 #include "platform/ParsingUtilities.h"
46 #include "platform/network/FormData.h" 47 #include "platform/network/FormData.h"
47 #include "platform/network/ResourceResponse.h" 48 #include "platform/network/ResourceResponse.h"
48 #include "weborigin/KURL.h" 49 #include "weborigin/KURL.h"
49 #include "weborigin/KnownPorts.h" 50 #include "weborigin/KnownPorts.h"
50 #include "weborigin/SchemeRegistry.h" 51 #include "weborigin/SchemeRegistry.h"
51 #include "weborigin/SecurityOrigin.h" 52 #include "weborigin/SecurityOrigin.h"
52 #include "wtf/HashSet.h" 53 #include "wtf/HashSet.h"
54 #include "wtf/SHA1.h"
55 #include "wtf/StringHasher.h"
56 #include "wtf/text/Base64.h"
57 #include "wtf/text/StringBuilder.h"
53 #include "wtf/text/TextPosition.h" 58 #include "wtf/text/TextPosition.h"
54 #include "wtf/text/WTFString.h" 59 #include "wtf/text/WTFString.h"
55 60
61 namespace WTF {
62
63 struct VectorIntHash {
64 static unsigned hash(const Vector<uint8_t>& v) { return StringHasher::comput eHash(v.data(), v.size()); }
65 static bool equal(const Vector<uint8_t>& a, const Vector<uint8_t>& b) { retu rn a == b; };
66 static const bool safeToCompareToEmptyOrDeleted = true;
67 };
68 template<> struct DefaultHash<Vector<uint8_t> > {
69 typedef VectorIntHash Hash;
70 };
71
72 } // namespace WTF
73
56 namespace WebCore { 74 namespace WebCore {
57 75
76 typedef std::pair<unsigned, Vector<uint8_t> > SourceHashValue;
77
58 // Normally WebKit uses "static" for internal linkage, but using "static" for 78 // Normally WebKit uses "static" for internal linkage, but using "static" for
59 // these functions causes a compile error because these functions are used as 79 // these functions causes a compile error because these functions are used as
60 // template parameters. 80 // template parameters.
61 namespace { 81 namespace {
62 82
63 bool isDirectiveNameCharacter(UChar c) 83 bool isDirectiveNameCharacter(UChar c)
64 { 84 {
65 return isASCIIAlphanumeric(c) || c == '-'; 85 return isASCIIAlphanumeric(c) || c == '-';
66 } 86 }
67 87
68 bool isDirectiveValueCharacter(UChar c) 88 bool isDirectiveValueCharacter(UChar c)
69 { 89 {
70 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR 90 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
71 } 91 }
72 92
73 bool isNonceCharacter(UChar c) 93 // Only checks for general Base64 encoded chars, not '=' chars since '=' is
94 // positional and may only appear at the end of a Base64 encoded string.
95 bool isBase64EncodedCharacter(UChar c)
74 { 96 {
75 return isASCIIAlphanumeric(c) || c == '+' || c == '/'; 97 return isASCIIAlphanumeric(c) || c == '+' || c == '/';
76 } 98 }
77 99
78 bool isSourceCharacter(UChar c) 100 bool isSourceCharacter(UChar c)
79 { 101 {
80 return !isASCIISpace(c); 102 return !isASCIISpace(c);
81 } 103 }
82 104
83 bool isPathComponentCharacter(UChar c) 105 bool isPathComponentCharacter(UChar c)
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 class CSPSourceList { 291 class CSPSourceList {
270 public: 292 public:
271 CSPSourceList(ContentSecurityPolicy*, const String& directiveName); 293 CSPSourceList(ContentSecurityPolicy*, const String& directiveName);
272 294
273 void parse(const UChar* begin, const UChar* end); 295 void parse(const UChar* begin, const UChar* end);
274 296
275 bool matches(const KURL&); 297 bool matches(const KURL&);
276 bool allowInline() const { return m_allowInline; } 298 bool allowInline() const { return m_allowInline; }
277 bool allowEval() const { return m_allowEval; } 299 bool allowEval() const { return m_allowEval; }
278 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); } 300 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); }
301 bool allowHash(const SourceHashValue& hashValue) const { return m_hashes.con tains(hashValue); }
302 uint8_t hashAlgorithmsUsed() const { return m_hashAlgorithmsUsed; }
279 303
280 private: 304 private:
281 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard); 305 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard);
282 bool parseScheme(const UChar* begin, const UChar* end, String& scheme); 306 bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
283 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard); 307 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard);
284 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard); 308 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard);
285 bool parsePath(const UChar* begin, const UChar* end, String& path); 309 bool parsePath(const UChar* begin, const UChar* end, String& path);
286 bool parseNonce(const UChar* begin, const UChar* end, String& nonce); 310 bool parseNonce(const UChar* begin, const UChar* end, String& nonce);
311 bool parseHash(const UChar* begin, const UChar* end, Vector<uint8_t>& hash, ContentSecurityPolicy::HashAlgorithms&);
287 312
288 void addSourceSelf(); 313 void addSourceSelf();
289 void addSourceStar(); 314 void addSourceStar();
290 void addSourceUnsafeInline(); 315 void addSourceUnsafeInline();
291 void addSourceUnsafeEval(); 316 void addSourceUnsafeEval();
292 void addSourceNonce(const String& nonce); 317 void addSourceNonce(const String& nonce);
318 void addSourceHash(const ContentSecurityPolicy::HashAlgorithms&, const Vecto r<uint8_t>& hash);
293 319
294 ContentSecurityPolicy* m_policy; 320 ContentSecurityPolicy* m_policy;
295 Vector<CSPSource> m_list; 321 Vector<CSPSource> m_list;
296 String m_directiveName; 322 String m_directiveName;
297 bool m_allowStar; 323 bool m_allowStar;
298 bool m_allowInline; 324 bool m_allowInline;
299 bool m_allowEval; 325 bool m_allowEval;
300 HashSet<String> m_nonces; 326 HashSet<String> m_nonces;
327 HashSet<SourceHashValue> m_hashes;
328 uint8_t m_hashAlgorithmsUsed;
301 }; 329 };
302 330
303 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) 331 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName)
304 : m_policy(policy) 332 : m_policy(policy)
305 , m_directiveName(directiveName) 333 , m_directiveName(directiveName)
306 , m_allowStar(false) 334 , m_allowStar(false)
307 , m_allowInline(false) 335 , m_allowInline(false)
308 , m_allowEval(false) 336 , m_allowEval(false)
337 , m_hashAlgorithmsUsed(0)
309 { 338 {
310 } 339 }
311 340
312 bool CSPSourceList::matches(const KURL& url) 341 bool CSPSourceList::matches(const KURL& url)
313 { 342 {
314 if (m_allowStar) 343 if (m_allowStar)
315 return true; 344 return true;
316 345
317 KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin: :extractInnerURL(url) : url; 346 KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin: :extractInnerURL(url) : url;
318 347
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 426
398 if (m_policy->experimentalFeaturesEnabled()) { 427 if (m_policy->experimentalFeaturesEnabled()) {
399 String nonce; 428 String nonce;
400 if (!parseNonce(begin, end, nonce)) 429 if (!parseNonce(begin, end, nonce))
401 return false; 430 return false;
402 431
403 if (!nonce.isNull()) { 432 if (!nonce.isNull()) {
404 addSourceNonce(nonce); 433 addSourceNonce(nonce);
405 return true; 434 return true;
406 } 435 }
436
437 Vector<uint8_t> hash;
438 ContentSecurityPolicy::HashAlgorithms algorithm = ContentSecurityPolicy: :HashAlgorithmsNone;
439 if (!parseHash(begin, end, hash, algorithm))
440 return false;
441
442 if (hash.size() > 0) {
443 addSourceHash(algorithm, hash);
444 return true;
445 }
407 } 446 }
408 447
409 const UChar* position = begin; 448 const UChar* position = begin;
410 const UChar* beginHost = begin; 449 const UChar* beginHost = begin;
411 const UChar* beginPath = end; 450 const UChar* beginPath = end;
412 const UChar* beginPort = 0; 451 const UChar* beginPort = 0;
413 452
414 skipWhile<UChar, isNotColonOrSlash>(position, end); 453 skipWhile<UChar, isNotColonOrSlash>(position, end);
415 454
416 if (position == end) { 455 if (position == end) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce) 525 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce)
487 { 526 {
488 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); 527 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-"));
489 528
490 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( ))) 529 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( )))
491 return true; 530 return true;
492 531
493 const UChar* position = begin + noncePrefix.length(); 532 const UChar* position = begin + noncePrefix.length();
494 const UChar* nonceBegin = position; 533 const UChar* nonceBegin = position;
495 534
496 skipWhile<UChar, isNonceCharacter>(position, end); 535 skipWhile<UChar, isBase64EncodedCharacter>(position, end);
497 ASSERT(nonceBegin <= position); 536 ASSERT(nonceBegin <= position);
498 537
499 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin )) 538 if ((position + 1) != end || *position != '\'' || !(position - nonceBegin))
500 return false; 539 return false;
501 540
502 nonce = String(nonceBegin, position - nonceBegin); 541 nonce = String(nonceBegin, position - nonceBegin);
503 return true; 542 return true;
504 } 543 }
505 544
545 // hash-source = "'" hash-algorithm "-" hash-value "'"
546 // hash-algorithm = "sha1" / "sha256"
547 // hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" )
548 //
549 bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, Vector<uint8 _t>& hash, ContentSecurityPolicy::HashAlgorithms& hashAlgorithm)
550 {
551 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("'sha1-"));
552 DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("'sha256-"));
553
554 String prefix;
555 if (equalIgnoringCase(sha1Prefix.characters8(), begin, sha1Prefix.length())) {
556 prefix = sha1Prefix;
557 hashAlgorithm = ContentSecurityPolicy::HashAlgorithmsSha1;
558 } else if (equalIgnoringCase(sha256Prefix.characters8(), begin, sha256Prefix .length())) {
559 notImplemented();
560 } else {
561 return true;
562 }
563
564 const UChar* position = begin + prefix.length();
565 const UChar* hashBegin = position;
566
567 skipWhile<UChar, isBase64EncodedCharacter>(position, end);
568 ASSERT(hashBegin <= position);
569
570 // Base64 encodings may end with exactly one or two '=' characters
571 skipExactly<UChar>(position, position + 1, '=');
572 skipExactly<UChar>(position, position + 1, '=');
573
574 if ((position + 1) != end || *position != '\'' || !(position - hashBegin))
575 return false;
576
577 Vector<char> hashVector;
578 base64Decode(hashBegin, position - hashBegin, hashVector);
579 hash.append(reinterpret_cast<uint8_t*>(hashVector.data()), hashVector.size() );
580 return true;
581 }
582
506 // ; <scheme> production from RFC 3986 583 // ; <scheme> production from RFC 3986
507 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 584 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
508 // 585 //
509 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme) 586 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme)
510 { 587 {
511 ASSERT(begin <= end); 588 ASSERT(begin <= end);
512 ASSERT(scheme.isEmpty()); 589 ASSERT(scheme.isEmpty());
513 590
514 if (begin == end) 591 if (begin == end)
515 return false; 592 return false;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 void CSPSourceList::addSourceUnsafeEval() 715 void CSPSourceList::addSourceUnsafeEval()
639 { 716 {
640 m_allowEval = true; 717 m_allowEval = true;
641 } 718 }
642 719
643 void CSPSourceList::addSourceNonce(const String& nonce) 720 void CSPSourceList::addSourceNonce(const String& nonce)
644 { 721 {
645 m_nonces.add(nonce); 722 m_nonces.add(nonce);
646 } 723 }
647 724
725 void CSPSourceList::addSourceHash(const ContentSecurityPolicy::HashAlgorithms& a lgorithm, const Vector<uint8_t>& hash)
726 {
727 m_hashes.add(SourceHashValue(algorithm, hash));
728 m_hashAlgorithmsUsed |= algorithm;
729 }
730
648 class CSPDirective { 731 class CSPDirective {
649 public: 732 public:
650 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) 733 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
651 : m_name(name) 734 : m_name(name)
652 , m_text(name + ' ' + value) 735 , m_text(name + ' ' + value)
653 , m_policy(policy) 736 , m_policy(policy)
654 { 737 {
655 } 738 }
656 739
657 const String& text() const { return m_text; } 740 const String& text() const { return m_text; }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 } 837 }
755 838
756 bool allows(const KURL& url) 839 bool allows(const KURL& url)
757 { 840 {
758 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); 841 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url);
759 } 842 }
760 843
761 bool allowInline() const { return m_sourceList.allowInline(); } 844 bool allowInline() const { return m_sourceList.allowInline(); }
762 bool allowEval() const { return m_sourceList.allowEval(); } 845 bool allowEval() const { return m_sourceList.allowEval(); }
763 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); } 846 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); }
847 bool allowHash(const SourceHashValue& hashValue) const { return m_sourceList .allowHash(hashValue); }
848
849 uint8_t hashAlgorithmsUsed() const { return m_sourceList.hashAlgorithmsUsed( ); }
764 850
765 private: 851 private:
766 CSPSourceList m_sourceList; 852 CSPSourceList m_sourceList;
767 }; 853 };
768 854
769 class CSPDirectiveList { 855 class CSPDirectiveList {
770 WTF_MAKE_FAST_ALLOCATED; 856 WTF_MAKE_FAST_ALLOCATED;
771 public: 857 public:
772 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); 858 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType);
773 859
(...skipping 14 matching lines...) Expand all
788 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; 874 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const;
789 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 875 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
790 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 876 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
791 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; 877 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const;
792 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 878 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
793 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 879 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
794 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; 880 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst;
795 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; 881 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ;
796 bool allowScriptNonce(const String&) const; 882 bool allowScriptNonce(const String&) const;
797 bool allowStyleNonce(const String&) const; 883 bool allowStyleNonce(const String&) const;
884 bool allowScriptHash(const SourceHashValue&) const;
798 885
799 void gatherReportURIs(DOMStringList&) const; 886 void gatherReportURIs(DOMStringList&) const;
800 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } 887 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; }
801 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } 888 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; }
802 bool isReportOnly() const { return m_reportOnly; } 889 bool isReportOnly() const { return m_reportOnly; }
803 const Vector<KURL>& reportURIs() const { return m_reportURIs; } 890 const Vector<KURL>& reportURIs() const { return m_reportURIs; }
804 891
805 private: 892 private:
806 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); 893 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType);
807 894
808 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); 895 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value);
809 void parseReportURI(const String& name, const String& value); 896 void parseReportURI(const String& name, const String& value);
810 void parsePluginTypes(const String& name, const String& value); 897 void parsePluginTypes(const String& name, const String& value);
811 void parseReflectedXSS(const String& name, const String& value); 898 void parseReflectedXSS(const String& name, const String& value);
812 void addDirective(const String& name, const String& value); 899 void addDirective(const String& name, const String& value);
813 void applySandboxPolicy(const String& name, const String& sandboxPolicy); 900 void applySandboxPolicy(const String& name, const String& sandboxPolicy);
814 901
815 template <class CSPDirectiveType> 902 template <class CSPDirectiveType>
816 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); 903 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&);
817 904
818 SourceListDirective* operativeDirective(SourceListDirective*) const; 905 SourceListDirective* operativeDirective(SourceListDirective*) const;
819 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const; 906 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const;
820 void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 907 void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
821 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const; 908 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const;
822 909
823 bool checkEval(SourceListDirective*) const; 910 bool checkEval(SourceListDirective*) const;
824 bool checkInline(SourceListDirective*) const; 911 bool checkInline(SourceListDirective*) const;
825 bool checkNonce(SourceListDirective*, const String&) const; 912 bool checkNonce(SourceListDirective*, const String&) const;
913 bool checkHash(SourceListDirective*, const SourceHashValue&) const;
826 bool checkSource(SourceListDirective*, const KURL&) const; 914 bool checkSource(SourceListDirective*, const KURL&) const;
827 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; 915 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const;
828 916
829 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } 917 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; }
830 918
831 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const; 919 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const;
832 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const; 920 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
833 921
834 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; 922 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const;
835 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const; 923 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const 1006 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
919 { 1007 {
920 return !directive || directive->allowInline(); 1008 return !directive || directive->allowInline();
921 } 1009 }
922 1010
923 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const 1011 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
924 { 1012 {
925 return !directive || directive->allowNonce(nonce); 1013 return !directive || directive->allowNonce(nonce);
926 } 1014 }
927 1015
1016 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const SourceHas hValue& hashValue) const
1017 {
1018 return !directive || directive->allowHash(hashValue);
1019 }
1020
928 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const 1021 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const
929 { 1022 {
930 return !directive || directive->allows(url); 1023 return !directive || directive->allows(url);
931 } 1024 }
932 1025
933 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const 1026 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const
934 { 1027 {
935 if (!directive) 1028 if (!directive)
936 return true; 1029 return true;
937 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) 1030 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const 1253 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
1161 { 1254 {
1162 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); 1255 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
1163 } 1256 }
1164 1257
1165 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const 1258 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
1166 { 1259 {
1167 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); 1260 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
1168 } 1261 }
1169 1262
1263 bool CSPDirectiveList::allowScriptHash(const SourceHashValue& hashValue) const
1264 {
1265 return checkHash(operativeDirective(m_scriptSrc.get()), hashValue);
1266 }
1267
1170 // policy = directive-list 1268 // policy = directive-list
1171 // directive-list = [ directive *( ";" [ directive ] ) ] 1269 // directive-list = [ directive *( ";" [ directive ] ) ]
1172 // 1270 //
1173 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) 1271 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
1174 { 1272 {
1175 m_header = String(begin, end - begin); 1273 m_header = String(begin, end - begin);
1176 1274
1177 if (begin == end) 1275 if (begin == end)
1178 return; 1276 return;
1179 1277
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 } 1445 }
1348 1446
1349 void CSPDirectiveList::addDirective(const String& name, const String& value) 1447 void CSPDirectiveList::addDirective(const String& name, const String& value)
1350 { 1448 {
1351 ASSERT(!name.isEmpty()); 1449 ASSERT(!name.isEmpty());
1352 1450
1353 if (equalIgnoringCase(name, defaultSrc)) { 1451 if (equalIgnoringCase(name, defaultSrc)) {
1354 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); 1452 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
1355 } else if (equalIgnoringCase(name, scriptSrc)) { 1453 } else if (equalIgnoringCase(name, scriptSrc)) {
1356 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); 1454 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
1455 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed());
1357 } else if (equalIgnoringCase(name, objectSrc)) { 1456 } else if (equalIgnoringCase(name, objectSrc)) {
1358 setCSPDirective<SourceListDirective>(name, value, m_objectSrc); 1457 setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
1359 } else if (equalIgnoringCase(name, frameSrc)) { 1458 } else if (equalIgnoringCase(name, frameSrc)) {
1360 setCSPDirective<SourceListDirective>(name, value, m_frameSrc); 1459 setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
1361 } else if (equalIgnoringCase(name, imgSrc)) { 1460 } else if (equalIgnoringCase(name, imgSrc)) {
1362 setCSPDirective<SourceListDirective>(name, value, m_imgSrc); 1461 setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
1363 } else if (equalIgnoringCase(name, styleSrc)) { 1462 } else if (equalIgnoringCase(name, styleSrc)) {
1364 setCSPDirective<SourceListDirective>(name, value, m_styleSrc); 1463 setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
1365 } else if (equalIgnoringCase(name, fontSrc)) { 1464 } else if (equalIgnoringCase(name, fontSrc)) {
1366 setCSPDirective<SourceListDirective>(name, value, m_fontSrc); 1465 setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
(...skipping 17 matching lines...) Expand all
1384 else 1483 else
1385 m_policy->reportUnsupportedDirective(name); 1484 m_policy->reportUnsupportedDirective(name);
1386 } else { 1485 } else {
1387 m_policy->reportUnsupportedDirective(name); 1486 m_policy->reportUnsupportedDirective(name);
1388 } 1487 }
1389 } 1488 }
1390 1489
1391 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContextClient* client) 1490 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContextClient* client)
1392 : m_client(client) 1491 : m_client(client)
1393 , m_overrideInlineStyleAllowed(false) 1492 , m_overrideInlineStyleAllowed(false)
1493 , m_sourceHashAlgorithmsUsed(HashAlgorithmsNone)
1394 { 1494 {
1395 } 1495 }
1396 1496
1397 ContentSecurityPolicy::~ContentSecurityPolicy() 1497 ContentSecurityPolicy::~ContentSecurityPolicy()
1398 { 1498 {
1399 } 1499 }
1400 1500
1401 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) 1501 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other)
1402 { 1502 {
1403 ASSERT(m_policies.isEmpty()); 1503 ASSERT(m_policies.isEmpty());
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 1611
1512 template<bool (CSPDirectiveList::*allowed)(const String&) const> 1612 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1513 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce) 1613 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce)
1514 { 1614 {
1515 for (size_t i = 0; i < policies.size(); ++i) { 1615 for (size_t i = 0; i < policies.size(); ++i) {
1516 if (!(policies[i].get()->*allowed)(nonce)) 1616 if (!(policies[i].get()->*allowed)(nonce))
1517 return false; 1617 return false;
1518 } 1618 }
1519 return true; 1619 return true;
1520 } 1620 }
1621
1622 template<bool (CSPDirectiveList::*allowed)(const SourceHashValue&) const>
1623 bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const Source HashValue& hashValue)
1624 {
1625 for (size_t i = 0; i < policies.size(); ++i) {
1626 if (!(policies[i].get()->*allowed)(hashValue))
1627 return false;
1628 }
1629 return true;
1630 }
1631
1521 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const> 1632 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const>
1522 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus) 1633 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus)
1523 { 1634 {
1524 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) 1635 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol()))
1525 return true; 1636 return true;
1526 1637
1527 for (size_t i = 0; i < policies.size(); ++i) { 1638 for (size_t i = 0; i < policies.size(); ++i) {
1528 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) 1639 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus))
1529 return false; 1640 return false;
1530 } 1641 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1584 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const 1695 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const
1585 { 1696 {
1586 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce); 1697 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce);
1587 } 1698 }
1588 1699
1589 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const 1700 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const
1590 { 1701 {
1591 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce); 1702 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce);
1592 } 1703 }
1593 1704
1705 bool ContentSecurityPolicy::allowScriptHash(const String& source) const
1706 {
1707 // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we
1708 // have that, we should implement a proper check for sha256 hash values here .
1709 if (HashAlgorithmsSha1 & m_sourceHashAlgorithmsUsed) {
1710 Vector<uint8_t, 20> digest;
1711 SHA1 sourceSha1;
1712 sourceSha1.addBytes(UTF8Encoding().normalizeAndEncode(source, WTF::Entit iesForUnencodables));
1713 sourceSha1.computeHash(digest);
1714
1715 if (isAllowedByAllWithHash<&CSPDirectiveList::allowScriptHash>(m_policie s, SourceHashValue(HashAlgorithmsSha1, Vector<uint8_t>(digest))))
1716 return true;
1717 }
1718
1719 return false;
1720 }
1721
1722 void ContentSecurityPolicy::usesScriptHashAlgorithms(uint8_t algorithms)
1723 {
1724 m_sourceHashAlgorithmsUsed |= algorithms;
1725 }
1726
1594 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const 1727 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const
1595 { 1728 {
1596 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); 1729 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus);
1597 } 1730 }
1598 1731
1599 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const 1732 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const
1600 { 1733 {
1601 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); 1734 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus);
1602 } 1735 }
1603 1736
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1839 { 1972 {
1840 ASSERT(invalidChar == '#' || invalidChar == '?'); 1973 ASSERT(invalidChar == '#' || invalidChar == '?');
1841 1974
1842 String ignoring = "The fragment identifier, including the '#', will be ignor ed."; 1975 String ignoring = "The fragment identifier, including the '#', will be ignor ed.";
1843 if (invalidChar == '?') 1976 if (invalidChar == '?')
1844 ignoring = "The query component, including the '?', will be ignored."; 1977 ignoring = "The query component, including the '?', will be ignored.";
1845 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; 1978 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring;
1846 logToConsole(message); 1979 logToConsole(message);
1847 } 1980 }
1848 1981
1849 void ContentSecurityPolicy::reportInvalidNonce(const String& nonce) const
1850 {
1851 String message = "Ignoring invalid Content Security Policy script nonce: '" + nonce + "'.\n";
1852 logToConsole(message);
1853 }
1854
1855 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const 1982 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const
1856 { 1983 {
1857 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored."; 1984 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored.";
1858 if (equalIgnoringCase(source, "'none'")) 1985 if (equalIgnoringCase(source, "'none'"))
1859 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; 1986 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list.";
1860 logToConsole(message); 1987 logToConsole(message);
1861 } 1988 }
1862 1989
1863 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const 1990 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const
1864 { 1991 {
(...skipping 30 matching lines...) Expand all
1895 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. 2022 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report.
1896 return !m_violationReportsSent.contains(report.impl()->hash()); 2023 return !m_violationReportsSent.contains(report.impl()->hash());
1897 } 2024 }
1898 2025
1899 void ContentSecurityPolicy::didSendViolationReport(const String& report) 2026 void ContentSecurityPolicy::didSendViolationReport(const String& report)
1900 { 2027 {
1901 m_violationReportsSent.add(report.impl()->hash()); 2028 m_violationReportsSent.add(report.impl()->hash());
1902 } 2029 }
1903 2030
1904 } // namespace WebCore 2031 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/frame/ContentSecurityPolicy.h ('k') | Source/wtf/text/Base64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698