Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp

Issue 2474903002: Part 3.1: Is policy list subsumed under subsuming policy? (Closed)
Patch Set: OperativeDirective test + other changes based on reviews Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 KURL resource = KURL(KURL(), "https://example.test/worker.js"); 428 KURL resource = KURL(KURL(), "https://example.test/worker.js");
429 Member<CSPDirectiveList> directiveList = 429 Member<CSPDirectiveList> directiveList =
430 createList(test.list, ContentSecurityPolicyHeaderTypeEnforce); 430 createList(test.list, ContentSecurityPolicyHeaderTypeEnforce);
431 EXPECT_EQ(test.allowed, 431 EXPECT_EQ(test.allowed,
432 directiveList->allowWorkerFromSource( 432 directiveList->allowWorkerFromSource(
433 resource, ResourceRequest::RedirectStatus::NoRedirect, 433 resource, ResourceRequest::RedirectStatus::NoRedirect,
434 ContentSecurityPolicy::SuppressReport)); 434 ContentSecurityPolicy::SuppressReport));
435 } 435 }
436 } 436 }
437 437
438 TEST_F(CSPDirectiveListTest, SubsumesBasedOnCSPSourcesOnly) {
439 CSPDirectiveList* A = createList(
440 "script-src http://*.one.com; img-src https://one.com "
441 "http://two.com/imgs/",
442 ContentSecurityPolicyHeaderTypeReport);
443
444 struct TestCase {
445 const std::vector<const char*> policies;
446 bool expected;
447 bool expectedFirstPolicyOpposite;
448 } cases[] = {
449 // `listB`, which is not as restrictive as `A`, is not subsumed.
450 {{""}, false, true},
451 {{"script-src http://example.com"}, false, false},
452 {{"img-src http://example.com"}, false, false},
453 {{"script-src http://*.one.com"}, false, true},
454 {{"img-src https://one.com http://two.com/imgs/"}, false, true},
455 {{"default-src http://example.com"}, false, false},
456 {{"default-src https://one.com http://two.com/imgs/"}, false, false},
457 {{"default-src http://one.com"}, false, false},
458 {{"script-src http://*.one.com; img-src http://two.com/"}, false, false},
459 {{"script-src http://*.one.com", "img-src http://one.com"}, false, true},
460 {{"script-src http://*.one.com", "script-src https://two.com"},
461 false,
462 true},
463 {{"script-src http://*.random.com", "script-src https://random.com"},
464 false,
465 false},
466 {{"script-src http://one.com", "script-src https://random.com"},
467 false,
468 false},
469 {{"script-src http://*.random.com; default-src http://one.com "
470 "http://two.com/imgs/",
471 "default-src https://random.com"},
472 false,
473 false},
474 // `listB`, which is as restrictive as `A`, is subsumed.
475 {{"default-src https://one.com"}, true, false},
476 {{"default-src http://random.com",
477 "default-src https://non-random.com:*"},
478 true,
479 false},
480 {{"script-src http://*.one.com; img-src https://one.com"}, true, false},
481 {{"script-src http://*.one.com; img-src https://one.com "
482 "http://two.com/imgs/"},
483 true,
484 true},
485 {{"script-src http://*.one.com",
486 "img-src https://one.com http://two.com/imgs/"},
487 true,
488 true},
489 {{"script-src http://*.random.com; default-src https://one.com "
490 "http://two.com/imgs/",
491 "default-src https://else.com"},
492 true,
493 false},
494 {{"script-src http://*.random.com; default-src https://one.com "
495 "http://two.com/imgs/",
496 "default-src https://one.com"},
497 true,
498 false},
499 };
500
501 CSPDirectiveList* emptyA =
502 createList("", ContentSecurityPolicyHeaderTypeReport);
503
504 for (const auto& test : cases) {
505 HeapVector<Member<CSPDirectiveList>> listB;
506 for (const auto& policy : test.policies) {
507 listB.append(createList(policy, ContentSecurityPolicyHeaderTypeReport));
508 }
509
510 EXPECT_EQ(test.expected, A->subsumes(listB));
511 // Empty CSPDirective subsumes any list.
512 EXPECT_TRUE(emptyA->subsumes(listB));
513 // Check if first policy of `listB` subsumes `A`.
514 EXPECT_EQ(test.expectedFirstPolicyOpposite,
515 listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A)));
516 }
517 }
518
519 TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
520 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
521
522 struct TestCase {
523 ContentSecurityPolicy::DirectiveType directive;
524 const DefaultBehaviour type;
525 } cases[] = {
526 // Directives with default directive.
527 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default},
528 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default},
529 {ContentSecurityPolicy::DirectiveType::FontSrc, Default},
530 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default},
531 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default},
532 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default},
533 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default},
534 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default},
535 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default},
536 // Directives with no default directive.
537 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault},
538 {ContentSecurityPolicy::DirectiveType::DefaultSrc, NoDefault},
539 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault},
540 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault},
541 // Directive with multiple default directives.
542 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault},
543 {ContentSecurityPolicy::DirectiveType::WorkerSrc, ChildAndDefault},
544 };
545
546 // Initial set-up.
547 std::stringstream allDirectives;
548 for (const auto& test : cases) {
549 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
550 allDirectives << name << " http://" << name << ".com; ";
551 }
552 CSPDirectiveList* allDirectivesList = createList(
553 allDirectives.str().c_str(), ContentSecurityPolicyHeaderTypeReport);
554 CSPDirectiveList* empty =
555 createList("", ContentSecurityPolicyHeaderTypeReport);
556
557 for (const auto& test : cases) {
558 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
559 // When CSPDirectiveList is empty, then `null` should be returned for any
560 // type.
561 EXPECT_FALSE(empty->operativeDirective(test.directive));
562
563 // When all directives present, then given a type that directive value
564 // should be returned.
565 HeapVector<Member<CSPSource>> sources =
566 allDirectivesList->operativeDirective(test.directive)->m_list;
567 EXPECT_EQ(sources.size(), 1u);
568 EXPECT_TRUE(sources[0]->m_host.startsWith(name));
569
570 std::stringstream allExceptThis;
571 for (const auto& subtest : cases) {
572 if (subtest.directive != test.directive) {
573 const char* directiveName =
574 ContentSecurityPolicy::getDirectiveName(subtest.directive);
575 allExceptThis << directiveName << " http://" << directiveName
576 << ".com; ";
577 }
578 }
579 CSPDirectiveList* allExceptThisList = createList(
580 allExceptThis.str().c_str(), ContentSecurityPolicyHeaderTypeReport);
581
582 switch (test.type) {
583 case Default:
584 sources = allExceptThisList->operativeDirective(test.directive)->m_list;
585 EXPECT_EQ(sources.size(), 1u);
586 EXPECT_EQ(sources[0]->m_host, "default-src.com");
587 break;
588 case NoDefault:
589 EXPECT_FALSE(allExceptThisList->operativeDirective(test.directive));
590 break;
591 case ChildAndDefault:
592 sources = allExceptThisList->operativeDirective(test.directive)->m_list;
593 EXPECT_EQ(sources.size(), 1u);
594 EXPECT_EQ(sources[0]->m_host, "child-src.com");
Mike West 2016/11/24 14:37:37 Can you verify that these fall back to `default-sr
amalika 2016/11/24 15:38:20 Added
595 break;
596 }
597 }
598 }
599
600 TEST_F(CSPDirectiveListTest, GetSourceVector) {
601 const std::vector<const char*> policies = {
602 // Policy 1
603 "default-src https://default-src.com",
604 // Policy 2
605 "child-src http://child-src.com",
606 // Policy 3
607 "child-src http://child-src.com; default-src https://default-src.com",
608 // Policy 4
609 "base-uri http://base-uri.com",
610 // Policy 5
611 "frame-src http://frame-src.com"};
612
613 // Check expectations on the initial set-up.
614 HeapVector<Member<CSPDirectiveList>> policyVector;
615 for (const auto& policy : policies) {
616 policyVector.append(
617 createList(policy, ContentSecurityPolicyHeaderTypeReport));
618 }
619 HeapVector<Member<SourceListDirective>> result =
620 CSPDirectiveList::getSourceVector(
621 ContentSecurityPolicy::DirectiveType::DefaultSrc, policyVector);
622 EXPECT_EQ(result.size(), 2u);
623 result = CSPDirectiveList::getSourceVector(
624 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector);
625 EXPECT_EQ(result.size(), 3u);
626 result = CSPDirectiveList::getSourceVector(
627 ContentSecurityPolicy::DirectiveType::BaseURI, policyVector);
628 EXPECT_EQ(result.size(), 1u);
629 result = CSPDirectiveList::getSourceVector(
630 ContentSecurityPolicy::DirectiveType::FrameSrc, policyVector);
631 EXPECT_EQ(result.size(), 4u);
632
633 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
634
635 struct TestCase {
636 ContentSecurityPolicy::DirectiveType directive;
637 const DefaultBehaviour type;
638 size_t expectedTotal;
639 int expectedCurrent;
640 int expectedDefaultSrc;
641 int expectedChildSrc;
642 } cases[] = {
643 // Directives with default directive.
644 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default, 4u, 3, 1, 3},
645 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default, 3u, 1, 2, 0},
646 {ContentSecurityPolicy::DirectiveType::FontSrc, Default, 3u, 1, 2, 0},
647 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default, 3u, 1, 2, 0},
648 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default, 3u, 1, 2, 0},
649 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default, 3u, 1, 2, 0},
650 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default, 3u, 1, 2, 0},
651 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default, 3u, 1, 2, 0},
652 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default, 3u, 1, 2, 0},
653 // Directives with no default directive.
654 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault, 2u, 2, 0, 0},
655 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault, 1u, 1,
656 0, 0},
657 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault, 1u, 1, 0,
658 0},
659 // Directive with multiple default directives.
660 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault, 5u, 2,
661 1, 2},
662 };
663
664 for (const auto& test : cases) {
665 // Initial set-up.
666 HeapVector<Member<CSPDirectiveList>> policyVector;
667 for (const auto& policy : policies) {
668 policyVector.append(
669 createList(policy, ContentSecurityPolicyHeaderTypeReport));
670 }
671 // Append current test's policy.
672 std::stringstream currentDirective;
673 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
674 currentDirective << name << " http://" << name << ".com;";
675 policyVector.append(createList(currentDirective.str().c_str(),
676 ContentSecurityPolicyHeaderTypeReport));
677
678 HeapVector<Member<SourceListDirective>> result =
679 CSPDirectiveList::getSourceVector(test.directive, policyVector);
680
681 EXPECT_EQ(result.size(), test.expectedTotal);
682
683 int actualCurrent = 0, actualDefault = 0, actualChild = 0;
684 for (const auto& srcList : result) {
685 HeapVector<Member<CSPSource>> sources = srcList->m_list;
686 for (const auto& source : sources) {
687 if (source->m_host.startsWith(name))
688 actualCurrent += 1;
689 else if (source->m_host == "default-src.com")
690 actualDefault += 1;
691
692 if (source->m_host == "child-src.com")
693 actualChild += 1;
694 }
695 }
696
697 EXPECT_EQ(actualDefault, test.expectedDefaultSrc);
698 EXPECT_EQ(actualCurrent, test.expectedCurrent);
699 EXPECT_EQ(actualChild, test.expectedChildSrc);
700
701 // If another default-src is added that should only impact Fetch Directives
702 policyVector.append(createList("default-src https://default-src.com;",
703 ContentSecurityPolicyHeaderTypeReport));
704 size_t udpatedTotal =
705 test.type != NoDefault ? test.expectedTotal + 1 : test.expectedTotal;
706 EXPECT_EQ(
707 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
708 udpatedTotal);
709 size_t expectedChildSrc =
710 test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc ? 5u
711 : 4u;
712 EXPECT_EQ(CSPDirectiveList::getSourceVector(
713 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
714 .size(),
715 expectedChildSrc);
716
717 // If another child-src is added that should only impact frame-src and
718 // child-src
719 policyVector.append(createList("child-src http://child-src.com;",
720 ContentSecurityPolicyHeaderTypeReport));
721 udpatedTotal =
722 test.type == ChildAndDefault ||
723 test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc
724 ? udpatedTotal + 1
725 : udpatedTotal;
726 EXPECT_EQ(
727 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
728 udpatedTotal);
729 expectedChildSrc = expectedChildSrc + 1u;
730 EXPECT_EQ(CSPDirectiveList::getSourceVector(
731 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
732 .size(),
733 expectedChildSrc);
734
735 // If we add sandbox, nothing should change since it is currenly not
736 // considered.
737 policyVector.append(createList("sandbox http://sandbox.com;",
738 ContentSecurityPolicyHeaderTypeReport));
739 EXPECT_EQ(
740 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
741 udpatedTotal);
742 EXPECT_EQ(CSPDirectiveList::getSourceVector(
743 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
744 .size(),
745 expectedChildSrc);
746 }
747 }
748
438 } // namespace blink 749 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698