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 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } | 526 } |
526 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); | 527 directive = adoptPtr(new CSPDirectiveType(name, value, m_policy)); |
527 } | 528 } |
528 | 529 |
529 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) | 530 void CSPDirectiveList::applySandboxPolicy(const String& name, const String& sand
boxPolicy) |
530 { | 531 { |
531 if (m_reportOnly) { | 532 if (m_reportOnly) { |
532 m_policy->reportInvalidInReportOnly(name); | 533 m_policy->reportInvalidInReportOnly(name); |
533 return; | 534 return; |
534 } | 535 } |
535 if (m_haveSandboxPolicy) { | 536 if (m_hasSandboxPolicy) { |
536 m_policy->reportDuplicateDirective(name); | 537 m_policy->reportDuplicateDirective(name); |
537 return; | 538 return; |
538 } | 539 } |
539 m_haveSandboxPolicy = true; | 540 m_hasSandboxPolicy = true; |
540 String invalidTokens; | 541 String invalidTokens; |
541 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); | 542 m_policy->enforceSandboxFlags(parseSandboxPolicy(sandboxPolicy, invalidToken
s)); |
542 if (!invalidTokens.isNull()) | 543 if (!invalidTokens.isNull()) |
543 m_policy->reportInvalidSandboxFlags(invalidTokens); | 544 m_policy->reportInvalidSandboxFlags(invalidTokens); |
544 } | 545 } |
545 | 546 |
546 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) | 547 void CSPDirectiveList::enforceStrictMixedContentChecking(const String& name, con
st String& value) |
547 { | 548 { |
548 if (m_reportOnly) { | 549 if (m_reportOnly) { |
549 m_policy->reportInvalidInReportOnly(name); | 550 m_policy->reportInvalidInReportOnly(name); |
(...skipping 19 matching lines...) Expand all Loading... |
569 m_policy->reportDuplicateDirective(name); | 570 m_policy->reportDuplicateDirective(name); |
570 return; | 571 return; |
571 } | 572 } |
572 m_upgradeInsecureRequests = true; | 573 m_upgradeInsecureRequests = true; |
573 | 574 |
574 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); | 575 m_policy->setInsecureRequestsPolicy(SecurityContext::InsecureRequestsUpgrade
); |
575 if (!value.isEmpty()) | 576 if (!value.isEmpty()) |
576 m_policy->reportValueForEmptyDirective(name, value); | 577 m_policy->reportValueForEmptyDirective(name, value); |
577 } | 578 } |
578 | 579 |
| 580 void CSPDirectiveList::applySuboriginPolicy(const String& name, const String& su
boriginPolicy) |
| 581 { |
| 582 ASSERT(RuntimeEnabledFeatures::suboriginsEnabled()); |
| 583 if (m_headerSource == ContentSecurityPolicyHeaderSourceMeta) { |
| 584 m_policy->reportSuboriginInMeta(suboriginPolicy); |
| 585 return; |
| 586 } |
| 587 |
| 588 if (m_hasSuboriginPolicy) { |
| 589 m_policy->reportDuplicateDirective(name); |
| 590 return; |
| 591 } |
| 592 m_hasSuboriginPolicy = true; |
| 593 String suboriginName = parseSuboriginName(suboriginPolicy); |
| 594 if (!suboriginName.isNull()) |
| 595 m_policy->enforceSuborigin(suboriginName); |
| 596 } |
| 597 |
579 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) | 598 void CSPDirectiveList::parseReflectedXSS(const String& name, const String& value
) |
580 { | 599 { |
581 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { | 600 if (m_reflectedXSSDisposition != ReflectedXSSUnset) { |
582 m_policy->reportDuplicateDirective(name); | 601 m_policy->reportDuplicateDirective(name); |
583 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 602 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
584 return; | 603 return; |
585 } | 604 } |
586 | 605 |
587 if (value.isEmpty()) { | 606 if (value.isEmpty()) { |
588 m_reflectedXSSDisposition = ReflectedXSSInvalid; | 607 m_reflectedXSSDisposition = ReflectedXSSInvalid; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 } | 688 } |
670 | 689 |
671 skipWhile<UChar, isASCIISpace>(position, end); | 690 skipWhile<UChar, isASCIISpace>(position, end); |
672 if (position == end) | 691 if (position == end) |
673 return; | 692 return; |
674 | 693 |
675 // value1 value2 | 694 // value1 value2 |
676 // ^ | 695 // ^ |
677 m_referrerPolicy = ReferrerPolicyNever; | 696 m_referrerPolicy = ReferrerPolicyNever; |
678 m_policy->reportInvalidReferrer(value); | 697 m_policy->reportInvalidReferrer(value); |
| 698 } |
679 | 699 |
| 700 String CSPDirectiveList::parseSuboriginName(const String& policy) |
| 701 { |
| 702 Vector<UChar> characters; |
| 703 policy.appendTo(characters); |
| 704 |
| 705 const UChar* position = characters.data(); |
| 706 const UChar* end = position + characters.size(); |
| 707 |
| 708 // Parse the name of the suborigin (no spaces, single string) |
| 709 skipWhile<UChar, isASCIISpace>(position, end); |
| 710 if (position == end) { |
| 711 m_policy->reportInvalidSuboriginFlags("No suborigin name specified."); |
| 712 return String(); |
| 713 } |
| 714 |
| 715 const UChar* begin = position; |
| 716 |
| 717 skipWhile<UChar, isASCIIAlphanumeric>(position, end); |
| 718 if (position != end && !isASCIISpace(*position)) { |
| 719 m_policy->reportInvalidSuboriginFlags("Invalid character \'" + String(po
sition, 1) + "\' in suborigin."); |
| 720 return String(); |
| 721 } |
| 722 size_t length = position - begin; |
| 723 skipWhile<UChar, isASCIISpace>(position, end); |
| 724 if (position != end) { |
| 725 m_policy->reportInvalidSuboriginFlags("Whitespace is not allowed in subo
rigin names."); |
| 726 return String(); |
| 727 } |
| 728 |
| 729 return String(begin, length); |
680 } | 730 } |
681 | 731 |
682 void CSPDirectiveList::addDirective(const String& name, const String& value) | 732 void CSPDirectiveList::addDirective(const String& name, const String& value) |
683 { | 733 { |
684 ASSERT(!name.isEmpty()); | 734 ASSERT(!name.isEmpty()); |
685 | 735 |
686 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { | 736 if (equalIgnoringCase(name, ContentSecurityPolicy::DefaultSrc)) { |
687 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); | 737 setCSPDirective<SourceListDirective>(name, value, m_defaultSrc); |
688 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { | 738 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ScriptSrc)) { |
689 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); | 739 setCSPDirective<SourceListDirective>(name, value, m_scriptSrc); |
(...skipping 24 matching lines...) Expand all Loading... |
714 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ChildSrc)) { | 764 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ChildSrc)) { |
715 setCSPDirective<SourceListDirective>(name, value, m_childSrc); | 765 setCSPDirective<SourceListDirective>(name, value, m_childSrc); |
716 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) { | 766 } else if (equalIgnoringCase(name, ContentSecurityPolicy::FormAction)) { |
717 setCSPDirective<SourceListDirective>(name, value, m_formAction); | 767 setCSPDirective<SourceListDirective>(name, value, m_formAction); |
718 } else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) { | 768 } else if (equalIgnoringCase(name, ContentSecurityPolicy::PluginTypes)) { |
719 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); | 769 setCSPDirective<MediaListDirective>(name, value, m_pluginTypes); |
720 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { | 770 } else if (equalIgnoringCase(name, ContentSecurityPolicy::ReflectedXSS)) { |
721 parseReflectedXSS(name, value); | 771 parseReflectedXSS(name, value); |
722 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { | 772 } else if (equalIgnoringCase(name, ContentSecurityPolicy::Referrer)) { |
723 parseReferrer(name, value); | 773 parseReferrer(name, value); |
| 774 } else if (RuntimeEnabledFeatures::suboriginsEnabled() && equalIgnoringCase(
name, ContentSecurityPolicy::Suborigin)) { |
| 775 applySuboriginPolicy(name, value); |
724 } else if (m_policy->experimentalFeaturesEnabled()) { | 776 } else if (m_policy->experimentalFeaturesEnabled()) { |
725 if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) | 777 if (equalIgnoringCase(name, ContentSecurityPolicy::ManifestSrc)) |
726 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); | 778 setCSPDirective<SourceListDirective>(name, value, m_manifestSrc); |
727 else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedCon
tent)) | 779 else if (equalIgnoringCase(name, ContentSecurityPolicy::BlockAllMixedCon
tent)) |
728 enforceStrictMixedContentChecking(name, value); | 780 enforceStrictMixedContentChecking(name, value); |
729 else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureR
equests)) | 781 else if (equalIgnoringCase(name, ContentSecurityPolicy::UpgradeInsecureR
equests)) |
730 enableInsecureRequestsUpgrade(name, value); | 782 enableInsecureRequestsUpgrade(name, value); |
731 else | 783 else |
732 m_policy->reportUnsupportedDirective(name); | 784 m_policy->reportUnsupportedDirective(name); |
733 } else { | 785 } else { |
734 m_policy->reportUnsupportedDirective(name); | 786 m_policy->reportUnsupportedDirective(name); |
735 } | 787 } |
736 } | 788 } |
737 | 789 |
738 | 790 |
739 } // namespace blink | 791 } // namespace blink |
OLD | NEW |