def delete(self): """ Deletes the Ip represented by this model in database. Also deletes the tools associated with this ip Also deletes the ports associated with this ip Also deletes the defects associated with this ip and its ports """ mongoInstance = MongoCalendar.getInstance() tools = mongoInstance.find("tools", {"ip": self.ip}, True) for tool in tools: tool_model = Tool(tool) tool_model.delete() defects = mongoInstance.find( "defects", { "ip": self.ip, "$or": [{ "port": { "$exists": False } }, { "port": None }] }, True) for defect in defects: defect_model = Defect(defect) defect_model.delete() ports = mongoInstance.find("ports", {"ip": self.ip}, True) for port in ports: port_model = Port(port) port_model.delete() mongoInstance.delete("ips", {"_id": self._id})
def update(self, pipeline_set=None): """Update this object in database. Args: pipeline_set: (Opt.) A dictionnary with custom values. If None (default) use model attributes. """ oldPort = Port.fetchObject({"_id": ObjectId(self._id)}) if oldPort is None: return oldService = oldPort.service mongoInstance = MongoCalendar.getInstance() if oldService != self.service: mongoInstance.delete("tools", { "lvl": "port", "ip": self.ip, "port": self.port, "proto": self.proto}, many=True) port_commands = mongoInstance.findInDb( "pollenisator", "commands", {"lvl": "port"}) for port_command in port_commands: allowed_services = port_command["ports"].split(",") for i, elem in enumerate(allowed_services): if not(elem.strip().startswith("tcp/") or elem.strip().startswith("udp/")): allowed_services[i] = "tcp/"+str(elem) if self.proto+"/"+str(self.service) in allowed_services: waves = mongoInstance.find("waves", {"wave_commands": {"$elemMatch": { "$eq": port_command["name"].strip()}}}) for wave in waves: tool_m = Tool().initialize(port_command["name"], wave["wave"], "", self.ip, self.port, self.proto, "port") tool_m.addInDb() # Update variable instance. (this avoid to refetch the whole command in database) if pipeline_set is None: mongoInstance.update("ports", {"_id": ObjectId(self._id)}, { "$set": {"service": self.service, "product":self.product, "notes": self.notes, "tags": self.tags, "infos": self.infos}}) else: mongoInstance.update("ports", {"_id": ObjectId(self._id)}, { "$set": pipeline_set})
def resetUnfinishedTools(): """ Reset all tools running to a ready state. This is useful if a command was running on a worker and the auto scanning was interrupted. """ # test all the cases if datef is defined or not. # Normally, only the first one is necessary from core.Models.Tool import Tool tools = Tool.fetchObjects({"datef": "None", "scanner_ip": {"$ne": "None"}}) for tool in tools: tool.markAsNotDone() tools = Tool.fetchObjects({"datef": "None", "dated": {"$ne": "None"}}) for tool in tools: tool.markAsNotDone() tools = Tool.fetchObjects({ "datef": { "$exists": False }, "dated": { "$ne": "None" } }) for tool in tools: tool.markAsNotDone() tools = Tool.fetchObjects({ "datef": { "$exists": False }, "scanner_ip": { "$ne": "None" } }) for tool in tools: tool.markAsNotDone()
def addInTreeview(self, parentNode=None, addChildren=True): """Add this view in treeview. Also stores infos in application treeview. Args: parentNode: if None, will calculate the parent. If setted, forces the node to be inserted inside given parentNode. addChildren: If False, skip the tool insert. Useful when displaying search results """ parentDbId = parentNode if parentNode is None: parentNode = self.getParent() elif 'scopes' not in parentNode: parentNode = ScopeView.DbToTreeviewListId(parentDbId) self.appliTw.views[str(self.controller.getDbId())] = {"view": self} try: parentNode = self.appliTw.insert(self.controller.getParent(), 0, parentNode, text="Scopes", image=self.getClassIcon()) except TclError: # trigger if tools list node already exist pass self.appliTw.insert(parentNode, "end", str(self.controller.getDbId()), text=str(self.controller.getModelRepr()), tags=self.controller.getTags(), image=self.getClassIcon()) if addChildren: tools = self.controller.getTools() for tool in tools: tool_o = ToolController(Tool(tool)) tool_vw = ToolView(self.appliTw, self.appliViewFrame, self.mainApp, tool_o) tool_vw.addInTreeview(str(self.controller.getDbId())) if "hidden" in self.controller.getTags(): self.hide()
def loadData(self): """ Fetch data from database """ self.ports = Port.fetchObjects({}) self.ips = Ip.fetchObjects({}) self.tools = Tool.fetchObjects({})
def findLaunchableTools(): """ Try to find tools that matches all criteria. Returns: A tuple with two values: * A list of launchable tools as dictionary with values _id, name and priority * A dictionary of waiting tools with tool's names as keys and integer as value. """ toolsLaunchable = [] waiting = {} time_compatible_waves_id = Wave.searchForAddressCompatibleWithTime() for wave_id in time_compatible_waves_id: commandsLaunchableWave = Wave.getNotDoneTools(wave_id) for tool in commandsLaunchableWave: toolModel = Tool.fetchObject({"_id": tool}) try: waiting[str(toolModel)] += 1 except KeyError: waiting[str(toolModel)] = 1 command = toolModel.getCommand() if command is None: prio = 0 else: prio = int(command.get("priority", 0)) toolsLaunchable.append({ "_id": tool, "name": str(toolModel), "priority": prio }) return toolsLaunchable, waiting
def delete(self): """ Delete the Scope represented by this model in database. Also delete the tools associated with this scope Also remove this scope from ips in_scopes attributes """ # deleting tool with scope lvl tools = Tool.fetchObjects({ "scope": self.scope, "wave": self.wave, "$or": [{ "lvl": "network" }, { "lvl": "domain" }] }) for tool in tools: tool.delete() # Deleting this scope against every ips ips = Ip.getIpsInScope(self._id) for ip in ips: ip.removeScopeFitting(self._id) mongoInstance = MongoCalendar.getInstance() mongoInstance.delete("scopes", {"_id": self._id}) parent_wave = mongoInstance.find("waves", {"wave": self.wave}, False) if parent_wave is None: return mongoInstance.notify(mongoInstance.calendarName, "waves", parent_wave["_id"], "update", "")
def announce_failed_tasks(self, event): """ Called when a celery task fails. Is used to reset dates and scanner of the targeted tool. Args: event: created automatically when the event occurs. Contains some info about the task """ self.state.event(event) task = self.state.tasks.get(event['uuid']) # get task # Get tasks arguments try: argsWere = json.loads(task.info()["args"].replace("'", "\"")) args = argsWere[0] toolId = ObjectId(args[1]) # args[1] is the tool_id for task_running in self.tasks_running: if str(task_running[1]) == str(toolId): task_running[0].revoke(terminate=True) del task_running tool = Tool.fetchObject({"_id": ObjectId(toolId)}) tool.markAsNotDone() except InvalidId: pass except json.decoder.JSONDecodeError: pass except KeyError: pass # Plugin failed so "args" does not exist
def getAllTools(self): """Return all tools being part of this wave as a list of mongo fetched tools dict. Differs from getTools as it fetches all tools of the name and not only tools of level wave. Returns: list of defect raw mongo data dictionnaries """ return Tool.fetchObjects({"wave": self.wave})
def _insertChildrenTools(self): """Create a tools list node and insert every children tools in database as ToolView under this node""" tools = self.controller.getTools() for tool in tools: tool_o = ToolController(Tool(tool)) tool_vw = ToolView(self.appliTw, self.appliViewFrame, self.mainApp, tool_o) tool_vw.addInTreeview(str(self.controller.getDbId()))
def setToolsInTime(self): """Get all OOT (Out of Time) tools in this wave and checks if this Interval makes them in time. If it is the case, set them in time. """ if Utils.fitNowTime(self.dated, self.datef): tools = Tool.fetchObjects({"wave": self.wave, "status": "OOT"}) for tool in tools: tool.setInTime()
def delete(self): """ Deletes the Port represented by this model in database. Also deletes the tools associated with this port Also deletes the defects associated with this port """ mongoInstance = MongoCalendar.getInstance() tools = mongoInstance.find("tools", {"port": self.port, "proto": self.proto, "ip": self.ip}, True) for tool in tools: tool_model = Tool(tool) tool_model.delete() defects = mongoInstance.find("defects", {"port": self.port, "proto": self.proto, "ip": self.ip}, True) for defect in defects: defect_model = Defect(defect) defect_model.delete() mongoInstance.delete("ports", {"_id": ObjectId(self._id)})
def removeScopeFitting(self, scopeId): """Remove the given scopeId from the list of scopes this IP fits in. Args: scopeId: a mongo ObjectId of a scope object. """ if str(scopeId) in self.in_scopes: self.in_scopes.remove(str(scopeId)) self.update() if not self.in_scopes: tools = Tool.fetchObjects({"ip": self.ip}) for tool in tools: tool.setOutOfScope()
def removeAllTool(self, command_name): """ Remove from every member of this wave the old tool corresponding to given command name but only if the tool is not done. We preserve history Args: command_name: The command that we want to remove all the tools. """ tools = Tool.fetchObjects({"name": command_name, "wave": self.wave}) for tool in tools: if "done" not in tool.getStatus(): tool.delete()
def addScopeFitting(self, scopeId): """Add the given scopeId to the list of scopes this IP fits in. Args: scopeId: a mongo ObjectId of a Scope object. """ if not self.in_scopes: tools = Tool.fetchObjects({"ip": self.ip}) for tool in tools: tool.setInScope() if str(scopeId) not in self.in_scopes: self.in_scopes.append(str(scopeId)) self.update()
def dispatchLaunchableTools(my_monitor, launchableTools): """ Try to launch given tools within the monitor Args: my_monitor: A Monitor instance which knows what tools are already launched and online workers launchableTools: A list of tools within a Wave that passed the Intervals checking. """ mongoInstance = MongoCalendar.getInstance() for launchableTool in launchableTools: tool = Tool.fetchObject({"_id": ObjectId(launchableTool["_id"])}) my_monitor.launchTask(mongoInstance.calendarName, tool)
def addAllTool(self, command_name, wave_name, scope): """ Kind of recursive operation as it will call the same function in its children ports. Add the appropriate tools (level check and wave's commands check) for this ip. Also add for all registered ports the appropriate tools. Args: command_name: The command that we want to create all the tools for. wave_name: the wave name from where we want to load tools scope: a scope object allowing to launch this command. Opt """ # retrieve the command level mongoInstance = MongoCalendar.getInstance() command = mongoInstance.findInDb(mongoInstance.calendarName, "commands", {"name": command_name}, False) if command["lvl"] == "ip": # finally add tool newTool = Tool() newTool.initialize(command_name, wave_name, "", self.ip, "", "", "ip") newTool.addInDb() return # Do the same thing for all children ports. ports = mongoInstance.find("ports", {"ip": self.ip}) for port in ports: p = Port(port) p.addAllTool(command_name, wave_name, scope)
def refreshUI(self): """Reload informations and renew widgets""" mongoInstance = MongoCalendar.getInstance() workernames = self.monitor.getWorkerList() running_scans = Tool.fetchObjects({"status":"running"}) for children in self.scanTv.get_children(): self.scanTv.delete(children) for running_scan in running_scans: self.scanTv.insert('','end', running_scan.getId(), text=running_scan.name, values=(running_scan.dated), image=self.running_icon) for children in self.workerTv.get_children(): self.workerTv.delete(children) registeredCommands = set() for workername in workernames: try: worker_node = self.workerTv.insert( '', 'end', workername, text=workername, image=self.ok_icon) except tk.TclError: worker_node = self.workerTv.item(workername) worker_registered = mongoInstance.findInDb("pollenisator", "workers", {"name":workername}, False) commands_registered = worker_registered["registeredCommands"] for command in commands_registered: try: self.workerTv.insert( worker_node, 'end', command, text=command, image=self.ok_icon) except tk.TclError: pass registeredCommands.add(str(command)) allCommands = Command.getList(None, mongoInstance.calendarName) for command in allCommands: if command not in registeredCommands: try: self.workerTv.insert( worker_node, '0', 'notRegistered|'+command, text=command, image=self.nok_icon) except tk.TclError: pass else: try: self.workerTv.delete('notRegistered|'+command) except tk.TclError: pass if len(registeredCommands) > 0 and self.btn_autoscan is None: if self.running_auto_scans: self.btn_autoscan = ttk.Button( self.parent, text="Stop Scanning", command=self.stopAutoscan) self.btn_autoscan.pack() else: self.btn_autoscan = ttk.Button( self.parent, text="Start Scanning", command=self.startAutoscan) self.btn_autoscan.pack()
def addInTreeview(self, parentNode=None, addChildren=True): """Add this view in treeview. Also stores infos in application treeview. Args: parentNode: if None, will calculate the parent. If setted, forces the node to be inserted inside given parentNode. addChildren: If False, skip the tool and defects insert. Useful when displaying search results """ if parentNode is None: parentNode = self.getParent() nodeText = str(self.controller.getModelRepr()) elif parentNode == '': nodeText = self.controller.getDetailedString() else: nodeText = str(self.controller.getModelRepr()) self.appliTw.views[str(self.controller.getDbId())] = {"view": self} try: self.appliTw.insert(parentNode, "end", str(self.controller.getDbId()), text=nodeText, tags=self.controller.getTags(), image=self.getClassIcon()) except TclError: pass if addChildren: defects = self.controller.getDefects() for defect in defects: defect_o = DefectController(Defect(defect)) defect_vw = DefectView(self.appliTw, self.appliViewFrame, self.mainApp, defect_o) defect_vw.addInTreeview(str(self.controller.getDbId())) tools = self.controller.getTools() for tool in tools: tool_o = ToolController(Tool(tool)) tool_vw = ToolView(self.appliTw, self.appliViewFrame, self.mainApp, tool_o) tool_vw.addInTreeview(str(self.controller.getDbId())) tools = self.controller.getTools() atleastone = False for tool in tools: # SALE atleastone = True break if not atleastone: if len(self.controller.getTags()) == 0: self.controller.addTag("unscanned") self.appliTw.sort(parentNode) if "hidden" in self.controller.getTags(): self.hide()
def announce_offline_worker(self, event): """ Called when a celery worker gets offline nicely. Is used to remove this worker from the worker_list Args: event: created automatically when the event occurs. Contains some info about the worker """ worker_hostname = event["hostname"].strip() workers = self.getWorkerList() print("RECEIVE OFFLINE WORKER "+str(worker_hostname)) if worker_hostname in list(workers): toolsToReset = Tool.fetchObjects( {"datef": "None", "scanner_ip": worker_hostname}) for tool in toolsToReset: tool.markAsNotDone() self.removeWorker(worker_hostname)
def findLaunchableToolsOnWorker(worker, calendarName): """ Try to find tools that matches all criteria. Args: workerName: the current working worker Returns: A tuple with two values: * A list of launchable tools as dictionary with values _id, name and priority * A dictionary of waiting tools with tool's names as keys and integer as value. """ mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(calendarName) toolsLaunchable = [] worker_registered = mongoInstance.findInDb("pollenisator", "workers", {"name": worker.name}, False) commands_registered = worker_registered["registeredCommands"] waiting = {} time_compatible_waves_id = Wave.searchForAddressCompatibleWithTime() for wave_id in time_compatible_waves_id: commandsLaunchableWave = Wave.getNotDoneTools(wave_id) for tool in commandsLaunchableWave: toolModel = Tool.fetchObject({"_id": tool}) if toolModel.name not in commands_registered: continue if worker.hasRegistered(toolModel): try: waiting[str(toolModel)] += 1 except KeyError: waiting[str(toolModel)] = 1 command = toolModel.getCommand() if command is None: prio = 0 else: prio = int(command.get("priority", 0)) toolsLaunchable.append({ "_id": tool, "name": str(toolModel), "priority": prio, "errored": "error" in toolModel.status }) return toolsLaunchable, waiting
def customCommand(self, _event=None): """ Ask the user for a custom tool to launch and which parser it will use. Args: _event: not used but mandatory """ mongoInstance = MongoCalendar.getInstance() workers = self.appli.scanManager.monitor.getWorkerList() workers.append("localhost") dialog = ChildDialogCustomCommand(self, workers, "localhost") self.wait_window(dialog.app) if isinstance(dialog.rvalue, tuple): commName = dialog.rvalue[0] commArgs = dialog.rvalue[1] parser = dialog.rvalue[2] worker = dialog.rvalue[3] for selected in self.selection(): view_o = self.getViewFromId(selected) if view_o is not None: lvl = "network" if isinstance(view_o, ScopeView) else None lvl = "wave" if isinstance(view_o, WaveView) else lvl lvl = "ip" if isinstance(view_o, IpView) else lvl lvl = "port" if isinstance(view_o, PortView) else lvl if lvl is not None: inst = view_o.controller.getData() wave = inst.get("wave", "Custom commands") if wave == "Custom commands": Wave().initialize("Custom commands").addInDb() tool = Tool() tool.initialize(commName, wave, inst.get("scope", ""), inst.get("ip", None), inst.get("port", None), inst.get("proto", None), lvl, commArgs, dated="None", datef="None", scanner_ip="None", notes="Arguments: " + commArgs) tool.addInDb() if tool is None: print("Tool already existing.") return self.appli.scanManager.monitor.launchTask( mongoInstance.calendarName, tool, parser, False, worker)
def addInDb(self): """ Add this IP in database. Returns: a tuple with : * bool for success * mongo ObjectId : already existing object if duplicate, create object id otherwise """ # Checking unicity if self.ip.strip() == "": raise ValueError("Ip insertion error: Cannot insert empty ip") base = self.getDbKey() mongoInstance = MongoCalendar.getInstance() existing = mongoInstance.find( "ips", base, False) if existing is not None: return False, existing["_id"] # Add ip as it is unique base["parent"] = self.getParent() base["notes"] = self.notes base["tags"] = self.tags base["in_scopes"] = self.in_scopes base["infos"] = self.infos resInsert = mongoInstance.insert( "ips", base) self._id = resInsert.inserted_id # adding the appropriate tools for this port. # 1. fetching the wave's commands waves = mongoInstance.find("waves", {}) for wave in waves: waveName = wave["wave"] commands = wave["wave_commands"] for commName in commands: # 2. finding the command only if lvl is port comm = mongoInstance.findInDb(mongoInstance.calendarName, "commands", {"name": commName, "lvl": "ip"}, False) if comm is not None: # 3. checking if the added port fit into the command's allowed service # 3.1 first, default the selected port as tcp if no protocole is defined. newTool = Tool() newTool.initialize( comm["name"], waveName, "", self.ip, "", "", "ip") newTool.addInDb() return True, self._id
def delete(self): """ Delete the Interval represented by this model in database. """ mongoInstance = MongoCalendar.getInstance() mongoInstance.delete( "intervals", {"_id": self._id}) parent_wave = mongoInstance.find("waves", {"wave": self.wave}, False) self._id = None if parent_wave is None: return mongoInstance.notify(mongoInstance.calendarName, "waves", parent_wave["_id"], "update", "") other_intervals = Interval.fetchObjects({"wave": self.wave}) no_interval_in_time = True for other_interval in other_intervals: if Utils.fitNowTime(other_interval.dated, other_interval.datef): no_interval_in_time = False break if no_interval_in_time: tools = Tool.fetchObjects({"wave": self.wave}) for tool in tools: tool.setOutOfTime()
def addAllTool(self, command_name): """ Kind of recursive operation as it will call the same function in its children ports. Add the appropriate tools (level check and wave's commands check) for this wave. Also add for all registered scopes the appropriate tools. Args: command_name: The command that we want to create all the tools for. """ mongoInstance = MongoCalendar.getInstance() command = mongoInstance.findInDb("pollenisator", "commands", {"name": command_name}, False) if command["lvl"] == "wave": newTool = Tool() newTool.initialize(command_name, self.wave, "", "", "", "", "wave") newTool.addInDb() return scopes = mongoInstance.find("scopes", {"wave": self.wave}) for scope in scopes: h = Scope(scope) h.addAllTool(command_name)
def initUI(self, parent): """Create widgets and initialize them Args: parent: the parent tkinter widget container.""" if self.workerTv is not None: self.refreshUI() return mongoInstance = MongoCalendar.getInstance() self.parent = parent ### WORKER TREEVIEW : Which worker knows which commands lblworker = ttk.Label(self.parent, text="Workers:") lblworker.pack(side=tk.TOP, padx=10, pady=5, fill=tk.X) self.workerTv = ttk.Treeview(self.parent) self.workerTv['columns'] = ('workers') self.workerTv.heading("#0", text='Workers', anchor=tk.W) self.workerTv.column("#0", anchor=tk.W) self.workerTv.pack(side=tk.TOP, padx=10, pady=10, fill=tk.X) registeredCommands = set() workernames = self.monitor.getWorkerList() for workername in workernames: worker_node = self.workerTv.insert('', 'end', workername, text=workername, image=self.ok_icon) commands_registered = mongoInstance.getRegisteredCommands( workername) for command in commands_registered: self.workerTv.insert(worker_node, 'end', None, text=command, image=self.ok_icon) registeredCommands.add(str(command)) allCommands = Command.getList() for command in allCommands: if command not in registeredCommands: try: self.workerTv.insert('', 'end', 'notRegistered', text='Laking commands', image=self.nok_icon) except tk.TclError: self.workerTv.item('notRegistered') try: self.workerTv.insert('notRegistered', 'end', 'notRegistered|' + str(command), text=str(command), image=self.nok_icon) except tk.TclError: pass #### TREEVIEW SCANS : overview of ongoing auto scan#### lblscan = ttk.Label(self.parent, text="Scan overview:") lblscan.pack(side=tk.TOP, padx=10, pady=5, fill=tk.X) self.scanTv = ttk.Treeview(self.parent) self.scanTv['columns'] = ('Started at') self.scanTv.heading("#0", text='Scans', anchor=tk.W) self.scanTv.column("#0", anchor=tk.W) self.scanTv.pack(side=tk.TOP, padx=10, pady=10, fill=tk.X) self.scanTv.bind("<Double-Button-1>", self.OnDoubleClick) running_scans = Tool.fetchObjects({"status": "running"}) for running_scan in running_scans: self.scanTv.insert('', 'end', running_scan.getId(), text=running_scan.name, values=(running_scan.dated), image=self.running_icon) #### BUTTONS FOR AUTO SCANNING #### if len(registeredCommands) > 0: if self.running_auto_scans: self.btn_autoscan = ttk.Button(self.parent, text="Stop Scanning", command=self.stopAutoscan) self.btn_autoscan.pack() else: self.btn_autoscan = ttk.Button(self.parent, text="Start Scanning", command=self.startAutoscan) self.btn_autoscan.pack() btn_parse_scans = ttk.Button(self.parent, text="Parse existing files", command=self.parseFiles) btn_parse_scans.pack()
def getTools(self): """Return scope assigned tools as a list of mongo fetched tools dict Returns: list of defect raw mongo data dictionnaries """ return Tool.fetchObjects({"wave": self.wave, "lvl": "wave"})
def executeCommand(calendarName, toolId, parser=""): """ CELERY remote task Execute the tool with the given toolId on the given calendar name. Then execute the plugin corresponding. Any unhandled exception will result in a task-failed event in the Monitor class. Args: calendarName: The calendar to search the given tool id for. toolId: the mongo Object id corresponding to the tool to execute. parser: plugin name to execute. If empty, the plugin specified in tools.d will be feteched. Raises: Terminated: if the task gets terminated OSError: if the output directory cannot be created (not if it already exists) Exception: if an exception unhandled occurs during the bash command execution. Exception: if a plugin considered a failure. """ # Connect to given calendar mongoInstance = MongoCalendar.getInstance() mongoInstance.connectToDb(calendarName) msg = "" # retrieve tool from tool sid toolModel = Tool.fetchObject({"_id": ObjectId(toolId)}) if toolModel is None: raise Exception("Tool does not exist : " + str(toolId)) command = Command.fetchObject({"name": toolModel.name}, calendarName) # Get time limit and output directory if toolModel.wave == "Custom commands": timeLimit = None else: timeLimit = getWaveTimeLimit(toolModel.wave) if command is not None: timeLimit = min(datetime.now() + timedelta(0, int(command.timeout)), timeLimit) outputRelDir = toolModel.getOutputDir(calendarName) abs_path = os.path.dirname(os.path.abspath(__file__)) outputDir = os.path.join(abs_path, "./results", outputRelDir) # Create the output directory try: os.makedirs(outputDir) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(outputDir): pass else: raise exc # Read Tool config file tools_infos = Utils.loadToolsConfig() comm = toolModel.getCommandToExecute(outputDir) if parser.strip() == "": if toolModel.name not in list(tools_infos.keys()): msg = "TASK FAILED Received tool that was not registered : " + \ str(toolModel.name)+" not in "+str(list(tools_infos.keys())) raise Exception(msg) # Fetch the command to execute if tools_infos.get(toolModel.name, None) is None: bin_path = "" else: bin_path = tools_infos[toolModel.name].get("bin") if bin_path is not None: if not bin_path.endswith(" "): bin_path = bin_path + " " comm = bin_path + comm if comm != "": try: # Load the plugin if parser.strip() == "": mod = Utils.loadPlugin(tools_infos[toolModel.name]["plugin"]) elif parser.strip() == "auto-detect": mod = Utils.loadPluginByBin(toolModel.name.split("::")[0]) else: mod = Utils.loadPlugin(parser) # Complete command with file output toolFileName = toolModel.name+"_" + \ str(time.time())+mod.getFileOutputExt() comm = mod.changeCommand(comm, outputDir, toolFileName) print(('TASK STARTED:' + toolModel.name)) print("Will timeout at " + str(timeLimit)) # Execute the command with a timeout returncode = Utils.execute(comm, timeLimit, True) except Exception as e: raise e # Execute found plugin if there is one if mod is not None: filepath = mod.getFileOutputPath(comm) try: # Open generated file as utf8 with io.open(filepath, "r", encoding="utf-8", errors='ignore') as file_opened: # Check return code by plugin (can be always true if the return code is inconsistent) if mod.checkReturnCode(returncode): notes, tags, _, _ = mod.Parse(file_opened) if notes is None: notes = "No results found by plugin." if tags is None: tags = [] if isinstance(tags, str): tags = [tags] # Success could be change to False by the plugin function (evaluating the return code for exemple) # if the success is validated, mark tool as done toolModel.markAsDone( os.path.join(outputRelDir, os.path.basename(filepath))) # And update the tool in database toolModel.notes = notes toolModel.tags = tags toolModel.update() # Upload file to SFTP mod.centralizeFile(filepath, outputDir) msg = "TASK SUCCESS : " + toolModel.name else: # BAS RESULT OF PLUGIN msg = "TASK FAILED (says the mod) : " + toolModel.name msg += "The return code was not the expected one. (" + str( returncode) + ")." toolModel.markAsError() raise Exception(msg) except IOError as e: toolModel.tags = ["todo"] toolModel.notes = "Failed to read results file" toolModel.markAsDone() else: msg = "TASK FAILED (no plugin found) : " + toolModel.name toolModel.markAsNotDone() raise Exception(msg) # Delay if command is not None: if float(command.sleep_between) > 0.0: msg += " (will sleep for " + \ str(float(command.sleep_between))+")" print(msg) time.sleep(float(command.sleep_between)) return
def addAllTool(self, command_name): """ Add the appropriate tools (level check and wave's commands check) for this scope. Args: command_name: The command that we want to create all the tools for. """ mongoInstance = MongoCalendar.getInstance() command = mongoInstance.findInDb("pollenisator", "commands", {"name": command_name}, False) if command["lvl"] == "network": newTool = Tool() newTool.initialize(command["name"], self.wave, self.scope, "", "", "", "network") newTool.addInDb() return if command["lvl"] == "domain": if not Utils.isNetworkIp(self.scope): newTool = Tool() newTool.initialize(command["name"], self.wave, self.scope, "", "", "", "domain") newTool.addInDb() return ips = self.getIpsFitting() for ip in ips: i = Ip(ip) i.addAllTool(command_name, self.wave, self.scope)
def addDomainInDb(self, checkDomain=True): """ Add this scope domain in database. Args: checkDomain: boolean. If true (Default), checks that the domain IP is in scope Returns: a tuple with : * bool for success * mongo ObjectId : already existing object if duplicate, create object id otherwise """ # Checking unicity base = self.getDbKey() mongoInstance = MongoCalendar.getInstance() existing = mongoInstance.find("scopes", base, False) if existing is not None: return 0, None # Check if domain's ip fit in one of the Scope of the wave if checkDomain: if not Scope.checkDomainFit(self.wave, self.scope): return -1, None # insert the domains in the scopes parent = self.getParent() res_insert = mongoInstance.insert("scopes", base, parent) ret = res_insert.inserted_id self._id = ret # Adding appropriate tools for this scopes wave = mongoInstance.find("waves", {"wave": self.wave}, False) commands = wave["wave_commands"] for commName in commands: comm = mongoInstance.findInDb("pollenisator", "commands", { "name": commName, "lvl": "network" }, False) if comm is not None: newTool = Tool() newTool.initialize(comm["name"], self.wave, self.scope, "", "", "", "network") newTool.addInDb() else: comm = mongoInstance.findInDb("pollenisator", "commands", { "name": commName, "lvl": "domain" }, False) if comm is not None: newTool = Tool() newTool.initialize(comm["name"], self.wave, self.scope, "", "", "", "domain") newTool.addInDb() # Testing this scope against every ips ips = Ip.fetchObjects({}) for ip in ips: if self._id not in ip.in_scopes: if ip.fitInScope(self.scope): ip.addScopeFitting(self.getId()) ipToInsert = Ip() ipToInsert.initialize(self.scope) ipToInsert.addInDb() return 1, ret