OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/frame/csp/CSPDirectiveList.h" | 6 #include "core/frame/csp/CSPDirectiveList.h" |
7 | 7 |
8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
9 #include "core/dom/SecurityContext.h" | 9 #include "core/dom/SecurityContext.h" |
10 #include "core/frame/LocalFrame.h" | 10 #include "core/frame/LocalFrame.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 return "sha256-" + base64URLEncode(reinterpret_cast<char*>(digest.data()), d
igest.size(), Base64DoNotInsertLFs); | 36 return "sha256-" + base64URLEncode(reinterpret_cast<char*>(digest.data()), d
igest.size(), Base64DoNotInsertLFs); |
37 } | 37 } |
38 | 38 |
39 } | 39 } |
40 | 40 |
41 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurit
yPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) | 41 CSPDirectiveList::CSPDirectiveList(ContentSecurityPolicy* policy, ContentSecurit
yPolicyHeaderType type, ContentSecurityPolicyHeaderSource source) |
42 : m_policy(policy) | 42 : m_policy(policy) |
43 , m_headerType(type) | 43 , m_headerType(type) |
44 , m_headerSource(source) | 44 , m_headerSource(source) |
45 , m_reportOnly(false) | 45 , m_reportOnly(false) |
46 , m_haveSandboxPolicy(false) | 46 , m_hasSandboxPolicy(false) |
| 47 , m_hasSuboriginPolicy(false) |
47 , m_reflectedXSSDisposition(ReflectedXSSUnset) | 48 , m_reflectedXSSDisposition(ReflectedXSSUnset) |
48 , m_didSetReferrerPolicy(false) | 49 , m_didSetReferrerPolicy(false) |
49 , m_referrerPolicy(ReferrerPolicyDefault) | 50 , m_referrerPolicy(ReferrerPolicyDefault) |
50 , m_strictMixedContentCheckingEnforced(false) | 51 , m_strictMixedContentCheckingEnforced(false) |
51 , m_upgradeInsecureRequests(false) | 52 , m_upgradeInsecureRequests(false) |
52 { | 53 { |
53 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport; | 54 m_reportOnly = type == ContentSecurityPolicyHeaderTypeReport; |
54 } | 55 } |
55 | 56 |
56 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* pol
icy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type,
ContentSecurityPolicyHeaderSource source) | 57 PassOwnPtr<CSPDirectiveList> CSPDirectiveList::create(ContentSecurityPolicy* pol
icy, const UChar* begin, const UChar* end, ContentSecurityPolicyHeaderType type,
ContentSecurityPolicyHeaderSource source) |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 } | 565 } |
565 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); | 566 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); |
566 } | 567 } |
567 | 568 |
568 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) | 569 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) |
569 { | 570 { |
570 if (m_reportOnly) { | 571 if (m_reportOnly) { |
571 m_policy->reportInvalidInReportOnly(name); | 572 m_policy->reportInvalidInReportOnly(name); |
572 return; | 573 return; |
573 } | 574 } |
574 if (m_haveSandboxPolicy) { | 575 if (m_hasSandboxPolicy) { |
575 m_policy->reportDuplicateDirective(name); | 576 m_policy->reportDuplicateDirective(name); |
576 return; | 577 return; |
577 } | 578 } |
578 m_haveSandboxPolicy = true; | 579 m_hasSandboxPolicy = true; |
579 String invalidTokens; | 580 String invalidTokens; |
580 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); | 581 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); |
581 if (!invalidTokens.isNull()) | 582 if (!invalidTokens.isNull()) |
582 m_policy->reportInvalidSandboxFlags(invalidTokens); | 583 m_policy->reportInvalidSandboxFlags(invalidTokens); |
583 } | 584 } |
584 | 585 |
585 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) | 586 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) |
586 { | 587 { |
587 if (m_reportOnly) { | 588 if (m_reportOnly) { |
588 m_policy->reportInvalidInReportOnly(name); | 589 m_policy->reportInvalidInReportOnly(name); |
(...skipping 19 matching lines...) Expand all Loading... |
608 m_policy->reportDuplicateDirective(name); | 609 m_policy->reportDuplicateDirective(name); |
609 return; | 610 return; |
610 } | 611 } |
611 m_upgradeInsecureRequests = true; | 612 m_upgradeInsecureRequests = true; |
612 | 613 |
613 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); | 614 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); |
614 if (!value.isEmpty()) | 615 if (!value.isEmpty()) |
615 m_policy->reportValueForEmptyDirective(name, value); | 616 m_policy->reportValueForEmptyDirective(name, value); |
616 } | 617 } |
617 | 618 |
| 619 void CSPDirectiveList::applySuboriginPolicy(const String& name, const String& su
boriginPolicy) |
| 620 { |
| 621 ASSERT(RuntimeEnabledFeatures::suboriginsEnabled()); |
| 622 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { |
| 623 m_policy->reportSuboriginInMeta(suboriginPolicy); |
| 624 return; |
| 625 } |
| 626 |
| 627 if (m_hasSuboriginPolicy) { |
| 628 m_policy->reportDuplicateDirective(name); |
| 629 return; |
| 630 } |
| 631 m_hasSuboriginPolicy = true; |
| 632 String suboriginName = parseSuboriginName(suboriginPolicy); |
| 633 if (!suboriginName.isNull()) |
| 634 m_policy->enforceSuborigin(suboriginName); |
| 635 } |
| 636 |
618 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) | 637 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) |
619 { | 638 { |
620 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { | 639 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { |
621 m_policy->reportDuplicateDirective(name); | 640 m_policy->reportDuplicateDirective(name); |
622 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 641 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
623 return; | 642 return; |
624 } | 643 } |
625 | 644 |
626 if (value.isEmpty()) { | 645 if (value.isEmpty()) { |
627 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 646 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 skipWhile<UChar, isASCIISpace>(position, end); | 728 skipWhile<UChar, isASCIISpace>(position, end); |
710 if (position == end) | 729 if (position == end) |
711 return; | 730 return; |
712 | 731 |
713 // value1 value2 | 732 // value1 value2 |
714 // ^ | 733 // ^ |
715 m_referrerPolicy = ReferrerPolicyNever; | 734 m_referrerPolicy = ReferrerPolicyNever; |
716 m_policy->reportInvalidReferrer(value); | 735 m_policy->reportInvalidReferrer(value); |
717 } | 736 } |
718 | 737 |
| 738 String CSPDirectiveList::parseSuboriginName(const String& policy) |
| 739 { |
| 740 Vector<UChar> characters; |
| 741 policy.appendTo(characters); |
| 742 |
| 743 const UChar* position = characters.data(); |
| 744 const UChar* end = position + characters.size(); |
| 745 |
| 746 // Parse the name of the suborigin (no spaces, single string) |
| 747 skipWhile<UChar, isASCIISpace>(position, end); |
| 748 if (position == end) { |
| 749 m_policy->reportInvalidSuboriginFlags("No suborigin name specified."); |
| 750 return String(); |
| 751 } |
| 752 |
| 753 const UChar* begin = position; |
| 754 |
| 755 skipWhile<UChar, isASCIIAlphanumeric>(position, end); |
| 756 if (position != end && !isASCIISpace(*position)) { |
| 757 m_policy->reportInvalidSuboriginFlags("Invalid character \'" + String(po
sition, 1) + "\' in suborigin."); |
| 758 return String(); |
| 759 } |
| 760 size_t length = position - begin; |
| 761 skipWhile<UChar, isASCIISpace>(position, end); |
| 762 if (position != end) { |
| 763 m_policy->reportInvalidSuboriginFlags("Whitespace is not allowed in subo
rigin names."); |
| 764 return String(); |
| 765 } |
| 766 |
| 767 return String(begin, length); |
| 768 } |
| 769 |
719 void CSPDirectiveList::addDirective(const String& name, const String& value) | 770 void CSPDirectiveList::addDirective(const String& name, const String& value) |
720 { | 771 { |
721 ASSERT(!name.isEmpty()); | 772 ASSERT(!name.isEmpty()); |
722 | 773 |
723 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { | 774 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { |
724 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); | 775 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); |
725 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { | 776 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { |
726 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); | 777 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); |
727 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); | 778 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); |
728 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) { | 779 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) { |
(...skipping 24 matching lines...) Expand all Loading... |
753 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) { | 804 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) { |
754 setCSPDirective<SourceListDirective>(name, value, m_formAction); | 805 setCSPDirective<SourceListDirective>(name, value, m_formAction); |
755 } else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) { | 806 } else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) { |
756 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); | 807 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); |
757 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { | 808 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { |
758 parseReflectedXSS(name, value); | 809 parseReflectedXSS(name, value); |
759 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { | 810 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { |
760 parseReferrer(name, value); | 811 parseReferrer(name, value); |
761 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq
uests)) { | 812 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq
uests)) { |
762 enableInsecureRequestsUpgrade(name, value); | 813 enableInsecureRequestsUpgrade(name, value); |
| 814 } else if (RuntimeEnabledFeatures::suboriginsEnabled() && equalIgnoringCase(
name, ContentSecurityPolicy::Suborigin)) { |
| 815 applySuboriginPolicy(name, value); |
763 } else if (m_policy->experimentalFeaturesEnabled()) { | 816 } else if (m_policy->experimentalFeaturesEnabled()) { |
764 if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) | 817 if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) |
765 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); | 818 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); |
766 else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedCon
tent)) | 819 else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedCon
tent)) |
767 enforceStrictMixedContentChecking(name, value); | 820 enforceStrictMixedContentChecking(name, value); |
768 else | 821 else |
769 m_policy->reportUnsupportedDirective(name); | 822 m_policy->reportUnsupportedDirective(name); |
770 } else { | 823 } else { |
771 m_policy->reportUnsupportedDirective(name); | 824 m_policy->reportUnsupportedDirective(name); |
772 } | 825 } |
773 } | 826 } |
774 | 827 |
775 | 828 |
776 } // namespace blink | 829 } // namespace blink |
OLD | NEW |