def processOutput(self, plugin, output, command_id, isReport=False): output_queue = multiprocessing.JoinableQueue() new_elem_queue = multiprocessing.Queue() plugin_process = PluginProcess( plugin, output_queue, new_elem_queue, isReport) getLogger(self).debug( "Created plugin_process (%d) for plugin instance (%d)" % (id(plugin_process), id(plugin))) plugin_process.start() output_queue.put(output) output_queue.put(None) output_queue.join() self._processAction(modelactions.PLUGINSTART, [plugin.id]) while True: try: current_action = new_elem_queue.get(block=False) if current_action is None: break action = current_action[0] parameters = current_action[1:] if hasattr(parameters[-1], '_metadata'): parameters[-1]._metadata.command_id = command_id getLogger(self).debug( "Core: Processing a new '%s', parameters (%s)\n" % (action, str(parameters))) self._processAction(action, parameters) except Queue.Empty: continue except IOError, e: if e.errno == errno.EINTR: continue else: getLogger(self).debug( "new_elem_queue Exception - " "something strange happened... " "unhandled exception?") break except Exception: getLogger(self).debug( "new_elem_queue Exception - " "something strange happened... " "unhandled exception?") break
def processOutput(self, plugin, output, command_id, isReport=False): output_queue = multiprocessing.JoinableQueue() new_elem_queue = multiprocessing.Queue() plugin_process = PluginProcess(plugin, output_queue, new_elem_queue, isReport) getLogger(self).debug( "Created plugin_process (%d) for plugin instance (%d)" % (id(plugin_process), id(plugin))) plugin_process.start() output_queue.put(output) output_queue.put(None) output_queue.join() self._processAction(modelactions.PLUGINSTART, [plugin.id]) while True: try: current_action = new_elem_queue.get(block=False) if current_action is None: break action = current_action[0] parameters = current_action[1:] parameters[-1]._metadata.command_id = command_id getLogger(self).debug( "Core: Processing a new '%s', parameters (%s)\n" % (action, str(parameters))) self._processAction(action, parameters) except Queue.Empty: continue except IOError, e: if e.errno == errno.EINTR: continue else: getLogger(self).debug("new_elem_queue Exception - " "something strange happened... " "unhandled exception?") break except Exception: getLogger(self).debug("new_elem_queue Exception - " "something strange happened... " "unhandled exception?") break
def processOutput(self, plugin, output, command, isReport=False): """ Process the output of the plugin. This will start the PluginProcess and also PluginCommiter (thread) that will informa to faraday server when the command finished. :param plugin: Plugin to execute :param output: read output from plugin or term :param command_id: command id that started the plugin :param isReport: Report or output from shell :return: None """ output_queue = JoinableQueue() plugin.set_actions_queue(self.pending_actions) plugin_process = PluginProcess( plugin, output_queue, isReport) getLogger(self).debug( "Created plugin_process (%d) for plugin instance (%d)" % (id(plugin_process), id(plugin))) self.pending_actions.put((Modelactions.PLUGINSTART, plugin.id, command.getID())) output_queue.put((output, command.getID())) plugin_commiter = PluginCommiter( output_queue, output, self.pending_actions, plugin, command, self._mapper_manager, self.end_event, ) plugin_commiter.start() # This process is stopped when plugin commiter joins output queue plugin_process.start()
class PluginController(Thread): """ TODO: Doc string. """ def __init__(self, id, plugin_manager, mapper_manager, pending_actions, end_event=None): super(PluginController, self).__init__() self.plugin_manager = plugin_manager self._plugins = plugin_manager.getPlugins() self.id = id self._actionDispatcher = None self._setupActionDispatcher() self._mapper_manager = mapper_manager self.output_path = os.path.join( os.path.expanduser(CONST_FARADAY_HOME_PATH), CONST_FARADAY_ZSH_OUTPUT_PATH) self._active_plugins = {} self.plugin_sets = {} self.plugin_manager.addController(self, self.id) self.stop = False self.pending_actions = pending_actions self.end_event = end_event def _find_plugin(self, plugin_id): return self._plugins.get(plugin_id, None) def _is_command_malformed(self, original_command, modified_command): """ Checks if the command to be executed is safe and it's not in the block list defined by the user. Returns False if the modified command is ok, True if otherwise. """ block_chars = set(["|", "$", "#"]) if original_command == modified_command: return False orig_cmd_args = shlex.split(original_command) if not isinstance(modified_command, basestring): modified_command = "" mod_cmd_args = shlex.split(modified_command) block_flag = False orig_args_len = len(orig_cmd_args) for index in xrange(0, len(mod_cmd_args)): if (index < orig_args_len and orig_cmd_args[index] == mod_cmd_args[index]): continue for char in block_chars: if char in mod_cmd_args[index]: block_flag = True break return block_flag def _get_plugins_by_input(self, cmd, plugin_set): for plugin in plugin_set.itervalues(): if plugin.canParseCommandString(cmd): return plugin return None def getAvailablePlugins(self): """ Return a dictionary with the available plugins. Plugin ID's as keys and plugin instences as values """ return self._plugins def stop(self): self.plugin_process.stop() self.stop = True def processOutput(self, plugin, output, command, isReport=False): """ Process the output of the plugin. This will start the PluginProcess and also PluginCommiter (thread) that will informa to faraday server when the command finished. :param plugin: Plugin to execute :param output: read output from plugin or term :param command_id: command id that started the plugin :param isReport: Report or output from shell :return: None """ output_queue = JoinableQueue() plugin.set_actions_queue(self.pending_actions) self.plugin_process = PluginProcess( plugin, output_queue, isReport) getLogger(self).debug( "Created plugin_process (%d) for plugin instance (%d)" % (id(self.plugin_process), id(plugin))) self.pending_actions.put((Modelactions.PLUGINSTART, plugin.id, command.getID())) output_queue.put((output, command.getID())) plugin_commiter = PluginCommiter( output_queue, output, self.pending_actions, plugin, command, self._mapper_manager, self.end_event, ) plugin_commiter.start() # This process is stopped when plugin commiter joins output queue self.plugin_process.start() def _processAction(self, action, parameters): """ decodes and performs the action given It works kind of a dispatcher """ getLogger(self).debug( "_processAction - %s - parameters = %s" % (action, str(parameters))) self._actionDispatcher[action](*parameters) def _setupActionDispatcher(self): self._actionDispatcher = { Modelactions.ADDHOST: model.api.addHost, Modelactions.ADDSERVICEHOST: model.api.addServiceToHost, #Vulnerability Modelactions.ADDVULNHOST: model.api.addVulnToHost, Modelactions.ADDVULNSRV: model.api.addVulnToService, #VulnWeb Modelactions.ADDVULNWEBSRV: model.api.addVulnWebToService, #Note Modelactions.ADDNOTEHOST: model.api.addNoteToHost, Modelactions.ADDNOTESRV: model.api.addNoteToService, Modelactions.ADDNOTENOTE: model.api.addNoteToNote, #Creds Modelactions.ADDCREDSRV: model.api.addCredToService, #LOG Modelactions.LOG: model.api.log, Modelactions.DEVLOG: model.api.devlog, # Plugin state Modelactions.PLUGINSTART: model.api.pluginStart, Modelactions.PLUGINEND: model.api.pluginEnd } def updatePluginSettings(self, plugin_id, new_settings): for plugin_set in self.plugin_sets.values(): if plugin_id in plugin_set: plugin_set[plugin_id].updateSettings(new_settings) if plugin_id in self._plugins: self._plugins[plugin_id].updateSettings(new_settings) def createPluginSet(self, pid): self.plugin_sets[pid] = self.plugin_manager.getPlugins() def processCommandInput(self, pid, cmd, pwd): """ This method tries to find a plugin to parse the command sent by the terminal (identiefied by the process id). """ if pid not in self.plugin_sets: self.createPluginSet(pid) plugin = self._get_plugins_by_input(cmd, self.plugin_sets[pid]) if plugin: modified_cmd_string = plugin.processCommandString("", pwd, cmd) if not self._is_command_malformed(cmd, modified_cmd_string): cmd_info = CommandRunInformation( **{'workspace': model.api.getActiveWorkspace().name, 'itime': time.time(), 'import_source': 'shell', 'command': cmd.split()[0], 'params': ' '.join(cmd.split()[1:])}) cmd_info.setID(self._mapper_manager.save(cmd_info)) self._active_plugins[pid] = plugin, cmd_info return plugin.id, modified_cmd_string return None, None def onCommandFinished(self, pid, exit_code, term_output): if pid not in self._active_plugins.keys(): return False if exit_code != 0: del self._active_plugins[pid] return False plugin, cmd_info = self._active_plugins.get(pid) cmd_info.duration = time.time() - cmd_info.itime self._mapper_manager.update(cmd_info) self.processOutput(plugin, term_output, cmd_info) del self._active_plugins[pid] return True def processReport(self, plugin, filepath, ws_name=None): if not ws_name: ws_name = model.api.getActiveWorkspace().name cmd_info = CommandRunInformation( **{'workspace': ws_name, 'itime': time.time(), 'import_source': 'report', 'command': plugin, 'params': filepath, }) self._mapper_manager.createMappers(ws_name) command_id = self._mapper_manager.save(cmd_info) cmd_info.setID(command_id) if plugin in self._plugins: logger.info('Processing report with plugin {0}'.format(plugin)) self._plugins[plugin].workspace = ws_name with open(filepath, 'rb') as output: self.processOutput(self._plugins[plugin], output.read(), cmd_info, True) return command_id # Plugin to process this report not found, update duration of plugin process cmd_info.duration = time.time() - cmd_info.itime self._mapper_manager.update(cmd_info) return False def clearActivePlugins(self): self._active_plugins = {}