def test_server_scan_completed(self): output_file = StringIO() generator = ConsoleOutputGenerator(output_file) server_info = MockServerConnectivityInfo() plugin_result_1 = MockPluginScanResult(server_info, MockPluginScanCommandOne(), u'Plugin ûnicôdé output', None) plugin_result_2 = MockPluginScanResult(server_info, MockPluginScanCommandTwo(), u'other plugin Output', None) server_scan = CompletedServerScan(server_info, [plugin_result_1, plugin_result_2]) generator.server_scan_completed(server_scan) received_output = output_file.getvalue() output_file.close() # Ensure the console output displayed the server's info self.assertIn(server_info.hostname, received_output.lower()) self.assertIn(str(server_info.port), received_output) self.assertIn(server_info.ip_address, received_output.lower()) # Ensure the console output displayed the plugin text outputs self.assertIn(plugin_result_1.text_output, received_output) self.assertIn(plugin_result_2.text_output, received_output)
def test(self): """The final output only gets written at the end, when calling scans_completed(). Hence we need to call all the methods in the right order and validate the final output at the end. """ output_file = StringIO() generator = XmlOutputGenerator(output_file) generator.command_line_parsed(None, MockCommandLineValues()) failed_scan = FailedServerScan( server_string=u'unibadeéè.com', connection_exception=ServerConnectivityError( error_msg=u'Some érrôr')) generator.server_connectivity_test_failed(failed_scan) server_info = MockServerConnectivityInfo() generator.server_connectivity_test_succeeded(server_info) generator.scans_started() plugin_xml_out_1 = Element(u'plugin1', attrib={'test1': 'value1'}) plugin_xml_out_1.text = u'Plugin ûnicôdé output' plugin_result_1 = MockPluginResult('plugin1', None, plugin_xml_out_1) plugin_xml_out_2 = Element(u'plugin2', attrib={'test2': 'value2'}) plugin_xml_out_2.text = u'other plugin Output' plugin_result_2 = MockPluginResult('plugin2', None, plugin_xml_out_2) server_scan = CompletedServerScan(server_info, [plugin_result_1, plugin_result_2]) generator.server_scan_completed(server_scan) scan_time = 1.3 generator.scans_completed(scan_time) received_output = unicode(output_file.getvalue(), 'utf-8') output_file.close() # Ensure the output properly listed the connectivity error with unicode escaped as \u sequences self.assertIn(u'unibadeéè.com', received_output) self.assertIn(u'Some érrôr', received_output) # Ensure the output properly listed the online domain self.assertIn(server_info.hostname, received_output) self.assertIn(str(server_info.port), received_output) self.assertIn(server_info.ip_address, received_output) # Ensure the output displayed the plugin's XML output self.assertIn(plugin_result_1.plugin_command, received_output) self.assertIn(plugin_result_2.plugin_command, received_output) self.assertIn(plugin_result_1.as_xml().text, received_output) self.assertIn(plugin_result_2.as_xml().text, received_output) # Ensure the console output displayed the total scan time self.assertIn('totalScanTime="{}"'.format(scan_time), received_output) self.assertIn( 'networkTimeout="{}"'.format(MockCommandLineValues().timeout), received_output) self.assertIn( 'networkMaxRetries="{}"'.format( MockCommandLineValues().nb_retries), received_output)
def test(self): """The final output only gets written at the end, when calling scans_completed(). Hence we need to call all the methods in the right order and validate the final output at the end. """ output_file = StringIO() generator = JsonOutputGenerator(output_file) generator.command_line_parsed(None, MockCommandLineValues()) failed_scan = FailedServerScan(server_string=u'unibadeéè.com', connection_exception=ServerConnectivityError(error_msg=u'Some érrôr')) generator.server_connectivity_test_failed(failed_scan) server_info = MockServerConnectivityInfo() generator.server_connectivity_test_succeeded(server_info) generator.scans_started() # noinspection PyTypeChecker plugin_result_1 = MockPluginResult('plugin1', u'Plugin ûnicôdé output', None) # noinspection PyTypeChecker plugin_result_2 = MockPluginResult('plugin2', u'other plugin Output', None) # noinspection PyTypeChecker server_scan = CompletedServerScan(server_info, [plugin_result_1, plugin_result_2]) generator.server_scan_completed(server_scan) scan_time = 1.3 generator.scans_completed(scan_time) received_output = output_file.getvalue() output_file.close() # Ensure the output properly listed the connectivity error with unicode escaped as \u sequences self.assertIn(json.dumps(u'unibadeéè.com', ensure_ascii=True), received_output) self.assertIn(json.dumps(u'Some érrôr', ensure_ascii=True), received_output) # Ensure the output properly listed the online domain self.assertIn(json.dumps(server_info.hostname, ensure_ascii=True), received_output) self.assertIn(str(server_info.port), received_output) self.assertIn(server_info.ip_address, received_output) # Ensure the output displayed the plugin's attributes as JSON self.assertIn(plugin_result_1.plugin_command, received_output) self.assertIn(plugin_result_2.plugin_command, received_output) self.assertIn('"text_output":', received_output) self.assertIn(json.dumps(plugin_result_1.text_output, ensure_ascii=True), received_output) self.assertIn(plugin_result_2.text_output, received_output) # Ensure the console output displayed the total scan time self.assertIn(str(scan_time), received_output) self.assertIn('"network_timeout": "{}"'.format(MockCommandLineValues().timeout), received_output) self.assertIn('"network_max_retries": "{}"'.format(MockCommandLineValues().nb_retries), received_output)
def test_with_http_tunneling(self): output_file = StringIO() generator = XmlOutputGenerator(output_file) # When scanning through a proxy, we do not know the final server's IP address # This makes sure the XML output properly handles that tunneling_settings = HttpConnectTunnelingSettings('prôxyé.com', 3128) server_info = MockServerConnectivityInfo(http_tunneling_settings=tunneling_settings) # noinspection PyTypeChecker server_scan = CompletedServerScan(server_info, []) generator.server_scan_completed(server_scan) generator.scans_completed(1.3) received_output = output_file.getvalue() output_file.close() # Ensure the output displayed the tunneling settings self.assertIn('httpsTunnelHostname="{}"'.format(tunneling_settings.hostname), received_output) self.assertIn('httpsTunnelPort="{}"'.format(tunneling_settings.port), received_output)
def test_server_scan_completed_with_http_tunneling(self): output_file = StringIO() generator = ConsoleOutputGenerator(output_file) # When scanning through a proxy, we do not know the final server's IP address # This makes sure the console output properly handles that tunneling_settings = HttpConnectTunnelingSettings('ûnicôdé.com', 3128) server_info = MockServerConnectivityInfo(http_tunneling_settings=tunneling_settings) server_scan = CompletedServerScan(server_info, []) generator.server_scan_completed(server_scan) received_output = output_file.getvalue() output_file.close() # Ensure the console output properly listed the online domain and that it was going through a proxy assert server_info.hostname in received_output.lower() assert str(server_info.port) in received_output.lower() assert 'proxy' in received_output.lower() assert tunneling_settings.hostname in received_output.lower() assert str(tunneling_settings.port) in received_output.lower()
def test(self): """The final output only gets written at the end, when calling scans_completed(). Hence we need to call all the methods in the right order and validate the final output at the end. """ output_file = StringIO() generator = XmlOutputGenerator(output_file) failed_parsing = ServerStringParsingError( supplied_server_string='www.badpãrsing.com', error_message='Pãrsing error' ) generator.command_line_parsed(set(), MockCommandLineValues(), [failed_parsing]) failed_scan = ServerConnectivityError( server_info=MockServerConnectivityTester(hostname='unibadeéè.com'), error_message='Some érrôr' ) generator.server_connectivity_test_failed(failed_scan) server_info = MockServerConnectivityInfo() generator.server_connectivity_test_succeeded(server_info) generator.scans_started() plugin_xml_out_1 = Element('plugin1', attrib={'test1': 'value1'}) plugin_xml_out_1.text = 'Plugin ûnicôdé output' plugin_result_1 = MockPluginScanResult(server_info, MockPluginScanCommandOne(), '', plugin_xml_out_1) plugin_xml_out_2 = Element('plugin2', attrib={'test2': 'value2'}) plugin_xml_out_2.text = 'other plugin Output' plugin_result_2 = MockPluginScanResult(server_info, MockPluginScanCommandTwo(), '', plugin_xml_out_2) server_scan = CompletedServerScan(server_info, [plugin_result_1, plugin_result_2]) generator.server_scan_completed(server_scan) scan_time = 1.3 generator.scans_completed(scan_time) received_output = output_file.getvalue() output_file.close() # Ensure the output properly listed the parsing error self.assertIn('www.badpãrsing.com', received_output) self.assertIn('Pãrsing error', received_output) # Ensure the output properly listed the connectivity error self.assertIn('unibadeéè.com', received_output) self.assertIn('Some érrôr', received_output) # Ensure the output properly listed the online domain self.assertIn(server_info.hostname, received_output) self.assertIn(str(server_info.port), received_output) self.assertIn(server_info.ip_address, received_output) # Ensure the output displayed the plugin's XML output self.assertIn(plugin_result_1.scan_command.get_cli_argument(), received_output) self.assertIn(plugin_result_2.scan_command.get_cli_argument(), received_output) self.assertIn(plugin_result_1.as_xml().text, received_output) self.assertIn(plugin_result_2.as_xml().text, received_output) # Ensure the console output displayed the total scan time self.assertIn('totalScanTime="{}"'.format(scan_time), received_output)
def test(self): """The final output only gets written at the end, when calling scans_completed(). Hence we need to call all the methods in the right order and validate the final output at the end. """ output_file = StringIO() generator = JsonOutputGenerator(output_file) failed_parsing = ServerStringParsingError( supplied_server_string='www.badpãrsing.com', error_message='Pãrsing error') generator.command_line_parsed(set(), MockCommandLineValues(), [failed_parsing]) failed_scan = ServerConnectivityError( server_info=MockServerConnectivityTester(hostname='unibadeéè.com'), error_message='Some érrôr') generator.server_connectivity_test_failed(failed_scan) server_info = MockServerConnectivityInfo() generator.server_connectivity_test_succeeded(server_info) generator.scans_started() plugin_result_1 = MockPluginScanResult(server_info, MockPluginScanCommandOne(), 'Plugin ûnicôdé output', None) plugin_result_2 = MockPluginScanResult(server_info, MockPluginScanCommandTwo(), 'other plugin Output', None) server_scan = CompletedServerScan(server_info, [plugin_result_1, plugin_result_2]) generator.server_scan_completed(server_scan) scan_time = 1.3 generator.scans_completed(scan_time) received_output = output_file.getvalue() output_file.close() # Ensure the output properly listed the parsing error with unicode escaped as \u sequences self.assertIn('www.badp\\u00e3rsing.com', received_output) self.assertIn('P\\u00e3rsing error', received_output) # Ensure the output properly listed the connectivity error with unicode escaped as \u sequences self.assertIn('unibade\\u00e9\\u00e8.com:443', received_output) self.assertIn('Some \\u00e9rr\\u00f4r', received_output) # Ensure the output properly listed the online domain self.assertIn(json.dumps(server_info.hostname, ensure_ascii=True), received_output) self.assertIn(str(server_info.port), received_output) self.assertIn(server_info.ip_address, received_output) # Ensure the output displayed the plugin's attributes as JSON self.assertIn(plugin_result_1.scan_command.get_cli_argument(), received_output) self.assertIn(plugin_result_2.scan_command.get_cli_argument(), received_output) self.assertIn('"text_output":', received_output) self.assertIn( json.dumps(plugin_result_1.text_output, ensure_ascii=True), received_output) self.assertIn(plugin_result_2.text_output, received_output) # Ensure the console output displayed the total scan time self.assertIn(str(scan_time), received_output)
def main() -> None: global global_scanner # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() plugins_repository = PluginsRepository() available_plugins = plugins_repository.get_available_plugins() available_commands = plugins_repository.get_available_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) try: good_server_list, malformed_server_list, args_command_list = sslyze_parser.parse_command_line( ) except CommandLineParsingError as e: print(e.get_error_msg()) return output_hub = OutputHub() output_hub.command_line_parsed(available_plugins, args_command_list, malformed_server_list) # Initialize the pool of processes that will run each plugin if args_command_list.https_tunnel or args_command_list.slow_connection: # Maximum one process to not kill the proxy or the connection global_scanner = ConcurrentScanner(max_processes_nb=1) else: global_scanner = ConcurrentScanner() # Figure out which hosts are up and fill the task queue with work to do connectivity_tester = ConcurrentServerConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing() # Store and print servers we were able to connect to online_servers_list = [] for server_connectivity_info in connectivity_tester.get_reachable_servers( ): online_servers_list.append(server_connectivity_info) output_hub.server_connectivity_test_succeeded(server_connectivity_info) # Send tasks to worker processes for scan_command_class in available_commands: if getattr(args_command_list, scan_command_class.get_cli_argument()): # Get this command's optional argument if there's any optional_args = {} for optional_arg_name in scan_command_class.get_optional_arguments( ): # Was this option set ? if getattr(args_command_list, optional_arg_name): optional_args[optional_arg_name] = getattr( args_command_list, optional_arg_name) scan_command = scan_command_class( **optional_args) # type: ignore global_scanner.queue_scan_command(server_connectivity_info, scan_command) # Store and print servers we were NOT able to connect to for connectivity_exception in connectivity_tester.get_invalid_servers(): output_hub.server_connectivity_test_failed(connectivity_exception) # Keep track of how many tasks have to be performed for each target task_num = 0 output_hub.scans_started() for scan_command_class in available_commands: if getattr(args_command_list, scan_command_class.get_cli_argument()): task_num += 1 # Each host has a list of results result_dict: Dict[Text, List[PluginScanResult]] = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = '{hostname}:{ip_address}:{port}' for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT.format(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in global_scanner.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT.format( hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) plugin_result_list = result_dict[RESULT_KEY_FORMAT.format( hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] if len(plugin_result_list) == task_num: # Done with this server; send the result to the output hub output_hub.server_scan_completed( CompletedServerScan(server_info, plugin_result_list)) # All done exec_time = time() - start_time output_hub.scans_completed(exec_time)
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() # Retrieve available plugins sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) try: good_server_list, bad_server_list, args_command_list = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return output_hub = OutputHub() output_hub.command_line_parsed(available_plugins, args_command_list) # Initialize the pool of processes that will run each plugin if args_command_list.https_tunnel: # Maximum one process to not kill the proxy plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout, max_processes_nb=1) else: plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout) # Figure out which hosts are up and fill the task queue with work to do connectivity_tester = ServersConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing(network_timeout=args_command_list.timeout) # Store and print server whose command line string was bad for failed_scan in bad_server_list: output_hub.server_connectivity_test_failed(failed_scan) # Store and print servers we were able to connect to online_servers_list = [] for server_connectivity_info in connectivity_tester.get_reachable_servers(): online_servers_list.append(server_connectivity_info) output_hub.server_connectivity_test_succeeded(server_connectivity_info) # Send tasks to worker processes for plugin_command in available_commands: if getattr(args_command_list, plugin_command): # Get this plugin's options if there's any plugin_options_dict = {} for option in available_commands[plugin_command].get_interface().get_options(): # Was this option set ? if getattr(args_command_list,option.dest): plugin_options_dict[option.dest] = getattr(args_command_list, option.dest) plugins_process_pool.queue_plugin_task(server_connectivity_info, plugin_command, plugin_options_dict) # Store and print servers we were NOT able to connect to for tentative_server_info, exception in connectivity_tester.get_invalid_servers(): failed_scan = FailedServerScan(tentative_server_info.server_string, exception) output_hub.server_connectivity_test_failed(failed_scan) # Keep track of how many tasks have to be performed for each target task_num = 0 output_hub.scans_started() for command in available_commands: if getattr(args_command_list, command): task_num += 1 # Each host has a list of results result_dict = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = u'{hostname}:{ip_address}:{port}'.format for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in plugins_process_pool.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) plugin_result_list = result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] if len(plugin_result_list) == task_num: # Done with this server; send the result to the output hub output_hub.server_scan_completed(CompletedServerScan(server_info, plugin_result_list)) # All done exec_time = time()-start_time output_hub.scans_completed(exec_time)