diff --git a/NmapOps.cc b/NmapOps.cc index 20a15e2f8..22dc426ab 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -377,6 +377,7 @@ void NmapOps::Initialize() { scripttrace = 0; scriptupdatedb = 0; scripthelp = false; + scripttimeout = 0; chosenScripts.clear(); #endif memset(&sourcesock, 0, sizeof(sourcesock)); diff --git a/NmapOps.h b/NmapOps.h index b65481e12..16a94a083 100644 --- a/NmapOps.h +++ b/NmapOps.h @@ -390,6 +390,7 @@ class NmapOps { int scripttrace; int scriptupdatedb; bool scripthelp; + double scripttimeout; void chooseScripts(char* argument); std::vector chosenScripts; #endif diff --git a/nmap.cc b/nmap.cc index 4f57e0609..1d8f07779 100644 --- a/nmap.cc +++ b/nmap.cc @@ -681,6 +681,8 @@ void parse_options(int argc, char **argv) { {"script_args_file", required_argument, 0, 0}, {"script-help", required_argument, 0, 0}, {"script_help", required_argument, 0, 0}, + {"script-timeout", required_argument, 0, 0}, + {"script_timeout", required_argument, 0, 0}, #endif {"ip_options", required_argument, 0, 0}, {"ip-options", required_argument, 0, 0}, @@ -719,6 +721,11 @@ void parse_options(int argc, char **argv) { } else if (optcmp(long_options[option_index].name, "script-help") == 0) { o.scripthelp = true; o.chooseScripts(optarg); + } else if (optcmp(long_options[option_index].name, "script-timeout") == 0) { + l = tval2secs(optarg); + if ( l <= 0 ) + fatal("Bogus --script-timeout argument specified"); + o.scripttimeout = l; } else #endif if (optcmp(long_options[option_index].name, "max-os-tries") == 0) { diff --git a/nse_main.cc b/nse_main.cc index 8b973866d..1125589f7 100644 --- a/nse_main.cc +++ b/nse_main.cc @@ -384,6 +384,7 @@ static void open_cnse (lua_State *L) nseU_setsfield(L, -1, "scriptargs", o.scriptargs); nseU_setsfield(L, -1, "scriptargsfile", o.scriptargsfile); nseU_setsfield(L, -1, "NMAP_URL", NMAP_URL); + nseU_setnfield(L, -1, "script_timeout", o.scripttimeout); } diff --git a/nse_main.lua b/nse_main.lua index 33ed5c93f..084ff9d2e 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -385,10 +385,16 @@ do -- prerule/postrule scripts may be timed out in the future -- based on start time and script lifetime? function Thread:timed_out () - if self.type == "hostrule" or self.type == "portrule" then - return cnse.timedOut(self.host); + local host_timeout, script_timeout = false, false; + -- checking whether user gave --script-timeout option or not + if cnse.script_timeout and cnse.script_timeout > 0 then + -- comparing script's timeout with time elapsed + script_timeout = cnse.script_timeout < os.difftime(os.time(), self.start_time) end - return nil; + if self.type == "hostrule" or self.type == "portrule" then + host_timeout = cnse.timedOut(self.host); + end + return script_timeout or host_timeout; end function Thread:start_time_out_clock () @@ -409,6 +415,12 @@ do timeouts[self.host] = timeouts[self.host] or {}; timeouts[self.host][self.co] = true; end + -- storing script's start time so as to account for script's timeout later + if self.worker then + self.start_time = self.parent.start_time + else + self.start_time = os.time() + end end -- Remove scripts from the timeouts list and call their @@ -474,6 +486,7 @@ do script = self, type = script_type, worker = false, + start_time = 0, --for script timeout }; thread.parent = thread; setmetatable(thread, Thread) @@ -490,6 +503,7 @@ do info = format("%s W:%s", self.id, match(tostring(co), "^thread: 0?[xX]?(.*)")); parent = self, worker = true, + start_time = 0, }; setmetatable(thread, Worker) local function info () @@ -1175,6 +1189,10 @@ do args[#args+1] = cnse.scriptargs; end + if cnse.script_timeout and cnse.script_timeout > 0 then + print_debug(1, "Set script-timeout as: %d seconds", cnse.script_timeout); + end + args = concat(args, ","); if #args > 0 then print_debug(1, "Arguments parsed: %s", args);