class TestIntegrationRestDownloadFirmware(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend = BackEndDbInterface(config=self.config) time.sleep(2) # wait for systems to start def tearDown(self): self.db_backend.shutdown() self._stop_backend() super().tearDown() def _rest_search(self): rv = self.test_client.get('/rest/firmware?query={}'.format(urllib.parse.quote('{"device_class": "test class"}')), follow_redirects=True) self.assertIn(self.test_fw.uid.encode(), rv.data, "test firmware not found in rest search") def _rest_download(self): rv = self.test_client.get('/rest/binary/{}'.format(self.test_fw.uid), follow_redirects=True) self.assertIn(standard_b64encode(self.test_fw.binary), rv.data, "rest download response incorrect") self.assertIn('"file_name": "{}"'.format(self.test_fw.file_name).encode(), rv.data, "rest download response incorrect") self.assertIn('"SHA256": "{}"'.format(self.test_fw.sha256).encode(), rv.data, "rest download response incorrect") def test_run_from_upload_to_show_analysis(self): self.test_fw = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor") self.db_backend.add_firmware(self.test_fw) self._rest_search() self._rest_download()
class TestRestMissingAnalyses(RestTestBase): def setup(self): super().setup() self.db_backend = BackEndDbInterface(config=self.config) def teardown(self): self.db_backend.shutdown() super().teardown() def test_rest_get_missing_files(self): test_fw = create_test_firmware() missing_uid = 'uid1234' test_fw.files_included.add(missing_uid) self.db_backend.add_firmware(test_fw) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'missing_files' in response assert test_fw.uid in response['missing_files'] assert missing_uid in response['missing_files'][test_fw.uid] assert response['missing_analyses'] == {} def test_rest_get_missing_analyses(self): test_fw = create_test_firmware() test_fo = create_test_file_object() test_fw.files_included.add(test_fo.uid) test_fo.virtual_file_path = {test_fw.uid: ['|foo|bar|']} test_fw.processed_analysis['foobar'] = {'foo': 'bar'} # test_fo is missing this analysis but is in files_included -> should count as missing analysis self.db_backend.add_firmware(test_fw) self.db_backend.add_file_object(test_fo) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'missing_analyses' in response assert test_fw.uid in response['missing_analyses'] assert test_fo.uid in response['missing_analyses'][test_fw.uid] assert response['missing_files'] == {} def test_rest_get_failed_analyses(self): test_fo = create_test_file_object() test_fo.processed_analysis['some_analysis'] = {'failed': 'oops'} self.db_backend.add_file_object(test_fo) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'failed_analyses' in response assert 'some_analysis' in response['failed_analyses'] assert test_fo.uid in response['failed_analyses']['some_analysis'] def test_rest_get_orphaned_objects(self): test_fo = create_test_file_object() test_fo.parent_firmware_uids = ['missing_uid'] self.db_backend.add_file_object(test_fo) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'orphaned_objects' in response assert response['orphaned_objects'] == { 'missing_uid': ['d558c9339cb967341d701e3184f863d3928973fccdc1d96042583730b5c7b76a_62'] }
class TestRestDownload(RestTestBase): def setup(self): super().setup() self.db_interface = BackEndDbInterface(self.config) self.test_queue = Queue() def teardown(self): self.test_queue.close() self.db_interface.shutdown() super().teardown() def test_rest_download_valid(self): backend_binding = InterComBackEndBinding( config=self.config, analysis_service=test_backend_scheduler.AnalysisServiceMock(), compare_service=test_backend_scheduler.ServiceMock( self.test_queue), unpacking_service=test_backend_scheduler.ServiceMock( self.test_queue)) test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') store_binary_on_file_system(self.tmp_dir.name, test_firmware) self.db_interface.add_firmware(test_firmware) try: rv = self.test_client.get('/rest/binary/{}'.format( test_firmware.uid), follow_redirects=True) finally: backend_binding.shutdown() assert standard_b64encode(test_firmware.binary) in rv.data assert '"file_name": "{}"'.format( test_firmware.file_name).encode() in rv.data assert '"SHA256": "{}"'.format( test_firmware.sha256).encode() in rv.data def test_rest_download_invalid_uid(self): rv = self.test_client.get('/rest/binary/not%20existing%20uid', follow_redirects=True) assert b'No firmware with UID not existing uid found in database' in rv.data def test_rest_download_invalid_data(self): rv = self.test_client.get('/rest/binary/', follow_redirects=True) assert b'404 Not Found' in rv.data
class TestAcceptanceDownloadFile(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend = BackEndDbInterface(config=self.config) time.sleep(10) # wait for systems to start def tearDown(self): self.db_backend.shutdown() self._stop_backend() super().tearDown() def _show_analysis_page(self, fw): rv = self.test_client.get('/analysis/{}'.format(fw.uid)) self.assertIn(fw.uid.encode(), rv.data) self.assertIn(b'test_router', rv.data) self.assertIn(b'Router', rv.data) self.assertIn(b'test_vendor', rv.data) def _start_binary_download(self, fw): rv = self.test_client.get('/download/{}'.format(fw.uid)) self.assertIn(fw.binary, rv.data, 'firmware download unsuccessful') self.assertIn('attachment; filename=test.zip', rv.headers['Content-Disposition']) def _start_tar_download(self, fw): rv = self.test_client.get('/tar-download/{}'.format(fw.uid)) self.assertNotIn( fw.binary, rv.data, 'tar download yielded original file instead of tar archive') tar_file = tarfile.open(fileobj=io.BytesIO(rv.data)) contents = ', '.join(tar_file.getnames()) self.assertIn('testfile1', contents, 'test files could not be found in tar download') def test_firmware_download(self): test_fw = create_test_firmware() test_fw.processed_analysis.pop('dummy') test_fw.uid = test_fw.get_uid() self.db_backend.add_firmware(test_fw) self.assertIsNotNone(self.db_backend.firmwares.find_one(test_fw.uid)) self._show_analysis_page(test_fw) self._start_binary_download(test_fw) self._start_tar_download(test_fw)
class TestBinaryService(unittest.TestCase): def setUp(self): self.config = get_config_for_testing() self.mongo_server = MongoMgr(config=self.config) self._init_test_data() self.binary_service = BinaryService(config=self.config) def _init_test_data(self): self.backend_db_interface = BackEndDbInterface(config=self.config) self.backend_db_interface.add_firmware(TEST_FW) self.backend_db_interface.shutdown() def tearDown(self): self.mongo_server.shutdown() gc.collect() def test_get_binary_and_file_name(self): binary, file_name = self.binary_service.get_binary_and_file_name( TEST_FW.uid) self.assertEqual(file_name, TEST_FW.file_name, 'file_name not correct') self.assertEqual(binary, TEST_FW.binary, 'invalid result not correct') def test_get_binary_and_file_name_invalid_uid(self): binary, file_name = self.binary_service.get_binary_and_file_name( 'invalid_uid') self.assertIsNone(binary, 'should be none') self.assertIsNone(file_name, 'should be none') def test_get_repacked_binary_and_file_name(self): tar, file_name = self.binary_service.get_repacked_binary_and_file_name( TEST_FW.uid) self.assertEqual(file_name, '{}.tar.gz'.format(TEST_FW.file_name), 'file_name not correct') file_type = magic.from_buffer(tar, mime=False) assert 'gzip compressed data' in file_type, 'Result is not an tar.gz file' def test_get_repacked_binary_and_file_name_invalid_uid(self): binary, file_name = self.binary_service.get_repacked_binary_and_file_name( 'invalid_uid') self.assertIsNone(binary, 'should be none') self.assertIsNone(file_name, 'should be none')
class TestBinaryService: def setup(self): self.tmp_dir = TemporaryDirectory() self.config = get_config_for_testing(temp_dir=self.tmp_dir) self.mongo_server = MongoMgr(config=self.config) self._init_test_data() self.binary_service = BinaryService(config=self.config) def _init_test_data(self): self.backend_db_interface = BackEndDbInterface(config=self.config) self.backend_db_interface.add_firmware(TEST_FW) store_binary_on_file_system(self.tmp_dir.name, TEST_FW) self.backend_db_interface.shutdown() def teardown(self): self.tmp_dir.cleanup() self.mongo_server.shutdown() gc.collect() def test_get_binary_and_file_name(self): binary, file_name = self.binary_service.get_binary_and_file_name(TEST_FW.uid) assert file_name == TEST_FW.file_name, 'file_name not correct' assert binary == TEST_FW.binary, 'invalid result not correct' def test_get_binary_and_file_name_invalid_uid(self): binary, file_name = self.binary_service.get_binary_and_file_name('invalid_uid') assert binary is None, 'should be none' assert file_name is None, 'should be none' def test_get_repacked_binary_and_file_name(self): tar, file_name = self.binary_service.get_repacked_binary_and_file_name(TEST_FW.uid) assert file_name == '{}.tar.gz'.format(TEST_FW.file_name), 'file_name not correct' file_type = magic.from_buffer(tar, mime=False) assert 'gzip compressed data' in file_type, 'Result is not an tar.gz file' def test_get_repacked_binary_and_file_name_invalid_uid(self): binary, file_name = self.binary_service.get_repacked_binary_and_file_name('invalid_uid') assert binary is None, 'should be none' assert file_name is None, 'should be none'
class TestRestMissingAnalyses(RestTestBase): def setUp(self): super().setUp() self.db_backend = BackEndDbInterface(config=self.config) def tearDown(self): self.db_backend.shutdown() super().tearDown() def test_rest_get_missing_files(self): test_fw = create_test_firmware() missing_uid = 'uid1234' test_fw.files_included.add(missing_uid) self.db_backend.add_firmware(test_fw) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'missing_files' in response assert test_fw.uid in response['missing_files'] assert missing_uid in response['missing_files'][test_fw.uid] assert response['missing_analyses'] == {} def test_rest_get_missing_analyses(self): test_fw = create_test_firmware() test_fo = create_test_file_object() test_fw.files_included.add(test_fo.uid) test_fo.virtual_file_path = {test_fw.uid: ['|foo|bar|']} test_fw.processed_analysis['foobar'] = {'foo': 'bar'} # test_fo is missing this analysis but is in files_included -> should count as missing analysis self.db_backend.add_firmware(test_fw) self.db_backend.add_file_object(test_fo) response = json.loads(self.test_client.get('/rest/missing', follow_redirects=True).data.decode()) assert 'missing_analyses' in response assert test_fw.uid in response['missing_analyses'] assert test_fo.uid in response['missing_analyses'][test_fw.uid] assert response['missing_files'] == {}
class TestAcceptanceIoRoutes(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend_interface = BackEndDbInterface(self.config) self.test_fw = create_test_firmware(device_name='test_fw') self.test_fw.processed_analysis['base64_decoder'] = BASE64_ANALYSIS def tearDown(self): self.db_backend_interface.shutdown() self._stop_backend() super().tearDown() def test_base64_download_success(self): self.test_fw.processed_analysis['base64_decoder']['1019 - 1882'][0]['span_in_section'] = (0, 848, 2) self.test_fw.processed_analysis['base64_decoder']['1019 - 1882'][0]['span_in_binary'] = (1019, 1882) self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get('/base64-download/{uid}/{section}/{expression_id}'.format(uid=self.test_fw.uid, section='1019 - 1882', expression_id='0')) self.assertIn('200', response.status, 'base64 download failed') def test_base64_download_bad_result(self): self.test_fw.processed_analysis['base64_decoder']['1019 - 1882'][0]['span_in_binary'] = None self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get('/base64-download/{uid}/{section}/{expression_id}'.format(uid=self.test_fw.uid, section='1019 - 1882', expression_id='0')) self.assertIn(b'Undisclosed error in base64 decoding', response.data, 'base64 download should break') def test_bad_base64_encoding(self): self.test_fw.processed_analysis['base64_decoder']['1019 - 1882'][0]['span_in_section'] = (8, 100, 2) self.test_fw.processed_analysis['base64_decoder']['1019 - 1882'][0]['span_in_binary'] = (0, 1000) self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get('/base64-download/{uid}/{section}/{expression_id}'.format(uid=self.test_fw.uid, section='1019 - 1882', expression_id='0')) self.assertIn(b'Incorrect padding', response.data, 'base64 did not break') def test_hex_dump_button(self): self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get('/hex-dump/{uid}'.format(uid=self.test_fw.uid)) self.assertIn('200', response.status, 'hex dump link failed') self.assertIn(b'0x0', response.data, 'no hex dump is shown') def test_hex_dump_bad_uid(self): response = self.test_client.get('/hex-dump/{uid}'.format(uid=self.test_fw.uid)) self.assertIn(b'File not found in database', response.data, 'uid should not exist') def test_ida_download(self): compare_interface = CompareDbInterface(config=self.config) self.db_backend_interface.add_firmware(self.test_fw) COMPARE_RESULT['general'] = {'a': {self.test_fw.uid: 'x'}, 'b': {self.test_fw.uid: 'y'}} compare_interface.add_compare_result(COMPARE_RESULT) cid = compare_interface._calculate_compare_result_id(COMPARE_RESULT) response = self.test_client.get('/ida-download/{cid}'.format(cid=cid)) self.assertIn(b'IDA database', response.data, 'mocked ida database not in result') def test_ida_download_bad_uid(self): compare_interface = CompareDbInterface(config=self.config) compare_interface.add_compare_result(COMPARE_RESULT) cid = compare_interface._calculate_compare_result_id(COMPARE_RESULT) response = self.test_client.get('/ida-download/{cid}'.format(cid=cid)) self.assertIn(b'not found in database', response.data, 'endpoint should dismiss result')
class TestStorageDbInterfaceBackend(unittest.TestCase): @classmethod def setUpClass(cls): cls._config = get_config_for_testing(TMP_DIR) cls.mongo_server = MongoMgr(config=cls._config) def setUp(self): self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.test_firmware = create_test_firmware() self.test_yara_match = { 'rule': 'OpenSSH', 'tags': [], 'namespace': 'default', 'strings': [(0, '$a', b'OpenSSH')], 'meta': { 'description': 'SSH library', 'website': 'http://www.openssh.com', 'open_source': True, 'software_name': 'OpenSSH' }, 'matches': True } self.test_fo = create_test_file_object() def tearDown(self): self.db_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface_backend.shutdown() self.db_interface.shutdown() gc.collect() @classmethod def tearDownClass(cls): cls.mongo_server.shutdown() TMP_DIR.cleanup() def _get_all_firmware_uids(self): uid_list = [] tmp = self.db_interface.firmwares.find() for item in tmp: uid_list.append(item['_id']) return uid_list def test_add_firmware(self): self.db_interface_backend.add_firmware(self.test_firmware) self.assertGreater(len(self._get_all_firmware_uids()), 0, 'No entry added to DB') recoverd_firmware_entry = self.db_interface_backend.firmwares.find_one( ) self.assertAlmostEqual(recoverd_firmware_entry['submission_date'], time(), msg='submission time not set correctly', delta=5.0) def test_add_and_get_firmware(self): self.db_interface_backend.add_firmware(self.test_firmware) result_backend = self.db_interface_backend.get_firmware( self.test_firmware.uid) self.assertIsNotNone(result_backend.binary, 'binary not set in backend result') result_common = self.db_interface.get_firmware(self.test_firmware.uid) self.assertIsNone(result_common.binary, 'binary set in common result') self.assertEqual(result_common.size, 787, 'file size not correct in common') self.assertIsInstance(result_common.tags, dict, 'tag field type not correct') def test_add_and_get_file_object(self): self.db_interface_backend.add_file_object(self.test_fo) result_backend = self.db_interface_backend.get_file_object( self.test_fo.uid) self.assertIsNotNone(result_backend.binary, 'binary not set in backend result') result_common = self.db_interface.get_file_object(self.test_fo.uid) self.assertIsNone(result_common.binary, 'binary set in common result') self.assertEqual(result_common.size, 62, 'file size not correct in common') def test_update_firmware(self): first_dict = { 'stub_plugin': { 'result': 0 }, 'other_plugin': { 'field': 'day' } } second_dict = {'stub_plugin': {'result': 1}} self.test_firmware.processed_analysis = first_dict self.db_interface_backend.add_firmware(self.test_firmware) self.assertEqual( 0, self.db_interface.get_object( self.test_firmware.uid).processed_analysis['stub_plugin'] ['result']) self.test_firmware.processed_analysis = second_dict self.db_interface_backend.add_firmware(self.test_firmware) self.assertEqual( 1, self.db_interface.get_object( self.test_firmware.uid).processed_analysis['stub_plugin'] ['result']) self.assertIn( 'other_plugin', self.db_interface.get_object( self.test_firmware.uid).processed_analysis.keys()) def test_update_file_object(self): first_dict = {'other_plugin': {'result': 0}} second_dict = {'stub_plugin': {'result': 1}} self.test_fo.processed_analysis = first_dict self.test_fo.files_included = {'file a', 'file b'} self.db_interface_backend.add_file_object(self.test_fo) self.test_fo.processed_analysis = second_dict self.test_fo.files_included = {'file b', 'file c'} self.db_interface_backend.add_file_object(self.test_fo) received_object = self.db_interface.get_object(self.test_fo.uid) self.assertEqual( 0, received_object.processed_analysis['other_plugin']['result']) self.assertEqual( 1, received_object.processed_analysis['stub_plugin']['result']) self.assertEqual(3, len(received_object.files_included)) def test_add_and_get_object_including_comment(self): comment, author, date, uid = 'this is a test comment!', 'author', '1473431685', self.test_fo.uid self.test_fo.comments.append({ 'time': str(date), 'author': author, 'comment': comment }) self.db_interface_backend.add_file_object(self.test_fo) retrieved_comment = self.db_interface.get_object(uid).comments[0] self.assertEqual(author, retrieved_comment['author']) self.assertEqual(comment, retrieved_comment['comment']) self.assertEqual(date, retrieved_comment['time']) def test_update_analysis_tag_no_firmware(self): self.db_interface_backend.add_file_object(self.test_fo) tag = {'value': 'yay', 'color': 'default', 'propagate': True} self.db_interface_backend.update_analysis_tags(self.test_fo.uid, plugin_name='dummy', tag_name='some_tag', tag=tag) processed_fo = self.db_interface_backend.get_object(self.test_fo.uid) assert not processed_fo.analysis_tags def test_update_analysis_tag_uid_not_found(self): self.db_interface_backend.update_analysis_tags(self.test_fo.uid, plugin_name='dummy', tag_name='some_tag', tag='should not matter') assert not self.db_interface_backend.get_object(self.test_fo.uid) def test_update_analysis_tag_bad_tag(self): self.db_interface_backend.add_firmware(self.test_firmware) self.db_interface_backend.update_analysis_tags(self.test_firmware.uid, plugin_name='dummy', tag_name='some_tag', tag='bad_tag') processed_firmware = self.db_interface_backend.get_object( self.test_firmware.uid) assert not processed_firmware.analysis_tags def test_update_analysis_tag_success(self): self.db_interface_backend.add_firmware(self.test_firmware) tag = {'value': 'yay', 'color': 'default', 'propagate': True} self.db_interface_backend.update_analysis_tags(self.test_firmware.uid, plugin_name='dummy', tag_name='some_tag', tag=tag) processed_firmware = self.db_interface_backend.get_object( self.test_firmware.uid) assert processed_firmware.analysis_tags assert processed_firmware.analysis_tags['dummy']['some_tag'] == tag def test_add_analysis_firmware(self): self.db_interface_backend.add_object(self.test_firmware) before = self.db_interface_backend.get_object( self.test_firmware.uid).processed_analysis self.test_firmware.processed_analysis['foo'] = {'bar': 5} self.db_interface_backend.add_analysis(self.test_firmware) after = self.db_interface_backend.get_object( self.test_firmware.uid).processed_analysis assert before != after assert 'foo' not in before assert 'foo' in after assert after['foo'] == {'bar': 5} def test_add_analysis_file_object(self): self.db_interface_backend.add_object(self.test_fo) self.test_fo.processed_analysis['foo'] = {'bar': 5} self.db_interface_backend.add_analysis(self.test_fo) analysis = self.db_interface_backend.get_object( self.test_fo.uid).processed_analysis assert 'foo' in analysis assert analysis['foo'] == {'bar': 5} def test_crash_add_analysis(self): with self.assertRaises(RuntimeError): self.db_interface_backend.add_analysis(dict()) with self.assertRaises(AttributeError): self.db_interface_backend._update_analysis(dict(), 'dummy', dict())
class TestStorageDbInterfaceFrontend(unittest.TestCase): @classmethod def setUpClass(cls): cls._config = get_config_for_testing(TMP_DIR) cls.mongo_server = MongoMgr(config=cls._config) def setUp(self): self.db_frontend_interface = FrontEndDbInterface(config=self._config) self.db_backend_interface = BackEndDbInterface(config=self._config) self.test_firmware = create_test_firmware() def tearDown(self): self.db_frontend_interface.shutdown() self.db_backend_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_backend_interface.shutdown() gc.collect() @classmethod def tearDownClass(cls): cls.mongo_server.shutdown() TMP_DIR.cleanup() def test_regression_meta_list(self): assert self.test_firmware.processed_analysis.pop('unpacker') self.db_backend_interface.add_firmware(self.test_firmware) list_of_firmwares = self.db_frontend_interface.get_meta_list() assert 'NOP' in list_of_firmwares.pop()[2] def test_get_meta_list(self): self.db_backend_interface.add_firmware(self.test_firmware) list_of_firmwares = self.db_frontend_interface.get_meta_list() test_output = list_of_firmwares.pop() self.assertEqual(test_output[1], 'test_vendor test_router - 0.1 (Router)', 'Firmware not successfully received') self.assertIsInstance(test_output[2], dict, 'tag field is not a dict') def test_get_meta_list_of_fo(self): test_fo = create_test_file_object() self.db_backend_interface.add_file_object(test_fo) files = self.db_frontend_interface.file_objects.find() meta_list = self.db_frontend_interface.get_meta_list(files) self.assertEqual(meta_list[0][0], test_fo.uid, 'uid of object not correct') self.assertEqual(meta_list[0][3], 0, 'non existing submission date should lead to 0') def test_get_hid_firmware(self): self.db_backend_interface.add_firmware(self.test_firmware) result = self.db_frontend_interface.get_hid(self.test_firmware.uid) self.assertEqual(result, 'test_vendor test_router - 0.1 (Router)', 'fw hid not correct') def test_get_hid_fo(self): test_fo = create_test_file_object(bin_path='get_files_test/testfile2') test_fo.virtual_file_path = { 'a': ['|a|/test_file'], 'b': ['|b|/get_files_test/testfile2'] } self.db_backend_interface.add_file_object(test_fo) result = self.db_frontend_interface.get_hid(test_fo.uid, root_uid='b') self.assertEqual(result, '/get_files_test/testfile2', 'fo hid not correct') result = self.db_frontend_interface.get_hid(test_fo.uid) self.assertIsInstance(result, str, 'result is not a string') self.assertEqual(result[0], '/', 'first character not correct if no root_uid set') result = self.db_frontend_interface.get_hid(test_fo.uid, root_uid='c') self.assertEqual( result[0], '/', 'first character not correct if invalid root_uid set') def test_get_file_name(self): self.db_backend_interface.add_firmware(self.test_firmware) result = self.db_frontend_interface.get_file_name( self.test_firmware.uid) self.assertEqual(result, 'test.zip', 'name not correct') def test_get_hid_invalid_uid(self): result = self.db_frontend_interface.get_hid('foo') self.assertEqual(result, '', 'invalid uid should result in empty string') def test_get_firmware_attribute_list(self): self.db_backend_interface.add_firmware(self.test_firmware) self.assertEqual(self.db_frontend_interface.get_device_class_list(), ['Router']) self.assertEqual(self.db_frontend_interface.get_vendor_list(), ['test_vendor']) self.assertEqual( self.db_frontend_interface.get_firmware_attribute_list( 'device_name', { 'vendor': 'test_vendor', 'device_class': 'Router' }), ['test_router']) self.assertEqual( self.db_frontend_interface.get_firmware_attribute_list('version'), ['0.1']) self.assertEqual(self.db_frontend_interface.get_device_name_dict(), {'Router': { 'test_vendor': ['test_router'] }}) def test_get_data_for_nice_list(self): uid_list = [self.test_firmware.uid] self.db_backend_interface.add_firmware(self.test_firmware) nice_list_data = self.db_frontend_interface.get_data_for_nice_list( uid_list, uid_list[0]) self.assertEqual( sorted([ 'size', 'virtual_file_paths', 'uid', 'mime-type', 'files_included' ]), sorted(nice_list_data[0].keys())) self.assertEqual(nice_list_data[0]['uid'], self.test_firmware.uid) def test_generic_search(self): self.db_backend_interface.add_firmware(self.test_firmware) # str input result = self.db_frontend_interface.generic_search( '{"file_name": "test.zip"}') self.assertEqual(result, [self.test_firmware.uid], 'Firmware not successfully received') # dict input result = self.db_frontend_interface.generic_search( {'file_name': 'test.zip'}) self.assertEqual(result, [self.test_firmware.uid], 'Firmware not successfully received') def test_all_uids_found_in_database(self): self.db_backend_interface.client.drop_database( self._config.get('data_storage', 'main_database')) uid_list = [self.test_firmware.uid] self.assertFalse( self.db_frontend_interface.all_uids_found_in_database(uid_list)) self.db_backend_interface.add_firmware(self.test_firmware) self.assertTrue( self.db_frontend_interface.all_uids_found_in_database( [self.test_firmware.uid])) def test_get_x_last_added_firmwares(self): self.assertEqual(self.db_frontend_interface.get_last_added_firmwares(), [], 'empty db should result in empty list') test_fw_one = create_test_firmware(device_name='fw_one') self.db_backend_interface.add_firmware(test_fw_one) test_fw_two = create_test_firmware(device_name='fw_two', bin_path='container/test.7z') self.db_backend_interface.add_firmware(test_fw_two) test_fw_three = create_test_firmware(device_name='fw_three', bin_path='container/test.cab') self.db_backend_interface.add_firmware(test_fw_three) result = self.db_frontend_interface.get_last_added_firmwares(limit_x=2) self.assertEqual(len(result), 2, 'Number of results should be 2') self.assertEqual(result[0][0], test_fw_three.uid, 'last firmware is not first entry') self.assertEqual(result[1][0], test_fw_two.uid, 'second last firmware is not the second entry') def test_generate_file_tree_level(self): parent_fw = create_test_firmware() child_fo = create_test_file_object() child_fo.processed_analysis['file_type'] = {'mime': 'sometype'} uid = parent_fw.uid child_fo.virtual_file_path = { uid: ['|{}|/folder/{}'.format(uid, child_fo.file_name)] } parent_fw.files_included = {child_fo.uid} self.db_backend_interface.add_object(parent_fw) self.db_backend_interface.add_object(child_fo) for node in self.db_frontend_interface.generate_file_tree_level( uid, uid): self.assertIsInstance(node, FileTreeNode) self.assertEqual(node.name, parent_fw.file_name) self.assertTrue(node.has_children) for node in self.db_frontend_interface.generate_file_tree_level( child_fo.uid, uid): self.assertIsInstance(node, FileTreeNode) self.assertEqual(node.name, 'folder') self.assertTrue(node.has_children) virtual_grand_child = node.get_list_of_child_nodes()[0] self.assertEqual(virtual_grand_child.type, 'sometype') self.assertFalse(virtual_grand_child.has_children) self.assertEqual(virtual_grand_child.name, child_fo.file_name) def test_get_number_of_total_matches(self): parent_fw = create_test_firmware() child_fo = create_test_file_object() uid = parent_fw.uid child_fo.virtual_file_path = { uid: ['|{}|/folder/{}'.format(uid, child_fo.file_name)] } self.db_backend_interface.add_object(parent_fw) self.db_backend_interface.add_object(child_fo) query = '{{"$or": [{{"_id": "{}"}}, {{"_id": "{}"}}]}}'.format( uid, child_fo.uid) self.assertEqual( self.db_frontend_interface.get_number_of_total_matches( query, only_parent_firmwares=False), 2) self.assertEqual( self.db_frontend_interface.get_number_of_total_matches( query, only_parent_firmwares=True), 1) def test_get_other_versions_of_firmware(self): parent_fw1 = create_test_firmware(version='1') self.db_backend_interface.add_object(parent_fw1) parent_fw2 = create_test_firmware(version='2', bin_path='container/test.7z') self.db_backend_interface.add_object(parent_fw2) parent_fw3 = create_test_firmware(version='3', bin_path='container/test.cab') self.db_backend_interface.add_object(parent_fw3) other_versions = self.db_frontend_interface.get_other_versions_of_firmware( parent_fw1) self.assertEqual(len(other_versions), 2, 'wrong number of other versions') self.assertIn({'_id': parent_fw2.uid, 'version': '2'}, other_versions) self.assertIn({'_id': parent_fw3.uid, 'version': '3'}, other_versions) other_versions = self.db_frontend_interface.get_other_versions_of_firmware( parent_fw2) self.assertIn({'_id': parent_fw3.uid, 'version': '3'}, other_versions) def test_get_specific_fields_for_multiple_entries(self): test_fw_1 = create_test_firmware(device_name='fw_one', vendor='test_vendor_one') self.db_backend_interface.add_firmware(test_fw_1) test_fw_2 = create_test_firmware(device_name='fw_two', vendor='test_vendor_two', bin_path='container/test.7z') self.db_backend_interface.add_firmware(test_fw_2) test_fo = create_test_file_object() self.db_backend_interface.add_file_object(test_fo) test_uid_list = [test_fw_1.uid, test_fw_2.uid] result = list( self.db_frontend_interface. get_specific_fields_for_multiple_entries(uid_list=test_uid_list, field_dict={ 'vendor': 1, 'device_name': 1 })) assert len(result) == 2 assert all( set(entry.keys()) == {'_id', 'vendor', 'device_name'} for entry in result) result_uids = [entry['_id'] for entry in result] assert all(uid in result_uids for uid in test_uid_list) test_uid_list = [test_fw_1.uid, test_fo.uid] result = list( self.db_frontend_interface. get_specific_fields_for_multiple_entries( uid_list=test_uid_list, field_dict={'virtual_file_path': 1})) assert len(result) == 2 assert all( set(entry.keys()) == {'_id', 'virtual_file_path'} for entry in result) result_uids = [entry['_id'] for entry in result] assert all(uid in result_uids for uid in test_uid_list) def test_find_missing_files(self): test_fw_1 = create_test_firmware() test_fw_1.files_included.add('uid1234') self.db_backend_interface.add_firmware(test_fw_1) missing_files = self.db_frontend_interface.find_missing_files() assert test_fw_1.uid in missing_files assert missing_files[test_fw_1.uid] == {'uid1234'} test_fo = create_test_file_object() test_fo.uid = 'uid1234' self.db_backend_interface.add_file_object(test_fo) missing_files = self.db_frontend_interface.find_missing_files() assert missing_files == {} def test_find_missing_analyses(self): test_fw_1 = create_test_firmware() test_fo = create_test_file_object() test_fw_1.files_included.add(test_fo.uid) test_fo.virtual_file_path = {test_fw_1.uid: ['|foo|bar|']} self.db_backend_interface.add_firmware(test_fw_1) self.db_backend_interface.add_file_object(test_fo) missing_analyses = self.db_frontend_interface.find_missing_analyses() assert missing_analyses == {} test_fw_1.processed_analysis['foobar'] = {'foo': 'bar'} self.db_backend_interface.add_analysis(test_fw_1) missing_analyses = self.db_frontend_interface.find_missing_analyses() assert test_fw_1.uid in missing_analyses assert missing_analyses[test_fw_1.uid] == {test_fo.uid}
class TestRestStartCompare(RestTestBase): def setup(self): super().setup() self.db_backend = BackEndDbInterface(config=self.config) def teardown(self): self.db_backend.shutdown() super().teardown() def test_rest_start_compare_valid(self): test_firmware_1 = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor") test_firmware_2 = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor", bin_path="container/test.7z") self.db_backend.add_firmware(test_firmware_1) self.db_backend.add_firmware(test_firmware_2) rv = self.test_client.put( '/rest/compare', data=json.dumps({ "uid_list": [test_firmware_1.uid, test_firmware_2.uid], "redo": True }), follow_redirects=True) assert b"Compare started." in rv.data def test_rest_start_compare_invalid_uid(self): rv = self.test_client.put('/rest/compare', data=json.dumps({"uid_list": ["123", "456"]}), follow_redirects=True) assert b"not found in database" in rv.data def test_rest_start_compare_invalid_data(self): test_firmware = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor") self.db_backend.add_firmware(test_firmware) rv = self.test_client.put('/rest/compare', data=json.dumps({"data": "invalid data"}), follow_redirects=True) assert b"Request should be of the form" in rv.data def test_rest_get_compare_valid_not_in_db(self): test_firmware_1 = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor") test_firmware_2 = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor", bin_path="container/test.7z") self.db_backend.add_firmware(test_firmware_1) self.db_backend.add_firmware(test_firmware_2) rv = self.test_client.get('/rest/compare/{};{}'.format( test_firmware_1.uid, test_firmware_2.uid), follow_redirects=True) assert b"Compare not found in database." in rv.data def test_rest_get_compare_invalid_uid(self): rv = self.test_client.get('/rest/compare/123;456', follow_redirects=True) assert b"not found in database" in rv.data def test_rest_get_compare_invalid_data(self): test_firmware = create_test_firmware(device_class="test class", device_name="test device", vendor="test vendor") self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/compare', follow_redirects=True) assert b"Compare ID must be of the form" in rv.data
class TestStorageDbInterfaceAdmin(unittest.TestCase): @classmethod def setUpClass(cls): cls.config = get_config_for_testing(TMP_DIR) cls.config.set('data_storage', 'sanitize_database', 'tmp_sanitize') cls.config.set('data_storage', 'report_threshold', '32') cls.mongo_server = MongoMgr(config=cls.config) def setUp(self): self.admin_interface = AdminDbInterface(config=self.config) self.db_backend_interface = BackEndDbInterface(config=self.config) copyfile(test_firmware_original, test_firmware_copy) self.test_firmware = create_test_firmware( bin_path='container/test_copy.zip') self.uid = self.test_firmware.get_uid() self.test_firmware.virtual_file_path = { self.uid: ['|{}|'.format(self.test_firmware.get_uid())] } copyfile(test_file_original, test_file_copy) self.child_fo = create_test_file_object(test_file_copy) self.child_fo.virtual_file_path = { self.uid: ['|{}|/folder/{}'.format(self.uid, self.child_fo.file_name)] } self.test_firmware.files_included = [self.child_fo.get_uid()] self.child_uid = self.child_fo.get_uid() def tearDown(self): self.admin_interface.client.drop_database( self.config.get('data_storage', 'main_database')) self.admin_interface.client.drop_database( self.config.get('data_storage', 'sanitize_database')) self.admin_interface.shutdown() self.db_backend_interface.shutdown() gc.collect() @classmethod def tearDownClass(cls): cls.mongo_server.shutdown() for test_file in [test_file_copy, test_firmware_copy]: if os.path.isfile(test_file): os.remove(test_file) TMP_DIR.cleanup() def test_remove_object_field(self): self.db_backend_interface.add_file_object(self.child_fo) self.assertIn( self.uid, self.db_backend_interface.file_objects.find_one( self.child_uid, {'virtual_file_path': 1})['virtual_file_path']) self.admin_interface.remove_object_field( self.child_uid, 'virtual_file_path.{}'.format(self.uid)) self.assertNotIn( self.uid, self.db_backend_interface.file_objects.find_one( self.child_uid, {'virtual_file_path': 1})['virtual_file_path']) def test_remove_virtual_path_entries_no_other_roots(self): self.db_backend_interface.add_file_object(self.child_fo) self.assertIn( self.uid, self.db_backend_interface.file_objects.find_one( self.child_uid, {'virtual_file_path': 1})['virtual_file_path']) removed_vps, deleted_files = self.admin_interface._remove_virtual_path_entries( self.uid, self.child_fo.get_uid()) self.assertIsNone( self.db_backend_interface.file_objects.find_one(self.child_uid)) self.assertEqual(removed_vps, 0) self.assertEqual(deleted_files, 1) def test_remove_virtual_path_entries_other_roots(self): self.child_fo.virtual_file_path.update( {'someuid': ['|someuid|/some/virtual/path']}) self.db_backend_interface.add_file_object(self.child_fo) self.assertIn( self.uid, self.db_backend_interface.file_objects.find_one( self.child_uid, {'virtual_file_path': 1})['virtual_file_path']) removed_vps, deleted_files = self.admin_interface._remove_virtual_path_entries( self.uid, self.child_fo.get_uid()) self.assertNotIn( self.uid, self.db_backend_interface.file_objects.find_one( self.child_uid, {'virtual_file_path': 1})['virtual_file_path']) self.assertEqual(removed_vps, 1) self.assertEqual(deleted_files, 0) def test_delete_swapped_analysis_entries(self): self.test_firmware.processed_analysis = { 'test_plugin': { 'result': 10000000000, 'misc': 'delete_swap_test' } } self.db_backend_interface.add_firmware(self.test_firmware) self.admin_interface.client.drop_database( self.config.get('data_storage', 'sanitize_database')) self.admin_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.uid) self.assertIn( 'test_plugin_result_{}'.format(self.test_firmware.get_uid()), self.admin_interface.sanitize_fs.list()) self.admin_interface._delete_swapped_analysis_entries( self.admin_interface.firmwares.find_one(self.uid)) self.assertNotIn( 'test_plugin_result_{}'.format(self.test_firmware.get_uid()), self.admin_interface.sanitize_fs.list()) def test_delete_file_object(self): self.db_backend_interface.add_file_object(self.child_fo) db_entry = self.db_backend_interface.file_objects.find_one( self.child_fo.get_uid()) self.assertIsNotNone(db_entry) self.admin_interface._delete_file_object(db_entry) self.assertIsNone( self.db_backend_interface.file_objects.find_one( self.child_fo.get_uid()), 'file not deleted from db') delete_tasks = self._get_delete_tasks() self.assertIn(self.child_fo.get_uid(), delete_tasks, 'file not found in delete tasks') def test_delete_firmware(self): self.db_backend_interface.add_firmware(self.test_firmware) self.db_backend_interface.add_file_object(self.child_fo) self.assertIsNotNone( self.db_backend_interface.firmwares.find_one(self.uid)) self.assertIsNotNone( self.db_backend_interface.file_objects.find_one(self.child_uid)) self.assertTrue(os.path.isfile(self.test_firmware.file_path)) self.assertTrue(os.path.isfile(self.child_fo.file_path)) removed_vps, deleted_files = self.admin_interface.delete_firmware( self.uid) self.assertIsNone( self.db_backend_interface.firmwares.find_one(self.uid), 'firmware not deleted from db') self.assertIsNone( self.db_backend_interface.file_objects.find_one(self.child_uid), 'child not deleted from db') self.assertEqual(removed_vps, 0) self.assertEqual(deleted_files, 2, 'number of removed files not correct') # check if file delete tasks were created delete_tasks = self._get_delete_tasks() self.assertIn(self.test_firmware.get_uid(), delete_tasks, 'fw delete task not found') self.assertIn(self.child_fo.get_uid(), delete_tasks, 'child delete task not found') self.assertEqual(len(delete_tasks), 2, 'number of delete tasks not correct') def _get_delete_tasks(self): intercom = InterComListener(config=self.config) intercom.CONNECTION_TYPE = 'file_delete_task' delete_tasks = [] while True: tmp = intercom.get_next_task() if tmp is None: break else: delete_tasks.append(tmp['_id']) intercom.shutdown() return delete_tasks
class TestMongoInterface(unittest.TestCase): @classmethod def setUpClass(cls): cls._config = get_config_for_testing(TMP_DIR) cls._config.set('data_storage', 'report_threshold', '32') cls._config.set('data_storage', 'sanitize_database', 'tmp_sanitize') cls.mongo_server = MongoMgr(config=cls._config) def setUp(self): self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.test_firmware = create_test_firmware() self.test_yara_match = { 'rule': 'OpenSSH', 'tags': [], 'namespace': 'default', 'strings': [(0, '$a', b'OpenSSH')], 'meta': { 'description': 'SSH library', 'website': 'http://www.openssh.com', 'open_source': True, 'software_name': 'OpenSSH' }, 'matches': True } self.test_fo = create_test_file_object() def tearDown(self): self.db_interface_backend.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface_backend.shutdown() self.db_interface.client.drop_database( self._config.get('data_storage', 'sanitize_database')) self.db_interface.shutdown() gc.collect() @classmethod def tearDownClass(cls): cls.mongo_server.shutdown() TMP_DIR.cleanup() def _get_all_firmware_uids(self): uid_list = [] tmp = self.db_interface.firmwares.find() for item in tmp: uid_list.append(item['_id']) return uid_list def test_existence_quick_check(self): self.assertFalse( self.db_interface.existence_quick_check('none_existing'), 'none existing firmware found') self.db_interface_backend.add_firmware(self.test_firmware) self.assertTrue( self.db_interface.existence_quick_check(self.test_firmware.uid), 'existing firmware not found') self.db_interface_backend.add_file_object(self.test_fo) self.assertTrue( self.db_interface.existence_quick_check(self.test_fo.uid), 'existing file not found') def test_get_firmware(self): self.db_interface_backend.add_firmware(self.test_firmware) fobject = self.db_interface.get_firmware(self.test_firmware.uid) self.assertEqual(fobject.vendor, 'test_vendor') self.assertEqual(fobject.device_name, 'test_router') self.assertEqual(fobject.part, '') def test_get_object(self): fo = self.db_interface.get_object(self.test_firmware.uid) self.assertIsNone( fo, 'found something but there is nothing in the database') self.db_interface_backend.add_firmware(self.test_firmware) fo = self.db_interface.get_object(self.test_firmware.uid) self.assertIsInstance(fo, Firmware, 'firmware has wrong type') self.assertEqual(fo.device_name, 'test_router', 'Device name in Firmware not correct') test_file = FileObject(file_path=path.join(get_test_data_dir(), 'get_files_test/testfile2')) self.db_interface_backend.add_file_object(test_file) fo = self.db_interface.get_object(test_file.uid) self.assertIsInstance(fo, FileObject, 'file object has wrong type') def test_get_complete_object_including_all_summaries(self): self.db_interface_backend.report_threshold = 1024 test_file = create_test_file_object() self.test_firmware.add_included_file(test_file) self.db_interface_backend.add_firmware(self.test_firmware) self.db_interface_backend.add_file_object(test_file) tmp = self.db_interface.get_complete_object_including_all_summaries( self.test_firmware.uid) self.assertIsInstance(tmp, Firmware, 'wrong type') self.assertIn('summary', tmp.processed_analysis['dummy'].keys(), 'summary not found in processed analysis') self.assertIn('sum a', tmp.processed_analysis['dummy']['summary'], 'summary of original file not included') self.assertIn('file exclusive sum b', tmp.processed_analysis['dummy']['summary'], 'summary of included file not found') def test_sanitize_analysis(self): short_dict = {'stub_plugin': {'result': 0}} long_dict = { 'stub_plugin': { 'result': 10000000000, 'misc': 'Bananarama', 'summary': [] } } self.test_firmware.processed_analysis = short_dict sanitized_dict = self.db_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.test_firmware.uid) self.assertIn('file_system_flag', sanitized_dict['stub_plugin'].keys()) self.assertFalse(sanitized_dict['stub_plugin']['file_system_flag']) self.assertEqual(self.db_interface.sanitize_fs.list(), [], 'file stored in db but should not') self.test_firmware.processed_analysis = long_dict sanitized_dict = self.db_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.test_firmware.uid) self.assertIn('stub_plugin_result_{}'.format(self.test_firmware.uid), self.db_interface.sanitize_fs.list(), 'sanitized file not stored') self.assertNotIn('summary_result_{}'.format(self.test_firmware.uid), self.db_interface.sanitize_fs.list(), 'summary is erroneously stored') self.assertIn('file_system_flag', sanitized_dict['stub_plugin'].keys()) self.assertTrue(sanitized_dict['stub_plugin']['file_system_flag']) self.assertEqual(type(sanitized_dict['stub_plugin']['summary']), list) def test_sanitize_db_duplicates(self): long_dict = { 'stub_plugin': { 'result': 10000000000, 'misc': 'Bananarama', 'summary': [] } } gridfs_file_name = 'stub_plugin_result_{}'.format( self.test_firmware.uid) self.test_firmware.processed_analysis = long_dict assert self.db_interface.sanitize_fs.find({ 'filename': gridfs_file_name }).count() == 0 self.db_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.test_firmware.uid) assert self.db_interface.sanitize_fs.find({ 'filename': gridfs_file_name }).count() == 1 self.db_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.test_firmware.uid) assert self.db_interface.sanitize_fs.find({ 'filename': gridfs_file_name }).count() == 1, 'duplicate entry was created' md5 = self.db_interface.sanitize_fs.find_one({ 'filename': gridfs_file_name }).md5 long_dict['stub_plugin']['result'] += 1 # new analysis result self.db_interface.sanitize_analysis( self.test_firmware.processed_analysis, self.test_firmware.uid) assert self.db_interface.sanitize_fs.find({ 'filename': gridfs_file_name }).count() == 1, 'duplicate entry was created' assert self.db_interface.sanitize_fs.find_one({ 'filename': gridfs_file_name }).md5 != md5, 'hash of new file did not change' def test_retrieve_analysis(self): self.db_interface.sanitize_fs.put(pickle.dumps('This is a test!'), filename='test_file_path') sanitized_dict = { 'stub_plugin': { 'result': 'test_file_path', 'file_system_flag': True } } sanitized_dict['inbound_result'] = { 'result': 'inbound result', 'file_system_flag': False } retrieved_dict = self.db_interface.retrieve_analysis(sanitized_dict) self.assertNotIn('file_system_flag', retrieved_dict['stub_plugin'].keys()) self.assertIn('result', retrieved_dict['stub_plugin'].keys()) self.assertEqual(retrieved_dict['stub_plugin']['result'], 'This is a test!') self.assertNotIn('file_system_flag', retrieved_dict['inbound_result'].keys()) self.assertEqual(retrieved_dict['inbound_result']['result'], 'inbound result') def test_retrieve_analysis_filter(self): self.db_interface.sanitize_fs.put(pickle.dumps('This is a test!'), filename='test_file_path') sanitized_dict = { 'selected_plugin': { 'result': 'test_file_path', 'file_system_flag': True } } sanitized_dict['other_plugin'] = { 'result': 'test_file_path', 'file_system_flag': True } retrieved_dict = self.db_interface.retrieve_analysis( sanitized_dict, analysis_filter=['selected_plugin']) self.assertEqual(retrieved_dict['selected_plugin']['result'], 'This is a test!') self.assertIn('file_system_flag', retrieved_dict['other_plugin']) def test_get_objects_by_uid_list(self): self.db_interface_backend.add_firmware(self.test_firmware) fo_list = self.db_interface.get_objects_by_uid_list( [self.test_firmware.uid]) self.assertIsInstance(fo_list[0], Firmware, 'firmware has wrong type') self.assertEqual(fo_list[0].device_name, 'test_router', 'Device name in Firmware not correct') test_file = FileObject(file_path=path.join(get_test_data_dir(), 'get_files_test/testfile2')) self.db_interface_backend.add_file_object(test_file) fo_list = self.db_interface.get_objects_by_uid_list([test_file.uid]) self.assertIsInstance(fo_list[0], FileObject, 'file object has wrong type') def test_sanitize_extract_and_retrieve_binary(self): test_data = {'dummy': {'test_key': 'test_value'}} test_data['dummy'] = self.db_interface._extract_binaries( test_data, 'dummy', 'uid') self.assertEqual(self.db_interface.sanitize_fs.list(), ['dummy_test_key_uid'], 'file not written') self.assertEqual(test_data['dummy']['test_key'], 'dummy_test_key_uid', 'new file path not set') test_data['dummy'] = self.db_interface._retrieve_binaries( test_data, 'dummy') self.assertEqual(test_data['dummy']['test_key'], 'test_value', 'value not recoverd') def test_get_firmware_number(self): result = self.db_interface.get_firmware_number() self.assertEqual(result, 0) self.db_interface_backend.add_firmware(self.test_firmware) result = self.db_interface.get_firmware_number(query={}) self.assertEqual(result, 1) result = self.db_interface.get_firmware_number( query={'_id': self.test_firmware.uid}) self.assertEqual(result, 1) test_fw_2 = create_test_firmware(bin_path='container/test.7z') self.db_interface_backend.add_firmware(test_fw_2) result = self.db_interface.get_firmware_number(query='{}') self.assertEqual(result, 2) result = self.db_interface.get_firmware_number( query={'_id': self.test_firmware.uid}) self.assertEqual(result, 1) def test_get_file_object_number(self): result = self.db_interface.get_file_object_number() self.assertEqual(result, 0) self.db_interface_backend.add_file_object(self.test_fo) result = self.db_interface.get_file_object_number( query={}, zero_on_empty_query=False) self.assertEqual(result, 1) result = self.db_interface.get_file_object_number( query={'_id': self.test_fo.uid}) self.assertEqual(result, 1) result = self.db_interface.get_file_object_number( query=json.dumps({'_id': self.test_fo.uid})) self.assertEqual(result, 1) result = self.db_interface.get_file_object_number( query={}, zero_on_empty_query=True) self.assertEqual(result, 0) result = self.db_interface.get_file_object_number( query='{}', zero_on_empty_query=True) self.assertEqual(result, 0) test_fo_2 = create_test_file_object( bin_path='get_files_test/testfile2') self.db_interface_backend.add_file_object(test_fo_2) result = self.db_interface.get_file_object_number( query={}, zero_on_empty_query=False) self.assertEqual(result, 2) result = self.db_interface.get_file_object_number( query={'_id': self.test_fo.uid}) self.assertEqual(result, 1) def test_unpacking_lock(self): first_uid, second_uid = 'id1', 'id2' assert not self.db_interface.check_unpacking_lock( first_uid) and not self.db_interface.check_unpacking_lock( second_uid), 'locks should not be set at start' self.db_interface.set_unpacking_lock(first_uid) assert self.db_interface.check_unpacking_lock( first_uid), 'locks should have been set' self.db_interface.set_unpacking_lock(second_uid) assert self.db_interface.check_unpacking_lock( first_uid) and self.db_interface.check_unpacking_lock( second_uid), 'both locks should be set' self.db_interface.release_unpacking_lock(first_uid) assert not self.db_interface.check_unpacking_lock( first_uid) and self.db_interface.check_unpacking_lock( second_uid), 'lock 1 should be released, lock 2 not' self.db_interface.drop_unpacking_locks() assert not self.db_interface.check_unpacking_lock( second_uid), 'all locks should be dropped' def test_lock_is_released(self): self.db_interface.set_unpacking_lock(self.test_fo.uid) assert self.db_interface.check_unpacking_lock( self.test_fo.uid), 'setting lock did not work' self.db_interface_backend.add_object(self.test_fo) assert not self.db_interface.check_unpacking_lock( self.test_fo.uid), 'add_object should release lock' def test_is_firmware(self): assert self.db_interface.is_firmware(self.test_firmware.uid) is False self.db_interface_backend.add_firmware(self.test_firmware) assert self.db_interface.is_firmware(self.test_firmware.uid) is True def test_is_file_object(self): assert self.db_interface.is_file_object(self.test_fo.uid) is False self.db_interface_backend.add_file_object(self.test_fo) assert self.db_interface.is_file_object(self.test_fo.uid) is True
class TestRestStartCompare(RestTestBase): def setup(self): super().setup() self.db_backend = BackEndDbInterface(config=self.config) def teardown(self): self.db_backend.shutdown() super().teardown() def test_rest_start_compare_valid(self): test_firmware_1 = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') test_firmware_2 = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor', bin_path='container/test.7z') self.db_backend.add_firmware(test_firmware_1) self.db_backend.add_firmware(test_firmware_2) data = { 'uid_list': [test_firmware_1.uid, test_firmware_2.uid], 'redo': True } rv = self.test_client.put('/rest/compare', json=data, follow_redirects=True) assert b'Compare started.' in rv.data def test_rest_start_compare_invalid_uid(self): rv = self.test_client.put('/rest/compare', json={'uid_list': ['123', '456']}, follow_redirects=True) assert b'not found in database' in rv.data def test_rest_start_compare_invalid_data(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.put('/rest/compare', json={'data': 'invalid data'}, follow_redirects=True) assert rv.json['message'] == 'Input payload validation failed' assert 'uid_list' in rv.json['errors'] assert '\'uid_list\' is a required property' in rv.json['errors'][ 'uid_list'] def test_rest_get_compare_valid_not_in_db(self): test_firmware_1 = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') test_firmware_2 = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor', bin_path='container/test.7z') self.db_backend.add_firmware(test_firmware_1) self.db_backend.add_firmware(test_firmware_2) rv = self.test_client.get( f'/rest/compare/{test_firmware_1.uid};{test_firmware_2.uid}', follow_redirects=True) assert b'Compare not found in database.' in rv.data def test_rest_get_compare_invalid_uid(self): rv = self.test_client.get(f'/rest/compare/{TEST_UID};{TEST_UID}', follow_redirects=True) assert b'not found in database' in rv.data def test_rest_get_compare_invalid_data(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/compare', follow_redirects=True) assert b'The method is not allowed for the requested URL' in rv.data
class TestAcceptanceIoRoutes(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend_interface = BackEndDbInterface(self.config) self.test_fw = create_test_firmware(device_name='test_fw') def tearDown(self): self.db_backend_interface.shutdown() self._stop_backend() super().tearDown() def test_radare_button(self): response = self.test_client.get( '/radare-view/{uid}'.format(uid=self.test_fw.uid)) self.assertIn('200', response.status, 'radare view link failed') self.assertIn(b'File not found in database', response.data, 'radare view should fail on missing uid') self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get( '/radare-view/{uid}'.format(uid=self.test_fw.uid)) self.assertIn('200', response.status, 'radare view link failed') self.assertIn(b'with url: /v1/retrieve', response.data, 'error coming from wrong request') self.assertIn(b'Failed to establish a new connection', response.data, 'connection shall fail') def test_ida_download(self): compare_interface = CompareDbInterface(config=self.config) self.db_backend_interface.add_firmware(self.test_fw) COMPARE_RESULT['general'] = { 'a': { self.test_fw.uid: 'x' }, 'b': { self.test_fw.uid: 'y' } } compare_interface.add_compare_result(COMPARE_RESULT) cid = compare_interface._calculate_compare_result_id(COMPARE_RESULT) response = self.test_client.get('/ida-download/{cid}'.format(cid=cid)) self.assertIn(b'IDA database', response.data, 'mocked ida database not in result') def test_ida_download_bad_uid(self): compare_interface = CompareDbInterface(config=self.config) compare_interface.add_compare_result(COMPARE_RESULT) cid = compare_interface._calculate_compare_result_id(COMPARE_RESULT) response = self.test_client.get('/ida-download/{cid}'.format(cid=cid)) self.assertIn(b'not found in database', response.data, 'endpoint should dismiss result') def test_pdf_download(self): response = self.test_client.get( '/pdf-download/{uid}'.format(uid=self.test_fw.uid)) assert response.status_code == 200, 'pdf download link failed' assert b'File not found in database' in response.data, 'radare view should fail on missing uid' self.db_backend_interface.add_firmware(self.test_fw) response = self.test_client.get( '/pdf-download/{uid}'.format(uid=self.test_fw.uid)) assert response.status_code == 200, 'pdf download failed' assert response.headers[ 'Content-Disposition'] == 'attachment; filename={}_analysis_report.pdf'.format( self.test_fw.device_name.replace(' ', '_')) assert get_file_type_from_binary( response.data)['mime'] == 'application/pdf'
class TestCompare: @classmethod def setup_class(cls): cls._config = get_config_for_testing() cls.mongo_server = MongoMgr(config=cls._config) def setup(self): self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.db_interface_compare = CompareDbInterface(config=self._config) self.db_interface_admin = AdminDbInterface(config=self._config) self.fw_one = create_test_firmware() self.fw_two = create_test_firmware() self.fw_two.set_binary(b'another firmware') self.compare_dict = self._create_compare_dict() self.compare_id = '{};{}'.format(self.fw_one.uid, self.fw_two.uid) def teardown(self): self.db_interface_compare.shutdown() self.db_interface_admin.shutdown() self.db_interface_backend.shutdown() self.db_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface.shutdown() gc.collect() @classmethod def teardown_class(cls): cls.mongo_server.shutdown() def _create_compare_dict(self): return { 'general': { 'hid': { self.fw_one.uid: 'foo', self.fw_two.uid: 'bar' }, 'virtual_file_path': { self.fw_one.uid: 'dev_one_name', self.fw_two.uid: 'dev_two_name' } }, 'plugins': {}, } def test_add_and_get_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) retrieved = self.db_interface_compare.get_compare_result( self.compare_id) assert retrieved['general']['virtual_file_path'][self.fw_one.uid] == 'dev_one_name',\ 'content of retrieval not correct' def test_get_not_existing_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) result = self.db_interface_compare.get_compare_result(self.compare_id) assert result is None, 'result not none' def test_calculate_compare_result_id(self): comp_id = self.db_interface_compare._calculate_compare_result_id( self.compare_dict) assert comp_id == self.compare_id def test_calculate_compare_result_id__incomplete_entries(self): compare_dict = { 'general': { 'stat_1': { 'a': None }, 'stat_2': { 'b': None } } } comp_id = self.db_interface_compare._calculate_compare_result_id( compare_dict) assert comp_id == 'a;b' def test_check_objects_exist(self): self.db_interface_backend.add_firmware(self.fw_one) assert self.db_interface_compare.check_objects_exist( self.fw_one.uid) is None, 'existing_object not found' with pytest.raises(FactCompareException): self.db_interface_compare.check_objects_exist( '{};none_existing_object'.format(self.fw_one.uid)) def test_get_compare_result_of_nonexistent_uid(self): self.db_interface_backend.add_firmware(self.fw_one) try: self.db_interface_compare.check_objects_exist( '{};none_existing_object'.format(self.fw_one.uid)) except FactCompareException as exception: assert exception.get_message( ) == 'none_existing_object not found in database', 'error message not correct' def test_get_latest_comparisons(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) before = time() self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) for id_, hids, submission_date in result: assert self.fw_one.uid in hids assert self.fw_two.uid in hids assert self.fw_one.uid in id_ assert self.fw_two.uid in id_ assert before <= submission_date <= time() def test_get_latest_comparisons_removed_firmware(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) assert result != [], 'A compare result should be available' self.db_interface_admin.delete_firmware(self.fw_two.uid) result = self.db_interface_compare.page_compare_results(limit=10) assert result == [], 'No compare result should be available' def test_get_total_number_of_results(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) number = self.db_interface_compare.get_total_number_of_results() assert number == 1, 'no compare result found in database' @pytest.mark.parametrize('root_uid, expected_result', [ ('the_root_uid', ['uid1', 'uid2']), ('some_other_uid', []), (None, []), ]) def test_get_exclusive_files(self, root_uid, expected_result): compare_dict = self._create_compare_dict() compare_dict['plugins'] = { 'File_Coverage': { 'exclusive_files': { 'the_root_uid': ['uid1', 'uid2'] } } } self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(compare_dict) exclusive_files = self.db_interface_compare.get_exclusive_files( self.compare_id, root_uid) assert exclusive_files == expected_result
class TestCompare(unittest.TestCase): def setUp(self): self._config = get_config_for_testing() self.mongo_server = MongoMgr(config=self._config) self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.db_interface_compare = CompareDbInterface(config=self._config) self.db_interface_admin = AdminDbInterface(config=self._config) self.fw_one = create_test_firmware() self.fw_two = create_test_firmware() self.fw_two.set_binary(b'another firmware') self.compare_dict = self._create_compare_dict() def tearDown(self): self.db_interface_compare.shutdown() self.db_interface_admin.shutdown() self.db_interface_backend.shutdown() self.db_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface.shutdown() self.mongo_server.shutdown() gc.collect() def _create_compare_dict(self): comp_dict = { 'general': { 'hid': { self.fw_one.get_uid(): 'foo', self.fw_two.get_uid(): 'bar' } }, 'plugins': {} } comp_dict['general']['virtual_file_path'] = { self.fw_one.get_uid(): 'dev_one_name', self.fw_two.get_uid(): 'dev_two_name' } return comp_dict def test_add_and_get_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) retrieved = self.db_interface_compare.get_compare_result( '{};{}'.format(self.fw_one.get_uid(), self.fw_two.get_uid())) self.assertEqual( retrieved['general']['virtual_file_path'][self.fw_one.get_uid()], 'dev_one_name', 'content of retrieval not correct') def test_get_not_existing_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) result = self.db_interface_compare.get_compare_result('{};{}'.format( self.fw_one.get_uid(), self.fw_two.get_uid())) self.assertIsNone(result, 'result not none') def test_calculate_compare_result_id(self): comp_id = self.db_interface_compare._calculate_compare_result_id( self.compare_dict) self.assertEqual( comp_id, '{};{}'.format(self.fw_one.get_uid(), self.fw_two.get_uid())) def test_object_existence_quick_check(self): self.db_interface_backend.add_firmware(self.fw_one) self.assertIsNone( self.db_interface_compare.object_existence_quick_check( self.fw_one.get_uid()), 'existing_object not found') self.assertEqual( self.db_interface_compare.object_existence_quick_check( '{};none_existing_object'.format(self.fw_one.get_uid())), 'none_existing_object not found in database', 'error message not correct') def test_get_compare_result_of_none_existing_uid(self): self.db_interface_backend.add_firmware(self.fw_one) result = self.db_interface_compare.get_compare_result( '{};none_existing_uid'.format(self.fw_one.get_uid())) self.assertEqual(result, 'none_existing_uid not found in database', 'no result not found error') def test_get_latest_comparisons(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) before = time() self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) for id, hids, submission_date in result: self.assertIn(self.fw_one.get_uid(), hids) self.assertIn(self.fw_two.get_uid(), hids) self.assertIn(self.fw_one.get_uid(), id) self.assertIn(self.fw_two.get_uid(), id) self.assertTrue(before <= submission_date <= time()) def test_get_latest_comparisons_removed_firmware(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) self.assertNotEqual(result, [], 'A compare result should be available') self.db_interface_admin.delete_firmware(self.fw_two.uid) result = self.db_interface_compare.page_compare_results(limit=10) self.assertEqual(result, [], 'No compare result should be available') def test_get_total_number_of_results(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) number = self.db_interface_compare.get_total_number_of_results() self.assertEqual(number, 1, 'no compare result found in database')
class TestAcceptanceNormalSearch(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend_interface = BackEndDbInterface(self.config) self.test_fw = create_test_firmware(device_name='test_fw') self.test_fw.release_date = '2001-02-03' self.db_backend_interface.add_firmware(self.test_fw) def tearDown(self): self.db_backend_interface.shutdown() self._stop_backend() super().tearDown() def _show_search_get(self): rv = self.test_client.get('/database/search') assert b'<h2>Search Firmware Database</h2>' in rv.data, 'search page not rendered correctly' def _show_browse_db(self): rv = self.test_client.get('/database/browse') assert self.test_fw.uid.encode( ) in rv.data, 'test firmware not found in browse database' def _show_browse_compare(self): rv = self.test_client.get('/database/browse_compare') assert '200' in rv.status, 'compare browsing site offline' def _show_search_post(self): data = { 'device_class_dropdown': '', 'file_name': '', 'vendor': '', 'device_name': '', 'version': '', 'release_date': '', 'hash_value': '' } rv = self.test_client.post('/database/search', content_type='multipart/form-data', follow_redirects=True, data=data) assert self.test_fw.uid.encode( ) in rv.data, 'test firmware not found in empty search' data['file_name'] = self.test_fw.file_name data['vendor'] = self.test_fw.vendor rv = self.test_client.post('/database/search', content_type='multipart/form-data', follow_redirects=True, data=data) assert self.test_fw.uid.encode( ) in rv.data, 'test firmware not found in specific search' def _show_quick_search(self): rv = self.test_client.get('/database/quick_search?search_term=test_fw', follow_redirects=True) assert self.test_fw.uid.encode( ) in rv.data, 'test firmware not found in specific search' def _search_date(self): rv = self.test_client.get('/database/browse?date=February 2001', follow_redirects=True) assert self.test_fw.uid.encode( ) in rv.data, 'date search does not work' rv = self.test_client.get('/database/browse?date=February 2002', follow_redirects=True) assert self.test_fw.uid.encode( ) not in rv.data, 'date search does not work' def test_search(self): self._show_browse_db() self._show_browse_compare() self._show_search_get() self._show_search_post() self._show_quick_search() self._search_date()
class TestCompare(unittest.TestCase): @classmethod def setUpClass(cls): cls._config = get_config_for_testing() cls.mongo_server = MongoMgr(config=cls._config) def setUp(self): self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.db_interface_compare = CompareDbInterface(config=self._config) self.db_interface_admin = AdminDbInterface(config=self._config) self.fw_one = create_test_firmware() self.fw_two = create_test_firmware() self.fw_two.set_binary(b'another firmware') self.compare_dict = self._create_compare_dict() def tearDown(self): self.db_interface_compare.shutdown() self.db_interface_admin.shutdown() self.db_interface_backend.shutdown() self.db_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface.shutdown() gc.collect() @classmethod def tearDownClass(cls): cls.mongo_server.shutdown() def _create_compare_dict(self): comp_dict = { 'general': { 'hid': { self.fw_one.uid: 'foo', self.fw_two.uid: 'bar' } }, 'plugins': {} } comp_dict['general']['virtual_file_path'] = { self.fw_one.uid: 'dev_one_name', self.fw_two.uid: 'dev_two_name' } return comp_dict def test_add_and_get_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) retrieved = self.db_interface_compare.get_compare_result( '{};{}'.format(self.fw_one.uid, self.fw_two.uid)) self.assertEqual( retrieved['general']['virtual_file_path'][self.fw_one.uid], 'dev_one_name', 'content of retrieval not correct') def test_get_not_existing_compare_result(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) result = self.db_interface_compare.get_compare_result('{};{}'.format( self.fw_one.uid, self.fw_two.uid)) self.assertIsNone(result, 'result not none') def test_calculate_compare_result_id(self): comp_id = self.db_interface_compare._calculate_compare_result_id( self.compare_dict) self.assertEqual(comp_id, '{};{}'.format(self.fw_one.uid, self.fw_two.uid)) def test_calculate_compare_result_id__incomplete_entries(self): compare_dict = { 'general': { 'stat_1': { 'a': None }, 'stat_2': { 'b': None } } } comp_id = self.db_interface_compare._calculate_compare_result_id( compare_dict) self.assertEqual('a;b', comp_id) def test_check_objects_exist(self): self.db_interface_backend.add_firmware(self.fw_one) assert self.db_interface_compare.check_objects_exist( self.fw_one.uid) is None, 'existing_object not found' with pytest.raises(FactCompareException): self.db_interface_compare.check_objects_exist( '{};none_existing_object'.format(self.fw_one.uid)) def test_get_compare_result_of_nonexistent_uid(self): self.db_interface_backend.add_firmware(self.fw_one) try: self.db_interface_compare.check_objects_exist( '{};none_existing_object'.format(self.fw_one.uid)) except FactCompareException as exception: assert exception.get_message( ) == 'none_existing_object not found in database', 'error message not correct' def test_get_latest_comparisons(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) before = time() self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) for id_, hids, submission_date in result: self.assertIn(self.fw_one.uid, hids) self.assertIn(self.fw_two.uid, hids) self.assertIn(self.fw_one.uid, id_) self.assertIn(self.fw_two.uid, id_) self.assertTrue(before <= submission_date <= time()) def test_get_latest_comparisons_removed_firmware(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) result = self.db_interface_compare.page_compare_results(limit=10) self.assertNotEqual(result, [], 'A compare result should be available') self.db_interface_admin.delete_firmware(self.fw_two.uid) result = self.db_interface_compare.page_compare_results(limit=10) self.assertEqual(result, [], 'No compare result should be available') def test_get_total_number_of_results(self): self.db_interface_backend.add_firmware(self.fw_one) self.db_interface_backend.add_firmware(self.fw_two) self.db_interface_compare.add_compare_result(self.compare_dict) number = self.db_interface_compare.get_total_number_of_results() self.assertEqual(number, 1, 'no compare result found in database')
def _init_test_data(config: ConfigParser, tmp_dir: str): backend_db_interface = BackEndDbInterface(config=config) backend_db_interface.add_firmware(TEST_FW) store_binary_on_file_system(tmp_dir, TEST_FW) backend_db_interface.shutdown()
class TestStorageDbInterfaceBackend(unittest.TestCase): def setUp(self): self._config = get_config_for_testing(TMP_DIR) self.mongo_server = MongoMgr(config=self._config) self.db_interface = MongoInterfaceCommon(config=self._config) self.db_interface_backend = BackEndDbInterface(config=self._config) self.test_firmware = create_test_firmware() self.test_yara_match = { 'rule': 'OpenSSH', 'tags': [], 'namespace': 'default', 'strings': [(0, '$a', b'OpenSSH')], 'meta': { 'description': 'SSH library', 'website': 'http://www.openssh.com', 'open_source': True, 'software_name': 'OpenSSH' }, 'matches': True } self.test_fo = create_test_file_object() def tearDown(self): self.db_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_interface_backend.shutdown() self.db_interface.shutdown() self.mongo_server.shutdown() TMP_DIR.cleanup() gc.collect() def _get_all_firmware_uids(self): uid_list = [] tmp = self.db_interface.firmwares.find() for item in tmp: uid_list.append(item['_id']) return uid_list def test_add_firmware(self): self.db_interface_backend.add_firmware(self.test_firmware) self.assertGreater(len(self._get_all_firmware_uids()), 0, 'No entry added to DB') recoverd_firmware_entry = self.db_interface_backend.firmwares.find_one( ) self.assertAlmostEqual(recoverd_firmware_entry['submission_date'], time(), msg='submission time not set correctly', delta=5.0) def test_add_and_get_firmware(self): self.db_interface_backend.add_firmware(self.test_firmware) result_backend = self.db_interface_backend.get_firmware( self.test_firmware.get_uid()) self.assertIsNotNone(result_backend.binary, 'binary not set in backend result') result_common = self.db_interface.get_firmware( self.test_firmware.get_uid()) self.assertIsNone(result_common.binary, 'binary set in common result') self.assertEqual(result_common.size, 787, 'file size not correct in common') self.assertIsInstance(result_common.tags, dict, 'tag field type not correct') def test_add_and_get_file_object(self): self.db_interface_backend.add_file_object(self.test_fo) result_backend = self.db_interface_backend.get_file_object( self.test_fo.get_uid()) self.assertIsNotNone(result_backend.binary, 'binary not set in backend result') result_common = self.db_interface.get_file_object( self.test_fo.get_uid()) self.assertIsNone(result_common.binary, 'binary set in common result') self.assertEqual(result_common.size, 62, 'file size not correct in common') def test_update_firmware(self): first_dict = { 'stub_plugin': { 'result': 0 }, 'other_plugin': { 'field': 'day' } } second_dict = {'stub_plugin': {'result': 1}} self.test_firmware.processed_analysis = first_dict self.db_interface_backend.add_firmware(self.test_firmware) self.assertEqual( 0, self.db_interface.get_object( self.test_firmware.get_uid()).processed_analysis['stub_plugin'] ['result']) self.test_firmware.processed_analysis = second_dict self.db_interface_backend.add_firmware(self.test_firmware) self.assertEqual( 1, self.db_interface.get_object( self.test_firmware.get_uid()).processed_analysis['stub_plugin'] ['result']) self.assertIn( 'other_plugin', self.db_interface.get_object( self.test_firmware.get_uid()).processed_analysis.keys()) def test_update_file_object(self): first_dict = {'other_plugin': {'result': 0}} second_dict = {'stub_plugin': {'result': 1}} self.test_fo.processed_analysis = first_dict self.test_fo.files_included = {'file a', 'file b'} self.db_interface_backend.add_file_object(self.test_fo) self.test_fo.processed_analysis = second_dict self.test_fo.files_included = {'file b', 'file c'} self.db_interface_backend.add_file_object(self.test_fo) received_object = self.db_interface.get_object(self.test_fo.get_uid()) self.assertEqual( 0, received_object.processed_analysis['other_plugin']['result']) self.assertEqual( 1, received_object.processed_analysis['stub_plugin']['result']) self.assertEqual(3, len(received_object.files_included)) def test_add_and_get_object_including_comment(self): comment, author, date, uid = 'this is a test comment!', 'author', '1473431685', self.test_fo.get_uid( ) self.test_fo.comments.append({ 'time': str(date), 'author': author, 'comment': comment }) self.db_interface_backend.add_file_object(self.test_fo) retrieved_comment = self.db_interface.get_object(uid).comments[0] self.assertEqual(author, retrieved_comment['author']) self.assertEqual(comment, retrieved_comment['comment']) self.assertEqual(date, retrieved_comment['time'])
class TestRestFirmware(RestTestBase): def setUp(self): super().setUp() self.db_backend = BackEndDbInterface(config=self.config) def tearDown(self): self.db_backend.shutdown() super().tearDown() def test_rest_firmware_existing(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware', follow_redirects=True) assert b'uids' in rv.data assert b'418a54d78550e8584291c96e5d6168133621f352bfc1d43cf84e81187fef4962_787' in rv.data def test_offset_to_empty_response(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware?offset=1', follow_redirects=True) assert b'uids' in rv.data assert b'418a54d78550e8584291c96e5d6168133621f352bfc1d43cf84e81187fef4962_787' not in rv.data def test_stable_response_on_bad_paging(self): rv = self.test_client.get('/rest/firmware?offset=Y', follow_redirects=True) assert b'error_message' in rv.data assert b'Malformed' in rv.data def test_rest_search_existing(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware?query={}'.format(urllib.parse.quote('{"device_class": "test class"}')), follow_redirects=True) assert b'uids' in rv.data assert b'418a54d78550e8584291c96e5d6168133621f352bfc1d43cf84e81187fef4962_787' in rv.data def test_rest_search_not_existing(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware?query={}'.format(urllib.parse.quote('{"device_class": "non-existing class"}')), follow_redirects=True) assert b'"uids": []' in rv.data def test_rest_upload_valid(self): rv = self.test_client.put('/rest/firmware', data=json.dumps( { 'binary': standard_b64encode(b'test_file_content').decode(), 'file_name': 'test_file.txt', 'device_name': 'test_device', 'device_class': 'test_class', 'firmware_version': '1', 'vendor': 'test_vendor', 'release_date': '01.01.1970', 'tags': '', 'requested_analysis_systems': ['dummy'] } ), follow_redirects=True) assert b'c1f95369a99b765e93c335067e77a7d91af3076d2d3d64aacd04e1e0a810b3ed_17' in rv.data assert b'"status": 0' in rv.data def test_rest_upload_invalid(self): rv = self.test_client.put('/rest/firmware', data=json.dumps( { 'binary': standard_b64encode(b'test_file_content').decode(), 'file_name': 'test_file.txt', 'device_name': 'test_device', 'device_class': 'test_class', 'vendor': 'test_vendor', 'release_date': '01.01.1970', 'tags': '', 'requested_analysis_systems': ['dummy'] } ), follow_redirects=True) assert b'"error_message": "firmware_version not found"' in rv.data assert b'"status": 1' in rv.data def test_rest_download_valid(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware/{}'.format(test_firmware.uid), follow_redirects=True) assert b'file_type' in rv.data assert b'test_type' in rv.data assert b'unpacker' in rv.data assert b'used_unpack_plugin' in rv.data def test_rest_download_invalid_uid(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware/invalid%20uid', follow_redirects=True) assert b'No firmware with UID invalid uid' in rv.data def test_rest_download_invalid_data(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.get('/rest/firmware/', follow_redirects=True) assert b'404 Not Found' in rv.data @pytest.mark.skip(reason='Intercom not running, thus not a single plugin known') def test_rest_update_analysis_success(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.put('/rest/firmware/{}?update={}'.format(test_firmware.uid, urllib.parse.quote('["printable_strings"]')), follow_redirects=True) assert test_firmware.uid.encode() in rv.data assert b'"status": 0' in rv.data def test_rest_update_bad_query(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) rv = self.test_client.put('/rest/firmware/{}?update=not_a_list'.format(test_firmware.uid), follow_redirects=True) assert b'"status": 1' in rv.data assert b'has to be a list' in rv.data def test_rest_download_with_summary(self): test_firmware = create_test_firmware(device_class='test class', device_name='test device', vendor='test vendor') self.db_backend.add_firmware(test_firmware) request_with_summary = self.test_client.get('/rest/firmware/{}?summary=true'.format(test_firmware.uid), follow_redirects=True) assert test_firmware.processed_analysis['dummy']['summary'][0].encode() in request_with_summary.data
class TestStorageDbInterfaceFrontend(unittest.TestCase): def setUp(self): self._config = get_config_for_testing(TMP_DIR) self.mongo_server = MongoMgr(config=self._config) self.db_frontend_interface = FrontEndDbInterface(config=self._config) self.db_backend_interface = BackEndDbInterface(config=self._config) self.test_firmware = create_test_firmware() def tearDown(self): self.db_frontend_interface.shutdown() self.db_backend_interface.client.drop_database( self._config.get('data_storage', 'main_database')) self.db_backend_interface.shutdown() self.mongo_server.shutdown() TMP_DIR.cleanup() gc.collect() def test_get_meta_list(self): self.db_backend_interface.add_firmware(self.test_firmware) list_of_firmwares = self.db_frontend_interface.get_meta_list() test_output = list_of_firmwares.pop() self.assertEqual(test_output[1], 'test_vendor test_router - 0.1 (Router)', 'Firmware not successfully received') def test_get_hid_firmware(self): self.db_backend_interface.add_firmware(self.test_firmware) result = self.db_frontend_interface.get_hid( self.test_firmware.get_uid()) self.assertEqual(result, 'test_vendor test_router - 0.1 (Router)', 'fw hid not correct') def test_get_hid_fo(self): test_fo = create_test_file_object(bin_path='get_files_test/testfile2') test_fo.virtual_file_path = { 'a': ['|a|/test_file'], 'b': ['|b|/get_files_test/testfile2'] } self.db_backend_interface.add_file_object(test_fo) result = self.db_frontend_interface.get_hid(test_fo.get_uid(), root_uid='b') self.assertEqual(result, '/get_files_test/testfile2', 'fo hid not correct') result = self.db_frontend_interface.get_hid(test_fo.get_uid()) self.assertIsInstance(result, str, 'result is not a string') self.assertEqual(result[0], '/', 'first character not correct if no root_uid set') result = self.db_frontend_interface.get_hid(test_fo.get_uid(), root_uid='c') self.assertEqual( result[0], '/', 'first character not correct if invalid root_uid set') def test_get_file_name(self): self.db_backend_interface.add_firmware(self.test_firmware) result = self.db_frontend_interface.get_file_name( self.test_firmware.get_uid()) self.assertEqual(result, 'test.zip', 'name not correct') def test_get_hid_invalid_uid(self): result = self.db_frontend_interface.get_hid('foo') self.assertEqual(result, '', 'invalid uid should result in empty string') def test_get_firmware_attribute_list(self): self.db_backend_interface.add_firmware(self.test_firmware) self.assertEqual(self.db_frontend_interface.get_device_class_list(), ['Router']) self.assertEqual(self.db_frontend_interface.get_vendor_list(), ['test_vendor']) self.assertEqual( self.db_frontend_interface.get_firmware_attribute_list( 'device_name', { 'vendor': 'test_vendor', 'device_class': 'Router' }), ['test_router']) self.assertEqual( self.db_frontend_interface.get_firmware_attribute_list('version'), ['0.1']) self.assertEqual(self.db_frontend_interface.get_device_name_dict(), {'Router': { 'test_vendor': ['test_router'] }}) def test_get_data_for_nice_list(self): uid_list = [self.test_firmware.get_uid()] self.db_backend_interface.add_firmware(self.test_firmware) nice_list_data = self.db_frontend_interface.get_data_for_nice_list( uid_list, uid_list[0]) self.assertEquals( sorted([ 'size', 'virtual_file_paths', 'uid', 'mime-type', 'files_included' ]), sorted(nice_list_data[0].keys())) self.assertEqual(nice_list_data[0]['uid'], self.test_firmware.get_uid()) def test_generic_search(self): self.db_backend_interface.add_firmware(self.test_firmware) # str input result = self.db_frontend_interface.generic_search( '{"file_name": "test.zip"}') self.assertEqual(result, [self.test_firmware.get_uid()], 'Firmware not successfully received') # dict input result = self.db_frontend_interface.generic_search( {'file_name': 'test.zip'}) self.assertEqual(result, [self.test_firmware.get_uid()], 'Firmware not successfully received') def test_all_uids_found_in_database(self): self.db_backend_interface.client.drop_database( self._config.get('data_storage', 'main_database')) uid_list = [self.test_firmware.get_uid()] self.assertFalse( self.db_frontend_interface.all_uids_found_in_database(uid_list)) self.db_backend_interface.add_firmware(self.test_firmware) self.assertTrue( self.db_frontend_interface.all_uids_found_in_database( [self.test_firmware.get_uid()])) def test_get_number_of_firmwares_in_db(self): self.assertEqual( self.db_frontend_interface.get_number_of_firmwares_in_db(), 0) self.db_backend_interface.add_firmware(self.test_firmware) self.assertEqual( self.db_frontend_interface.get_number_of_firmwares_in_db(), 1) def test_get_x_last_added_firmwares(self): self.assertEqual(self.db_frontend_interface.get_last_added_firmwares(), [], 'empty db should result in empty list') test_fw_one = create_test_firmware(device_name='fw_one') self.db_backend_interface.add_firmware(test_fw_one) test_fw_two = create_test_firmware(device_name='fw_two', bin_path='container/test.7z') self.db_backend_interface.add_firmware(test_fw_two) test_fw_three = create_test_firmware(device_name='fw_three', bin_path='container/test.cab') self.db_backend_interface.add_firmware(test_fw_three) result = self.db_frontend_interface.get_last_added_firmwares(limit_x=2) self.assertEqual(len(result), 2, 'Number of results should be 2') self.assertEqual(result[0]['device_name'], 'fw_three', 'last firmware is not first entry') self.assertEqual(result[1]['device_name'], 'fw_two', 'second last firmware is not the second entry') def test_generate_file_tree_node(self): parent_fw = create_test_firmware() child_fo = create_test_file_object() child_fo.processed_analysis['file_type'] = {'mime': 'sometype'} uid = parent_fw.get_uid() child_fo.virtual_file_path = { uid: ['|{}|/folder/{}'.format(uid, child_fo.file_name)] } parent_fw.files_included = {child_fo.get_uid()} self.db_backend_interface.add_object(parent_fw) self.db_backend_interface.add_object(child_fo) for node in self.db_frontend_interface.generate_file_tree_node( uid, uid): self.assertIsInstance(node, FileTreeNode) self.assertEqual(node.name, parent_fw.file_name) self.assertTrue(node.has_children) for node in self.db_frontend_interface.generate_file_tree_node( child_fo.get_uid(), uid): self.assertIsInstance(node, FileTreeNode) self.assertEqual(node.name, 'folder') self.assertTrue(node.has_children) virtual_grand_child = node.get_list_of_child_nodes()[0] self.assertEqual(virtual_grand_child.type, 'sometype') self.assertFalse(virtual_grand_child.has_children) self.assertEqual(virtual_grand_child.name, child_fo.file_name) def test_get_number_of_total_matches(self): parent_fw = create_test_firmware() child_fo = create_test_file_object() uid = parent_fw.get_uid() child_fo.virtual_file_path = { uid: ['|{}|/folder/{}'.format(uid, child_fo.file_name)] } self.db_backend_interface.add_object(parent_fw) self.db_backend_interface.add_object(child_fo) query = '{{"$or": [{{"_id": "{}"}}, {{"_id": "{}"}}]}}'.format( uid, child_fo.get_uid()) self.assertEqual( self.db_frontend_interface.get_number_of_total_matches( query, only_parent_firmwares=False), 2) self.assertEqual( self.db_frontend_interface.get_number_of_total_matches( query, only_parent_firmwares=True), 1) def test_get_other_versions_of_firmware(self): parent_fw1 = create_test_firmware(version='1') self.db_backend_interface.add_object(parent_fw1) parent_fw2 = create_test_firmware(version='2', bin_path='container/test.7z') self.db_backend_interface.add_object(parent_fw2) parent_fw3 = create_test_firmware(version='3', bin_path='container/test.cab') self.db_backend_interface.add_object(parent_fw3) other_versions = self.db_frontend_interface.get_other_versions_of_firmware( parent_fw1) self.assertEqual(len(other_versions), 2, 'wrong number of other versions') self.assertIn({ '_id': parent_fw2.get_uid(), 'version': '2' }, other_versions) self.assertIn({ '_id': parent_fw3.get_uid(), 'version': '3' }, other_versions) other_versions = self.db_frontend_interface.get_other_versions_of_firmware( parent_fw2) self.assertIn({ '_id': parent_fw3.get_uid(), 'version': '3' }, other_versions)
class TestAcceptanceNormalSearch(TestAcceptanceBase): def setUp(self): super().setUp() self._start_backend() self.db_backend_interface = BackEndDbInterface(self.config) self.test_fw = create_test_firmware(device_name='test_fw') self.db_backend_interface.add_firmware(self.test_fw) def tearDown(self): self.db_backend_interface.shutdown() self._stop_backend() super().tearDown() def _show_database_access_page(self): rv = self.test_client.get('/database') self.assertIn(b'<b>Search Database</b>', rv.data, 'database access page not rendered correctly') def _show_search_get(self): rv = self.test_client.get('/database/search') self.assertIn(b'<h2>Search Firmware Database</h2>', rv.data, 'search page not rendered correctly') def _show_browse_db(self): rv = self.test_client.get('/database/browse') self.assertIn(self.test_fw.get_uid().encode(), rv.data, 'test firmware not found in browse database') def _show_search_post(self): data = { 'device_class_dropdown': '', 'file_name': '', 'vendor': '', 'device_name': '', 'version': '', 'release_date': '', 'hash_value': '' } rv = self.test_client.post('/database/search', content_type='multipart/form-data', follow_redirects=True, data=data) self.assertIn(self.test_fw.get_uid().encode(), rv.data, 'test firmware not found in empty search') data['file_name'] = self.test_fw.file_name data['vendor'] = self.test_fw.vendor rv = self.test_client.post('/database/search', content_type='multipart/form-data', follow_redirects=True, data=data) self.assertIn(self.test_fw.get_uid().encode(), rv.data, 'test firmware not found in specific search') def _show_quick_search(self): rv = self.test_client.get('/database/quick_search?search_term=test_fw', follow_redirects=True) self.assertIn(self.test_fw.get_uid().encode(), rv.data, 'test firmware not found in specific search') def test_search(self): self._show_database_access_page() self._show_browse_db() self._show_search_get() self._show_search_post() self._show_quick_search()