def run(self): self.online_plugins.start() tmp_timer = .0 while not self._stop: time.sleep(.1) tmp_timer += .1 if tmp_timer >= self.timer: try: self.syncReports() if not self.polling: break except Exception: getLogger(self).error( "An exception was captured while saving reports\n%s" % traceback.format_exc()) finally: tmp_timer = 0
def syncReports(self): """ Synchronize report directory using the DataManager and Plugins online We first make sure that all shared reports were added to the repo """ for root, dirs, files in os.walk(self._report_path, False): # skip processed and unprocessed directories if root == self._report_path: for name in files: filename = os.path.join(root, name) name = os.path.basename(filename) # If plugin not is detected... move to unprocessed # PluginCommiter will rename the file to processed or unprocessed # when the plugin finishes if self.processor.processReport(filename) is False: getLogger(self).info( 'Plugin not detected. Moving {0} to unprocessed'. format(filename)) os.rename(filename, os.path.join(self._report_upath, name)) else: getLogger(self).info( 'Detected valid report {0}'.format(filename)) os.rename(filename, os.path.join(self._report_ppath, name))
def check_faraday_version(): try: server.check_faraday_version() except RuntimeError: getLogger("launcher").error( "The server is running a different Faraday version than the client you are running. Version numbers must match!") sys.exit(2)
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 addWrapper(new_obj, parent_id=None, *args): parent = self.mappers_manager.find(parent_type, parent_id) if parent: add_func(new_obj, parent_id, *args) else: msg = "A parent is needed for %s objects" % new_obj.class_signature getLogger(self).error(msg) return False
def exit_faraday_without_confirm(self, widget=None): """Exits faraday without confirm. Used as a middle-man between connect callbacks (which will send the widget as an argument and self.window.destroy, which takes none. """ getLogger(self).error("Faraday exited because you didn't connect " "to a valid Faraday Server.") GObject.idle_add(self.window.destroy) GObject.idle_add(self.on_quit)
def _pluginStart(self, name, command_id): self.active_plugins_count_lock.acquire() self.processing = True if name not in ["MetasploitOn", "Beef", "Sentinel"]: getLogger(self).info("Plugin Started: {0}. ".format( name, command_id)) self.active_plugins_count += 1 self.active_plugins_count_lock.release() return True
def getServicesCount(self): """Get how many services are in the workspace. If it can't, it will return zero.""" try: services = models.Service.class_signature count = self.mappers_manager.getMapper(services).getCount() except: getLogger(self).debug( "Couldn't get services count: assuming it is zero.") count = 0 return count
def run(self, args): workspace = args.workspace try: self.workspace_manager.openWorkspace(workspace) except Exception as e: getLogger(self).error( ("The workspace %s is not accessible, " "check configuration") % workspace) getLogger(self).error(str(e)) return -1 rp = ReportProcessor(self.plugin_controller) rp.processReport(args.filename)
def getVulnsCount(self): """Get how many vulns (web + normal) are in the workspace. If it can't, it will return zero.""" try: vulns = models.Vuln.class_signature web_vulns = models.WebVuln.class_signature count = (self.mappers_manager.getMapper(vulns).getCount() + self.mappers_manager.getMapper(web_vulns).getCount()) except: getLogger(self).debug( "Couldn't get vulnerabilities count: assuming it is zero.") count = 0 return count
def __init__(self, report_path): self.report_type = None root_tag, output = self.getRootTag(report_path) if root_tag: self.report_type = self.rType(root_tag, output) if self.report_type is None: getLogger(self).debug( 'Automatical detection FAILED... Trying manual...') self.report_type = self.getUserPluginName(report_path)
def processReport(self, filename): """ Process one Report """ getLogger(self).debug("Report file is %s" % filename) parser = ReportParser(filename) if parser.report_type is None: getLogger(self).error( 'Plugin not found: automatic and manual try!') return False return self.sendReport(parser.report_type, filename)
def _pluginEnd(self, name, command_id): self.active_plugins_count_lock.acquire() if name not in ["MetasploitOn", "Beef", "Sentinel"]: getLogger(self).info("Plugin Ended: {0}".format(name)) if self.active_plugins_count == 0: self.active_plugins_count_lock.release() getLogger(self).warn( "All plugins ended, but a plugin end action was received.") return True self.active_plugins_count -= 1 if self.active_plugins_count == 0: self.processing = False self.active_plugins_count_lock.release() return True
def open_file(self, file_path): """ This method uses file signatures to recognize file types :param file_path: report file. If you need add support to a new report type add the file signature here and add the code in self.getRootTag() for get the root tag. """ f = result = None signatures = { "\x50\x4B": "zip", "\x3C\x3F\x78\x6D\x6C": "xml", "# Lynis Re": "dat", } try: if file_path == None: return None, None f = open(file_path, 'rb') file_signature = f.read(10) for key in signatures: if file_signature.find(key) == 0: result = signatures[key] break if not result: # try json loads to detect a json file. try: f.seek(0) json.loads(f.read()) result = 'json' except ValueError: pass except IOError as err: self.report_type = None getLogger(self).error("Error while opening file.\n%s. %s" % (err, file_path)) getLogger(self).debug("Report type detected: %s" % result) f.seek(0) return f, result
def background_process(): """Change workspace. This function runs on a separated thread created by the parent function. DO NOT call any Gtk methods withing its scope, except by emiting signals to the window """ GObject.idle_add(loading_workspace, 'show') try: ws = super(GuiApp, self).openWorkspace(workspace_name) GObject.idle_add(CONF.setLastWorkspace, ws.name) GObject.idle_add(CONF.saveConfig) except Exception as e: GObject.idle_add(self.handle_no_active_workspace) getLogger("GTK").error(e) GObject.idle_add(loading_workspace, 'destroy') return True
def log(msg, level="INFO"): """ This api will log the text in the GUI console without the level it will also log to a file with the corresponding level if logger was configured that way """ levels = { "CRITICAL": logging.CRITICAL, "ERROR": logging.ERROR, "WARNING": logging.WARNING, "INFO": logging.INFO, "DEBUG": logging.DEBUG, "NOTSET": logging.NOTSET } level = levels.get(level, logging.NOTSET) getLogger().log(level, msg)
def sendReport(self, plugin_id, filename): """Sends a report to the appropiate plugin specified by plugin_id""" getLogger(self).info('The file is %s, %s' % (filename, plugin_id)) command_id = self.plugin_controller.processReport(plugin_id, filename, ws_name=self.ws_name) if not command_id: getLogger(self).error( "Faraday doesn't have a plugin for this tool... Processing: ABORT" ) return False return command_id
def startAPIs(plugin_controller, model_controller, hostname, port): global _rest_controllers global _http_server global ioloop_instance _rest_controllers = [ PluginControllerAPI(plugin_controller), ModelControllerAPI(model_controller) ] app = Flask('APISController') ioloop_instance = IOLoop.current() _http_server = HTTPServer(WSGIContainer(app)) hostnames = [hostname] #Fixed hostname bug if hostname == "localhost": hostnames.append("127.0.0.1") listening = False for hostname in hostnames: try: _http_server.listen(port, address=hostname) logger.getLogger().info("REST API server configured on %s" % str(CONF.getApiRestfulConInfo())) listening = True CONF.setApiConInfoHost(hostname) CONF.saveConfig() break except socket.error as exception: continue if not listening: raise RuntimeError("Port already in use") routes = [r for c in _rest_controllers for r in c.getRoutes()] for route in routes: app.add_url_rule(route.path, view_func=route.view_func, methods=route.methods) logging.getLogger("tornado.access").addHandler(logger.getLogger(app)) logging.getLogger("tornado.access").propagate = False threading.Thread(target=startServer).start()
def run(self): while not self._stop: for name, config_dict in self.online_plugins.iteritems(): if name in self.plugins_settings: if self.plugins_settings[name]['settings'][ 'Enable'] == "1": t = Timer(config_dict["time"], self.runPluginThread, args=(config_dict["command"], )) getLogger(self).debug( "Starting Thread for online plugin: %s" % name) self.online_plugins[name]["thread_running"] = True t.start() time.sleep(60)
def processAction(self): # check the queue for new actions # if there is no new action it will block until timeout is reached try: # get new action or timeout (in secs) # TODO: timeout should be set through config current_action = self._pending_actions.get(timeout=2) action = current_action[0] parameters = current_action[1:] # dispatch the action self._processAction(action, list(parameters)) except Empty: # if timeout was reached, just let the daemon run again # this is done just to be able to test the stop flag # because if we don't do it, the daemon will be blocked forever pass except Exception as ex: getLogger(self).debug( "something strange happened... unhandled exception?") getLogger(self).debug(traceback.format_exc())
def getRootTag(self, file_path): report_type = result = f = None f, report_type = self.open_file(file_path) # Check error in open_file() if f is None and report_type is None: self.report_type = None return None, None # Find root tag based in report_type if report_type == "zip": result = "maltego" elif report_type == "dat": result = 'lynis' elif report_type == 'json': # this will work since recon-ng is the first plugin to use json. # we need to add json detection here! result = 'reconng' else: try: for event, elem in ET.iterparse(f, ('start', )): result = elem.tag break except SyntaxError as err: self.report_type = None getLogger(self).error("Not an xml file.\n %s" % (err)) f.seek(0) output = f.read() if f: f.close() return result, output
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 run(self, args): workspace = args.workspace try: ws = super(GuiApp, self).openWorkspace(workspace) except Exception as e: getLogger(self).error( ("Your last workspace %s is not accessible, " "check configuration.") % workspace) getLogger(self).error( "You may try and go to ~/.faraday/config/user.xml " "to set a valid api_uri and last_workspace") getLogger(self).error(str(e)) return -1 workspace = ws.name CONF.setLastWorkspace(workspace) CONF.saveConfig() getLogger(self).info("Workspace %s loaded" % workspace) while True: if self._stop: return time.sleep(0.01)
def main(): """ Main function for launcher. """ global logger, args logger = getLogger("launcher") args = getParserArgs() setupFolders(CONST_FARADAY_FOLDER_LIST) setUpLogger(args.debug) printBanner() if args.cert_path: os.environ[REQUESTS_CA_BUNDLE_VAR] = args.cert_path checkConfiguration(args.gui) setConf() login(args.login) check_faraday_version() checkUpdates() startFaraday()
def wrapper(*args, **kwargs): try: res = func(*args, **kwargs) except ServerRequestException as e: res = response_in_emergency getLogger("Server-GTK IO").warning(e) except (requests.exceptions.MissingSchema, requests.exceptions.InvalidSchema): res = response_in_emergency getLogger("Server-GTK IO").error( "It looks like the Faraday Server " "URL is not correctly formated. Please change it and " "remember to set it with a valid protocol, like http.\n" "For example: http://faradayserver:port/") except Exception: res = response_in_emergency getLogger("Server-GTK IO").error( "It looks like the Faraday Server is not running\n") return res
def _postCustomEvent(self, text, level, customEventClass): getLogger().log(text, "INFO") if self.widget is not None: event = customEventClass(text, level) faraday.client.model.guiapi.postEvent(event, self.widget)
def __init__(self): self.logger = getLogger(self)
def runPluginThread(self, cmd): random_id = random() self.plugin_controller.processCommandInput(random_id, cmd, './') self.plugin_controller.onCommandFinished(random_id, 0, cmd) getLogger(self).debug("Running online plugin...")
def update(self, event): if event.type() == CHANGEFROMINSTANCE: getLogger(self).info("[Update Received] " + event.change.getMessage())
def __getattr__(self, name): getLogger(self).debug("ModelObject attribute to refactor: %s" % name)