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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 } | 540 } |
540 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); | 541 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); |
541 } | 542 } |
542 | 543 |
543 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) | 544 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) |
544 { | 545 { |
545 if (m_reportOnly) { | 546 if (m_reportOnly) { |
546 m_policy->reportInvalidInReportOnly(name); | 547 m_policy->reportInvalidInReportOnly(name); |
547 return; | 548 return; |
548 } | 549 } |
549 if (m_haveSandboxPolicy) { | 550 if (m_hasSandboxPolicy) { |
550 m_policy->reportDuplicateDirective(name); | 551 m_policy->reportDuplicateDirective(name); |
551 return; | 552 return; |
552 } | 553 } |
553 m_haveSandboxPolicy = true; | 554 m_hasSandboxPolicy = true; |
554 String invalidTokens; | 555 String invalidTokens; |
555 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); | 556 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); |
556 if (!invalidTokens.isNull()) | 557 if (!invalidTokens.isNull()) |
557 m_policy->reportInvalidSandboxFlags(invalidTokens); | 558 m_policy->reportInvalidSandboxFlags(invalidTokens); |
558 } | 559 } |
559 | 560 |
560 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) | 561 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) |
561 { | 562 { |
562 if (m_reportOnly) { | 563 if (m_reportOnly) { |
563 m_policy->reportInvalidInReportOnly(name); | 564 m_policy->reportInvalidInReportOnly(name); |
(...skipping 19 matching lines...) Expand all Loading... |
583 m_policy->reportDuplicateDirective(name); | 584 m_policy->reportDuplicateDirective(name); |
584 return; | 585 return; |
585 } | 586 } |
586 m_upgradeInsecureRequests = true; | 587 m_upgradeInsecureRequests = true; |
587 | 588 |
588 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); | 589 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); |
589 if (!value.isEmpty()) | 590 if (!value.isEmpty()) |
590 m_policy->reportValueForEmptyDirective(name, value); | 591 m_policy->reportValueForEmptyDirective(name, value); |
591 } | 592 } |
592 | 593 |
| 594 void CSPDirectiveList::applySuboriginPolicy(const String& name, const String& su
boriginPolicy) |
| 595 { |
| 596 ASSERT(RuntimeEnabledFeatures::suboriginsEnabled()); |
| 597 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { |
| 598 m_policy->reportSuboriginInMeta(suboriginPolicy); |
| 599 return; |
| 600 } |
| 601 |
| 602 if (m_hasSuboriginPolicy) { |
| 603 m_policy->reportDuplicateDirective(name); |
| 604 return; |
| 605 } |
| 606 m_hasSuboriginPolicy = true; |
| 607 String suboriginName = parseSuboriginName(suboriginPolicy); |
| 608 if (!suboriginName.isNull()) |
| 609 m_policy->enforceSuborigin(suboriginName); |
| 610 } |
| 611 |
593 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) | 612 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) |
594 { | 613 { |
595 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { | 614 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { |
596 m_policy->reportDuplicateDirective(name); | 615 m_policy->reportDuplicateDirective(name); |
597 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 616 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
598 return; | 617 return; |
599 } | 618 } |
600 | 619 |
601 if (value.isEmpty()) { | 620 if (value.isEmpty()) { |
602 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 621 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 skipWhile<UChar, isASCIISpace>(position, end); | 703 skipWhile<UChar, isASCIISpace>(position, end); |
685 if (position == end) | 704 if (position == end) |
686 return; | 705 return; |
687 | 706 |
688 // value1 value2 | 707 // value1 value2 |
689 // ^ | 708 // ^ |
690 m_referrerPolicy = ReferrerPolicyNever; | 709 m_referrerPolicy = ReferrerPolicyNever; |
691 m_policy->reportInvalidReferrer(value); | 710 m_policy->reportInvalidReferrer(value); |
692 } | 711 } |
693 | 712 |
| 713 String CSPDirectiveList::parseSuboriginName(const String& policy) |
| 714 { |
| 715 Vector<UChar> characters; |
| 716 policy.appendTo(characters); |
| 717 |
| 718 const UChar* position = characters.data(); |
| 719 const UChar* end = position + characters.size(); |
| 720 |
| 721 // Parse the name of the suborigin (no spaces, single string) |
| 722 skipWhile<UChar, isASCIISpace>(position, end); |
| 723 if (position == end) { |
| 724 m_policy->reportInvalidSuboriginFlags("No suborigin name specified."); |
| 725 return String(); |
| 726 } |
| 727 |
| 728 const UChar* begin = position; |
| 729 |
| 730 skipWhile<UChar, isASCIIAlphanumeric>(position, end); |
| 731 if (position != end && !isASCIISpace(*position)) { |
| 732 m_policy->reportInvalidSuboriginFlags("Invalid character \'" + String(po
sition, 1) + "\' in suborigin."); |
| 733 return String(); |
| 734 } |
| 735 size_t length = position - begin; |
| 736 skipWhile<UChar, isASCIISpace>(position, end); |
| 737 if (position != end) { |
| 738 m_policy->reportInvalidSuboriginFlags("Whitespace is not allowed in subo
rigin names."); |
| 739 return String(); |
| 740 } |
| 741 |
| 742 return String(begin, length); |
| 743 } |
| 744 |
694 void CSPDirectiveList::addDirective(const String& name, const String& value) | 745 void CSPDirectiveList::addDirective(const String& name, const String& value) |
695 { | 746 { |
696 ASSERT(!name.isEmpty()); | 747 ASSERT(!name.isEmpty()); |
697 | 748 |
698 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { | 749 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { |
699 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); | 750 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); |
700 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { | 751 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { |
701 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); | 752 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); |
702 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); | 753 m_policy->usesScriptHashAlgorithms(m_scriptSrc->hashAlgorithmsUsed()); |
703 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) { | 754 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ObjectSrc)) { |
(...skipping 28 matching lines...) Expand all Loading... |
732 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { | 783 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { |
733 parseReflectedXSS(name, value); | 784 parseReflectedXSS(name, value); |
734 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { | 785 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { |
735 parseReferrer(name, value); | 786 parseReferrer(name, value); |
736 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq
uests)) { | 787 } else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureReq
uests)) { |
737 enableInsecureRequestsUpgrade(name, value); | 788 enableInsecureRequestsUpgrade(name, value); |
738 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte
nt)) { | 789 } else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedConte
nt)) { |
739 enforceStrictMixedContentChecking(name, value); | 790 enforceStrictMixedContentChecking(name, value); |
740 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) { | 791 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) { |
741 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); | 792 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); |
| 793 } else if (RuntimeEnabledFeatures::suboriginsEnabled() && equalIgnoringCase(
name, ContentSecurityPolicy::Suborigin)) { |
| 794 applySuboriginPolicy(name, value); |
742 } else { | 795 } else { |
743 m_policy->reportUnsupportedDirective(name); | 796 m_policy->reportUnsupportedDirective(name); |
744 } | 797 } |
745 } | 798 } |
746 | 799 |
747 | 800 |
748 } // namespace blink | 801 } // namespace blink |
OLD | NEW |