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 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 struct TestCase { | |
440 const std::vector<const char*> policies; | |
Mike West
2016/11/17 11:25:15
If you move the |listA| definition above this stru
| |
441 bool expected; | |
442 bool expectedFirstPolicyOpposite; | |
Mike West
2016/11/17 11:25:16
This is a strange name. :)
| |
443 } cases[] = { | |
444 // `listB`, which is not as restrictive as `A`, is not subsumed. | |
445 {{""}, false, true}, | |
446 {{"script-src http://example.com"}, false, false}, | |
447 {{"img-src http://example.com"}, false, false}, | |
448 {{"script-src http://*.one.com"}, false, true}, | |
449 {{"img-src https://one.com http://two.com/imgs/"}, false, true}, | |
450 {{"default-src http://example.com"}, false, false}, | |
451 {{"default-src https://one.com http://two.com/imgs/"}, false, false}, | |
452 {{"default-src http://one.com"}, false, false}, | |
453 {{"script-src http://*.one.com; img-src http://two.com/"}, false, false}, | |
454 {{"script-src http://*.one.com", "img-src http://one.com"}, false, true}, | |
455 {{"script-src http://*.one.com", "script-src https://two.com"}, | |
456 false, | |
457 true}, | |
458 {{"script-src http://*.random.com", "script-src https://random.com"}, | |
459 false, | |
460 false}, | |
461 {{"script-src http://one.com", "script-src https://random.com"}, | |
462 false, | |
463 false}, | |
464 {{"script-src http://*.random.com; default-src http://one.com " | |
465 "http://two.com/imgs/", | |
466 "default-src https://random.com"}, | |
467 false, | |
468 false}, | |
469 // `listB`, which is as restrictive as `A`, is subsumed. | |
470 {{"default-src https://one.com"}, true, false}, | |
471 {{"default-src http://random.com", | |
472 "default-src https://non-random.com:*"}, | |
473 true, | |
474 false}, | |
475 {{"script-src http://*.one.com; img-src https://one.com"}, true, false}, | |
476 {{"script-src http://*.one.com; img-src https://one.com " | |
477 "http://two.com/imgs/"}, | |
478 true, | |
479 true}, | |
480 {{"script-src http://*.one.com", | |
481 "img-src https://one.com http://two.com/imgs/"}, | |
482 true, | |
483 true}, | |
484 {{"script-src http://*.random.com; default-src https://one.com " | |
485 "http://two.com/imgs/", | |
486 "default-src https://else.com"}, | |
487 true, | |
488 false}, | |
489 {{"script-src http://*.random.com; default-src https://one.com " | |
490 "http://two.com/imgs/", | |
491 "default-src https://one.com"}, | |
492 true, | |
493 false}, | |
494 }; | |
495 | |
496 Member<CSPDirectiveList> A = createList( | |
497 "script-src http://*.one.com; img-src https://one.com " | |
498 "http://two.com/imgs/", | |
499 ContentSecurityPolicyHeaderTypeReport); | |
500 | |
501 Member<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, GetSourceList) { | |
520 const std::vector<const char*> policies = { | |
521 // Policy 1 | |
522 "default-src https://default-src.com", | |
523 // Policy 2 | |
524 "child-src http://child-src.com", | |
525 // Policy 3 | |
526 "child-src http://child-src.com; default-src https://default-src.com", | |
527 // Policy 4 | |
528 "base-uri http://base-uri.com", | |
529 // Policy 5 | |
530 "frame-src http://frame-src.com"}; | |
531 | |
532 // Check expectations on the initial set-up. | |
533 HeapVector<Member<CSPDirectiveList>> policyVector; | |
534 for (const auto& policy : policies) { | |
535 policyVector.append( | |
536 createList(policy, ContentSecurityPolicyHeaderTypeReport)); | |
537 } | |
538 HeapVector<Member<SourceListDirective>> result = | |
539 CSPDirectiveList::getSourceList(ContentSecurityPolicy::DefaultSrc, | |
540 policyVector); | |
541 EXPECT_EQ(result.size(), 0u); | |
542 result = CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, | |
543 policyVector); | |
544 EXPECT_EQ(result.size(), 3u); | |
545 result = CSPDirectiveList::getSourceList(ContentSecurityPolicy::BaseURI, | |
546 policyVector); | |
547 EXPECT_EQ(result.size(), 1u); | |
548 result = CSPDirectiveList::getSourceList(ContentSecurityPolicy::FrameSrc, | |
549 policyVector); | |
550 EXPECT_EQ(result.size(), 4u); | |
551 | |
552 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault }; | |
553 | |
554 struct TestCase { | |
555 const char* directive; | |
556 const DefaultBehaviour type; | |
557 size_t expectedTotal; | |
558 int expectedCurrent; | |
559 int expectedDefaultSrc; | |
560 int expectedChildSrc; | |
561 } cases[] = { | |
562 // Directives with default directive. | |
563 {ContentSecurityPolicy::ChildSrc, Default, 4u, 3, 1, 3}, | |
564 {ContentSecurityPolicy::ConnectSrc, Default, 3u, 1, 2, 0}, | |
565 {ContentSecurityPolicy::FontSrc, Default, 3u, 1, 2, 0}, | |
566 {ContentSecurityPolicy::ImgSrc, Default, 3u, 1, 2, 0}, | |
567 {ContentSecurityPolicy::ManifestSrc, Default, 3u, 1, 2, 0}, | |
568 {ContentSecurityPolicy::MediaSrc, Default, 3u, 1, 2, 0}, | |
569 {ContentSecurityPolicy::ObjectSrc, Default, 3u, 1, 2, 0}, | |
570 {ContentSecurityPolicy::ScriptSrc, Default, 3u, 1, 2, 0}, | |
571 {ContentSecurityPolicy::StyleSrc, Default, 3u, 1, 2, 0}, | |
572 // Directives with no default directive. | |
573 {ContentSecurityPolicy::BaseURI, NoDefault, 2u, 2, 0, 0}, | |
574 {ContentSecurityPolicy::FrameAncestors, NoDefault, 1u, 1, 0, 0}, | |
575 {ContentSecurityPolicy::FormAction, NoDefault, 1u, 1, 0, 0}, | |
576 // Directive with multiple default directives. | |
577 {ContentSecurityPolicy::FrameSrc, ChildAndDefault, 5u, 2, 1, 2}, | |
578 }; | |
579 | |
580 for (const auto& test : cases) { | |
581 // Initial set-up. | |
582 HeapVector<Member<CSPDirectiveList>> policyVector; | |
583 for (const auto& policy : policies) { | |
584 policyVector.append( | |
585 createList(policy, ContentSecurityPolicyHeaderTypeReport)); | |
586 } | |
587 // Append current test's policy. | |
588 std::stringstream currentDirective; | |
589 currentDirective << test.directive << " http://" << test.directive | |
590 << ".com;"; | |
591 policyVector.append(createList(currentDirective.str().c_str(), | |
592 ContentSecurityPolicyHeaderTypeReport)); | |
593 | |
594 HeapVector<Member<SourceListDirective>> result = | |
595 CSPDirectiveList::getSourceList(test.directive, policyVector); | |
596 | |
597 EXPECT_EQ(result.size(), test.expectedTotal); | |
598 | |
599 int actualCurrent = 0, actualDefault = 0, actualChild = 0; | |
600 for (const auto& srcList : result) { | |
601 HeapVector<Member<CSPSource>> sources = srcList->m_list; | |
602 for (const auto& source : sources) { | |
603 if (source->m_host.startsWith(test.directive)) | |
604 actualCurrent += 1; | |
605 else if (source->m_host == "default-src.com") | |
606 actualDefault += 1; | |
607 | |
608 if (source->m_host == "child-src.com") | |
609 actualChild += 1; | |
610 } | |
611 } | |
612 | |
613 EXPECT_EQ(actualDefault, test.expectedDefaultSrc); | |
614 EXPECT_EQ(actualCurrent, test.expectedCurrent); | |
615 EXPECT_EQ(actualChild, test.expectedChildSrc); | |
616 | |
617 // If another default-src is added that should only impact Fetch Directives | |
618 policyVector.append(createList("default-src https://default-src.com;", | |
619 ContentSecurityPolicyHeaderTypeReport)); | |
620 size_t udpatedTotal = | |
621 test.type != NoDefault ? test.expectedTotal + 1 : test.expectedTotal; | |
622 EXPECT_EQ( | |
623 CSPDirectiveList::getSourceList(test.directive, policyVector).size(), | |
624 udpatedTotal); | |
625 size_t expectedChildSrc = | |
626 test.directive == ContentSecurityPolicy::ChildSrc ? 5u : 4u; | |
627 EXPECT_EQ(CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, | |
628 policyVector) | |
629 .size(), | |
630 expectedChildSrc); | |
631 | |
632 // If another child-src is added that should only impact frame-src and | |
633 // child-src | |
634 policyVector.append(createList("child-src http://child-src.com;", | |
635 ContentSecurityPolicyHeaderTypeReport)); | |
636 udpatedTotal = test.type == ChildAndDefault || | |
637 test.directive == ContentSecurityPolicy::ChildSrc | |
638 ? udpatedTotal + 1 | |
639 : udpatedTotal; | |
640 EXPECT_EQ( | |
641 CSPDirectiveList::getSourceList(test.directive, policyVector).size(), | |
642 udpatedTotal); | |
643 expectedChildSrc = expectedChildSrc + 1u; | |
644 EXPECT_EQ(CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, | |
645 policyVector) | |
646 .size(), | |
647 expectedChildSrc); | |
648 | |
649 // If we add sandbox, nothing should change since it is currenly not | |
650 // considered. | |
651 policyVector.append(createList("sandbox http://sandbox.com;", | |
652 ContentSecurityPolicyHeaderTypeReport)); | |
653 EXPECT_EQ( | |
654 CSPDirectiveList::getSourceList(test.directive, policyVector).size(), | |
655 udpatedTotal); | |
656 EXPECT_EQ(CSPDirectiveList::getSourceList(ContentSecurityPolicy::ChildSrc, | |
657 policyVector) | |
658 .size(), | |
659 expectedChildSrc); | |
660 } | |
661 } | |
662 | |
438 } // namespace blink | 663 } // namespace blink |
OLD | NEW |