Пример #1
0
class DirectoryEntryAuthTest(TestCase):
    def setUp(self):
        User = get_user_model()
        self.client = Client()
        self.username = "******"
        self.email = "*****@*****.**"
        self.password = "******"
        self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True)
        self.user.save()
        # Create a verified email address object for this user via allauth
        EmailAddress.objects.create(user=self.user, email=self.email, verified=True)
        # Setup pages. Site is needed for valid urls.
        site = Site.objects.get()
        directory = DirectoryPageFactory(parent=site.root_page)
        self.unowned_sd_page = DirectoryEntryFactory(live=True, parent=directory)
        self.unowned_sd_page.save()
        self.user_owned_sd_page = DirectoryEntryFactory(live=True, parent=directory)
        self.user_owned_sd_page.save()
        SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save()

    def test_logged_in_user_should_see_edit_on_owned_pages(self):
        # Login
        self.client.post(reverse_lazy('account_login'), {'login': self.email, 'password': self.password})
        response = self.client.get(self.user_owned_sd_page.url)
        self.assertTrue(response.context['page'].editable)

    def test_logged_out_user_should_not_see_edit(self):
        response = self.client.get(self.user_owned_sd_page.url)
        self.assertFalse(response.context['page'].editable)

    def test_logged_in_user_should_not_see_edit_on_unowned_pages(self):
        self.client.post(reverse_lazy('account_login'), {'login': self.email, 'password': self.password})
        response = self.client.get(self.unowned_sd_page.url)
        self.assertFalse(response.context['page'].editable)
Пример #2
0
class DirectoryLanguageFilterTest(TestCase):
    def setUp(self):
        self.directory = DirectoryPageFactory()
        # set up languages
        spanish = LanguageFactory(title='Spanish')
        chinese = LanguageFactory(title='Chinese')
        spanish.save()
        chinese.save()
        # set up instances that are children of the directory and have those languages
        self.spanish_instance = DirectoryEntryFactory(parent=self.directory)
        self.spanish_instance.languages.add(spanish)
        self.spanish_instance.save()

        self.chinese_instance = DirectoryEntryFactory(parent=self.directory)
        self.chinese_instance.languages.add(chinese)
        self.chinese_instance.save()
        self.lang_filter = {'languages': spanish}

    def test_language_filtered_for_is_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.lang_filter)
        self.assertIn(self.spanish_instance, filtered_instances)

    def test_langauge_not_filtered_for_is_not_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.lang_filter)
        self.assertNotIn(self.chinese_instance, filtered_instances)
Пример #3
0
 def test_securedrop_can_save_expected_urls(self):
     securedrop = DirectoryEntryFactory(
         landing_page_url='https://www.something.org',
         onion_address='https://notreal.onion',
     )
     securedrop.save()
     self.assertIn(securedrop, DirectoryEntry.objects.all())
Пример #4
0
class DirectoryCountryFilterTest(TestCase):
    def setUp(self):
        self.directory = DirectoryPageFactory()
        # set up countries
        mexico = CountryFactory(title='Mexico')
        azerbaijan = CountryFactory(title='Azerbaijan')
        mexico.save()
        azerbaijan.save()
        # set up instances that are children of the directory and have those countries
        self.mexico_instance = DirectoryEntryFactory(parent=self.directory)
        self.mexico_instance.countries.add(mexico)
        self.mexico_instance.save()

        self.azerbaijan_instance = DirectoryEntryFactory(parent=self.directory)
        self.azerbaijan_instance.countries.add(azerbaijan)
        self.azerbaijan_instance.save()
        self.country_filter = {'countries': mexico}

    def test_country_filtered_for_is_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.country_filter)
        self.assertIn(self.mexico_instance, filtered_instances)

    def test_country_not_filtered_for_is_not_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.country_filter)
        self.assertNotIn(self.azerbaijan_instance, filtered_instances)
Пример #5
0
class DirectoryTopicFilterTest(TestCase):
    def setUp(self):
        self.directory = DirectoryPageFactory()
        # set up topics
        pf = TopicFactory(title='Press Freedom')
        irs = TopicFactory(title='IRS')
        pf.save()
        irs.save()
        # set up instances that are children of the directory and have those topics
        self.pf_instance = DirectoryEntryFactory(parent=self.directory)
        self.pf_instance.topics.add(pf)
        self.pf_instance.save()

        self.irs_instance = DirectoryEntryFactory(parent=self.directory)
        self.irs_instance.topics.add(irs)
        self.irs_instance.save()
        self.topic_filter = {'topics': pf}

    def test_topic_filtered_for_is_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.topic_filter)
        self.assertIn(self.pf_instance, filtered_instances)

    def test_topic_not_filtered_for_is_not_in_queryset(self):
        filtered_instances = self.directory.get_instances(
            filters=self.topic_filter)
        self.assertNotIn(self.irs_instance, filtered_instances)
Пример #6
0
class DirectorySevereWarningTest(TestCase):
    def setUp(self):
        site = Site.objects.get()
        self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory(
            parent=site.root_page))
        self.result = ScanResultFactory(
            securedrop=self.entry,
            landing_page_url=self.entry.landing_page_url,
            severe_warning=True,
        )
        self.result.save()
        self.entry.save()

        self.client = Client()

    def test_warning_presence(self):
        """warning should be displayed if warnings flag in request"""
        response = self.client.get(self.entry.url)
        self.assertContains(
            response,
            'We strongly advise you to only visit this landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>, with the <a href="https://tb-manual.torproject.org/en-US/security-slider.html">security slider</a> set to "safest".',
            status_code=200,
        )

    def test_warning_message_suppressed_if_page_ignores_all_triggered_warnings(
            self):
        self.entry.warnings_ignored = ['no_third_party_assets']
        self.entry.save()
        self.entry.refresh_from_db()
        response = self.client.get(self.entry.url)
        self.assertNotContains(
            response,
            'We strongly advise you to only visit this landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>, with the <a href="https://tb-manual.torproject.org/en-US/security-slider.html">security slider</a> set to "safest".',
            status_code=200,
        )
Пример #7
0
    def handle(self, *args, **options):
        number_of_instances = options['number_of_instances']

        home_page = HomePage.objects.get(slug='home')
        directory = DirectoryPage.objects.first()
        if not directory:
            directory = DirectoryPageFactory(parent=home_page, title="Directory")
            directory.save()
        for i in range(number_of_instances):
            instance = DirectoryEntryFactory(parent=directory)
            if i % 3 == 0:
                scan = ScanResultFactory(
                    securedrop=instance,
                    landing_page_url=instance.landing_page_url,
                    no_failures=True,
                )
            elif i % 3 == 1:
                scan = ScanResultFactory(
                    securedrop=instance,
                    landing_page_url=instance.landing_page_url,
                    severe_warning=True,
                )
            else:
                scan = ScanResultFactory(
                    securedrop=instance,
                    landing_page_url=instance.landing_page_url,
                    moderate_warning=True,
                )
            scan.save()
            instance.save()
Пример #8
0
    def test_save_associates_results(self):
        landing_page_url = 'https://www.something.org'
        result = ScanResult(
            live=True,
            hsts=True,
            hsts_max_age=True,
            securedrop=None,
            landing_page_url=landing_page_url,
        )
        result.save()

        securedrop = DirectoryEntryFactory(
            landing_page_url=landing_page_url,
            onion_address='https://notreal.onion',
        )
        securedrop.save()
        result.refresh_from_db()
        self.assertEqual(result.securedrop, securedrop)
Пример #9
0
class DirectoryNoWarningTest(TestCase):
    def setUp(self):
        site = Site.objects.get()
        self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory(
            parent=site.root_page))
        self.result = ScanResultFactory(
            securedrop=self.entry,
            landing_page_url=self.entry.landing_page_url,
            no_failures=True,
        )
        self.result.save()
        self.entry.save()

        self.client = Client()

    def test_page_request_should_succeed_if_no_warnings_on_result(self):
        response = self.client.get(self.entry.url)
        self.assertEqual(response.status_code, 200)
Пример #10
0
class AuthenticatedTest(TestCase):
    @classmethod
    def setUpTestData(self):
        turn_on_instance_management()

    def setUp(self):
        User = get_user_model()
        self.client = Client()
        self.username = "******"
        self.email = "*****@*****.**"
        self.password = "******"
        self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True)
        self.user.save()
        # Create a verified email address object for this user via allauth
        EmailAddress.objects.create(user=self.user, email=self.email, verified=True)

        self.unowned_sd_page = DirectoryEntryFactory()
        self.unowned_sd_page.save()
        self.user_owned_sd_page = DirectoryEntryFactory()
        self.user_owned_sd_page.save()
        SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save()
        # Login
        self.client.post(reverse('account_login'), {'login': self.email, 'password': self.password})

    def test_authenticated_login_should_redirect_to_2fa_setup(self):
        """login without setting up a device should redirect to 2FA setup page"""
        response = self.client.post(
            reverse('account_login'),
            {'login': self.email, 'password': self.password},
        )
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, reverse('two-factor-setup'))

    def test_authenticated_user_cannot_view_dashboard(self):
        """dashboard should redirect unverified users users to the login page"""
        response = self.client.get(reverse('dashboard'))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, reverse('account_login'))
Пример #11
0
class DirectoryModerateWarningTest(TestCase):
    def setUp(self):
        site = Site.objects.get()
        self.entry = DirectoryEntryFactory(parent=DirectoryPageFactory(
            parent=site.root_page))
        self.result = ScanResultFactory(
            securedrop=self.entry,
            landing_page_url=self.entry.landing_page_url,
            moderate_warning=True,
        )
        self.result.save()
        self.entry.save()

        self.client = Client()

    def test_warning_presence(self):
        """warning should always be displayed"""
        response = self.client.get(self.entry.url)
        self.assertContains(
            response,
            'We recommend only visiting this SecureDrop landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>.',
            status_code=200,
        )

    def test_warning_message_suppressed_if_page_ignores_all_triggered_warnings(
            self):
        self.entry.warnings_ignored = ['safe_onion_address']
        self.entry.save()

        response = self.client.get(self.entry.url)

        self.assertNotContains(
            response,
            'We recommend only visiting this SecureDrop landing page <a href="https://www.torproject.org/download/download-easy.html.en">using the Tor browser</a>.',
            status_code=200,
        )

    def test_single_warning_message_suppressed_if_page_ignores_that_warning(
            self):
        self.result.subdomain = True
        self.result.save()
        self.entry.warnings_ignored = ['safe_onion_address']
        self.entry.save()

        response = self.client.get(self.entry.url)
        self.assertContains(
            response,
            'is hosted on a subdomain',
            status_code=200,
        )

        self.assertNotContains(
            response,
            'includes a clickable link to a Tor Onion Service',
            status_code=200,
        )
Пример #12
0
class DirectoryMultipleFiltersTest(TestCase):
    def setUp(self):
        self.directory = DirectoryPageFactory()
        # set up languages
        spanish = LanguageFactory(title='Spanish')
        chinese = LanguageFactory(title='Chinese')
        spanish.save()
        chinese.save()
        # set up countries
        mexico = CountryFactory(title='Mexico')
        azerbaijan = CountryFactory(title='Azerbaijan')
        mexico.save()
        azerbaijan.save()
        # set up topics
        pf = TopicFactory(title='Press Freedom')
        irs = TopicFactory(title='IRS')
        pf.save()
        irs.save()
        # set up instances that are children of the directory and have multiple categories
        self.sp_mx_instance = DirectoryEntryFactory(parent=self.directory)
        self.sp_mx_instance.languages.add(spanish)
        self.sp_mx_instance.countries.add(mexico)
        self.sp_mx_instance.save()

        self.az_pf_instance = DirectoryEntryFactory(parent=self.directory)
        self.az_pf_instance.countries.add(azerbaijan)
        self.az_pf_instance.topics.add(pf)
        self.az_pf_instance.save()

        self.other_instance = DirectoryEntryFactory(parent=self.directory)
        self.other_instance.languages.add(spanish)
        self.other_instance.topics.add(pf)
        self.other_instance.save()

        # filters
        self.lang_country_filter = {
            'languages': spanish,
            'countries': mexico
        }

        self.country_topic_filter = {
            'countries': azerbaijan,
            'topics': pf
        }

    def test_country_and_language_filter(self):
        filtered_instances = self.directory.get_instances(filters=self.lang_country_filter)
        self.assertIn(self.sp_mx_instance, filtered_instances)
        self.assertNotIn(self.other_instance, filtered_instances)

    def test_country_and_topic_filter(self):
        filtered_instances = self.directory.get_instances(filters=self.country_topic_filter)
        self.assertIn(self.az_pf_instance, filtered_instances)
        self.assertNotIn(self.other_instance, filtered_instances)
Пример #13
0
class ScanResultTest(TestCase):
    def setUp(self):
        self.securedrop = DirectoryEntryFactory()
        self.securedrop.save()

    def test_instance_on_subdomain_gets_moderate_warning(self):
        result = ScanResultFactory(no_failures=True, subdomain=True)
        self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE)

    def test_instance_with_incorrect_referrer_policy_gets_moderate_warning(self):
        result = ScanResultFactory(no_failures=True, referrer_policy_set_to_no_referrer=False)
        self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE)

    def test_instance_with_unsafe_onion_addresses_gets_moderate_warning(self):
        result = ScanResultFactory(no_failures=True, safe_onion_address=False)
        self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.MODERATE)

    def test_instance_with_third_party_cookies_gets_no_warning(self):
        result = ScanResultFactory(no_failures=True, no_cookies=False)
        self.assertEqual(self.securedrop.get_warnings(result), [])

    def test_instance_with_analytics_gets_severe_warning(self):
        result = ScanResultFactory(no_failures=True, no_analytics=False)
        self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.SEVERE)

    def test_instance_with_cdn_gets_no_warning(self):
        result = ScanResultFactory(no_failures=True, no_cdn=False)

        self.assertEqual(self.securedrop.get_warnings(result), [])

    def test_instance_with_cross_domain_assets_gets_severe_warning(self):
        result = ScanResultFactory(no_failures=True, no_cross_domain_assets=False)
        self.assertEqual(self.securedrop.get_warnings(result)[0].level, WarningLevel.SEVERE)

    def test_grade_computed_on_save(self):
        result = ScanResult(live=True, hsts=True, hsts_max_age=True,
                            securedrop=self.securedrop)
        self.assertEqual(result.grade, '?')
        result.save()
        self.assertEqual(result.grade, 'A')

    def test_an_instance_using_cookies_gets_an_F(self):
        result = ScanResult(live=True, no_cookies=False, securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'F')

    def test_an_instance_using_a_cdn_gets_a_D(self):
        result = ScanResult(live=True, no_cdn=False, securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'D')

    def test_an_instance_using_a_subdomain_gets_a_D(self):
        result = ScanResult(live=True, subdomain=True, securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'D')

    def test_an_instance_showing_server_software_in_headers_gets_a_D(self):
        result = ScanResult(live=True, no_server_info=False,
                            securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'D')

    def test_an_instance_showing_server_version_in_headers_gets_a_D(self):
        result = ScanResult(live=True, no_server_version=False,
                            securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'D')

    def test_an_instance_with_expires_not_set_gets_a_C(self):
        result = ScanResult(live=True, expires_set=False,
                            securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'C')

    def test_an_instance_with_cache_control_nostore_not_set_gets_a_B(self):
        result = ScanResult(live=True, cache_control_nostore_set=False,
                            hsts_max_age=True, securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, 'B')

    def test_a_down_instance_gets_a_null_grade(self):
        result = ScanResult(live=False, securedrop=self.securedrop)
        result.save()
        self.assertEqual(result.grade, '?')

    def test_securedrop_can_get_most_recent_scan(self):
        result1 = ScanResult(live=True, hsts=True, hsts_max_age=True,
                             securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url)
        result1.save()
        result2 = ScanResult(live=True, hsts=False, hsts_max_age=True,
                             securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url)
        result2.save()
        securedrop = DirectoryEntry.objects.get(id=self.securedrop.pk)
        most_recent = securedrop.results.latest()
        self.assertEqual(most_recent.grade, 'C')

    def test_result_string_representation(self):
        result1 = ScanResult(live=True, hsts=True, hsts_max_age=True,
                             securedrop=self.securedrop, landing_page_url=self.securedrop.landing_page_url)
        self.assertIn(result1.landing_page_url, result1.__str__())

    def test_is_equal_to_compares_only_scan_attributes__same_result(self):
        """Test is_equal_to does not compare pk, _state, etc."""
        result1 = ScanResult(live=True, hsts=True, hsts_max_age=True,
                             securedrop=self.securedrop)
        result2 = ScanResult(live=True, hsts=True, hsts_max_age=True,
                             securedrop=self.securedrop)
        self.assertTrue(result1.is_equal_to(result2))

    def test_is_equal_to_compares_only_scan_attributes__new_result(self):
        result1 = ScanResult(live=True, hsts=True, hsts_max_age=True, securedrop=self.securedrop)
        result2 = ScanResult(live=False, securedrop=self.securedrop)
        self.assertFalse(result1.is_equal_to(result2))

    def test_save_associates_results(self):
        result = ScanResult(
            live=True,
            hsts=True,
            hsts_max_age=True,
            securedrop=None,
            landing_page_url=self.securedrop.landing_page_url,
        )
        result.save()
        self.assertEqual(result.securedrop, self.securedrop)
Пример #14
0
class VerifiedTest(TestCase):
    @classmethod
    def setUpTestData(self):
        turn_on_instance_management()

    def setUp(self):
        User = get_user_model()
        self.client = Client()
        self.username = "******"
        self.email = "*****@*****.**"
        self.password = "******"
        self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password, is_active=True)

        self.site = Site.objects.get()
        self.directory = DirectoryPageFactory(
            parent=self.site.root_page,
        )

        self.unowned_sd_page = DirectoryEntryFactory()
        self.unowned_sd_page.save()
        self.user_owned_sd_page = DirectoryEntryFactory()
        self.user_owned_sd_page.save()
        SecuredropOwner(owner=self.user, page=self.user_owned_sd_page).save()

        # Create a verified email address object for this user via allauth
        EmailAddress.objects.create(user=self.user, email=self.email, verified=True)

        # Create a device with pre-determined parameters to allow 2FA
        # token verification.  Numbers copied from django_otp unit
        # tests.
        device = TOTPDevice.objects.create(
            user=self.user,
            confirmed=True,
            key='2a2bbba1092ffdd25a328ad1a0a5f5d61d7aacc4',
            step=30,
            t0=int(time() - (30 * 3)),
            digits=6,
            tolerance=0,
            drift=0,
        )
        self.client.post(
            reverse('account_login'),
            {'login': self.email, 'password': self.password},
        )
        self.client.post(
            reverse('two-factor-authenticate'),
            # The token below corresponds to the parameters on the
            # device just created.
            {'otp_device': device.id, 'otp_token': '154567'},
        )

    def test_verified_user_can_view_dashboard(self):
        response = self.client.get(reverse('dashboard'))
        self.assertEqual(response.status_code, 200)

    def test_verified_user_can_view_their_instances(self):
        slug = self.user_owned_sd_page.slug
        response = self.client.get(reverse('securedroppage_edit', kwargs={'slug': slug}))
        self.assertEqual(response.status_code, 200)

    def test_verified_user_cannot_view_other_instances(self):
        slug = self.unowned_sd_page.slug
        response = self.client.get(reverse('securedroppage_edit', kwargs={'slug': slug}))
        self.assertEqual(response.status_code, 403)

    def test_verified_user_can_edit_their_instances(self):
        new_title = 'New'
        slug = self.user_owned_sd_page.slug
        response = self.client.post(
            reverse('securedroppage_edit', kwargs={'slug': slug}),
            {
                'title': new_title,
                # The autocomplete widget parses the below form values
                # as JSON, and 'null' is the least obtrusive value to
                # send.
                'languages': 'null',
                'topics': 'null',
                'countries': 'null',
            },
        )
        self.assertEqual(response.status_code, 200)

    def test_verified_user_cannot_edit_other_instances(self):
        new_title = 'New'
        slug = self.unowned_sd_page.slug
        response = self.client.post(
            reverse('securedroppage_edit', kwargs={'slug': slug}),
            {
                'title': new_title,
                # The autocomplete widget parses the below form values
                # as JSON, and 'null' is the least obtrusive value to
                # send.
                'languages': 'null',
                'topics': 'null',
                'countries': 'null',
            }
        )
        self.assertEqual(response.status_code, 403)