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

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: Created 7 years, 2 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 /* 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 #include "core/page/UseCounter.h" 42 #include "core/page/UseCounter.h"
43 #include "core/platform/ParsingUtilities.h" 43 #include "core/platform/ParsingUtilities.h"
44 #include "core/platform/network/FormData.h" 44 #include "core/platform/network/FormData.h"
45 #include "core/platform/network/ResourceResponse.h" 45 #include "core/platform/network/ResourceResponse.h"
46 #include "platform/JSONValues.h" 46 #include "platform/JSONValues.h"
47 #include "weborigin/KURL.h" 47 #include "weborigin/KURL.h"
48 #include "weborigin/KnownPorts.h" 48 #include "weborigin/KnownPorts.h"
49 #include "weborigin/SchemeRegistry.h" 49 #include "weborigin/SchemeRegistry.h"
50 #include "weborigin/SecurityOrigin.h" 50 #include "weborigin/SecurityOrigin.h"
51 #include "wtf/HashSet.h" 51 #include "wtf/HashSet.h"
52 #include "wtf/SHA1.h"
53 #include "wtf/text/Base64.h"
52 #include "wtf/text/TextPosition.h" 54 #include "wtf/text/TextPosition.h"
53 #include "wtf/text/WTFString.h" 55 #include "wtf/text/WTFString.h"
54 56
55 namespace WebCore { 57 namespace WebCore {
56 58
57 // Normally WebKit uses "static" for internal linkage, but using "static" for 59 // Normally WebKit uses "static" for internal linkage, but using "static" for
58 // these functions causes a compile error because these functions are used as 60 // these functions causes a compile error because these functions are used as
59 // template parameters. 61 // template parameters.
60 namespace { 62 namespace {
61 63
62 bool isDirectiveNameCharacter(UChar c) 64 bool isDirectiveNameCharacter(UChar c)
63 { 65 {
64 return isASCIIAlphanumeric(c) || c == '-'; 66 return isASCIIAlphanumeric(c) || c == '-';
65 } 67 }
66 68
67 bool isDirectiveValueCharacter(UChar c) 69 bool isDirectiveValueCharacter(UChar c)
68 { 70 {
69 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR 71 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
70 } 72 }
71 73
72 bool isNonceCharacter(UChar c) 74 bool isNonceCharacter(UChar c)
73 { 75 {
74 return isASCIIAlphanumeric(c) || c == '+' || c == '/'; 76 return isASCIIAlphanumeric(c) || c == '+' || c == '/';
75 } 77 }
76 78
79 bool isHashCharacter(UChar c)
80 {
81 return isASCIIAlphanumeric(c) || c == '+' || c == '/' || c == '=';
Mike West 2013/10/16 14:53:02 It seems that we should be able to get away with c
jww 2013/10/16 21:49:21 Good point, and it actually brings up a more inter
82 }
83
77 bool isSourceCharacter(UChar c) 84 bool isSourceCharacter(UChar c)
78 { 85 {
79 return !isASCIISpace(c); 86 return !isASCIISpace(c);
80 } 87 }
81 88
82 bool isPathComponentCharacter(UChar c) 89 bool isPathComponentCharacter(UChar c)
83 { 90 {
84 return c != '?' && c != '#'; 91 return c != '?' && c != '#';
85 } 92 }
86 93
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 class CSPSourceList { 279 class CSPSourceList {
273 public: 280 public:
274 CSPSourceList(ContentSecurityPolicy*, const String& directiveName); 281 CSPSourceList(ContentSecurityPolicy*, const String& directiveName);
275 282
276 void parse(const UChar* begin, const UChar* end); 283 void parse(const UChar* begin, const UChar* end);
277 284
278 bool matches(const KURL&); 285 bool matches(const KURL&);
279 bool allowInline() const { return m_allowInline; } 286 bool allowInline() const { return m_allowInline; }
280 bool allowEval() const { return m_allowEval; } 287 bool allowEval() const { return m_allowEval; }
281 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); } 288 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); }
289 bool allowHash(const String& hash) const { return !hash.isNull() && m_hashes .contains(hash); }
282 290
283 private: 291 private:
284 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard); 292 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard);
285 bool parseScheme(const UChar* begin, const UChar* end, String& scheme); 293 bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
286 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard); 294 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard);
287 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard); 295 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard);
288 bool parsePath(const UChar* begin, const UChar* end, String& path); 296 bool parsePath(const UChar* begin, const UChar* end, String& path);
289 bool parseNonce(const UChar* begin, const UChar* end, String& nonce); 297 bool parseNonce(const UChar* begin, const UChar* end, String& nonce);
298 bool parseHash(const UChar* begin, const UChar* end, String& hash);
290 299
291 void addSourceSelf(); 300 void addSourceSelf();
292 void addSourceStar(); 301 void addSourceStar();
293 void addSourceUnsafeInline(); 302 void addSourceUnsafeInline();
294 void addSourceUnsafeEval(); 303 void addSourceUnsafeEval();
295 void addSourceNonce(const String& nonce); 304 void addSourceNonce(const String& nonce);
305 void addSourceHash(const String& hash);
296 306
297 ContentSecurityPolicy* m_policy; 307 ContentSecurityPolicy* m_policy;
298 Vector<CSPSource> m_list; 308 Vector<CSPSource> m_list;
299 String m_directiveName; 309 String m_directiveName;
300 bool m_allowStar; 310 bool m_allowStar;
301 bool m_allowInline; 311 bool m_allowInline;
302 bool m_allowEval; 312 bool m_allowEval;
303 HashSet<String> m_nonces; 313 HashSet<String> m_nonces;
314 HashSet<String> m_hashes;
304 }; 315 };
305 316
306 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) 317 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName)
307 : m_policy(policy) 318 : m_policy(policy)
308 , m_directiveName(directiveName) 319 , m_directiveName(directiveName)
309 , m_allowStar(false) 320 , m_allowStar(false)
310 , m_allowInline(false) 321 , m_allowInline(false)
311 , m_allowEval(false) 322 , m_allowEval(false)
312 { 323 {
313 } 324 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 413
403 if (m_policy->experimentalFeaturesEnabled()) { 414 if (m_policy->experimentalFeaturesEnabled()) {
404 String nonce; 415 String nonce;
405 if (!parseNonce(begin, end, nonce)) 416 if (!parseNonce(begin, end, nonce))
406 return false; 417 return false;
407 418
408 if (!nonce.isNull()) { 419 if (!nonce.isNull()) {
409 addSourceNonce(nonce); 420 addSourceNonce(nonce);
410 return true; 421 return true;
411 } 422 }
423
424 String hash;
425 if (!parseHash(begin, end, hash))
426 return false;
427
428 if (!hash.isNull()) {
429 addSourceHash(hash);
430 return true;
431 }
412 } 432 }
413 433
414 const UChar* position = begin; 434 const UChar* position = begin;
415 const UChar* beginHost = begin; 435 const UChar* beginHost = begin;
416 const UChar* beginPath = end; 436 const UChar* beginPath = end;
417 const UChar* beginPort = 0; 437 const UChar* beginPort = 0;
418 438
419 skipWhile<UChar, isNotColonOrSlash>(position, end); 439 skipWhile<UChar, isNotColonOrSlash>(position, end);
420 440
421 if (position == end) { 441 if (position == end) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 skipWhile<UChar, isNonceCharacter>(position, end); 521 skipWhile<UChar, isNonceCharacter>(position, end);
502 ASSERT(nonceBegin <= position); 522 ASSERT(nonceBegin <= position);
503 523
504 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin )) 524 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin ))
505 return false; 525 return false;
506 526
507 nonce = String(nonceBegin, position - nonceBegin); 527 nonce = String(nonceBegin, position - nonceBegin);
508 return true; 528 return true;
509 } 529 }
510 530
531 // hash-source = "'" hash-algorithm "-" hash-value "'"
532 // hash-algorithm = "sha1" / "sha256"
533 // hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" )
534 //
535 bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, String& hash )
536 {
537 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("'sha1-"));
538 DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("'sha256-"));
539
540 bool isSha1 = equalIgnoringCase(sha1Prefix.characters8(), begin, sha1Prefix. length());
541 bool isSha256 = equalIgnoringCase(sha256Prefix.characters8(), begin, sha256P refix.length());
542
543 if (!isSha1 && !isSha256)
544 return true;
Mike West 2013/10/16 14:53:02 We might want to be more clever about this to warn
jww 2013/10/16 21:49:21 Yeah, I'll put in a todo to make a warning message
545
546 const String& prefix = (isSha1 ? sha1Prefix : sha256Prefix);
Mike West 2013/10/16 14:53:02 You're only using this to determine the initial po
jww 2013/10/16 21:49:21 Ah, yes, good call. Remnants from an earlier versi
547 const UChar* position = begin + prefix.length();
548 const UChar* hashBegin = position;
549
550 skipWhile<UChar, isHashCharacter>(position, end);
551 ASSERT(hashBegin <= position);
552
553 if (((position + 1) != end && *position != '\'') || !(position - hashBegin) )
554 return false;
555
556 hash = String(begin + 1, position - begin - 1);
Mike West 2013/10/16 14:53:02 You need to pass the hash type back to the caller
jww 2013/10/16 21:49:21 This actually leaves the prefix on the beginning o
557 return true;
558 }
559
511 // ; <scheme> production from RFC 3986 560 // ; <scheme> production from RFC 3986
512 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 561 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
513 // 562 //
514 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme) 563 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme)
515 { 564 {
516 ASSERT(begin <= end); 565 ASSERT(begin <= end);
517 ASSERT(scheme.isEmpty()); 566 ASSERT(scheme.isEmpty());
518 567
519 if (begin == end) 568 if (begin == end)
520 return false; 569 return false;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 void CSPSourceList::addSourceUnsafeEval() 692 void CSPSourceList::addSourceUnsafeEval()
644 { 693 {
645 m_allowEval = true; 694 m_allowEval = true;
646 } 695 }
647 696
648 void CSPSourceList::addSourceNonce(const String& nonce) 697 void CSPSourceList::addSourceNonce(const String& nonce)
649 { 698 {
650 m_nonces.add(nonce); 699 m_nonces.add(nonce);
651 } 700 }
652 701
702 void CSPSourceList::addSourceHash(const String& hash)
703 {
704 m_hashes.add(hash);
Mike West 2013/10/16 14:53:02 Again, I think you'll need the type as well.
jww 2013/10/16 21:49:21 See above reply. The hash string actually includes
705 }
706
653 class CSPDirective { 707 class CSPDirective {
654 public: 708 public:
655 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) 709 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
656 : m_name(name) 710 : m_name(name)
657 , m_text(name + ' ' + value) 711 , m_text(name + ' ' + value)
658 , m_policy(policy) 712 , m_policy(policy)
659 { 713 {
660 } 714 }
661 715
662 const String& text() const { return m_text; } 716 const String& text() const { return m_text; }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 } 813 }
760 814
761 bool allows(const KURL& url) 815 bool allows(const KURL& url)
762 { 816 {
763 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); 817 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url);
764 } 818 }
765 819
766 bool allowInline() const { return m_sourceList.allowInline(); } 820 bool allowInline() const { return m_sourceList.allowInline(); }
767 bool allowEval() const { return m_sourceList.allowEval(); } 821 bool allowEval() const { return m_sourceList.allowEval(); }
768 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); } 822 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); }
823 bool allowHash(const String& hash) const { return m_sourceList.allowHash(has h); }
769 824
770 private: 825 private:
771 CSPSourceList m_sourceList; 826 CSPSourceList m_sourceList;
772 }; 827 };
773 828
774 class CSPDirectiveList { 829 class CSPDirectiveList {
775 WTF_MAKE_FAST_ALLOCATED; 830 WTF_MAKE_FAST_ALLOCATED;
776 public: 831 public:
777 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); 832 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType);
778 833
(...skipping 14 matching lines...) Expand all
793 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; 848 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const;
794 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 849 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
795 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 850 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
796 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; 851 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const;
797 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 852 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
798 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 853 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
799 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; 854 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst;
800 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; 855 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ;
801 bool allowScriptNonce(const String&) const; 856 bool allowScriptNonce(const String&) const;
802 bool allowStyleNonce(const String&) const; 857 bool allowStyleNonce(const String&) const;
858 bool allowScriptHash(const String&) const;
859 bool allowStyleHash(const String&) const;
803 860
804 void gatherReportURIs(DOMStringList&) const; 861 void gatherReportURIs(DOMStringList&) const;
805 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } 862 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; }
806 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } 863 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; }
807 bool isReportOnly() const { return m_reportOnly; } 864 bool isReportOnly() const { return m_reportOnly; }
808 const Vector<KURL>& reportURIs() const { return m_reportURIs; } 865 const Vector<KURL>& reportURIs() const { return m_reportURIs; }
809 866
810 private: 867 private:
811 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); 868 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType);
812 869
813 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); 870 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value);
814 void parseReportURI(const String& name, const String& value); 871 void parseReportURI(const String& name, const String& value);
815 void parsePluginTypes(const String& name, const String& value); 872 void parsePluginTypes(const String& name, const String& value);
816 void parseReflectedXSS(const String& name, const String& value); 873 void parseReflectedXSS(const String& name, const String& value);
817 void addDirective(const String& name, const String& value); 874 void addDirective(const String& name, const String& value);
818 void applySandboxPolicy(const String& name, const String& sandboxPolicy); 875 void applySandboxPolicy(const String& name, const String& sandboxPolicy);
819 876
820 template <class CSPDirectiveType> 877 template <class CSPDirectiveType>
821 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); 878 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&);
822 879
823 SourceListDirective* operativeDirective(SourceListDirective*) const; 880 SourceListDirective* operativeDirective(SourceListDirective*) const;
824 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const; 881 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const;
825 void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const; 882 void reportViolationWithLocation(const String& directiveText, const String& effectiveDirective, const String& consoleMessage, const KURL& blockedURL, const String& contextURL, const WTF::OrdinalNumber& contextLine) const;
826 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const; 883 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const;
827 884
828 bool checkEval(SourceListDirective*) const; 885 bool checkEval(SourceListDirective*) const;
829 bool checkInline(SourceListDirective*) const; 886 bool checkInline(SourceListDirective*) const;
830 bool checkNonce(SourceListDirective*, const String&) const; 887 bool checkNonce(SourceListDirective*, const String&) const;
888 bool checkHash(SourceListDirective*, const String&) const;
831 bool checkSource(SourceListDirective*, const KURL&) const; 889 bool checkSource(SourceListDirective*, const KURL&) const;
832 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; 890 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const;
833 891
834 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } 892 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; }
835 893
836 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const; 894 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const;
837 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const; 895 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
838 896
839 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; 897 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const;
840 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const; 898 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
923 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const 981 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
924 { 982 {
925 return !directive || directive->allowInline(); 983 return !directive || directive->allowInline();
926 } 984 }
927 985
928 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const 986 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
929 { 987 {
930 return !directive || directive->allowNonce(nonce); 988 return !directive || directive->allowNonce(nonce);
931 } 989 }
932 990
991 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const String& h ash) const
992 {
993 return !directive || directive->allowHash(hash);
994 }
995
933 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const 996 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const
934 { 997 {
935 return !directive || directive->allows(url); 998 return !directive || directive->allows(url);
936 } 999 }
937 1000
938 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const 1001 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const
939 { 1002 {
940 if (!directive) 1003 if (!directive)
941 return true; 1004 return true;
942 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) 1005 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type)
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const 1231 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
1169 { 1232 {
1170 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); 1233 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
1171 } 1234 }
1172 1235
1173 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const 1236 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
1174 { 1237 {
1175 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); 1238 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
1176 } 1239 }
1177 1240
1241 bool CSPDirectiveList::allowScriptHash(const String& hash) const
1242 {
1243 return checkHash(operativeDirective(m_scriptSrc.get()), hash);
1244 }
1245
1246 bool CSPDirectiveList::allowStyleHash(const String& hash) const
1247 {
1248 return checkHash(operativeDirective(m_styleSrc.get()), hash);
1249 }
1250
1178 // policy = directive-list 1251 // policy = directive-list
1179 // directive-list = [ directive *( ";" [ directive ] ) ] 1252 // directive-list = [ directive *( ";" [ directive ] ) ]
1180 // 1253 //
1181 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) 1254 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
1182 { 1255 {
1183 m_header = String(begin, end - begin); 1256 m_header = String(begin, end - begin);
1184 1257
1185 if (begin == end) 1258 if (begin == end)
1186 return; 1259 return;
1187 1260
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1590
1518 template<bool (CSPDirectiveList::*allowed)(const String&) const> 1591 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1519 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce) 1592 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce)
1520 { 1593 {
1521 for (size_t i = 0; i < policies.size(); ++i) { 1594 for (size_t i = 0; i < policies.size(); ++i) {
1522 if (!(policies[i].get()->*allowed)(nonce)) 1595 if (!(policies[i].get()->*allowed)(nonce))
1523 return false; 1596 return false;
1524 } 1597 }
1525 return true; 1598 return true;
1526 } 1599 }
1600
1601 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1602 bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const String & hash)
1603 {
1604 for (size_t i = 0; i < policies.size(); ++i) {
1605 if (!(policies[i].get()->*allowed)(hash))
1606 return false;
1607 }
1608 return true;
1609 }
1610
1527 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const> 1611 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const>
1528 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus) 1612 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus)
1529 { 1613 {
1530 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) 1614 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol()))
1531 return true; 1615 return true;
1532 1616
1533 for (size_t i = 0; i < policies.size(); ++i) { 1617 for (size_t i = 0; i < policies.size(); ++i) {
1534 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) 1618 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus))
1535 return false; 1619 return false;
1536 } 1620 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const 1674 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const
1591 { 1675 {
1592 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce); 1676 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce);
1593 } 1677 }
1594 1678
1595 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const 1679 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const
1596 { 1680 {
1597 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce); 1681 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce);
1598 } 1682 }
1599 1683
1684 bool ContentSecurityPolicy::allowScriptHash(const String& source) const
1685 {
1686 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("sha1-"));
Mike West 2013/10/16 14:53:02 If you're using this string in two places, extract
jww 2013/10/16 21:49:21 Done.
1687 DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("sha256-"));
1688
1689 // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we
1690 // have that, we should implement a proper check for sha256 hash values here .
1691 SHA1 sourceSha1;
1692 sourceSha1.addBytes(source.utf8());
1693 String sha1Hash(sourceSha1.computeHexDigest().data());
1694
1695 String lowerHash = sha1Hash.lower();
1696 String hash = sha1Prefix + base64Encode(lowerHash.utf8());
1697 return isAllowedByAllWithHash<&CSPDirectiveList::allowScriptHash>(m_policies , hash);
Mike West 2013/10/16 14:53:02 Ah, I see. You're storing the whole string. I thi
jww 2013/10/16 21:49:21 Good idea. What about just storing some bits that
1698 }
1699
1700 bool ContentSecurityPolicy::allowStyleHash(const String& hash) const
1701 {
1702 return isAllowedByAllWithHash<&CSPDirectiveList::allowStyleHash>(m_policies, hash);
1703 }
1704
1600 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const 1705 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const
1601 { 1706 {
1602 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); 1707 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus);
1603 } 1708 }
1604 1709
1605 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const 1710 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const
1606 { 1711 {
1607 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); 1712 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus);
1608 } 1713 }
1609 1714
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
1850 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; 1955 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring;
1851 logToConsole(message); 1956 logToConsole(message);
1852 } 1957 }
1853 1958
1854 void ContentSecurityPolicy::reportInvalidNonce(const String& nonce) const 1959 void ContentSecurityPolicy::reportInvalidNonce(const String& nonce) const
1855 { 1960 {
1856 String message = "Ignoring invalid Content Security Policy script nonce: '" + nonce + "'.\n"; 1961 String message = "Ignoring invalid Content Security Policy script nonce: '" + nonce + "'.\n";
1857 logToConsole(message); 1962 logToConsole(message);
1858 } 1963 }
1859 1964
1965 void ContentSecurityPolicy::reportInvalidHash(const String& hash) const
1966 {
1967 String message = "Ignoring invalid Content Security Policy script hash: '" + hash + "'.\n";
Mike West 2013/10/16 14:53:02 I'd suggest changing both this and reportInvalidNo
jww 2013/10/16 21:49:21 Hmmm, not that you point this out, I believe this
1968 logToConsole(message);
1969 }
1970
1860 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const 1971 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const
1861 { 1972 {
1862 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored."; 1973 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored.";
1863 if (equalIgnoringCase(source, "'none'")) 1974 if (equalIgnoringCase(source, "'none'"))
1864 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; 1975 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list.";
1865 logToConsole(message); 1976 logToConsole(message);
1866 } 1977 }
1867 1978
1868 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const 1979 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const
1869 { 1980 {
(...skipping 30 matching lines...) Expand all
1900 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. 2011 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report.
1901 return !m_violationReportsSent.contains(report.impl()->hash()); 2012 return !m_violationReportsSent.contains(report.impl()->hash());
1902 } 2013 }
1903 2014
1904 void ContentSecurityPolicy::didSendViolationReport(const String& report) 2015 void ContentSecurityPolicy::didSendViolationReport(const String& report)
1905 { 2016 {
1906 m_violationReportsSent.add(report.impl()->hash()); 2017 m_violationReportsSent.add(report.impl()->hash());
1907 } 2018 }
1908 2019
1909 } // namespace WebCore 2020 } // namespace WebCore
OLDNEW
« Source/core/frame/ContentSecurityPolicy.h ('K') | « Source/core/frame/ContentSecurityPolicy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698