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 |