Exemplo n.º 1
0
 def test_submit_empty_message(self):
     with self.client as client:
         new_codename(client, session)
         resp = client.post('/submit', data=dict(
             msg="",
             fh=(StringIO(''), ''),
         ), follow_redirects=True)
         self.assertIn("You must enter a message or choose a file to "
                       "submit.",
                       resp.data)
Exemplo n.º 2
0
 def test_submit_file(self):
     with self.client as client:
         new_codename(client, session)
         self._dummy_submission(client)
         resp = client.post('/submit', data=dict(
             msg="",
             fh=(StringIO('This is a test'), 'test.txt'),
         ), follow_redirects=True)
         self.assertEqual(resp.status_code, 200)
         self.assertIn('Thanks! We received your document', resp.data)
Exemplo n.º 3
0
 def test_submit_empty_message(self):
     with self.client as client:
         new_codename(client, session)
         resp = client.post('/submit', data=dict(
             msg="",
             fh=(StringIO(''), ''),
         ), follow_redirects=True)
         self.assertIn("You must enter a message or choose a file to "
                       "submit.",
                       resp.data)
Exemplo n.º 4
0
 def test_submit_file(self):
     with self.client as client:
         new_codename(client, session)
         self._dummy_submission(client)
         resp = client.post('/submit', data=dict(
             msg="",
             fh=(StringIO('This is a test'), 'test.txt'),
         ), follow_redirects=True)
         self.assertEqual(resp.status_code, 200)
         self.assertIn('Thanks! We received your document', resp.data)
Exemplo n.º 5
0
 def test_generate_already_logged_in(self):
     with self.client as client:
         new_codename(client, session)
         # Make sure it redirects to /lookup when logged in
         resp = client.get('/generate')
         self.assertEqual(resp.status_code, 302)
         # Make sure it flashes the message on the lookup page
         resp = client.get('/generate', follow_redirects=True)
         # Should redirect to /lookup
         self.assertEqual(resp.status_code, 200)
         self.assertIn("because you are already logged in.", resp.data)
Exemplo n.º 6
0
 def test_generate_already_logged_in(self):
     with self.client as client:
         new_codename(client, session)
         # Make sure it redirects to /lookup when logged in
         resp = client.get('/generate')
         self.assertEqual(resp.status_code, 302)
         # Make sure it flashes the message on the lookup page
         resp = client.get('/generate', follow_redirects=True)
         # Should redirect to /lookup
         self.assertEqual(resp.status_code, 200)
         self.assertIn("because you are already logged in.", resp.data)
Exemplo n.º 7
0
 def test_initial_submission_notification(self):
     """
     Regardless of the type of submission (message, file, or both), the
     first submission is always greeted with a notification
     reminding sources to check back later for replies.
     """
     with self.client as client:
         new_codename(client, session)
         resp = self._dummy_submission(client)
         self.assertEqual(resp.status_code, 200)
         self.assertIn("Thank you for sending this information to us.",
                       resp.data)
Exemplo n.º 8
0
    def test_submit_message_with_enough_entropy(self, get_entropy_estimate,
                                                async_genkey):
        get_entropy_estimate.return_value = 2400

        with self.client as client:
            new_codename(client, session)
            self._dummy_submission(client)
            resp = client.post('/submit', data=dict(
                msg="This is a test.",
                fh=(StringIO(''), ''),
            ), follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertTrue(async_genkey.called)
Exemplo n.º 9
0
 def test_initial_submission_notification(self):
     """
     Regardless of the type of submission (message, file, or both), the
     first submission is always greeted with a notification
     reminding sources to check back later for replies.
     """
     with self.client as client:
         new_codename(client, session)
         resp = self._dummy_submission(client)
         self.assertEqual(resp.status_code, 200)
         self.assertIn(
             "Thank you for sending this information to us.",
             resp.data)
Exemplo n.º 10
0
    def test_submit_sanitizes_filename(self, gzipfile):
        """Test that upload file name is sanitized"""
        insecure_filename = '../../bin/gpg'
        sanitized_filename = 'bin_gpg'

        with self.client as client:
            new_codename(client, session)
            client.post('/submit', data=dict(
                msg="",
                fh=(StringIO('This is a test'), insecure_filename),
            ), follow_redirects=True)
            gzipfile.assert_called_with(filename=sanitized_filename,
                                        mode=ANY,
                                        fileobj=ANY)
Exemplo n.º 11
0
    def test_submit_sanitizes_filename(self, gzipfile):
        """Test that upload file name is sanitized"""
        insecure_filename = '../../bin/gpg'
        sanitized_filename = 'bin_gpg'

        with self.client as client:
            new_codename(client, session)
            client.post('/submit', data=dict(
                msg="",
                fh=(StringIO('This is a test'), insecure_filename),
            ), follow_redirects=True)
            gzipfile.assert_called_with(filename=sanitized_filename,
                                        mode=ANY,
                                        fileobj=ANY)
Exemplo n.º 12
0
 def test_submit_big_message(self):
     '''
     When the message is larger than 512KB it's written to disk instead of
     just residing in memory. Make sure the different return type of
     SecureTemporaryFile is handled as well as BytesIO.
     '''
     with self.client as client:
         new_codename(client, session)
         self._dummy_submission(client)
         resp = client.post('/submit', data=dict(
             msg="AA" * (1024 * 512),
             fh=(StringIO(''), ''),
         ), follow_redirects=True)
         self.assertEqual(resp.status_code, 200)
         self.assertIn("Thanks! We received your message", resp.data)
Exemplo n.º 13
0
 def test_submit_big_message(self):
     '''
     When the message is larger than 512KB it's written to disk instead of
     just residing in memory. Make sure the different return type of
     SecureTemporaryFile is handled as well as BytesIO.
     '''
     with self.client as client:
         new_codename(client, session)
         self._dummy_submission(client)
         resp = client.post('/submit', data=dict(
             msg="AA" * (1024 * 512),
             fh=(StringIO(''), ''),
         ), follow_redirects=True)
         self.assertEqual(resp.status_code, 200)
         self.assertIn("Thanks! We received your message", resp.data)
Exemplo n.º 14
0
    def test_submit_message_with_enough_entropy(self, get_entropy_estimate,
                                                async_genkey):
        get_entropy_estimate.return_value = 2400

        with self.client as client:
            new_codename(client, session)
            self._dummy_submission(client)
            resp = client.post('/submit',
                               data=dict(
                                   msg="This is a test.",
                                   fh=(StringIO(''), ''),
                               ),
                               follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertTrue(async_genkey.called)
Exemplo n.º 15
0
    def _test_source_session_expiration(self):
        try:
            old_expiration = config.SESSION_EXPIRATION_MINUTES
            has_session_expiration = True
        except AttributeError:
            has_session_expiration = False

        try:
            with self.client as client:
                codename = new_codename(client, session)

                # set the expiration to ensure we trigger an expiration
                config.SESSION_EXPIRATION_MINUTES = -1

                resp = client.post('/login',
                                   data=dict(codename=codename),
                                   follow_redirects=True)
                assert resp.status_code == 200
                resp = client.get('/lookup', follow_redirects=True)

                # check that the session was cleared (apart from 'expires'
                # which is always present and 'csrf_token' which leaks no info)
                session.pop('expires', None)
                session.pop('csrf_token', None)
                assert not session, session
                assert ('You have been logged out due to inactivity'
                        in resp.data.decode('utf-8'))
        finally:
            if has_session_expiration:
                config.SESSION_EXPIRATION_MINUTES = old_expiration
            else:
                del config.SESSION_EXPIRATION_MINUTES
Exemplo n.º 16
0
    def test_source_is_deleted_while_logged_in(self, logger):
        """If a source is deleted by a journalist when they are logged in,
        a NoResultFound will occur. The source should be redirected to the
        index when this happens, and a warning logged."""

        with self.client as client:
            codename = new_codename(client, session)
            resp = client.post('login',
                               data=dict(codename=codename),
                               follow_redirects=True)

            # Now the journalist deletes the source
            filesystem_id = crypto_util.hash_codename(codename)
            crypto_util.delete_reply_keypair(filesystem_id)
            source = Source.query.filter_by(filesystem_id=filesystem_id).one()
            db_session.delete(source)
            db_session.commit()

            # Source attempts to continue to navigate
            resp = client.post('/lookup', follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn('Submit documents for the first time', resp.data)
            self.assertNotIn('logged_in', session.keys())
            self.assertNotIn('codename', session.keys())

        logger.assert_called_once_with(
            "Found no Sources when one was expected: "
            "No row was found for one()")
Exemplo n.º 17
0
    def test_source_is_deleted_while_logged_in(self, logger):
        """If a source is deleted by a journalist when they are logged in,
        a NoResultFound will occur. The source should be redirected to the
        index when this happens, and a warning logged."""

        with self.client as client:
            codename = new_codename(client, session)
            resp = client.post('login', data=dict(codename=codename),
                               follow_redirects=True)

            # Now the journalist deletes the source
            filesystem_id = crypto_util.hash_codename(codename)
            crypto_util.delete_reply_keypair(filesystem_id)
            source = Source.query.filter_by(filesystem_id=filesystem_id).one()
            db_session.delete(source)
            db_session.commit()

            # Source attempts to continue to navigate
            resp = client.post('/lookup', follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn('Submit documents for the first time', resp.data)
            self.assertNotIn('logged_in', session.keys())
            self.assertNotIn('codename', session.keys())

        logger.assert_called_once_with(
            "Found no Sources when one was expected: "
            "No row was found for one()")
Exemplo n.º 18
0
    def _test_source_session_expiration(self):
        try:
            old_expiration = config.SESSION_EXPIRATION_MINUTES
            has_session_expiration = True
        except AttributeError:
            has_session_expiration = False

        try:
            with self.client as client:
                codename = new_codename(client, session)

                # set the expiration to ensure we trigger an expiration
                config.SESSION_EXPIRATION_MINUTES = -1

                resp = client.post('/login',
                                   data=dict(codename=codename),
                                   follow_redirects=True)
                assert resp.status_code == 200
                resp = client.get('/lookup', follow_redirects=True)

                # check that the session was cleared (apart from 'expires'
                # which is always present and 'csrf_token' which leaks no info)
                session.pop('expires', None)
                session.pop('csrf_token', None)
                assert not session, session
                assert ('You have been logged out due to inactivity' in
                        resp.data.decode('utf-8'))
        finally:
            if has_session_expiration:
                config.SESSION_EXPIRATION_MINUTES = old_expiration
            else:
                del config.SESSION_EXPIRATION_MINUTES
Exemplo n.º 19
0
    def test_failed_normalize_timestamps_logs_warning(self, call, logger):
        """If a normalize timestamps event fails, the subprocess that calls
        touch will fail and exit 1. When this happens, the submission should
        still occur, but a warning should be logged (this will trigger an
        OSSEC alert)."""

        with self.client as client:
            new_codename(client, session)
            self._dummy_submission(client)
            resp = client.post('/submit', data=dict(
                msg="This is a test.",
                fh=(StringIO(''), ''),
            ), follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn("Thanks! We received your message", resp.data)

            logger.assert_called_once_with(
                "Couldn't normalize submission "
                "timestamps (touch exited with 1)"
            )
Exemplo n.º 20
0
 def test_lookup(self):
     """Test various elements on the /lookup page."""
     with self.client as client:
         codename = new_codename(client, session)
         resp = client.post('login', data=dict(codename=codename),
                            follow_redirects=True)
         # redirects to /lookup
         self.assertIn("public key", resp.data)
         # download the public key
         resp = client.get('journalist-key')
         self.assertIn("BEGIN PGP PUBLIC KEY BLOCK", resp.data)
Exemplo n.º 21
0
 def test_lookup(self):
     """Test various elements on the /lookup page."""
     with self.client as client:
         codename = new_codename(client, session)
         resp = client.post('login', data=dict(codename=codename),
                            follow_redirects=True)
         # redirects to /lookup
         self.assertIn("public key", resp.data)
         # download the public key
         resp = client.get('journalist-key')
         self.assertIn("BEGIN PGP PUBLIC KEY BLOCK", resp.data)
Exemplo n.º 22
0
    def test_failed_normalize_timestamps_logs_warning(self, call, logger):
        """If a normalize timestamps event fails, the subprocess that calls
        touch will fail and exit 1. When this happens, the submission should
        still occur, but a warning should be logged (this will trigger an
        OSSEC alert)."""

        with self.client as client:
            new_codename(client, session)
            self._dummy_submission(client)
            resp = client.post('/submit',
                               data=dict(
                                   msg="This is a test.",
                                   fh=(StringIO(''), ''),
                               ),
                               follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn("Thanks! We received your message", resp.data)

            logger.assert_called_once_with("Couldn't normalize submission "
                                           "timestamps (touch exited with 1)")
Exemplo n.º 23
0
    def test_login_with_whitespace(self):
        """
        Test that codenames with leading or trailing whitespace still work"""

        with self.client as client:
            def login_test(codename):
                resp = client.get('/login')
                self.assertEqual(resp.status_code, 200)
                self.assertIn("Enter Codename", resp.data)

                resp = client.post('/login', data=dict(codename=codename),
                                   follow_redirects=True)
                self.assertEqual(resp.status_code, 200)
                self.assertIn("Submit Materials", resp.data)
                self.assertTrue(session['logged_in'])
                resp = client.get('/logout', follow_redirects=True)

            codename = new_codename(client, session)
            login_test(codename + ' ')
            login_test(' ' + codename + ' ')
            login_test(' ' + codename)
Exemplo n.º 24
0
    def test_login_with_whitespace(self):
        """
        Test that codenames with leading or trailing whitespace still work"""

        with self.client as client:
            def login_test(codename):
                resp = client.get('/login')
                self.assertEqual(resp.status_code, 200)
                self.assertIn("Enter Codename", resp.data)

                resp = client.post('/login', data=dict(codename=codename),
                                   follow_redirects=True)
                self.assertEqual(resp.status_code, 200)
                self.assertIn("Submit Materials", resp.data)
                self.assertTrue(session['logged_in'])
                resp = client.get('/logout', follow_redirects=True)

            codename = new_codename(client, session)
            login_test(codename + ' ')
            login_test(' ' + codename + ' ')
            login_test(' ' + codename)
Exemplo n.º 25
0
    def test_login_and_logout(self):
        resp = self.client.get('/login')
        self.assertEqual(resp.status_code, 200)
        self.assertIn("Enter Codename", resp.data)

        with self.client as client:
            codename = new_codename(client, session)
            resp = client.post('/login',
                               data=dict(codename=codename),
                               follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn("Submit Materials", resp.data)
            self.assertTrue(session['logged_in'])
            resp = client.get('/logout', follow_redirects=True)

        with self.client as c:
            resp = c.post('/login',
                          data=dict(codename='invalid'),
                          follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn('Sorry, that is not a recognized codename.',
                          resp.data)
            self.assertNotIn('logged_in', session)

        with self.client as c:
            resp = c.post('/login',
                          data=dict(codename=codename),
                          follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertTrue(session['logged_in'])
            resp = c.get('/logout', follow_redirects=True)

            # sessions always have 'expires', so pop it for the next check
            session.pop('expires', None)

            self.assertNotIn('logged_in', session)
            self.assertNotIn('codename', session)

            self.assertIn('Thank you for exiting your session!', resp.data)
Exemplo n.º 26
0
    def test_login_and_logout(self):
        resp = self.client.get('/login')
        self.assertEqual(resp.status_code, 200)
        self.assertIn("Enter Codename", resp.data)

        with self.client as client:
            codename = new_codename(client, session)
            resp = client.post('/login', data=dict(codename=codename),
                               follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn("Submit Materials", resp.data)
            self.assertTrue(session['logged_in'])
            resp = client.get('/logout', follow_redirects=True)

        with self.client as c:
            resp = c.post('/login', data=dict(codename='invalid'),
                          follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertIn('Sorry, that is not a recognized codename.',
                          resp.data)
            self.assertNotIn('logged_in', session)

        with self.client as c:
            resp = c.post('/login', data=dict(codename=codename),
                          follow_redirects=True)
            self.assertEqual(resp.status_code, 200)
            self.assertTrue(session['logged_in'])
            resp = c.get('/logout', follow_redirects=True)

            # sessions always have 'expires', so pop it for the next check
            session.pop('expires', None)

            self.assertNotIn('logged_in', session)
            self.assertNotIn('codename', session)

            self.assertIn('Thank you for exiting your session!', resp.data)