OLD | NEW |
---|---|
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 Loading... | |
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" | |
54 #include "wtf/text/StringBuilder.h" | |
52 #include "wtf/text/TextPosition.h" | 55 #include "wtf/text/TextPosition.h" |
53 #include "wtf/text/WTFString.h" | 56 #include "wtf/text/WTFString.h" |
54 | 57 |
55 namespace WebCore { | 58 namespace WebCore { |
56 | 59 |
57 // Normally WebKit uses "static" for internal linkage, but using "static" for | 60 // Normally WebKit uses "static" for internal linkage, but using "static" for |
58 // these functions causes a compile error because these functions are used as | 61 // these functions causes a compile error because these functions are used as |
59 // template parameters. | 62 // template parameters. |
60 namespace { | 63 namespace { |
61 | 64 |
62 bool isDirectiveNameCharacter(UChar c) | 65 bool isDirectiveNameCharacter(UChar c) |
63 { | 66 { |
64 return isASCIIAlphanumeric(c) || c == '-'; | 67 return isASCIIAlphanumeric(c) || c == '-'; |
65 } | 68 } |
66 | 69 |
67 bool isDirectiveValueCharacter(UChar c) | 70 bool isDirectiveValueCharacter(UChar c) |
68 { | 71 { |
69 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR | 72 return isASCIISpace(c) || (c >= 0x21 && c <= 0x7e); // Whitespace + VCHAR |
70 } | 73 } |
71 | 74 |
72 bool isNonceCharacter(UChar c) | 75 // Only checks for general Base64 encoded chars, not '=' chars since '=' is |
76 // positional and may only appear at the end of a Base64 encoded string. | |
77 bool isBase64EncodedCharacter(UChar c) | |
73 { | 78 { |
74 return isASCIIAlphanumeric(c) || c == '+' || c == '/'; | 79 return isASCIIAlphanumeric(c) || c == '+' || c == '/'; |
75 } | 80 } |
76 | 81 |
77 bool isSourceCharacter(UChar c) | 82 bool isSourceCharacter(UChar c) |
78 { | 83 { |
79 return !isASCIISpace(c); | 84 return !isASCIISpace(c); |
80 } | 85 } |
81 | 86 |
82 bool isPathComponentCharacter(UChar c) | 87 bool isPathComponentCharacter(UChar c) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 static const char sandbox[] = "sandbox"; | 126 static const char sandbox[] = "sandbox"; |
122 static const char scriptSrc[] = "script-src"; | 127 static const char scriptSrc[] = "script-src"; |
123 static const char styleSrc[] = "style-src"; | 128 static const char styleSrc[] = "style-src"; |
124 | 129 |
125 // CSP 1.1 Directives | 130 // CSP 1.1 Directives |
126 static const char baseURI[] = "base-uri"; | 131 static const char baseURI[] = "base-uri"; |
127 static const char formAction[] = "form-action"; | 132 static const char formAction[] = "form-action"; |
128 static const char pluginTypes[] = "plugin-types"; | 133 static const char pluginTypes[] = "plugin-types"; |
129 static const char reflectedXSS[] = "reflected-xss"; | 134 static const char reflectedXSS[] = "reflected-xss"; |
130 | 135 |
136 // Supported script hashes and their prefix name | |
137 static const char sha1Label[] = "sha1"; | |
138 static const char sha256Label[] = "sha256"; | |
139 | |
131 bool isDirectiveName(const String& name) | 140 bool isDirectiveName(const String& name) |
132 { | 141 { |
133 return (equalIgnoringCase(name, connectSrc) | 142 return (equalIgnoringCase(name, connectSrc) |
134 || equalIgnoringCase(name, defaultSrc) | 143 || equalIgnoringCase(name, defaultSrc) |
135 || equalIgnoringCase(name, fontSrc) | 144 || equalIgnoringCase(name, fontSrc) |
136 || equalIgnoringCase(name, frameSrc) | 145 || equalIgnoringCase(name, frameSrc) |
137 || equalIgnoringCase(name, imgSrc) | 146 || equalIgnoringCase(name, imgSrc) |
138 || equalIgnoringCase(name, mediaSrc) | 147 || equalIgnoringCase(name, mediaSrc) |
139 || equalIgnoringCase(name, objectSrc) | 148 || equalIgnoringCase(name, objectSrc) |
140 || equalIgnoringCase(name, reportURI) | 149 || equalIgnoringCase(name, reportURI) |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 class CSPSourceList { | 281 class CSPSourceList { |
273 public: | 282 public: |
274 CSPSourceList(ContentSecurityPolicy*, const String& directiveName); | 283 CSPSourceList(ContentSecurityPolicy*, const String& directiveName); |
275 | 284 |
276 void parse(const UChar* begin, const UChar* end); | 285 void parse(const UChar* begin, const UChar* end); |
277 | 286 |
278 bool matches(const KURL&); | 287 bool matches(const KURL&); |
279 bool allowInline() const { return m_allowInline; } | 288 bool allowInline() const { return m_allowInline; } |
280 bool allowEval() const { return m_allowEval; } | 289 bool allowEval() const { return m_allowEval; } |
281 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); } | 290 bool allowNonce(const String& nonce) const { return !nonce.isNull() && m_non ces.contains(nonce); } |
291 bool allowHash(const String& hash) const { return !hash.isNull() && m_hashes .contains(hash); } | |
282 | 292 |
283 private: | 293 private: |
284 bool parseSource(const UChar* begin, const UChar* end, String& scheme, Strin g& host, int& port, String& path, bool& hostHasWildcard, bool& portHasWildcard); | 294 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); | 295 bool parseScheme(const UChar* begin, const UChar* end, String& scheme); |
286 bool parseHost(const UChar* begin, const UChar* end, String& host, bool& hos tHasWildcard); | 296 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); | 297 bool parsePort(const UChar* begin, const UChar* end, int& port, bool& portHa sWildcard); |
288 bool parsePath(const UChar* begin, const UChar* end, String& path); | 298 bool parsePath(const UChar* begin, const UChar* end, String& path); |
289 bool parseNonce(const UChar* begin, const UChar* end, String& nonce); | 299 bool parseNonce(const UChar* begin, const UChar* end, String& nonce); |
300 bool parseHash(const UChar* begin, const UChar* end, String& hash); | |
290 | 301 |
291 void addSourceSelf(); | 302 void addSourceSelf(); |
292 void addSourceStar(); | 303 void addSourceStar(); |
293 void addSourceUnsafeInline(); | 304 void addSourceUnsafeInline(); |
294 void addSourceUnsafeEval(); | 305 void addSourceUnsafeEval(); |
295 void addSourceNonce(const String& nonce); | 306 void addSourceNonce(const String& nonce); |
307 void addSourceHash(const String& hash); | |
296 | 308 |
297 ContentSecurityPolicy* m_policy; | 309 ContentSecurityPolicy* m_policy; |
298 Vector<CSPSource> m_list; | 310 Vector<CSPSource> m_list; |
299 String m_directiveName; | 311 String m_directiveName; |
300 bool m_allowStar; | 312 bool m_allowStar; |
301 bool m_allowInline; | 313 bool m_allowInline; |
302 bool m_allowEval; | 314 bool m_allowEval; |
303 HashSet<String> m_nonces; | 315 HashSet<String> m_nonces; |
316 HashSet<String> m_hashes; | |
304 }; | 317 }; |
305 | 318 |
306 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) | 319 CSPSourceList::CSPSourceList(ContentSecurityPolicy* policy, const String& direct iveName) |
307 : m_policy(policy) | 320 : m_policy(policy) |
308 , m_directiveName(directiveName) | 321 , m_directiveName(directiveName) |
309 , m_allowStar(false) | 322 , m_allowStar(false) |
310 , m_allowInline(false) | 323 , m_allowInline(false) |
311 , m_allowEval(false) | 324 , m_allowEval(false) |
312 { | 325 { |
313 } | 326 } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 if (!parseHash(begin, end, hash)) | |
428 return false; | |
429 | |
430 if (!hash.isNull()) { | |
431 addSourceHash(hash); | |
432 return true; | |
433 } | |
412 } | 434 } |
413 | 435 |
414 const UChar* position = begin; | 436 const UChar* position = begin; |
415 const UChar* beginHost = begin; | 437 const UChar* beginHost = begin; |
416 const UChar* beginPath = end; | 438 const UChar* beginPath = end; |
417 const UChar* beginPort = 0; | 439 const UChar* beginPort = 0; |
418 | 440 |
419 skipWhile<UChar, isNotColonOrSlash>(position, end); | 441 skipWhile<UChar, isNotColonOrSlash>(position, end); |
420 | 442 |
421 if (position == end) { | 443 if (position == end) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
491 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce) | 513 bool CSPSourceList::parseNonce(const UChar* begin, const UChar* end, String& non ce) |
492 { | 514 { |
493 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); | 515 DEFINE_STATIC_LOCAL(const String, noncePrefix, ("'nonce-")); |
494 | 516 |
495 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( ))) | 517 if (!equalIgnoringCase(noncePrefix.characters8(), begin, noncePrefix.length( ))) |
496 return true; | 518 return true; |
497 | 519 |
498 const UChar* position = begin + noncePrefix.length(); | 520 const UChar* position = begin + noncePrefix.length(); |
499 const UChar* nonceBegin = position; | 521 const UChar* nonceBegin = position; |
500 | 522 |
501 skipWhile<UChar, isNonceCharacter>(position, end); | 523 skipWhile<UChar, isBase64EncodedCharacter>(position, end); |
502 ASSERT(nonceBegin <= position); | 524 ASSERT(nonceBegin <= position); |
503 | 525 |
504 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin )) | 526 if (((position + 1) != end && *position != '\'') || !(position - nonceBegin )) |
505 return false; | 527 return false; |
506 | 528 |
507 nonce = String(nonceBegin, position - nonceBegin); | 529 nonce = String(nonceBegin, position - nonceBegin); |
508 return true; | 530 return true; |
509 } | 531 } |
510 | 532 |
533 // hash-source = "'" hash-algorithm "-" hash-value "'" | |
534 // hash-algorithm = "sha1" / "sha256" | |
535 // hash-value = 1*( ALPHA / DIGIT / "+" / "/" / "=" ) | |
536 // | |
537 bool CSPSourceList::parseHash(const UChar* begin, const UChar* end, String& hash ) | |
538 { | |
539 // TODO(jww) For now, we are not supporting SHA-256 (or any hashes other | |
540 // than SHA-1), so we need to put in a log message here to indicate that. | |
541 StringBuilder sha1Prefix; | |
542 sha1Prefix.append("'"); | |
543 sha1Prefix.append(sha1Label); | |
544 sha1Prefix.append("-"); | |
abarth-chromium
2013/10/17 02:28:09
There's no reason to use a StringBuilder here. Yo
jww
2013/10/18 22:58:04
Done.
| |
545 bool isSha1 = equalIgnoringCase(sha1Prefix.toString().characters8(), begin, sha1Prefix.length()); | |
546 StringBuilder sha256Prefix; | |
547 sha256Prefix.append("'"); | |
548 sha256Prefix.append(sha256Label); | |
549 sha256Prefix.append("-"); | |
550 bool isSha256 = equalIgnoringCase(sha256Prefix.toString().characters8(), beg in, sha256Prefix.length()); | |
abarth-chromium
2013/10/17 02:28:09
Ditto
jww
2013/10/18 22:58:04
Done.
| |
551 | |
552 if (!isSha1) | |
553 return true; | |
abarth-chromium
2013/10/17 02:28:09
You should call notImplemented() for the isSha256
jww
2013/10/18 22:58:04
Done.
| |
554 | |
555 const UChar* position = begin + (isSha1 ? sha1Prefix.length() : sha256Prefix .length()); | |
556 const UChar* hashBegin = position; | |
557 | |
558 skipWhile<UChar, isBase64EncodedCharacter>(position, end); | |
559 ASSERT(hashBegin <= position); | |
560 | |
561 // Base64 encodings may end with exactly one or two '=' characters | |
562 for (size_t i = 0; i < 2 && position != end; i++) { | |
563 if (*position != '=') | |
564 break; | |
565 position = position + 1; | |
566 } | |
567 | |
568 if (((position + 1) != end && *position != '\'') || !(position - hashBegin) ) | |
569 return false; | |
570 | |
571 hash = String(begin + 1, position - begin - 1); | |
572 return true; | |
573 } | |
574 | |
511 // ; <scheme> production from RFC 3986 | 575 // ; <scheme> production from RFC 3986 |
512 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | 576 // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
513 // | 577 // |
514 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme) | 578 bool CSPSourceList::parseScheme(const UChar* begin, const UChar* end, String& sc heme) |
515 { | 579 { |
516 ASSERT(begin <= end); | 580 ASSERT(begin <= end); |
517 ASSERT(scheme.isEmpty()); | 581 ASSERT(scheme.isEmpty()); |
518 | 582 |
519 if (begin == end) | 583 if (begin == end) |
520 return false; | 584 return false; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 void CSPSourceList::addSourceUnsafeEval() | 707 void CSPSourceList::addSourceUnsafeEval() |
644 { | 708 { |
645 m_allowEval = true; | 709 m_allowEval = true; |
646 } | 710 } |
647 | 711 |
648 void CSPSourceList::addSourceNonce(const String& nonce) | 712 void CSPSourceList::addSourceNonce(const String& nonce) |
649 { | 713 { |
650 m_nonces.add(nonce); | 714 m_nonces.add(nonce); |
651 } | 715 } |
652 | 716 |
717 void CSPSourceList::addSourceHash(const String& hash) | |
718 { | |
719 m_hashes.add(hash); | |
720 } | |
721 | |
653 class CSPDirective { | 722 class CSPDirective { |
654 public: | 723 public: |
655 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) | 724 CSPDirective(const String& name, const String& value, ContentSecurityPolicy* policy) |
656 : m_name(name) | 725 : m_name(name) |
657 , m_text(name + ' ' + value) | 726 , m_text(name + ' ' + value) |
658 , m_policy(policy) | 727 , m_policy(policy) |
659 { | 728 { |
660 } | 729 } |
661 | 730 |
662 const String& text() const { return m_text; } | 731 const String& text() const { return m_text; } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 } | 828 } |
760 | 829 |
761 bool allows(const KURL& url) | 830 bool allows(const KURL& url) |
762 { | 831 { |
763 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); | 832 return m_sourceList.matches(url.isEmpty() ? policy()->url() : url); |
764 } | 833 } |
765 | 834 |
766 bool allowInline() const { return m_sourceList.allowInline(); } | 835 bool allowInline() const { return m_sourceList.allowInline(); } |
767 bool allowEval() const { return m_sourceList.allowEval(); } | 836 bool allowEval() const { return m_sourceList.allowEval(); } |
768 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); } | 837 bool allowNonce(const String& nonce) const { return m_sourceList.allowNonce( nonce.stripWhiteSpace()); } |
838 bool allowHash(const String& hash) const { return m_sourceList.allowHash(has h); } | |
769 | 839 |
770 private: | 840 private: |
771 CSPSourceList m_sourceList; | 841 CSPSourceList m_sourceList; |
772 }; | 842 }; |
773 | 843 |
774 class CSPDirectiveList { | 844 class CSPDirectiveList { |
775 WTF_MAKE_FAST_ALLOCATED; | 845 WTF_MAKE_FAST_ALLOCATED; |
776 public: | 846 public: |
777 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); | 847 static PassOwnPtr<CSPDirectiveList> create(ContentSecurityPolicy*, const UCh ar* begin, const UChar* end, ContentSecurityPolicy::HeaderType); |
778 | 848 |
(...skipping 14 matching lines...) Expand all Loading... | |
793 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; | 863 bool allowChildFrameFromSource(const KURL&, ContentSecurityPolicy::Reporting Status) const; |
794 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; | 864 bool allowImageFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; |
795 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; | 865 bool allowStyleFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; |
796 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; | 866 bool allowFontFromSource(const KURL&, ContentSecurityPolicy::ReportingStatus ) const; |
797 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; | 867 bool allowMediaFromSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; |
798 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; | 868 bool allowConnectToSource(const KURL&, ContentSecurityPolicy::ReportingStatu s) const; |
799 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; | 869 bool allowFormAction(const KURL&, ContentSecurityPolicy::ReportingStatus) co nst; |
800 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; | 870 bool allowBaseURI(const KURL&, ContentSecurityPolicy::ReportingStatus) const ; |
801 bool allowScriptNonce(const String&) const; | 871 bool allowScriptNonce(const String&) const; |
802 bool allowStyleNonce(const String&) const; | 872 bool allowStyleNonce(const String&) const; |
873 bool allowHash(const String&) const; | |
803 | 874 |
804 void gatherReportURIs(DOMStringList&) const; | 875 void gatherReportURIs(DOMStringList&) const; |
805 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } | 876 const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorM essage; } |
806 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } | 877 ReflectedXSSDisposition reflectedXSSDisposition() const { return m_reflected XSSDisposition; } |
807 bool isReportOnly() const { return m_reportOnly; } | 878 bool isReportOnly() const { return m_reportOnly; } |
808 const Vector<KURL>& reportURIs() const { return m_reportURIs; } | 879 const Vector<KURL>& reportURIs() const { return m_reportURIs; } |
809 | 880 |
810 private: | 881 private: |
811 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); | 882 CSPDirectiveList(ContentSecurityPolicy*, ContentSecurityPolicy::HeaderType); |
812 | 883 |
813 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); | 884 bool parseDirective(const UChar* begin, const UChar* end, String& name, Stri ng& value); |
814 void parseReportURI(const String& name, const String& value); | 885 void parseReportURI(const String& name, const String& value); |
815 void parsePluginTypes(const String& name, const String& value); | 886 void parsePluginTypes(const String& name, const String& value); |
816 void parseReflectedXSS(const String& name, const String& value); | 887 void parseReflectedXSS(const String& name, const String& value); |
817 void addDirective(const String& name, const String& value); | 888 void addDirective(const String& name, const String& value); |
818 void applySandboxPolicy(const String& name, const String& sandboxPolicy); | 889 void applySandboxPolicy(const String& name, const String& sandboxPolicy); |
819 | 890 |
820 template <class CSPDirectiveType> | 891 template <class CSPDirectiveType> |
821 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); | 892 void setCSPDirective(const String& name, const String& value, OwnPtr<CSPDire ctiveType>&); |
822 | 893 |
823 SourceListDirective* operativeDirective(SourceListDirective*) const; | 894 SourceListDirective* operativeDirective(SourceListDirective*) const; |
824 void reportViolation(const String& directiveText, const String& effectiveDir ective, const String& consoleMessage, const KURL& blockedURL) const; | 895 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; | 896 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; | 897 void reportViolationWithState(const String& directiveText, const String& eff ectiveDirective, const String& consoleMessage, const KURL& blockedURL, ScriptSta te*) const; |
827 | 898 |
828 bool checkEval(SourceListDirective*) const; | 899 bool checkEval(SourceListDirective*) const; |
829 bool checkInline(SourceListDirective*) const; | 900 bool checkInline(SourceListDirective*) const; |
830 bool checkNonce(SourceListDirective*, const String&) const; | 901 bool checkNonce(SourceListDirective*, const String&) const; |
902 bool checkHash(SourceListDirective*, const String&) const; | |
831 bool checkSource(SourceListDirective*, const KURL&) const; | 903 bool checkSource(SourceListDirective*, const KURL&) const; |
832 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; | 904 bool checkMediaType(MediaListDirective*, const String& type, const String& t ypeAttribute) const; |
833 | 905 |
834 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } | 906 void setEvalDisabledErrorMessage(const String& errorMessage) { m_evalDisable dErrorMessage = errorMessage; } |
835 | 907 |
836 bool checkEvalAndReportViolation(SourceListDirective*, const String& console Message, ScriptState*) const; | 908 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; | 909 bool checkInlineAndReportViolation(SourceListDirective*, const String& conso leMessage, const String& contextURL, const WTF::OrdinalNumber& contextLine, bool isScript) const; |
838 | 910 |
839 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; | 911 bool checkSourceAndReportViolation(SourceListDirective*, const KURL&, const String& effectiveDirective) const; |
840 bool checkMediaTypeAndReportViolation(MediaListDirective*, const String& typ e, const String& typeAttribute, const String& consoleMessage) const; | 912 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 Loading... | |
923 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const | 995 bool CSPDirectiveList::checkInline(SourceListDirective* directive) const |
924 { | 996 { |
925 return !directive || directive->allowInline(); | 997 return !directive || directive->allowInline(); |
926 } | 998 } |
927 | 999 |
928 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const | 1000 bool CSPDirectiveList::checkNonce(SourceListDirective* directive, const String& nonce) const |
929 { | 1001 { |
930 return !directive || directive->allowNonce(nonce); | 1002 return !directive || directive->allowNonce(nonce); |
931 } | 1003 } |
932 | 1004 |
1005 bool CSPDirectiveList::checkHash(SourceListDirective* directive, const String& h ash) const | |
1006 { | |
1007 return !directive || directive->allowHash(hash); | |
1008 } | |
1009 | |
933 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const | 1010 bool CSPDirectiveList::checkSource(SourceListDirective* directive, const KURL& u rl) const |
934 { | 1011 { |
935 return !directive || directive->allows(url); | 1012 return !directive || directive->allows(url); |
936 } | 1013 } |
937 | 1014 |
938 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const | 1015 bool CSPDirectiveList::checkMediaType(MediaListDirective* directive, const Strin g& type, const String& typeAttribute) const |
939 { | 1016 { |
940 if (!directive) | 1017 if (!directive) |
941 return true; | 1018 return true; |
942 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) | 1019 if (typeAttribute.isEmpty() || typeAttribute.stripWhiteSpace() != type) |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1168 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const | 1245 bool CSPDirectiveList::allowScriptNonce(const String& nonce) const |
1169 { | 1246 { |
1170 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); | 1247 return checkNonce(operativeDirective(m_scriptSrc.get()), nonce); |
1171 } | 1248 } |
1172 | 1249 |
1173 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const | 1250 bool CSPDirectiveList::allowStyleNonce(const String& nonce) const |
1174 { | 1251 { |
1175 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); | 1252 return checkNonce(operativeDirective(m_styleSrc.get()), nonce); |
1176 } | 1253 } |
1177 | 1254 |
1255 bool CSPDirectiveList::allowHash(const String& hash) const | |
1256 { | |
1257 return checkHash(operativeDirective(m_scriptSrc.get()), hash); | |
abarth-chromium
2013/10/17 02:28:09
Notice the m_scriptSrc here.
jww
2013/10/18 22:58:04
Ah, right, that's why we have separate script and
| |
1258 } | |
1259 | |
1178 // policy = directive-list | 1260 // policy = directive-list |
1179 // directive-list = [ directive *( ";" [ directive ] ) ] | 1261 // directive-list = [ directive *( ";" [ directive ] ) ] |
1180 // | 1262 // |
1181 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) | 1263 void CSPDirectiveList::parse(const UChar* begin, const UChar* end) |
1182 { | 1264 { |
1183 m_header = String(begin, end - begin); | 1265 m_header = String(begin, end - begin); |
1184 | 1266 |
1185 if (begin == end) | 1267 if (begin == end) |
1186 return; | 1268 return; |
1187 | 1269 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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::allowHash(const String& source) const | |
1694 { | |
1695 // TODO(jww) We don't currently have a WTF SHA256 implementation. Once we | |
1696 // have that, we should implement a proper check for sha256 hash values here . | |
1697 SHA1 sourceSha1; | |
1698 sourceSha1.addBytes(source.utf8()); | |
abarth-chromium
2013/10/17 02:28:09
Woah there cowboy. There are a couple of importan
jww
2013/10/18 22:58:04
Done.
| |
1699 Vector<uint8_t, 20> digest; | |
1700 sourceSha1.computeHash(digest); | |
1701 | |
1702 StringBuilder hash; | |
abarth-chromium
2013/10/17 02:28:09
Please call |hash.reserveCapacity(...)| with the e
jww
2013/10/18 22:58:04
Done.
| |
1703 hash.append(sha1Label); | |
1704 hash.append("-"); | |
1705 hash.append(base64Encode(reinterpret_cast<char*>(digest.data()), 20)); | |
abarth-chromium
2013/10/17 02:28:09
20 -> digest.size()
jww
2013/10/18 22:58:04
Done.
| |
1706 return isAllowedByAllWithHash<&CSPDirectiveList::allowHash>(m_policies, hash .toString()); | |
1707 } | |
1708 | |
1600 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const | 1709 bool ContentSecurityPolicy::allowObjectFromSource(const KURL& url, ContentSecuri tyPolicy::ReportingStatus reportingStatus) const |
1601 { | 1710 { |
1602 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); | 1711 return isAllowedByAllWithURL<&CSPDirectiveList::allowObjectFromSource>(m_pol icies, url, reportingStatus); |
1603 } | 1712 } |
1604 | 1713 |
1605 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const | 1714 bool ContentSecurityPolicy::allowChildFrameFromSource(const KURL& url, ContentSe curityPolicy::ReportingStatus reportingStatus) const |
1606 { | 1715 { |
1607 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); | 1716 return isAllowedByAllWithURL<&CSPDirectiveList::allowChildFrameFromSource>(m _policies, url, reportingStatus); |
1608 } | 1717 } |
1609 | 1718 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1844 { | 1953 { |
1845 ASSERT(invalidChar == '#' || invalidChar == '?'); | 1954 ASSERT(invalidChar == '#' || invalidChar == '?'); |
1846 | 1955 |
1847 String ignoring = "The fragment identifier, including the '#', will be ignor ed."; | 1956 String ignoring = "The fragment identifier, including the '#', will be ignor ed."; |
1848 if (invalidChar == '?') | 1957 if (invalidChar == '?') |
1849 ignoring = "The query component, including the '?', will be ignored."; | 1958 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; | 1959 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains a source with an invalid path: '" + value + "'. " + ignoring; |
1851 logToConsole(message); | 1960 logToConsole(message); |
1852 } | 1961 } |
1853 | 1962 |
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 | 1963 void ContentSecurityPolicy::reportInvalidSourceExpression(const String& directiv eName, const String& source) const |
1861 { | 1964 { |
1862 String message = "The source list for Content Security Policy directive '" + directiveName + "' contains an invalid source: '" + source + "'. It will be ign ored."; | 1965 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'")) | 1966 if (equalIgnoringCase(source, "'none'")) |
1864 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; | 1967 message = message + " Note that 'none' has no effect unless it is the on ly expression in the source list."; |
1865 logToConsole(message); | 1968 logToConsole(message); |
1866 } | 1969 } |
1867 | 1970 |
1868 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const | 1971 void ContentSecurityPolicy::reportMissingReportURI(const String& policy) const |
1869 { | 1972 { |
(...skipping 30 matching lines...) Expand all Loading... | |
1900 // Collisions have no security impact, so we can save space by storing only the string's hash rather than the whole report. | 2003 // 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()); | 2004 return !m_violationReportsSent.contains(report.impl()->hash()); |
1902 } | 2005 } |
1903 | 2006 |
1904 void ContentSecurityPolicy::didSendViolationReport(const String& report) | 2007 void ContentSecurityPolicy::didSendViolationReport(const String& report) |
1905 { | 2008 { |
1906 m_violationReportsSent.add(report.impl()->hash()); | 2009 m_violationReportsSent.add(report.impl()->hash()); |
1907 } | 2010 } |
1908 | 2011 |
1909 } // namespace WebCore | 2012 } // namespace WebCore |
OLD | NEW |