def _test_server(self, hostname): try: target = ServersConnectivityTester._test_server(hostname, settings.SHARED_SETTINGS) except InvalidTargetError as e: self.result_queue.put(((hostname, None, None, None), None, e.get_error_txt())) return return target
def _test_server(self, hostname): try: target = ServersConnectivityTester._test_server(hostname, settings.SHARED_SETTINGS) except InvalidTargetError as err: result_dict = dict(target=(hostname, None, None), result=err.get_error_txt()) self._qm.put_result(result_dict) return return target
def _analyze_ssl_cert(self): """ Analyze the SSL cert and store the information in the KB. """ sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() sslyze_parser = CommandLineParser(available_plugins, None) command_line_arguments = [ "--hsts", "--chrome_sha1", "--heartbleed", "--sslv2", "--sslv3", "--certinfo=basic", self._target_url.get_domain() ] original_argv = argv[:] argv[1:] = command_line_arguments (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() argv[:] = original_argv target_results = ServersConnectivityTester.test_server_list(target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here for plugin_class in available_commands.itervalues(): plugin_class._shared_settings = shared_settings for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] # Instantiate the proper plugin plugin_instance = available_commands[command]() try: # Process the task result = plugin_instance.process_task(target, command, args) self._plugin_xml_result[command] = result.get_xml_result() except Exception as e: om.out.error('Unhandled exception when processing --{}: {}.{} - {}'.format(command, e.__class__.__module__, e.__class__.__name__, e)) self._is_trusted_cert() self._is_certificate_matches_server_hostname() self._is_ocsp_stapling_supported() self._is_cert_expired() self._is_sha1_signature() self._is_vulnerable_to_heartbleed() self._is_hsts_supported() self._is_sslv2_supported() self._is_sslv3_supported()
def main(): #--PLUGINS INITIALIZATION-- start_time = time() print '\n\n\n' + _format_title('Registering available plugins') sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() print '' for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, PROJECT_VERSION) try: # Parse the command line (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return print command_list #--PROCESSES INITIALIZATION-- nb_processes = command_list.nb_processes if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue() # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues process_list = [] for _ in xrange(nb_processes): p = WorkerProcess(task_queue, result_queue, available_commands, \ shared_settings) p.start() process_list.append(p) # Keep track of the processes that were started #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do print _format_title('Checking host(s) availability') targets_OK = [] targets_ERR = [] target_results = ServersConnectivityTester.test_server_list(target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here # Send tasks to worker processes targets_OK.append(target) for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] task_queue.put( (target, command, args) ) for exception in target_results: targets_ERR.append(exception) print ServersConnectivityTester.get_printable_result(targets_OK, targets_ERR) print '\n\n' # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed [task_queue.put(None) for _ in process_list] # Keep track of how many tasks have to be performed for each target task_num=0 for command in available_commands: if getattr(command_list, command): task_num+=1 # --REPORTING SECTION-- processes_running = nb_processes # XML output if shared_settings['xml_file']: xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result == None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc print _format_txt_target_result(target, result_dict[target]) if shared_settings['xml_file']: xml_output_list.append(_format_xml_target_result(target, result_dict[target])) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() #[process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time()-start_time # Output XML doc to a file if needed if shared_settings['xml_file']: result_xml_attr = {'httpsTunnel':str(shared_settings['https_tunnel_host']), 'totalScanTime' : str(exec_time), 'defaultTimeout' : str(shared_settings['timeout']), 'startTLS' : str(shared_settings['starttls'])} result_xml = Element('results', attrib = result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title = "SSLyze Scan Results", SSLyzeVersion = PROJECT_VERSION, SSLyzeWeb = PROJECT_URL) # Add the list of invalid targets xml_final_doc.append(ServersConnectivityTester.get_xml_result(targets_ERR)) # Add the output of the plugins xml_final_doc.append(result_xml) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString(tostring(xml_final_doc, encoding='UTF-8')) with open(shared_settings['xml_file'],'w') as xml_file: xml_file.write(xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8" )) print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() #--PLUGINS INITIALIZATION-- 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, PROJECT_VERSION) try: # Parse the command line (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return if not shared_settings['quiet']: print '\n\n\n' + _format_title('Available plugins') print '' for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' #--PROCESSES INITIALIZATION-- # Three processes per target from MIN_PROCESSES up to MAX_PROCESSES nb_processes = max(MIN_PROCESSES, min(MAX_PROCESSES, len(target_list) * 3)) if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue( ) # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues for _ in xrange(nb_processes): priority_queue = JoinableQueue() # Each process gets a priority queue p = WorkerProcess(priority_queue, task_queue, result_queue, available_commands, \ shared_settings) p.start() process_list.append( (p, priority_queue)) # Keep track of each process and priority_queue #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do if not shared_settings['quiet']: print _format_title('Checking host(s) availability') targets_OK = [] targets_ERR = [] # Each server gets assigned a priority queue for aggressive commands # so that they're never run in parallel against this single server cycle_priority_queues = cycle(process_list) target_results = ServersConnectivityTester.test_server_list( target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here # Send tasks to worker processes targets_OK.append(target) (_, current_priority_queue) = cycle_priority_queues.next() for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] if command in sslyze_plugins.get_aggressive_commands(): # Aggressive commands should not be run in parallel against # a given server so we use the priority queues to prevent this current_priority_queue.put((target, command, args)) else: # Normal commands get put in the standard/shared queue task_queue.put((target, command, args)) for exception in target_results: targets_ERR.append(exception) if not shared_settings['quiet']: print ServersConnectivityTester.get_printable_result( targets_OK, targets_ERR) print '\n\n' # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed for (proc, priority_queue) in process_list: task_queue.put(None) # One sentinel in the task_queue per proc priority_queue.put(None) # One sentinel in each priority_queue # Keep track of how many tasks have to be performed for each target task_num = 0 for command in available_commands: if getattr(command_list, command): task_num += 1 # --REPORTING SECTION-- processes_running = nb_processes # XML output xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result is None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc if shared_settings['xml_file']: xml_output_list.append( _format_xml_target_result(target, result_dict[target])) if not shared_settings['quiet']: print _format_txt_target_result( target, result_dict[target]) else: print _format_txt_target_result(target, result_dict[target]) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() #[process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time() - start_time # Output XML doc to a file if needed if shared_settings['xml_file']: result_xml_attr = { 'httpsTunnel': str(shared_settings['https_tunnel_host']), 'totalScanTime': str(exec_time), 'defaultTimeout': str(shared_settings['timeout']), 'startTLS': str(shared_settings['starttls']) } result_xml = Element('results', attrib=result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title="SSLyze Scan Results", SSLyzeVersion=PROJECT_VERSION, SSLyzeWeb=PROJECT_URL) # Add the list of invalid targets xml_final_doc.append( ServersConnectivityTester.get_xml_result(targets_ERR)) # Add the output of the plugins xml_final_doc.append(result_xml) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString( tostring(xml_final_doc, encoding='UTF-8')) with open(shared_settings['xml_file'], 'w') as xml_file: xml_file.write( xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8")) if not shared_settings['quiet']: print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) # --PLUGINS INITIALIZATION-- start_time = time() print "\n\n\n" + _format_title("Registering available plugins") sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() print "" for plugin in available_plugins: print " " + plugin.__name__ print "\n\n" # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, PROJECT_VERSION) try: # Parse the command line (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return # --PROCESSES INITIALIZATION-- # Three processes per target from MIN_PROCESSES up to MAX_PROCESSES nb_processes = max(MIN_PROCESSES, min(MAX_PROCESSES, len(target_list) * 3)) if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue() # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues for _ in xrange(nb_processes): priority_queue = JoinableQueue() # Each process gets a priority queue p = WorkerProcess(priority_queue, task_queue, result_queue, available_commands, shared_settings) p.start() process_list.append((p, priority_queue)) # Keep track of each process and priority_queue # --TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do print _format_title("Checking host(s) availability") targets_OK = [] targets_ERR = [] # Each server gets assigned a priority queue for aggressive commands # so that they're never run in parallel against this single server cycle_priority_queues = cycle(process_list) target_results = ServersConnectivityTester.test_server_list(target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here # Send tasks to worker processes targets_OK.append(target) (_, current_priority_queue) = cycle_priority_queues.next() for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] if command in sslyze_plugins.get_aggressive_commands(): # Aggressive commands should not be run in parallel against # a given server so we use the priority queues to prevent this current_priority_queue.put((target, command, args)) else: # Normal commands get put in the standard/shared queue task_queue.put((target, command, args)) for exception in target_results: targets_ERR.append(exception) print ServersConnectivityTester.get_printable_result(targets_OK, targets_ERR) print "\n\n" # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed for (proc, priority_queue) in process_list: task_queue.put(None) # One sentinel in the task_queue per proc priority_queue.put(None) # One sentinel in each priority_queue # Keep track of how many tasks have to be performed for each target task_num = 0 for command in available_commands: if getattr(command_list, command): task_num += 1 # --REPORTING SECTION-- processes_running = nb_processes # XML output xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result is None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc print _format_txt_target_result(target, result_dict[target]) if shared_settings["xml_file"]: xml_output_list.append(_format_xml_target_result(target, result_dict[target])) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() # [process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time() - start_time # Output XML doc to a file if needed if shared_settings["xml_file"]: result_xml_attr = { "httpsTunnel": str(shared_settings["https_tunnel_host"]), "totalScanTime": str(exec_time), "defaultTimeout": str(shared_settings["timeout"]), "startTLS": str(shared_settings["starttls"]), } result_xml = Element("results", attrib=result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib["host"]) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element( "document", title="SSLyze Scan Results", SSLyzeVersion=PROJECT_VERSION, SSLyzeWeb=PROJECT_URL ) # Add the list of invalid targets xml_final_doc.append(ServersConnectivityTester.get_xml_result(targets_ERR)) # Add the output of the plugins xml_final_doc.append(result_xml) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString(tostring(xml_final_doc, encoding="UTF-8")) with open(shared_settings["xml_file"], "w") as xml_file: xml_file.write(xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8")) print _format_title("Scan Completed in {0:.2f} s".format(exec_time))
def get(target_list,shared_settings): #--PLUGINS INITIALIZATION-- start_time = time() if debug: print '\n\n\n' + _format_title('Registering available plugins') sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() if debug: print '' for plugin in available_plugins: if debug: print ' ' + plugin.__name__ if debug: print '\n\n' # jonk: goodbye cli parser # Create the command line parser and the list of available options # sslyze_parser = CommandLineParser(available_plugins, PROJECT_VERSION) # # try: # Parse the command line # (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() # except CommandLineParsingError as e: # print e.get_error_msg() # return # JON_K: I need a way to make command_list instance go away in code here, # the class is needed for a getattr() call, I am not sure how to factor out the getattr() call, # so that I can drive this entire thing purely by shared settings, so hence, I wrote an internal class which maps # to an instance. class command_list(object): certinfo = shared_settings['certinfo'] starttls = shared_settings['starttls'] resum = shared_settings['resum'] resum_rate = shared_settings['resum_rate'] http_get = shared_settings['http_get'] xml_file = shared_settings['xml_file'] compression = shared_settings['compression'] tlsv1 = shared_settings['tlsv1'] reneg = shared_settings['reneg'] targets_in = shared_settings['targets_in'] cert = shared_settings['cert'] https_tunnel_port = shared_settings['https_tunnel_port'] keyform = shared_settings['keyform'] hsts = shared_settings['hsts'] sslv3 = shared_settings['sslv3'] sslv2 = shared_settings['sslv2'] https_tunnel = shared_settings['https_tunnel'] sni = shared_settings['sni'] https_tunnel_host = shared_settings['https_tunnel_host'] regular = shared_settings['regular'] key = shared_settings['key'] tlsv1_2 = shared_settings['tlsv1_2'] tlsv1_1 = shared_settings['tlsv1_1'] hide_rejected_ciphers = shared_settings['hide_rejected_ciphers'] keypass = shared_settings['keypass'] nb_processes = shared_settings['nb_processes'] certform = shared_settings['certform'] timeout = shared_settings['timeout'] xmpp_to = shared_settings['xmpp_to'] #--PROCESSES INITIALIZATION-- nb_processes = command_list.nb_processes if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue() # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues process_list = [] for _ in xrange(nb_processes): p = WorkerProcess(task_queue, result_queue, available_commands, \ shared_settings) p.start() process_list.append(p) # Keep track of the processes that were started #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do if debug: print _format_title('Checking host(s) availability') targets_OK = [] targets_ERR = [] target_results = ServersConnectivityTester.test_server_list(target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here # Send tasks to worker processes targets_OK.append(target) for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] task_queue.put( (target, command, args) ) for exception in target_results: targets_ERR.append(exception) if debug: print ServersConnectivityTester.get_printable_result(targets_OK, targets_ERR) if debug: print '\n\n' # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed [task_queue.put(None) for _ in process_list] # Keep track of how many tasks have to be performed for each target task_num=0 for command in available_commands: if getattr(command_list, command): task_num+=1 # --REPORTING SECTION-- processes_running = nb_processes # XML output if shared_settings['xml_file']: xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result == None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc if debug: print _format_txt_target_result(target, result_dict[target]) if shared_settings['xml_file']: xml_output_list.append(_format_xml_target_result(target, result_dict[target])) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() #[process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time()-start_time # Output XML doc to a file if needed if shared_settings['xml_file']: result_xml_attr = {'httpsTunnel':str(shared_settings['https_tunnel_host']), 'totalScanTime' : str(exec_time), 'defaultTimeout' : str(shared_settings['timeout']), 'startTLS' : str(shared_settings['starttls'])} result_xml = Element('results', attrib = result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title = "SSLyze Scan Results", MyPurpose = 'To send you a dictionary with json back. Cool huh?', SSLyzeVersion = PROJECT_VERSION, SSLyzeWeb = PROJECT_URL) # Add the list of invalid targets xml_final_doc.append(ServersConnectivityTester.get_xml_result(targets_ERR)) # Add the output of the plugins xml_final_doc.append(result_xml) xml_final_pretty = minidom.parseString(tostring(xml_final_doc, encoding='UTF-8')) xmlout = xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8" ) dictout = xmltodict.parse(xmlout) return dictout # Hack: Prettify the XML file so it's (somewhat) diff-able # xml_final_pretty = minidom.parseString(tostring(xml_final_doc, encoding='UTF-8')) # with open(shared_settings['xml_file'],'w') as xml_file: # xml_file.write(xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8" )) if debug: print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() #--PLUGINS INITIALIZATION-- 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, PROJECT_VERSION) try: # Parse the command line (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return if not shared_settings['quiet'] and shared_settings['xml_file'] != '-': print '\n\n\n' + _format_title('Available plugins') print '' for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' #--PROCESSES INITIALIZATION-- # Three processes per target from MIN_PROCESSES up to MAX_PROCESSES nb_processes = max(MIN_PROCESSES, min(MAX_PROCESSES, len(target_list)*3)) if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue() # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues for _ in xrange(nb_processes): priority_queue = JoinableQueue() # Each process gets a priority queue p = WorkerProcess(priority_queue, task_queue, result_queue, available_commands, \ shared_settings) p.start() process_list.append((p, priority_queue)) # Keep track of each process and priority_queue #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do if not shared_settings['quiet'] and shared_settings['xml_file'] != '-': print _format_title('Checking host(s) availability') targets_OK = [] targets_ERR = [] # Each server gets assigned a priority queue for aggressive commands # so that they're never run in parallel against this single server cycle_priority_queues = cycle(process_list) target_results = ServersConnectivityTester.test_server_list(target_list, shared_settings) for target in target_results: if target is None: break # None is a sentinel here # Send tasks to worker processes targets_OK.append(target) (_, current_priority_queue) = cycle_priority_queues.next() for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] if command in sslyze_plugins.get_aggressive_commands(): # Aggressive commands should not be run in parallel against # a given server so we use the priority queues to prevent this current_priority_queue.put( (target, command, args) ) else: # Normal commands get put in the standard/shared queue task_queue.put( (target, command, args) ) for exception in target_results: targets_ERR.append(exception) if not shared_settings['quiet'] and shared_settings['xml_file'] != '-': print ServersConnectivityTester.get_printable_result(targets_OK, targets_ERR) print '\n\n' # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed for (proc, priority_queue) in process_list: task_queue.put(None) # One sentinel in the task_queue per proc priority_queue.put(None) # One sentinel in each priority_queue # Keep track of how many tasks have to be performed for each target task_num=0 for command in available_commands: if getattr(command_list, command): task_num+=1 # --REPORTING SECTION-- processes_running = nb_processes # XML output xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result is None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc if shared_settings['xml_file']: xml_output_list.append(_format_xml_target_result(target, result_dict[target])) if not shared_settings['quiet'] and shared_settings['xml_file'] != '-': print _format_txt_target_result(target, result_dict[target]) else: print _format_txt_target_result(target, result_dict[target]) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() #[process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time()-start_time # Output XML doc to a file if needed if shared_settings['xml_file']: result_xml_attr = {'httpsTunnel':str(shared_settings['https_tunnel_host']), 'totalScanTime' : str(exec_time), 'defaultTimeout' : str(shared_settings['timeout']), 'startTLS' : str(shared_settings['starttls'])} result_xml = Element('results', attrib = result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title = "SSLyze Scan Results", SSLyzeVersion = PROJECT_VERSION, SSLyzeWeb = PROJECT_URL) # Add the list of invalid targets xml_final_doc.append(ServersConnectivityTester.get_xml_result(targets_ERR)) # Add the output of the plugins xml_final_doc.append(result_xml) # Remove characters that are illegal for XML # https://lsimons.wordpress.com/2011/03/17/stripping-illegal-characters-out-of-xml-in-python/ xml_final_string = tostring(xml_final_doc, encoding='UTF-8') illegal_xml_chars_RE = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]') xml_sanitized_final_string = illegal_xml_chars_RE.sub('', xml_final_string) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString(xml_sanitized_final_string).toprettyxml(indent=" ", encoding="utf-8" ) if shared_settings['xml_file'] == '-': # Print XML output to the console if needed print xml_final_pretty else: # Otherwise save the XML output to the console with open(shared_settings['xml_file'],'w') as xml_file: xml_file.write(xml_final_pretty) if not shared_settings['quiet'] and shared_settings['xml_file'] != '-': print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
def main(): nb_processes = DEFAULT_NB_PROCESSES #--PLUGINS INITIALIZATION-- start_time = time() print '\n\n\n' + _format_title('Registering available plugins') sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() print '' for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, SSLYZE_VERSION, DEFAULT_TIMEOUT) try: # Parse the command line (command_list, target_list, shared_settings) = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return #--PROCESSES INITIALIZATION-- if command_list.https_tunnel: nb_processes = 1 # Let's not kill the proxy task_queue = JoinableQueue() # Processes get tasks from task_queue and result_queue = JoinableQueue() # put the result of each task in result_queue # Spawn a pool of processes, and pass them the queues process_list = [] for _ in xrange(nb_processes): p = WorkerProcess(task_queue, result_queue, available_commands, \ shared_settings) p.start() process_list.append(p) # Keep track of the processes that were started #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do print _format_title('Checking host(s) availability') if command_list.https_tunnel: targets_tester = ProxyConnectivityTester(target_list, command_list.https_tunnel) else: targets_tester = ServersConnectivityTester(target_list, command_list.starttls, command_list.xmpp_to) targets_OK = [] for target in targets_tester.test_connectivity(command_list.timeout): # Send tasks to worker processes targets_OK.append(target) for command in available_commands: if getattr(command_list, command): args = command_list.__dict__[command] task_queue.put( (target, command, args) ) print targets_tester.get_result_str() print '\n\n' # Put a 'None' sentinel in the queue to let the each process know when every # task has been completed [task_queue.put(None) for _ in process_list] # Keep track of how many tasks have to be performed for each target task_num=0 for command in available_commands: if getattr(command_list, command): task_num+=1 # --REPORTING SECTION-- processes_running = nb_processes # XML output if shared_settings['xml_file']: xml_output_list = [] # Each host has a list of results result_dict = {} for target in targets_OK: result_dict[target] = [] # If all processes have stopped, all the work is done while processes_running: result = result_queue.get() if result == None: # Getting None means that one process was done processes_running -= 1 else: # Getting an actual result (target, command, plugin_result) = result result_dict[target].append((command, plugin_result)) if len(result_dict[target]) == task_num: # Done with this target # Print the results and update the xml doc print _format_txt_target_result(target, result_dict[target]) if shared_settings['xml_file']: xml_output_list.append(_format_xml_target_result(target, result_dict[target])) result_queue.task_done() # --TERMINATE-- # Make sure all the processes had time to terminate task_queue.join() result_queue.join() #[process.join() for process in process_list] # Causes interpreter shutdown errors exec_time = time()-start_time # Output XML doc to a file if needed if shared_settings['xml_file']: result_xml_attr = {'httpsTunnel':str(shared_settings['https_tunnel_host']), 'totalScanTime' : str(exec_time), 'defaultTimeout' : str(shared_settings['timeout']), 'startTLS' : str(shared_settings['starttls'])} result_xml = Element('results', attrib = result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title = "SSLyze Scan Results", SSLyzeVersion = SSLYZE_VERSION, SSLyzeWeb = PROJECT_URL) xml_final_doc.append(result_xml) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString(tostring(xml_final_doc, encoding='UTF-8')) with open(shared_settings['xml_file'],'w') as xml_file: xml_file.write(xml_final_pretty.toprettyxml(indent=" ", encoding="utf-8" )) print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))