| 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 |