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

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: More fixes from mkwst comments 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 26 matching lines...) Expand all
37 #include "core/inspector/ScriptCallStack.h" 37 #include "core/inspector/ScriptCallStack.h"
38 #include "core/loader/DocumentLoader.h" 38 #include "core/loader/DocumentLoader.h"
39 #include "core/loader/PingLoader.h" 39 #include "core/loader/PingLoader.h"
40 #include "core/frame/ContentSecurityPolicyResponseHeaders.h" 40 #include "core/frame/ContentSecurityPolicyResponseHeaders.h"
41 #include "core/frame/Frame.h" 41 #include "core/frame/Frame.h"
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 "platform/NotImplemented.h"
47 #include "weborigin/KURL.h" 48 #include "weborigin/KURL.h"
48 #include "weborigin/KnownPorts.h" 49 #include "weborigin/KnownPorts.h"
49 #include "weborigin/SchemeRegistry.h" 50 #include "weborigin/SchemeRegistry.h"
50 #include "weborigin/SecurityOrigin.h" 51 #include "weborigin/SecurityOrigin.h"
51 #include "wtf/HashSet.h" 52 #include "wtf/HashSet.h"
53 #include "wtf/SHA1.h"
54 #include "wtf/text/Base64.h"
55 #include "wtf/text/StringBuilder.h"
52 #include "wtf/text/TextPosition.h" 56 #include "wtf/text/TextPosition.h"
53 #include "wtf/text/WTFString.h" 57 #include "wtf/text/WTFString.h"
54 58
55 namespace WebCore { 59 namespace WebCore {
56 60
57 // Normally WebKit uses "static" for internal linkage, but using "static" for 61 // Normally WebKit uses "static" for internal linkage, but using "static" for
58 // these functions causes a compile error because these functions are used as 62 // these functions causes a compile error because these functions are used as
59 // template parameters. 63 // template parameters.
60 namespace { 64 namespace {
61 65
62 bool isDirectiveNameCharacter(UChar c) 66 bool isDirectiveNameCharacter(UChar c)
63 { 67 {
64 return isASCIIAlphanumeric(c) || c == '-'; 68 return isASCIIAlphanumeric(c) || c == '-';
65 } 69 }
66 70
67 bool isDirectiveValueCharacter(UChar c) 71 bool isDirectiveValueCharacter(UChar c)
68 { 72 {
69 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR 73 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR
70 } 74 }
71 75
72 bool isNonceCharacter(UChar c) 76 // Only checks for general Base64 encoded chars, not '=' chars since '=' is
77 // positional and may only appear at the end of a Base64 encoded string.
78 bool isBase64EncodedCharacter(UChar c)
73 { 79 {
74 return isASCIIAlphanumeric(c) || c == '+' || c == '/'; 80 return isASCIIAlphanumeric(c) || c == '+' || c == '/';
75 } 81 }
76 82
77 bool isSourceCharacter(UChar c) 83 bool isSourceCharacter(UChar c)
78 { 84 {
79 return !isASCIISpace(c); 85 return !isASCIISpace(c);
80 } 86 }
81 87
82 bool isPathComponentCharacter(UChar c) 88 bool isPathComponentCharacter(UChar c)
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 class CSPSourceList { 278 class CSPSourceList {
273 public: 279 public:
274 CSPSourceList(ContentSecurityPolicy*, const String& directiveName); 280 CSPSourceList(ContentSecurityPolicy*, const String& directiveName);
275 281
276 void parse(const UChar* begin, const UChar* end); 282 void parse(const UChar* begin, const UChar* end);
277 283
278 bool matches(const KURL&); 284 bool matches(const KURL&);
279 bool allowInline() const { return m_allowInline; } 285 bool allowInline() const { return m_allowInline; }
280 bool allowEval() const { return m_allowEval; } 286 bool allowEval() const { return m_allowEval; }
281 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); } 287 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); }
288 bool allowHash(const String& hash) const { return !hash.isNull() && m_hashes .contains(hash); }
289 uint8_t getHashFunctionsUsed() const { return m_hashFunctionsUsed; }
abarth-chromium 2013/10/22 17:46:49 getHashFunctionsUsed -> hashFunctionsUsed (The "g
jww 2013/10/28 19:36:23 Done.
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, ContentSe curityPolicy::HashFunctions&);
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, const ContentSecurityPolicy::HashFunc tions&);
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;
315 uint8_t m_hashFunctionsUsed;
abarth-chromium 2013/10/22 17:46:49 Don't we need to keep track of which hash function
jww 2013/10/28 19:36:23 Fixed by other changes.
304 }; 316 };
305 317
306 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) 318 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName)
307 : m_policy(policy) 319 : m_policy(policy)
308 , m_directiveName(directiveName) 320 , m_directiveName(directiveName)
309 , m_allowStar(false) 321 , m_allowStar(false)
310 , m_allowInline(false) 322 , m_allowInline(false)
311 , m_allowEval(false) 323 , m_allowEval(false)
324 , m_hashFunctionsUsed(0)
312 { 325 {
313 } 326 }
314 327
315 bool CSPSourceList::matches(const KURL& url) 328 bool CSPSourceList::matches(const KURL& url)
316 { 329 {
317 if (m_allowStar) 330 if (m_allowStar)
318 return true; 331 return true;
319 332
320 KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin: :extractInnerURL(url) : url; 333 KURL effectiveURL = SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin: :extractInnerURL(url) : url;
321 334
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 415
403 if (m_policy->experimentalFeaturesEnabled()) { 416 if (m_policy->experimentalFeaturesEnabled()) {
404 String nonce; 417 String nonce;
405 if (!parseNonce(begin, end, nonce)) 418 if (!parseNonce(begin, end, nonce))
406 return false; 419 return false;
407 420
408 if (!nonce.isNull()) { 421 if (!nonce.isNull()) {
409 addSourceNonce(nonce); 422 addSourceNonce(nonce);
410 return true; 423 return true;
411 } 424 }
425
426 String hash;
427 ContentSecurityPolicy::HashFunctions hashFunction = ContentSecurityPolic y::HashFunctionsNone;
428 if (!parseHash(begin, end, hash, hashFunction))
429 return false;
430
431 if (!hash.isNull()) {
432 addSourceHash(hash, hashFunction);
433 return true;
434 }
412 } 435 }
413 436
414 const UChar* position = begin; 437 const UChar* position = begin;
415 const UChar* beginHost = begin; 438 const UChar* beginHost = begin;
416 const UChar* beginPath = end; 439 const UChar* beginPath = end;
417 const UChar* beginPort = 0; 440 const UChar* beginPort = 0;
418 441
419 skipWhile<UChar, isNotColonOrSlash>(position, end); 442 skipWhile<UChar, isNotColonOrSlash>(position, end);
420 443
421 if (position == end) { 444 if (position == end) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce) 514 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce)
492 { 515 {
493 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); 516 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-"));
494 517
495 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( ))) 518 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( )))
496 return true; 519 return true;
497 520
498 const UChar* position = begin + noncePrefix.length(); 521 const UChar* position = begin + noncePrefix.length();
499 const UChar* nonceBegin = position; 522 const UChar* nonceBegin = position;
500 523
501 skipWhile<UChar, isNonceCharacter>(position, end); 524 skipWhile<UChar, isBase64EncodedCharacter>(position, end);
502 ASSERT(nonceBegin <= position); 525 ASSERT(nonceBegin <= position);
503 526
504 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin )) 527 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin ))
505 return false; 528 return false;
506 529
507 nonce = String(nonceBegin, position - nonceBegin); 530 nonce = String(nonceBegin, position - nonceBegin);
508 return true; 531 return true;
509 } 532 }
510 533
534 // hash-source = "'" hash-algorithm "-" hash-value "'"
535 // hash-algorithm = "sha1" / "sha256"
536 // hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" )
537 //
538 bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, String& hash , ContentSecurityPolicy::HashFunctions& hashFunction)
539 {
540 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("'sha1-"));
541 DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("'sha256-"));
542
543 String prefix;
544 if (equalIgnoringCase(sha1Prefix.characters8(), begin, sha1Prefix.length())) {
545 prefix = sha1Prefix;
546 hashFunction = ContentSecurityPolicy::HashFunctionsSha1;
547 } else if (equalIgnoringCase(sha256Prefix.characters8(), begin, sha256Prefix .length())) {
548 notImplemented();
549 } else {
550 return true;
551 }
552
553 const UChar* position = begin + prefix.length();
554 const UChar* hashBegin = position;
555
556 skipWhile<UChar, isBase64EncodedCharacter>(position, end);
557 ASSERT(hashBegin <= position);
558
559 // Base64 encodings may end with exactly one or two '=' characters
560 skipExactly<UChar>(position, position + 1, '=');
561 skipExactly<UChar>(position, position + 1, '=');
562
563 if (((position + 1) != end && *position != '\'') || !(position - hashBegin) )
564 return false;
abarth-chromium 2013/10/22 17:46:49 Is this logic right? I would have expected: if (
jww 2013/10/28 19:36:23 Done.
565
566 hash = String(begin + 1, position - begin - 1);
abarth-chromium 2013/10/22 17:46:49 Why begin + 1 rather than hashBegin? I would have
jww 2013/10/28 19:36:23 Hashes are now stored as a struct that contain the
567 return true;
568 }
569
511 // ; <scheme> production from RFC 3986 570 // ; <scheme> production from RFC 3986
512 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) 571 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
513 // 572 //
514 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme) 573 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme)
515 { 574 {
516 ASSERT(begin <= end); 575 ASSERT(begin <= end);
517 ASSERT(scheme.isEmpty()); 576 ASSERT(scheme.isEmpty());
518 577
519 if (begin == end) 578 if (begin == end)
520 return false; 579 return false;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 void CSPSourceList::addSourceUnsafeEval() 702 void CSPSourceList::addSourceUnsafeEval()
644 { 703 {
645 m_allowEval = true; 704 m_allowEval = true;
646 } 705 }
647 706
648 void CSPSourceList::addSourceNonce(const String& nonce) 707 void CSPSourceList::addSourceNonce(const String& nonce)
649 { 708 {
650 m_nonces.add(nonce); 709 m_nonces.add(nonce);
651 } 710 }
652 711
712 void CSPSourceList::addSourceHash(const String& hash, const ContentSecurityPolic y::HashFunctions& hashFunction)
713 {
714 m_hashes.add(hash);
715 m_hashFunctionsUsed |= hashFunction;
716 }
717
653 class CSPDirective { 718 class CSPDirective {
654 public: 719 public:
655 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) 720 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy)
656 : m_name(name) 721 : m_name(name)
657 , m_text(name + ' ' + value) 722 , m_text(name + ' ' + value)
658 , m_policy(policy) 723 , m_policy(policy)
659 { 724 {
660 } 725 }
661 726
662 const String& text() const { return m_text; } 727 const String& text() const { return m_text; }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 } 824 }
760 825
761 bool allows(const KURL& url) 826 bool allows(const KURL& url)
762 { 827 {
763 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); 828 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url);
764 } 829 }
765 830
766 bool allowInline() const { return m_sourceList.allowInline(); } 831 bool allowInline() const { return m_sourceList.allowInline(); }
767 bool allowEval() const { return m_sourceList.allowEval(); } 832 bool allowEval() const { return m_sourceList.allowEval(); }
768 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); } 833 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); }
834 bool allowHash(const String& hash) const { return m_sourceList.allowHash(has h); }
835
836 uint8_t getHashFunctionsUsed() const { return m_sourceList.getHashFunctionsU sed(); }
769 837
770 private: 838 private:
771 CSPSourceList m_sourceList; 839 CSPSourceList m_sourceList;
772 }; 840 };
773 841
774 class CSPDirectiveList { 842 class CSPDirectiveList {
775 WTF_MAKE_FAST_ALLOCATED; 843 WTF_MAKE_FAST_ALLOCATED;
776 public: 844 public:
777 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); 845 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType);
778 846
(...skipping 14 matching lines...) Expand all
793 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; 861 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const;
794 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 862 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
795 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 863 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
796 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; 864 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const;
797 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 865 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
798 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 866 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
799 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; 867 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst;
800 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; 868 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ;
801 bool allowScriptNonce(const String&) const; 869 bool allowScriptNonce(const String&) const;
802 bool allowStyleNonce(const String&) const; 870 bool allowStyleNonce(const String&) const;
871 bool allowScriptHash(const String&) const;
803 872
804 void gatherReportURIs(DOMStringList&) const; 873 void gatherReportURIs(DOMStringList&) const;
805 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } 874 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; }
806 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } 875 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; }
807 bool isReportOnly() const { return m_reportOnly; } 876 bool isReportOnly() const { return m_reportOnly; }
808 const Vector<KURL>& reportURIs() const { return m_reportURIs; } 877 const Vector<KURL>& reportURIs() const { return m_reportURIs; }
809 878
810 private: 879 private:
811 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); 880 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType);
812 881
813 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); 882 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value);
814 void parseReportURI(const String& name, const String& value); 883 void parseReportURI(const String& name, const String& value);
815 void parsePluginTypes(const String& name, const String& value); 884 void parsePluginTypes(const String& name, const String& value);
816 void parseReflectedXSS(const String& name, const String& value); 885 void parseReflectedXSS(const String& name, const String& value);
817 void addDirective(const String& name, const String& value); 886 void addDirective(const String& name, const String& value);
818 void applySandboxPolicy(const String& name, const String& sandboxPolicy); 887 void applySandboxPolicy(const String& name, const String& sandboxPolicy);
819 888
820 template <class CSPDirectiveType> 889 template <class CSPDirectiveType>
821 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); 890 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&);
822 891
823 SourceListDirective* operativeDirective(SourceListDirective*) const; 892 SourceListDirective* operativeDirective(SourceListDirective*) const;
824 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const; 893 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; 894 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; 895 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const;
827 896
828 bool checkEval(SourceListDirective*) const; 897 bool checkEval(SourceListDirective*) const;
829 bool checkInline(SourceListDirective*) const; 898 bool checkInline(SourceListDirective*) const;
830 bool checkNonce(SourceListDirective*, const String&) const; 899 bool checkNonce(SourceListDirective*, const String&) const;
900 bool checkHash(SourceListDirective*, const String&) const;
831 bool checkSource(SourceListDirective*, const KURL&) const; 901 bool checkSource(SourceListDirective*, const KURL&) const;
832 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; 902 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const;
833 903
834 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } 904 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; }
835 905
836 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const; 906 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; 907 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
838 908
839 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; 909 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const;
840 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const; 910 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 993 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
924 { 994 {
925 return !directive || directive->allowInline(); 995 return !directive || directive->allowInline();
926 } 996 }
927 997
928 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const 998 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
929 { 999 {
930 return !directive || directive->allowNonce(nonce); 1000 return !directive || directive->allowNonce(nonce);
931 } 1001 }
932 1002
1003 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const String& h ash) const
1004 {
1005 return !directive || directive->allowHash(hash);
1006 }
1007
933 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const 1008 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const
934 { 1009 {
935 return !directive || directive->allows(url); 1010 return !directive || directive->allows(url);
936 } 1011 }
937 1012
938 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const 1013 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const
939 { 1014 {
940 if (!directive) 1015 if (!directive)
941 return true; 1016 return true;
942 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) 1017 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 1243 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
1169 { 1244 {
1170 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); 1245 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
1171 } 1246 }
1172 1247
1173 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const 1248 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
1174 { 1249 {
1175 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); 1250 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
1176 } 1251 }
1177 1252
1253 bool CSPDirectiveList::allowScriptHash(const String& hash) const
1254 {
1255 return checkHash(operativeDirective(m_scriptSrc.get()), hash);
1256 }
1257
1178 // policy = directive-list 1258 // policy = directive-list
1179 // directive-list = [ directive *( ";" [ directive ] ) ] 1259 // directive-list = [ directive *( ";" [ directive ] ) ]
1180 // 1260 //
1181 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) 1261 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
1182 { 1262 {
1183 m_header = String(begin, end - begin); 1263 m_header = String(begin, end - begin);
1184 1264
1185 if (begin == end) 1265 if (begin == end)
1186 return; 1266 return;
1187 1267
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 // value1 value2 1431 // value1 value2
1352 // ^ 1432 // ^
1353 m_reflectedXSSDisposition = ReflectedXSSInvalid; 1433 m_reflectedXSSDisposition = ReflectedXSSInvalid;
1354 m_policy->reportInvalidReflectedXSS(value); 1434 m_policy->reportInvalidReflectedXSS(value);
1355 } 1435 }
1356 1436
1357 void CSPDirectiveList::addDirective(const String& name, const String& value) 1437 void CSPDirectiveList::addDirective(const String& name, const String& value)
1358 { 1438 {
1359 ASSERT(!name.isEmpty()); 1439 ASSERT(!name.isEmpty());
1360 1440
1361 if (equalIgnoringCase(name, defaultSrc)) 1441 if (equalIgnoringCase(name, defaultSrc)) {
1362 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); 1442 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc);
1363 else if (equalIgnoringCase(name, scriptSrc)) 1443 } else if (equalIgnoringCase(name, scriptSrc)) {
1364 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); 1444 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc);
1365 else if (equalIgnoringCase(name, objectSrc)) 1445 m_policy->usesScriptHashFunctions(m_scriptSrc->getHashFunctionsUsed());
1446 } else if (equalIgnoringCase(name, objectSrc)) {
1366 setCSPDirective<SourceListDirective>(name, value, m_objectSrc); 1447 setCSPDirective<SourceListDirective>(name, value, m_objectSrc);
1367 else if (equalIgnoringCase(name, frameSrc)) 1448 } else if (equalIgnoringCase(name, frameSrc)) {
1368 setCSPDirective<SourceListDirective>(name, value, m_frameSrc); 1449 setCSPDirective<SourceListDirective>(name, value, m_frameSrc);
1369 else if (equalIgnoringCase(name, imgSrc)) 1450 } else if (equalIgnoringCase(name, imgSrc)) {
1370 setCSPDirective<SourceListDirective>(name, value, m_imgSrc); 1451 setCSPDirective<SourceListDirective>(name, value, m_imgSrc);
1371 else if (equalIgnoringCase(name, styleSrc)) 1452 } else if (equalIgnoringCase(name, styleSrc)) {
1372 setCSPDirective<SourceListDirective>(name, value, m_styleSrc); 1453 setCSPDirective<SourceListDirective>(name, value, m_styleSrc);
1373 else if (equalIgnoringCase(name, fontSrc)) 1454 } else if (equalIgnoringCase(name, fontSrc)) {
1374 setCSPDirective<SourceListDirective>(name, value, m_fontSrc); 1455 setCSPDirective<SourceListDirective>(name, value, m_fontSrc);
1375 else if (equalIgnoringCase(name, mediaSrc)) 1456 } else if (equalIgnoringCase(name, mediaSrc)) {
1376 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc); 1457 setCSPDirective<SourceListDirective>(name, value, m_mediaSrc);
1377 else if (equalIgnoringCase(name, connectSrc)) 1458 } else if (equalIgnoringCase(name, connectSrc)) {
1378 setCSPDirective<SourceListDirective>(name, value, m_connectSrc); 1459 setCSPDirective<SourceListDirective>(name, value, m_connectSrc);
1379 else if (equalIgnoringCase(name, sandbox)) 1460 } else if (equalIgnoringCase(name, sandbox)) {
1380 applySandboxPolicy(name, value); 1461 applySandboxPolicy(name, value);
1381 else if (equalIgnoringCase(name, reportURI)) 1462 } else if (equalIgnoringCase(name, reportURI)) {
1382 parseReportURI(name, value); 1463 parseReportURI(name, value);
1383 else if (m_policy->experimentalFeaturesEnabled()) { 1464 } else if (m_policy->experimentalFeaturesEnabled()) {
1384 if (equalIgnoringCase(name, baseURI)) 1465 if (equalIgnoringCase(name, baseURI))
1385 setCSPDirective<SourceListDirective>(name, value, m_baseURI); 1466 setCSPDirective<SourceListDirective>(name, value, m_baseURI);
1386 else if (equalIgnoringCase(name, formAction)) 1467 else if (equalIgnoringCase(name, formAction))
1387 setCSPDirective<SourceListDirective>(name, value, m_formAction); 1468 setCSPDirective<SourceListDirective>(name, value, m_formAction);
1388 else if (equalIgnoringCase(name, pluginTypes)) 1469 else if (equalIgnoringCase(name, pluginTypes))
1389 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); 1470 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes);
1390 else if (equalIgnoringCase(name, reflectedXSS)) 1471 else if (equalIgnoringCase(name, reflectedXSS))
1391 parseReflectedXSS(name, value); 1472 parseReflectedXSS(name, value);
1392 else 1473 else
1393 m_policy->reportUnsupportedDirective(name); 1474 m_policy->reportUnsupportedDirective(name);
1475 } else {
1476 m_policy->reportUnsupportedDirective(name);
1394 } 1477 }
1395 else
1396 m_policy->reportUnsupportedDirective(name);
1397 } 1478 }
1398 1479
1399 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext) 1480 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext)
1400 : m_executionContext(executionContext) 1481 : m_executionContext(executionContext)
1401 , m_overrideInlineStyleAllowed(false) 1482 , m_overrideInlineStyleAllowed(false)
1483 , m_sourceHashFunctionsUsed(HashFunctionsNone)
1402 { 1484 {
1403 } 1485 }
1404 1486
1405 ContentSecurityPolicy::~ContentSecurityPolicy() 1487 ContentSecurityPolicy::~ContentSecurityPolicy()
1406 { 1488 {
1407 } 1489 }
1408 1490
1409 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) 1491 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other)
1410 { 1492 {
1411 ASSERT(m_policies.isEmpty()); 1493 ASSERT(m_policies.isEmpty());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1599
1518 template<bool (CSPDirectiveList::*allowed)(const String&) const> 1600 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1519 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce) 1601 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce)
1520 { 1602 {
1521 for (size_t i = 0; i < policies.size(); ++i) { 1603 for (size_t i = 0; i < policies.size(); ++i) {
1522 if (!(policies[i].get()->*allowed)(nonce)) 1604 if (!(policies[i].get()->*allowed)(nonce))
1523 return false; 1605 return false;
1524 } 1606 }
1525 return true; 1607 return true;
1526 } 1608 }
1609
1610 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1611 bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const String & hash)
1612 {
1613 for (size_t i = 0; i < policies.size(); ++i) {
1614 if (!(policies[i].get()->*allowed)(hash))
1615 return false;
1616 }
1617 return true;
1618 }
1619
1527 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const> 1620 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const>
1528 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus) 1621 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus)
1529 { 1622 {
1530 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) 1623 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol()))
1531 return true; 1624 return true;
1532 1625
1533 for (size_t i = 0; i < policies.size(); ++i) { 1626 for (size_t i = 0; i < policies.size(); ++i) {
1534 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) 1627 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus))
1535 return false; 1628 return false;
1536 } 1629 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const 1683 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const
1591 { 1684 {
1592 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce); 1685 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce);
1593 } 1686 }
1594 1687
1595 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const 1688 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const
1596 { 1689 {
1597 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce); 1690 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce);
1598 } 1691 }
1599 1692
1693 bool ContentSecurityPolicy::allowScriptHash(const String& source) const
1694 {
1695 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("sha1-"));
1696
1697 // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we
1698 // have that, we should implement a proper check for sha256 hash values here .
1699 if (HashFunctionsSha1 & m_sourceHashFunctionsUsed) {
1700 SHA1 sourceSha1;
1701 sourceSha1.addBytes(UTF8Encoding().normalizeAndEncode(source, WTF::Entit iesForUnencodables));
1702 Vector<uint8_t, 20> digest;
1703 sourceSha1.computeHash(digest);
1704
1705 StringBuilder hash;
1706 hash.reserveCapacity(sha1Prefix.length() + digest.size());
1707 hash.append(sha1Prefix);
1708 hash.append(base64Encode(reinterpret_cast<char*>(digest.data()), digest. size()));
abarth-chromium 2013/10/22 17:46:49 What about the trailing = characters? Do we need
jww 2013/10/28 19:36:23 Addressed by other changes (now storing the hash a
1709 if (isAllowedByAllWithHash<&CSPDirectiveList::allowScriptHash>(m_policie s, hash.toString()))
1710 return true;
1711 }
1712
1713 return false;
1714 }
1715
1716 void ContentSecurityPolicy::usesScriptHashFunctions(uint8_t hashFunctions)
1717 {
1718 m_sourceHashFunctionsUsed |= hashFunctions;
1719 }
1720
1600 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const 1721 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const
1601 { 1722 {
1602 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); 1723 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus);
1603 } 1724 }
1604 1725
1605 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const 1726 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const
1606 { 1727 {
1607 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); 1728 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus);
1608 } 1729 }
1609 1730
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 { 1965 {
1845 ASSERT(invalidChar == '#' || invalidChar == '?'); 1966 ASSERT(invalidChar == '#' || invalidChar == '?');
1846 1967
1847 String ignoring = "The fragment identifier, including the '#', will be ignor ed."; 1968 String ignoring = "The fragment identifier, including the '#', will be ignor ed.";
1848 if (invalidChar == '?') 1969 if (invalidChar == '?')
1849 ignoring = "The query component, including the '?', will be ignored."; 1970 ignoring = "The query component, including the '?', will be ignored.";
1850 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; 1971 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring;
1851 logToConsole(message); 1972 logToConsole(message);
1852 } 1973 }
1853 1974
1854 void ContentSecurityPolicy::reportInvalidNonce(const String& nonce) const
1855 {
1856 String message = "Ignoring invalid Content Security Policy script nonce: '" + nonce + "'.\n";
1857 logToConsole(message);
1858 }
1859
1860 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const 1975 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const
1861 { 1976 {
1862 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored."; 1977 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'")) 1978 if (equalIgnoringCase(source, "'none'"))
1864 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; 1979 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list.";
1865 logToConsole(message); 1980 logToConsole(message);
1866 } 1981 }
1867 1982
1868 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const 1983 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const
1869 { 1984 {
(...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. 2015 // 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()); 2016 return !m_violationReportsSent.contains(report.impl()->hash());
1902 } 2017 }
1903 2018
1904 void ContentSecurityPolicy::didSendViolationReport(const String& report) 2019 void ContentSecurityPolicy::didSendViolationReport(const String& report)
1905 { 2020 {
1906 m_violationReportsSent.add(report.impl()->hash()); 2021 m_violationReportsSent.add(report.impl()->hash());
1907 } 2022 }
1908 2023
1909 } // namespace WebCore 2024 } // 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