def executeCommand(apiclient, toolId, local=True, allowAnyCommand=False): """ 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 class. Args: apiclient: the apiclient instance. toolId: the mongo Object id corresponding to the tool to execute. local: boolean, set the execution in a local context 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 APIClient.setInstance(apiclient) toolModel = Tool.fetchObject({"_id": ObjectId(toolId)}) command_dict = toolModel.getCommand() if command_dict is None and toolModel.text != "": command_dict = {"plugin": toolModel.plugin_used, "timeout": 0} msg = "" success, comm, fileext = apiclient.getCommandLine(toolId) if not success: print(str(comm)) toolModel.setStatus(["error"]) return False, str(comm) outputRelDir = toolModel.getOutputDir(apiclient.getCurrentPentest()) abs_path = os.path.dirname(os.path.abspath(__file__)) toolFileName = toolModel.name+"_" + \ str(time.time()) # ext already added in command 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: print(str(exc)) toolModel.setStatus(["error"]) return False, str(exc) outputDir = os.path.join(outputDir, toolFileName) comm = comm.replace("|outputDir|", outputDir) toolModel.updateInfos({"cmdline": comm}) # Get tool's wave time limit searching the wave intervals if toolModel.wave == "Custom commands" or local: timeLimit = None else: timeLimit = getWaveTimeLimit(toolModel.wave) # adjust timeLimit if the command has a lower timeout if command_dict is not None and timeLimit is not None: timeLimit = min( datetime.now() + timedelta(0, int(command_dict.get("timeout", 0))), timeLimit) ## try: print(('TASK STARTED:' + toolModel.name)) print("Will timeout at " + str(timeLimit)) # Execute the command with a timeout returncode, stdout = Utils.execute(comm, timeLimit, True) if returncode == -1: toolModel.setStatus(["timedout"]) return False, "timedout" except Exception as e: print(str(e)) toolModel.setStatus(["error"]) return False, str(e) # Execute found plugin if there is one outputfile = outputDir + fileext plugin = "auto-detect" if command_dict["plugin"] == "" else command_dict[ "plugin"] msg = apiclient.importToolResult(toolId, plugin, outputfile) if msg != "Success": #toolModel.markAsNotDone() print(str(msg)) toolModel.setStatus(["error"]) return False, str(msg) # Delay if command_dict is not None: if float(command_dict.get("sleep_between", 0)) > 0.0: msg += " (will sleep for " + \ str(float(command_dict.get("sleep_between", 0)))+")" print(msg) time.sleep(float(command_dict.get("sleep_between", 0))) return True, outputfile
def pollex(): """Send a command to execute for pollenisator-gui running instance """ verbose = False if sys.argv[1] == "-v": verbose = True execCmd = shlex.join(sys.argv[2:]) else: execCmd = shlex.join(sys.argv[1:]) bin_name = shlex.split(execCmd)[0] if bin_name in [ "echo", "print", "vim", "vi", "tmux", "nano", "code", "cd", "pwd", "cat" ]: return cmdName = os.path.splitext(os.path.basename(execCmd.split(" ")[0]))[0] apiclient = APIClient.getInstance() apiclient.tryConnection() cmdName += "::" + str(time.time()).replace(" ", "-") commands = Command.fetchObjects({"bin_path": {'$regex': bin_name}}) choices = set() if commands is not None: for command in commands: choices.add(command.plugin) if len(choices) == 0: plugin = "Default" elif len(choices) == 1: plugin = choices.pop() else: choice = -1 while choice == -1: print("Choose plugin:") for i, choice in enumerate(choices): print(f"{i+1}. {choice}") try: choice_str = input() choice = int(choice_str) except ValueError as e: print("You must type a valid number") if choice > len(choices) or choice < 1: choice = -1 print("You must type a number between 1 and " + str(len(choices))) plugin = list(choices)[choice - 1] print("INFO : Executing plugin " + str(plugin)) success, comm, fileext = apiclient.getDesiredOutputForPlugin( execCmd, plugin) if not success: print("ERROR : An error as occured : " + str(comm)) return with tempfile.TemporaryDirectory() as tmpdirname: outputFilePath = os.path.join(tmpdirname, cmdName) comm = comm.replace("|outputDir|", outputFilePath) if (verbose): print("Executing command : " + str(comm)) returncode, stdout = Utils.execute(comm, None, True) #if stdout.strip() != "": # print(stdout.strip()) if not os.path.exists(outputFilePath): if os.path.exists(outputFilePath + fileext): outputFilePath += fileext else: print( f"ERROR : Expected file was not generated {outputFilePath}" ) return print(f"INFO : Uploading results {outputFilePath}") msg = apiclient.importExistingResultFile( outputFilePath, plugin, os.environ.get("POLLENISATOR_DEFAULT_TARGET", ""), comm) print(msg)