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

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: Fixed abarth's comments, added tests, and added short circuit for unused hashes. 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); }
282 289
283 private: 290 private:
284 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard); 291 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); 292 bool parseScheme(const UChar* begin, const UChar* end, String& scheme);
286 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard); 293 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); 294 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard);
288 bool parsePath(const UChar* begin, const UChar* end, String& path); 295 bool parsePath(const UChar* begin, const UChar* end, String& path);
289 bool parseNonce(const UChar* begin, const UChar* end, String& nonce); 296 bool parseNonce(const UChar* begin, const UChar* end, String& nonce);
297 bool parseHash(const UChar* begin, const UChar* end, String& hash, ContentSe curityPolicy::HashFunctions&);
290 298
291 void addSourceSelf(); 299 void addSourceSelf();
292 void addSourceStar(); 300 void addSourceStar();
293 void addSourceUnsafeInline(); 301 void addSourceUnsafeInline();
294 void addSourceUnsafeEval(); 302 void addSourceUnsafeEval();
295 void addSourceNonce(const String& nonce); 303 void addSourceNonce(const String& nonce);
304 void addSourceScriptHash(const String& hash, const ContentSecurityPolicy::Ha shFunctions&);
296 305
297 ContentSecurityPolicy* m_policy; 306 ContentSecurityPolicy* m_policy;
298 Vector<CSPSource> m_list; 307 Vector<CSPSource> m_list;
299 String m_directiveName; 308 String m_directiveName;
300 bool m_allowStar; 309 bool m_allowStar;
301 bool m_allowInline; 310 bool m_allowInline;
302 bool m_allowEval; 311 bool m_allowEval;
303 HashSet<String> m_nonces; 312 HashSet<String> m_nonces;
313 HashSet<String> m_hashes;
Mike West 2013/10/21 07:11:55 I don't think we need two sets of hashes here (tho
jww 2013/10/21 19:18:04 My only objection is that, in theory, there are va
Mike West 2013/10/21 19:28:48 You'd have a policy like `script-src '<hash goes h
304 }; 314 };
305 315
306 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) 316 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName)
307 : m_policy(policy) 317 : m_policy(policy)
308 , m_directiveName(directiveName) 318 , m_directiveName(directiveName)
309 , m_allowStar(false) 319 , m_allowStar(false)
310 , m_allowInline(false) 320 , m_allowInline(false)
311 , m_allowEval(false) 321 , m_allowEval(false)
312 { 322 {
313 } 323 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 412
403 if (m_policy->experimentalFeaturesEnabled()) { 413 if (m_policy->experimentalFeaturesEnabled()) {
404 String nonce; 414 String nonce;
405 if (!parseNonce(begin, end, nonce)) 415 if (!parseNonce(begin, end, nonce))
406 return false; 416 return false;
407 417
408 if (!nonce.isNull()) { 418 if (!nonce.isNull()) {
409 addSourceNonce(nonce); 419 addSourceNonce(nonce);
410 return true; 420 return true;
411 } 421 }
422
423 String hash;
424 ContentSecurityPolicy::HashFunctions hashFunction = ContentSecurityPolic y::HashFunctionsNone;
425 if (!parseHash(begin, end, hash, hashFunction))
426 return false;
427
428 if (!hash.isNull()) {
429 addSourceScriptHash(hash, hashFunction);
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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce) 511 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce)
492 { 512 {
493 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); 513 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-"));
494 514
495 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( ))) 515 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( )))
496 return true; 516 return true;
497 517
498 const UChar* position = begin + noncePrefix.length(); 518 const UChar* position = begin + noncePrefix.length();
499 const UChar* nonceBegin = position; 519 const UChar* nonceBegin = position;
500 520
501 skipWhile<UChar, isNonceCharacter>(position, end); 521 skipWhile<UChar, isBase64EncodedCharacter>(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 / "+" / "/" / "=" )
Mike West 2013/10/21 07:11:55 Spec: If we want to be explicit about this being b
534 //
535 bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, String& hash , ContentSecurityPolicy::HashFunctions& hashFunction)
536 {
537 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("'sha1-"));
538 DEFINE_STATIC_LOCAL(const String, sha256Prefix, ("'sha256-"));
539
540 String prefix;
541 if (equalIgnoringCase(sha1Prefix.characters8(), begin, sha1Prefix.length())) {
542 prefix = sha1Prefix;
543 hashFunction = ContentSecurityPolicy::HashFunctionsSha1;
544 } else if (equalIgnoringCase(sha256Prefix.characters8(), begin, sha256Prefix .length())) {
545 notImplemented();
546 } else {
547 return true;
548 }
549
550 const UChar* position = begin + prefix.length();
551 const UChar* hashBegin = position;
552
553 skipWhile<UChar, isBase64EncodedCharacter>(position, end);
554 ASSERT(hashBegin <= position);
555
556 // Base64 encodings may end with exactly one or two '=' characters
Mike West 2013/10/21 07:11:55 Might be clearer if you "skipExactly" twice (ignor
jww 2013/10/21 19:18:04 Done.
557 for (size_t i = 0; i < 2 && position != end; i++) {
558 if (*position != '=')
559 break;
560 position = position + 1;
561 }
562
563 if (((position + 1) != end && *position != '\'') || !(position - hashBegin) )
564 return false;
565
566 hash = String(begin + 1, position - begin - 1);
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::addSourceScriptHash(const String& hash, const ContentSecurit yPolicy::HashFunctions& hashFunction)
713 {
714 m_hashes.add(hash);
715 m_policy->usesScriptHashFunction(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); }
769 835
770 private: 836 private:
771 CSPSourceList m_sourceList; 837 CSPSourceList m_sourceList;
772 }; 838 };
773 839
774 class CSPDirectiveList { 840 class CSPDirectiveList {
775 WTF_MAKE_FAST_ALLOCATED; 841 WTF_MAKE_FAST_ALLOCATED;
776 public: 842 public:
777 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); 843 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType);
778 844
(...skipping 14 matching lines...) Expand all
793 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; 859 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const;
794 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 860 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
795 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 861 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
796 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; 862 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const;
797 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 863 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
798 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; 864 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const;
799 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; 865 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst;
800 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; 866 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ;
801 bool allowScriptNonce(const String&) const; 867 bool allowScriptNonce(const String&) const;
802 bool allowStyleNonce(const String&) const; 868 bool allowStyleNonce(const String&) const;
869 bool allowScriptHash(const String&) const;
803 870
804 void gatherReportURIs(DOMStringList&) const; 871 void gatherReportURIs(DOMStringList&) const;
805 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } 872 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; }
806 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } 873 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; }
807 bool isReportOnly() const { return m_reportOnly; } 874 bool isReportOnly() const { return m_reportOnly; }
808 const Vector<KURL>& reportURIs() const { return m_reportURIs; } 875 const Vector<KURL>& reportURIs() const { return m_reportURIs; }
809 876
810 private: 877 private:
811 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); 878 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType);
812 879
813 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); 880 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value);
814 void parseReportURI(const String& name, const String& value); 881 void parseReportURI(const String& name, const String& value);
815 void parsePluginTypes(const String& name, const String& value); 882 void parsePluginTypes(const String& name, const String& value);
816 void parseReflectedXSS(const String& name, const String& value); 883 void parseReflectedXSS(const String& name, const String& value);
817 void addDirective(const String& name, const String& value); 884 void addDirective(const String& name, const String& value);
818 void applySandboxPolicy(const String& name, const String& sandboxPolicy); 885 void applySandboxPolicy(const String& name, const String& sandboxPolicy);
819 886
820 template <class CSPDirectiveType> 887 template <class CSPDirectiveType>
821 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); 888 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&);
822 889
823 SourceListDirective* operativeDirective(SourceListDirective*) const; 890 SourceListDirective* operativeDirective(SourceListDirective*) const;
824 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const; 891 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; 892 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; 893 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const;
827 894
828 bool checkEval(SourceListDirective*) const; 895 bool checkEval(SourceListDirective*) const;
829 bool checkInline(SourceListDirective*) const; 896 bool checkInline(SourceListDirective*) const;
830 bool checkNonce(SourceListDirective*, const String&) const; 897 bool checkNonce(SourceListDirective*, const String&) const;
898 bool checkHash(SourceListDirective*, const String&) const;
831 bool checkSource(SourceListDirective*, const KURL&) const; 899 bool checkSource(SourceListDirective*, const KURL&) const;
832 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; 900 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const;
833 901
834 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } 902 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; }
835 903
836 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const; 904 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; 905 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const;
838 906
839 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; 907 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const;
840 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const; 908 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 991 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const
924 { 992 {
925 return !directive || directive->allowInline(); 993 return !directive || directive->allowInline();
926 } 994 }
927 995
928 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const 996 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const
929 { 997 {
930 return !directive || directive->allowNonce(nonce); 998 return !directive || directive->allowNonce(nonce);
931 } 999 }
932 1000
1001 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const String& h ash) const
1002 {
1003 return !directive || directive->allowHash(hash);
1004 }
1005
933 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const 1006 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const
934 { 1007 {
935 return !directive || directive->allows(url); 1008 return !directive || directive->allows(url);
936 } 1009 }
937 1010
938 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const 1011 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const
939 { 1012 {
940 if (!directive) 1013 if (!directive)
941 return true; 1014 return true;
942 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) 1015 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 1241 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const
1169 { 1242 {
1170 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); 1243 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce);
1171 } 1244 }
1172 1245
1173 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const 1246 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const
1174 { 1247 {
1175 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); 1248 return checkNonce(operativeDirective(m_styleSrc.get()), nonce);
1176 } 1249 }
1177 1250
1251 bool CSPDirectiveList::allowScriptHash(const String& hash) const
1252 {
1253 return checkHash(operativeDirective(m_scriptSrc.get()), hash);
1254 }
1255
1178 // policy = directive-list 1256 // policy = directive-list
1179 // directive-list = [ directive *( ";" [ directive ] ) ] 1257 // directive-list = [ directive *( ";" [ directive ] ) ]
1180 // 1258 //
1181 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) 1259 void CSPDirectiveList::parse(const UChar* begin, const UChar* end)
1182 { 1260 {
1183 m_header = String(begin, end - begin); 1261 m_header = String(begin, end - begin);
1184 1262
1185 if (begin == end) 1263 if (begin == end)
1186 return; 1264 return;
1187 1265
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1392 else 1470 else
1393 m_policy->reportUnsupportedDirective(name); 1471 m_policy->reportUnsupportedDirective(name);
1394 } 1472 }
1395 else 1473 else
1396 m_policy->reportUnsupportedDirective(name); 1474 m_policy->reportUnsupportedDirective(name);
1397 } 1475 }
1398 1476
1399 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext) 1477 ContentSecurityPolicy::ContentSecurityPolicy(ExecutionContext* executionContext)
1400 : m_executionContext(executionContext) 1478 : m_executionContext(executionContext)
1401 , m_overrideInlineStyleAllowed(false) 1479 , m_overrideInlineStyleAllowed(false)
1480 , m_sourceHashFunctionsUsed(HashFunctionsNone)
1402 { 1481 {
1403 } 1482 }
1404 1483
1405 ContentSecurityPolicy::~ContentSecurityPolicy() 1484 ContentSecurityPolicy::~ContentSecurityPolicy()
1406 { 1485 {
1407 } 1486 }
1408 1487
1409 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other) 1488 void ContentSecurityPolicy::copyStateFrom(const ContentSecurityPolicy* other)
1410 { 1489 {
1411 ASSERT(m_policies.isEmpty()); 1490 ASSERT(m_policies.isEmpty());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1517 1596
1518 template<bool (CSPDirectiveList::*allowed)(const String&) const> 1597 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1519 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce) 1598 bool isAllowedByAllWithNonce(const CSPDirectiveListVector& policies, const Strin g& nonce)
1520 { 1599 {
1521 for (size_t i = 0; i < policies.size(); ++i) { 1600 for (size_t i = 0; i < policies.size(); ++i) {
1522 if (!(policies[i].get()->*allowed)(nonce)) 1601 if (!(policies[i].get()->*allowed)(nonce))
1523 return false; 1602 return false;
1524 } 1603 }
1525 return true; 1604 return true;
1526 } 1605 }
1606
1607 template<bool (CSPDirectiveList::*allowed)(const String&) const>
1608 bool isAllowedByAllWithHash(const CSPDirectiveListVector& policies, const String & hash)
1609 {
1610 for (size_t i = 0; i < policies.size(); ++i) {
1611 if (!(policies[i].get()->*allowed)(hash))
1612 return false;
1613 }
1614 return true;
1615 }
1616
1527 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const> 1617 template<bool (CSPDirectiveList::*allowFromURL)(const KURL&, ContentSecurityPoli cy::ReportingStatus) const>
1528 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus) 1618 bool isAllowedByAllWithURL(const CSPDirectiveListVector& policies, const KURL& u rl, ContentSecurityPolicy::ReportingStatus reportingStatus)
1529 { 1619 {
1530 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol())) 1620 if (SchemeRegistry::schemeShouldBypassContentSecurityPolicy(url.protocol()))
1531 return true; 1621 return true;
1532 1622
1533 for (size_t i = 0; i < policies.size(); ++i) { 1623 for (size_t i = 0; i < policies.size(); ++i) {
1534 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus)) 1624 if (!(policies[i].get()->*allowFromURL)(url, reportingStatus))
1535 return false; 1625 return false;
1536 } 1626 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const 1680 bool ContentSecurityPolicy::allowScriptNonce(const String& nonce) const
1591 { 1681 {
1592 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce); 1682 return isAllowedByAllWithNonce<&CSPDirectiveList::allowScriptNonce>(m_polici es, nonce);
1593 } 1683 }
1594 1684
1595 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const 1685 bool ContentSecurityPolicy::allowStyleNonce(const String& nonce) const
1596 { 1686 {
1597 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce); 1687 return isAllowedByAllWithNonce<&CSPDirectiveList::allowStyleNonce>(m_policie s, nonce);
1598 } 1688 }
1599 1689
1690 bool ContentSecurityPolicy::allowScriptHash(const String& source) const
1691 {
1692 DEFINE_STATIC_LOCAL(const String, sha1Prefix, ("sha1-"));
1693
1694 // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we
1695 // have that, we should implement a proper check for sha256 hash values here .
1696 if (HashFunctionsSha1 & m_sourceHashFunctionsUsed) {
1697 SHA1 sourceSha1;
1698 sourceSha1.addBytes(UTF8Encoding().normalizeAndEncode(source, WTF::Entit iesForUnencodables));
Mike West 2013/10/21 07:11:55 This all looks quite sane to me, but I'd like Adam
jww 2013/10/21 19:18:04 sgtm
1699 Vector<uint8_t, 20> digest;
1700 sourceSha1.computeHash(digest);
1701
1702 StringBuilder hash;
1703 hash.reserveCapacity(sha1Prefix.length() + digest.size());
1704 hash.append(sha1Prefix);
1705 hash.append(base64Encode(reinterpret_cast<char*>(digest.data()), digest. size()));
1706 if (isAllowedByAllWithHash<&CSPDirectiveList::allowScriptHash>(m_policie s, hash.toString()))
Mike West 2013/10/21 07:11:55 Ok, this makes sense. You put the hash types on th
jww 2013/10/21 19:18:04 Done.
1707 return true;
1708 }
1709
1710 return false;
1711 }
1712
1713 void ContentSecurityPolicy::usesScriptHashFunction(HashFunctions hashFunction)
1714 {
1715 m_sourceHashFunctionsUsed |= hashFunction;
1716 }
1717
1600 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const 1718 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const
1601 { 1719 {
1602 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); 1720 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus);
1603 } 1721 }
1604 1722
1605 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const 1723 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const
1606 { 1724 {
1607 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); 1725 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus);
1608 } 1726 }
1609 1727
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 { 1962 {
1845 ASSERT(invalidChar == '#' || invalidChar == '?'); 1963 ASSERT(invalidChar == '#' || invalidChar == '?');
1846 1964
1847 String ignoring = "The fragment identifier, including the '#', will be ignor ed."; 1965 String ignoring = "The fragment identifier, including the '#', will be ignor ed.";
1848 if (invalidChar == '?') 1966 if (invalidChar == '?')
1849 ignoring = "The query component, including the '?', will be ignored."; 1967 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; 1968 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring;
1851 logToConsole(message); 1969 logToConsole(message);
1852 } 1970 }
1853 1971
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 1972 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const
1861 { 1973 {
1862 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored."; 1974 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'")) 1975 if (equalIgnoringCase(source, "'none'"))
1864 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; 1976 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list.";
1865 logToConsole(message); 1977 logToConsole(message);
1866 } 1978 }
1867 1979
1868 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const 1980 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const
1869 { 1981 {
(...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. 2012 // 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()); 2013 return !m_violationReportsSent.contains(report.impl()->hash());
1902 } 2014 }
1903 2015
1904 void ContentSecurityPolicy::didSendViolationReport(const String& report) 2016 void ContentSecurityPolicy::didSendViolationReport(const String& report)
1905 { 2017 {
1906 m_violationReportsSent.add(report.impl()->hash()); 2018 m_violationReportsSent.add(report.impl()->hash());
1907 } 2019 }
1908 2020
1909 } // namespace WebCore 2021 } // 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