OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/SourceListDirective.h" | 5 #include "core/frame/csp/SourceListDirective.h" |
6 | 6 |
7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
8 #include "core/frame/csp/CSPSource.h" | 8 #include "core/frame/csp/CSPSource.h" |
9 #include "core/frame/csp/ContentSecurityPolicy.h" | 9 #include "core/frame/csp/ContentSecurityPolicy.h" |
10 #include "platform/network/ResourceRequest.h" | 10 #include "platform/network/ResourceRequest.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 | 31 |
32 virtual void SetUp() { | 32 virtual void SetUp() { |
33 KURL secureURL(ParsedURLString, "https://example.test/image.png"); | 33 KURL secureURL(ParsedURLString, "https://example.test/image.png"); |
34 RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(secureURL)); | 34 RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(secureURL)); |
35 document = Document::create(); | 35 document = Document::create(); |
36 document->setSecurityOrigin(secureOrigin); | 36 document->setSecurityOrigin(secureOrigin); |
37 csp->bindToExecutionContext(document.get()); | 37 csp->bindToExecutionContext(document.get()); |
38 } | 38 } |
39 | 39 |
40 ContentSecurityPolicy* SetUpWithOrigin(const String& origin) { | 40 ContentSecurityPolicy* SetUpWithOrigin(const String& origin) { |
41 KURL url(ParsedURLString, origin); | 41 KURL secureURL(ParsedURLString, origin); |
42 RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(url)); | 42 RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(secureURL)); |
43 Document* document = Document::create(); | 43 Document* document = Document::create(); |
44 document->setSecurityOrigin(secureOrigin); | 44 document->setSecurityOrigin(secureOrigin); |
45 ContentSecurityPolicy* csp = ContentSecurityPolicy::create(); | 45 ContentSecurityPolicy* csp = ContentSecurityPolicy::create(); |
46 csp->bindToExecutionContext(document); | 46 csp->bindToExecutionContext(document); |
47 return csp; | 47 return csp; |
48 } | 48 } |
49 | 49 |
50 bool equalSources(const Source& a, const Source& b) { | 50 bool equalSources(const Source& a, const Source& b) { |
51 return a.scheme == b.scheme && a.host == b.host && a.port == b.port && | 51 return a.scheme == b.scheme && a.host == b.host && a.port == b.port && |
52 a.path == b.path && a.hostWildcard == b.hostWildcard && | 52 a.path == b.path && a.hostWildcard == b.hostWildcard && |
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 for (const auto& sources : test.sourcesB) { | 557 for (const auto& sources : test.sourcesB) { |
558 SourceListDirective* member = | 558 SourceListDirective* member = |
559 new SourceListDirective("script-src", sources, cspB); | 559 new SourceListDirective("script-src", sources, cspB); |
560 vectorB.append(member); | 560 vectorB.append(member); |
561 } | 561 } |
562 | 562 |
563 EXPECT_EQ(test.expected, A.subsumes(vectorB)); | 563 EXPECT_EQ(test.expected, A.subsumes(vectorB)); |
564 } | 564 } |
565 } | 565 } |
566 | 566 |
| 567 TEST_F(SourceListDirectiveTest, AllowAllInline) { |
| 568 struct TestCase { |
| 569 String sources; |
| 570 bool expected; |
| 571 } cases[] = { |
| 572 // List does not contain 'unsafe-inline'. |
| 573 {"http://example1.com/foo/", false}, |
| 574 {"'sha512-321cba'", false}, |
| 575 {"'nonce-yay'", false}, |
| 576 {"'strict-dynamic'", false}, |
| 577 {"'sha512-321cba' http://example1.com/foo/", false}, |
| 578 {"http://example1.com/foo/ 'sha512-321cba'", false}, |
| 579 {"http://example1.com/foo/ 'nonce-yay'", false}, |
| 580 {"'sha512-321cba' 'nonce-yay'", false}, |
| 581 {"http://example1.com/foo/ 'sha512-321cba' 'nonce-yay'", false}, |
| 582 {"http://example1.com/foo/ 'sha512-321cba' 'nonce-yay'", false}, |
| 583 {" 'sha512-321cba' 'nonce-yay' 'strict-dynamic'", false}, |
| 584 // List contains 'unsafe-inline'. |
| 585 {"'unsafe-inline'", true}, |
| 586 {"'self' 'unsafe-inline'", true}, |
| 587 {"'unsafe-inline' http://example1.com/foo/", true}, |
| 588 {"'sha512-321cba' 'unsafe-inline'", false}, |
| 589 {"'nonce-yay' 'unsafe-inline'", false}, |
| 590 {"'strict-dynamic' 'unsafe-inline' 'nonce-yay'", false}, |
| 591 {"'sha512-321cba' http://example1.com/foo/ 'unsafe-inline'", false}, |
| 592 {"http://example1.com/foo/ 'sha512-321cba' 'unsafe-inline'", false}, |
| 593 {"http://example1.com/foo/ 'nonce-yay' 'unsafe-inline'", false}, |
| 594 {"'sha512-321cba' 'nonce-yay' 'unsafe-inline'", false}, |
| 595 {"http://example1.com/foo/ 'sha512-321cba' 'unsafe-inline' 'nonce-yay'", |
| 596 false}, |
| 597 {"http://example1.com/foo/ 'sha512-321cba' 'nonce-yay' 'unsafe-inline'", |
| 598 false}, |
| 599 {" 'sha512-321cba' 'unsafe-inline' 'nonce-yay' 'strict-dynamic'", false}, |
| 600 }; |
| 601 |
| 602 // Script-src and style-src differently handle presence of 'strict-dynamic'. |
| 603 SourceListDirective scriptSrc("script-src", |
| 604 "'strict-dynamic' 'unsafe-inline'", csp.get()); |
| 605 EXPECT_FALSE(scriptSrc.allowAllInline()); |
| 606 |
| 607 SourceListDirective styleSrc("style-src", "'strict-dynamic' 'unsafe-inline'", |
| 608 csp.get()); |
| 609 EXPECT_TRUE(styleSrc.allowAllInline()); |
| 610 |
| 611 for (const auto& test : cases) { |
| 612 SourceListDirective scriptSrc("script-src", test.sources, csp.get()); |
| 613 EXPECT_EQ(scriptSrc.allowAllInline(), test.expected); |
| 614 |
| 615 SourceListDirective styleSrc("style-src", test.sources, csp.get()); |
| 616 EXPECT_EQ(styleSrc.allowAllInline(), test.expected); |
| 617 |
| 618 // If source list doesn't have a valid type, it must not allow all inline. |
| 619 SourceListDirective imgSrc("img-src", test.sources, csp.get()); |
| 620 EXPECT_FALSE(imgSrc.allowAllInline()); |
| 621 } |
| 622 } |
| 623 |
| 624 TEST_F(SourceListDirectiveTest, SubsumesAllowAllInline) { |
| 625 struct TestCase { |
| 626 bool isScriptSrc; |
| 627 String sourcesA; |
| 628 std::vector<String> sourcesB; |
| 629 bool expected; |
| 630 } cases[] = { |
| 631 // `sourcesA` allows all inline behavior. |
| 632 {false, |
| 633 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic'", |
| 634 {"'unsafe-inline' http://example1.com/foo/bar.html"}, |
| 635 true}, |
| 636 {true, |
| 637 "http://example1.com/foo/ 'self' 'unsafe-inline'", |
| 638 {"http://example1.com/foo/ 'unsafe-inline'"}, |
| 639 true}, |
| 640 {true, |
| 641 "http://example1.com/foo/ 'self' 'unsafe-inline'", |
| 642 {"'unsafe-inline' 'nonce-yay'", "'unsafe-inline'"}, |
| 643 true}, |
| 644 {true, |
| 645 "http://example1.com/foo/ 'self' 'unsafe-inline'", |
| 646 {"'unsafe-inline' 'nonce-yay'", "'unsafe-inline'", "'strict-dynamic'"}, |
| 647 true}, |
| 648 {true, |
| 649 "http://example1.com/foo/ 'self' 'unsafe-inline'", |
| 650 {"'unsafe-inline' 'nonce-yay'", "'unsafe-inline'", |
| 651 "'strict-dynamic' 'nonce-yay'"}, |
| 652 true}, |
| 653 // `sourcesA` does not allow all inline behavior. |
| 654 {false, |
| 655 "http://example1.com/foo/ 'self' 'strict-dynamic'", |
| 656 {"'unsafe-inline' http://example1.com/foo/bar.html"}, |
| 657 false}, |
| 658 {true, "http://example1.com/foo/ 'self'", {"'unsafe-inline'"}, false}, |
| 659 {true, |
| 660 "http://example1.com/foo/ 'self' 'unsafe-inline'", |
| 661 {"'unsafe-inline' 'nonce-yay'", "'nonce-abc'"}, |
| 662 true}, |
| 663 {true, |
| 664 "http://example1.com/foo/ 'self'", |
| 665 {"'unsafe-inline' https://example.test/"}, |
| 666 false}, |
| 667 {true, |
| 668 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic'", |
| 669 {"'unsafe-inline' https://example.test/"}, |
| 670 false}, |
| 671 {true, |
| 672 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic'", |
| 673 {"'unsafe-inline' 'strict-dynamic'"}, |
| 674 true}, |
| 675 {true, |
| 676 "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-yay'", |
| 677 {"'unsafe-inline' 'nonce-yay'"}, |
| 678 true}, |
| 679 {true, |
| 680 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic' " |
| 681 "'nonce-yay'", |
| 682 {"'unsafe-inline' 'nonce-yay'"}, |
| 683 true}, |
| 684 {true, |
| 685 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic' " |
| 686 "'nonce-yay'", |
| 687 {"http://example1.com/foo/ 'unsafe-inline' 'strict-dynamic'"}, |
| 688 true}, |
| 689 {true, |
| 690 "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba' " |
| 691 "'strict-dynamic'", |
| 692 {"'unsafe-inline' 'sha512-321cba'"}, |
| 693 true}, |
| 694 {true, |
| 695 "http://example1.com/foo/ 'self' 'unsafe-inline' 'strict-dynamic' " |
| 696 "'sha512-321cba'", |
| 697 {"http://example1.com/foo/ 'unsafe-inline' 'strict-dynamic'"}, |
| 698 true}, |
| 699 {true, |
| 700 "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", |
| 701 {"http://example1.com/foo/ 'unsafe-inline'", |
| 702 "http://example1.com/foo/ 'sha512-321cba'"}, |
| 703 true}, |
| 704 {true, |
| 705 "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", |
| 706 {"http://example1.com/foo/ 'unsafe-inline'", |
| 707 "http://example1.com/foo/ 'unsafe-inline' 'sha512-321cba'"}, |
| 708 false}, |
| 709 {true, |
| 710 "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'", |
| 711 {"http://example1.com/foo/ 'unsafe-inline' 'nonce-yay'", |
| 712 "http://example1.com/foo/ 'unsafe-inline' 'sha512-321cba'"}, |
| 713 true}, |
| 714 }; |
| 715 |
| 716 for (const auto& test : cases) { |
| 717 SourceListDirective A(test.isScriptSrc ? "script-src" : "style-src", |
| 718 test.sourcesA, csp.get()); |
| 719 ContentSecurityPolicy* cspB = |
| 720 SetUpWithOrigin("https://another.test/image.png"); |
| 721 |
| 722 HeapVector<Member<SourceListDirective>> vectorB; |
| 723 for (const auto& sources : test.sourcesB) { |
| 724 SourceListDirective* member = new SourceListDirective( |
| 725 test.isScriptSrc ? "script-src" : "style-src", sources, cspB); |
| 726 vectorB.append(member); |
| 727 } |
| 728 |
| 729 EXPECT_EQ(A.subsumes(vectorB), test.expected); |
| 730 } |
| 731 } |
| 732 |
567 } // namespace blink | 733 } // namespace blink |
OLD | NEW |