Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/frame/csp/CSPDirectiveList.h" | 5 #include "core/frame/csp/CSPDirectiveList.h" |
| 6 | 6 |
| 7 #include "core/frame/csp/ContentSecurityPolicy.h" | 7 #include "core/frame/csp/ContentSecurityPolicy.h" |
| 8 #include "core/frame/csp/SourceListDirective.h" | 8 #include "core/frame/csp/SourceListDirective.h" |
| 9 #include "platform/network/ContentSecurityPolicyParsers.h" | 9 #include "platform/network/ContentSecurityPolicyParsers.h" |
| 10 #include "platform/network/ResourceRequest.h" | 10 #include "platform/network/ResourceRequest.h" |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 struct TestCase { | 395 struct TestCase { |
| 396 const char* list; | 396 const char* list; |
| 397 bool allowed; | 397 bool allowed; |
| 398 } cases[] = { | 398 } cases[] = { |
| 399 {"worker-src 'none'", false}, | 399 {"worker-src 'none'", false}, |
| 400 {"worker-src http://not.example.test", false}, | 400 {"worker-src http://not.example.test", false}, |
| 401 {"worker-src https://example.test", true}, | 401 {"worker-src https://example.test", true}, |
| 402 {"default-src *; worker-src 'none'", false}, | 402 {"default-src *; worker-src 'none'", false}, |
| 403 {"default-src *; worker-src http://not.example.test", false}, | 403 {"default-src *; worker-src http://not.example.test", false}, |
| 404 {"default-src *; worker-src https://example.test", true}, | 404 {"default-src *; worker-src https://example.test", true}, |
| 405 {"child-src *; worker-src 'none'", false}, | 405 {"script-src *; worker-src 'none'", false}, |
| 406 {"child-src *; worker-src http://not.example.test", false}, | 406 {"script-src *; worker-src http://not.example.test", false}, |
| 407 {"child-src *; worker-src https://example.test", true}, | 407 {"script-src *; worker-src https://example.test", true}, |
| 408 {"default-src *; child-src *; worker-src 'none'", false}, | 408 {"default-src *; script-src *; worker-src 'none'", false}, |
| 409 {"default-src *; child-src *; worker-src http://not.example.test", false}, | 409 {"default-src *; script-src *; worker-src http://not.example.test", |
| 410 {"default-src *; child-src *; worker-src https://example.test", true}, | 410 false}, |
| 411 {"default-src *; script-src *; worker-src https://example.test", true}, | |
| 411 | 412 |
| 412 // Fallback to child-src. | 413 // Fallback to script-src. |
| 413 {"child-src 'none'", false}, | 414 {"script-src 'none'", false}, |
| 414 {"child-src http://not.example.test", false}, | 415 {"script-src http://not.example.test", false}, |
| 415 {"child-src https://example.test", true}, | 416 {"script-src https://example.test", true}, |
| 416 {"default-src *; child-src 'none'", false}, | 417 {"default-src *; script-src 'none'", false}, |
| 417 {"default-src *; child-src http://not.example.test", false}, | 418 {"default-src *; script-src http://not.example.test", false}, |
| 418 {"default-src *; child-src https://example.test", true}, | 419 {"default-src *; script-src https://example.test", true}, |
| 419 | 420 |
|
estark
2016/11/29 22:01:16
Maybe add
script-src 'none'; child-src *
to test t
Mike West
2016/11/30 12:34:30
Added a new test for the fallback behavior. Thanks
| |
| 420 // Fallback to default-src. | 421 // Fallback to default-src. |
| 421 {"default-src 'none'", false}, | 422 {"default-src 'none'", false}, |
| 422 {"default-src http://not.example.test", false}, | 423 {"default-src http://not.example.test", false}, |
| 423 {"default-src https://example.test", true}, | 424 {"default-src https://example.test", true}, |
| 424 }; | 425 }; |
| 425 | 426 |
| 426 for (const auto& test : cases) { | 427 for (const auto& test : cases) { |
| 427 SCOPED_TRACE(test.list); | 428 SCOPED_TRACE(test.list); |
| 428 KURL resource = KURL(KURL(), "https://example.test/worker.js"); | 429 KURL resource = KURL(KURL(), "https://example.test/worker.js"); |
| 429 Member<CSPDirectiveList> directiveList = | 430 Member<CSPDirectiveList> directiveList = |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 EXPECT_EQ(test.expected, A->subsumes(listB)); | 511 EXPECT_EQ(test.expected, A->subsumes(listB)); |
| 511 // Empty CSPDirective subsumes any list. | 512 // Empty CSPDirective subsumes any list. |
| 512 EXPECT_TRUE(emptyA->subsumes(listB)); | 513 EXPECT_TRUE(emptyA->subsumes(listB)); |
| 513 // Check if first policy of `listB` subsumes `A`. | 514 // Check if first policy of `listB` subsumes `A`. |
| 514 EXPECT_EQ(test.expectedFirstPolicyOpposite, | 515 EXPECT_EQ(test.expectedFirstPolicyOpposite, |
| 515 listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A))); | 516 listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A))); |
| 516 } | 517 } |
| 517 } | 518 } |
| 518 | 519 |
| 519 TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) { | 520 TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) { |
| 520 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault }; | 521 enum DefaultBehaviour { |
| 522 Default, | |
| 523 NoDefault, | |
| 524 ChildAndDefault, | |
| 525 ScriptAndDefault | |
| 526 }; | |
| 521 | 527 |
| 522 struct TestCase { | 528 struct TestCase { |
| 523 ContentSecurityPolicy::DirectiveType directive; | 529 ContentSecurityPolicy::DirectiveType directive; |
| 524 const DefaultBehaviour type; | 530 const DefaultBehaviour type; |
| 525 } cases[] = { | 531 } cases[] = { |
| 526 // Directives with default directive. | 532 // Directives with default directive. |
| 527 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default}, | 533 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default}, |
| 528 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default}, | 534 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default}, |
| 529 {ContentSecurityPolicy::DirectiveType::FontSrc, Default}, | 535 {ContentSecurityPolicy::DirectiveType::FontSrc, Default}, |
| 530 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default}, | 536 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default}, |
| 531 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default}, | 537 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default}, |
| 532 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default}, | 538 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default}, |
| 533 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default}, | 539 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default}, |
| 534 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default}, | 540 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default}, |
| 535 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default}, | 541 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default}, |
| 536 // Directives with no default directive. | 542 // Directives with no default directive. |
| 537 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault}, | 543 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault}, |
| 538 {ContentSecurityPolicy::DirectiveType::DefaultSrc, NoDefault}, | 544 {ContentSecurityPolicy::DirectiveType::DefaultSrc, NoDefault}, |
| 539 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault}, | 545 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault}, |
| 540 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault}, | 546 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault}, |
| 541 // Directive with multiple default directives. | 547 // Directive with multiple default directives. |
| 542 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault}, | 548 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault}, |
| 543 {ContentSecurityPolicy::DirectiveType::WorkerSrc, ChildAndDefault}, | 549 {ContentSecurityPolicy::DirectiveType::WorkerSrc, ScriptAndDefault}, |
| 544 }; | 550 }; |
| 545 | 551 |
| 546 // Initial set-up. | 552 // Initial set-up. |
| 547 std::stringstream allDirectives; | 553 std::stringstream allDirectives; |
| 548 for (const auto& test : cases) { | 554 for (const auto& test : cases) { |
| 549 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive); | 555 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive); |
| 550 allDirectives << name << " http://" << name << ".com; "; | 556 allDirectives << name << " http://" << name << ".com; "; |
| 551 } | 557 } |
| 552 CSPDirectiveList* allDirectivesList = createList( | 558 CSPDirectiveList* allDirectivesList = createList( |
| 553 allDirectives.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce); | 559 allDirectives.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce); |
| 554 CSPDirectiveList* empty = | 560 CSPDirectiveList* empty = |
| 555 createList("", ContentSecurityPolicyHeaderTypeEnforce); | 561 createList("", ContentSecurityPolicyHeaderTypeEnforce); |
| 556 | 562 |
| 557 for (const auto& test : cases) { | 563 for (const auto& test : cases) { |
| 558 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive); | 564 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive); |
| 559 // When CSPDirectiveList is empty, then `null` should be returned for any | 565 // When CSPDirectiveList is empty, then `null` should be returned for any |
| 560 // type. | 566 // type. |
| 561 EXPECT_FALSE(empty->operativeDirective(test.directive)); | 567 EXPECT_FALSE(empty->operativeDirective(test.directive)); |
| 562 | 568 |
| 563 // When all directives present, then given a type that directive value | 569 // When all directives present, then given a type that directive value |
| 564 // should be returned. | 570 // should be returned. |
| 565 HeapVector<Member<CSPSource>> sources = | 571 HeapVector<Member<CSPSource>> sources = |
| 566 allDirectivesList->operativeDirective(test.directive)->m_list; | 572 allDirectivesList->operativeDirective(test.directive)->m_list; |
| 567 EXPECT_EQ(sources.size(), 1u); | 573 EXPECT_EQ(sources.size(), 1u); |
| 568 EXPECT_TRUE(sources[0]->m_host.startsWith(name)); | 574 EXPECT_TRUE(sources[0]->m_host.startsWith(name)); |
| 569 | 575 |
| 570 std::stringstream allExceptThis; | 576 std::stringstream allExceptThis; |
| 571 std::stringstream allExceptChildSrcAndThis; | 577 std::stringstream allExceptChildSrcAndThis; |
| 578 std::stringstream allExceptScriptSrcAndThis; | |
| 572 for (const auto& subtest : cases) { | 579 for (const auto& subtest : cases) { |
| 573 if (subtest.directive == test.directive) | 580 if (subtest.directive == test.directive) |
| 574 continue; | 581 continue; |
| 575 const char* directiveName = | 582 const char* directiveName = |
| 576 ContentSecurityPolicy::getDirectiveName(subtest.directive); | 583 ContentSecurityPolicy::getDirectiveName(subtest.directive); |
| 577 allExceptThis << directiveName << " http://" << directiveName << ".com; "; | 584 allExceptThis << directiveName << " http://" << directiveName << ".com; "; |
| 578 if (subtest.directive != ContentSecurityPolicy::DirectiveType::ChildSrc) { | 585 if (subtest.directive != ContentSecurityPolicy::DirectiveType::ChildSrc) { |
| 579 allExceptChildSrcAndThis << directiveName << " http://" << directiveName | 586 allExceptChildSrcAndThis << directiveName << " http://" << directiveName |
| 580 << ".com; "; | 587 << ".com; "; |
| 581 } | 588 } |
| 589 if (subtest.directive != | |
| 590 ContentSecurityPolicy::DirectiveType::ScriptSrc) { | |
| 591 allExceptScriptSrcAndThis << directiveName << " http://" | |
| 592 << directiveName << ".com; "; | |
| 593 } | |
| 582 } | 594 } |
| 583 CSPDirectiveList* allExceptThisList = createList( | 595 CSPDirectiveList* allExceptThisList = createList( |
| 584 allExceptThis.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce); | 596 allExceptThis.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce); |
| 585 CSPDirectiveList* allExceptChildSrcAndThisList = | 597 CSPDirectiveList* allExceptChildSrcAndThisList = |
| 586 createList(allExceptChildSrcAndThis.str().c_str(), | 598 createList(allExceptChildSrcAndThis.str().c_str(), |
| 587 ContentSecurityPolicyHeaderTypeEnforce); | 599 ContentSecurityPolicyHeaderTypeEnforce); |
| 600 CSPDirectiveList* allExceptScriptSrcAndThisList = | |
| 601 createList(allExceptScriptSrcAndThis.str().c_str(), | |
| 602 ContentSecurityPolicyHeaderTypeEnforce); | |
| 588 | 603 |
| 589 switch (test.type) { | 604 switch (test.type) { |
| 590 case Default: | 605 case Default: |
| 591 sources = allExceptThisList->operativeDirective(test.directive)->m_list; | 606 sources = allExceptThisList->operativeDirective(test.directive)->m_list; |
| 592 EXPECT_EQ(sources.size(), 1u); | 607 EXPECT_EQ(sources.size(), 1u); |
| 593 EXPECT_EQ(sources[0]->m_host, "default-src.com"); | 608 EXPECT_EQ(sources[0]->m_host, "default-src.com"); |
| 594 break; | 609 break; |
| 595 case NoDefault: | 610 case NoDefault: |
| 596 EXPECT_FALSE(allExceptThisList->operativeDirective(test.directive)); | 611 EXPECT_FALSE(allExceptThisList->operativeDirective(test.directive)); |
| 597 break; | 612 break; |
| 598 case ChildAndDefault: | 613 case ChildAndDefault: |
| 599 sources = allExceptThisList->operativeDirective(test.directive)->m_list; | 614 sources = allExceptThisList->operativeDirective(test.directive)->m_list; |
| 600 EXPECT_EQ(sources.size(), 1u); | 615 EXPECT_EQ(sources.size(), 1u); |
| 601 EXPECT_EQ(sources[0]->m_host, "child-src.com"); | 616 EXPECT_EQ(sources[0]->m_host, "child-src.com"); |
| 602 sources = | 617 sources = |
| 603 allExceptChildSrcAndThisList->operativeDirective(test.directive) | 618 allExceptChildSrcAndThisList->operativeDirective(test.directive) |
| 604 ->m_list; | 619 ->m_list; |
| 605 EXPECT_EQ(sources.size(), 1u); | 620 EXPECT_EQ(sources.size(), 1u); |
| 606 EXPECT_EQ(sources[0]->m_host, "default-src.com"); | 621 EXPECT_EQ(sources[0]->m_host, "default-src.com"); |
| 607 break; | 622 break; |
| 623 case ScriptAndDefault: | |
| 624 sources = allExceptThisList->operativeDirective(test.directive)->m_list; | |
| 625 EXPECT_EQ(sources.size(), 1u); | |
| 626 EXPECT_EQ(sources[0]->m_host, "script-src.com"); | |
| 627 sources = | |
| 628 allExceptScriptSrcAndThisList->operativeDirective(test.directive) | |
| 629 ->m_list; | |
| 630 EXPECT_EQ(sources.size(), 1u); | |
| 631 EXPECT_EQ(sources[0]->m_host, "default-src.com"); | |
| 632 break; | |
| 608 } | 633 } |
| 609 } | 634 } |
| 610 } | 635 } |
| 611 | 636 |
| 612 TEST_F(CSPDirectiveListTest, GetSourceVector) { | 637 TEST_F(CSPDirectiveListTest, GetSourceVector) { |
| 613 const std::vector<const char*> policies = { | 638 const std::vector<const char*> policies = { |
| 614 // Policy 1 | 639 // Policy 1 |
| 615 "default-src https://default-src.com", | 640 "default-src https://default-src.com", |
| 616 // Policy 2 | 641 // Policy 2 |
| 617 "child-src http://child-src.com", | 642 "child-src http://child-src.com", |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 752 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(), | 777 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(), |
| 753 udpatedTotal); | 778 udpatedTotal); |
| 754 EXPECT_EQ(CSPDirectiveList::getSourceVector( | 779 EXPECT_EQ(CSPDirectiveList::getSourceVector( |
| 755 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector) | 780 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector) |
| 756 .size(), | 781 .size(), |
| 757 expectedChildSrc); | 782 expectedChildSrc); |
| 758 } | 783 } |
| 759 } | 784 } |
| 760 | 785 |
| 761 } // namespace blink | 786 } // namespace blink |
| OLD | NEW |