diff --git a/docs/nmap.dtd b/docs/nmap.dtd index 41bde3a53..45932fb53 100644 --- a/docs/nmap.dtd +++ b/docs/nmap.dtd @@ -73,8 +73,9 @@ It represents to the topmost element of the output document. --> + ((taskbegin, taskprogress*, taskend) | + prescripts | postscripts | host | output)*, + runstats) > + + diff --git a/global_structures.h b/global_structures.h index 41d927e29..d25a79ca1 100644 --- a/global_structures.h +++ b/global_structures.h @@ -244,6 +244,6 @@ struct scan_lists { int prot_count; }; -typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_SCAN, TRACEROUTE}stype; +typedef enum { STYPE_UNKNOWN, HOST_DISCOVERY, ACK_SCAN, SYN_SCAN, FIN_SCAN, XMAS_SCAN, UDP_SCAN, CONNECT_SCAN, NULL_SCAN, WINDOW_SCAN, SCTP_INIT_SCAN, SCTP_COOKIE_ECHO_SCAN, RPC_SCAN, MAIMON_SCAN, IPPROT_SCAN, PING_SCAN, PING_SCAN_ARP, IDLE_SCAN, BOUNCE_SCAN, SERVICE_SCAN, OS_SCAN, SCRIPT_PRE_SCAN, SCRIPT_SCAN, SCRIPT_POST_SCAN, TRACEROUTE}stype; #endif /*GLOBAL_STRUCTURES_H */ diff --git a/nmap.cc b/nmap.cc index ae14d5e97..f576f6cb5 100644 --- a/nmap.cc +++ b/nmap.cc @@ -442,6 +442,10 @@ int nmap_main(int argc, char *argv[]) { HostGroupState *hstate = NULL; char *endptr = NULL; struct scan_lists ports = { 0 }; +#ifndef NOLUA + /* Pre-Scan and Post-Scan script results datastructure */ + ScriptResults *script_scan_results = NULL; +#endif TargetGroup *exclude_group = NULL; char myname[MAXHOSTNAMELEN + 1]; #if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS)) @@ -1602,6 +1606,13 @@ int nmap_main(int argc, char *argv[]) { o.scriptversion = 1; if (o.scriptversion || o.script || o.scriptupdatedb) open_nse(); + + if (o.script) { + script_scan_results = get_script_scan_results_obj(); + script_scan(Targets, SCRIPT_PRE_SCAN); + printscriptresults(script_scan_results, SCRIPT_PRE_SCAN); + script_scan_results->clear(); + } #endif /* Time to create a hostgroup state object filled with all the requested @@ -1815,7 +1826,7 @@ int nmap_main(int argc, char *argv[]) { #ifndef NOLUA if(o.script || o.scriptversion) { - script_scan(Targets); + script_scan(Targets, SCRIPT_SCAN); } #endif @@ -1866,6 +1877,14 @@ int nmap_main(int argc, char *argv[]) { o.numhosts_scanning = 0; } while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned); +#ifndef NOLUA + if (o.script) { + script_scan(Targets, SCRIPT_POST_SCAN); + printscriptresults(script_scan_results, SCRIPT_POST_SCAN); + script_scan_results->clear(); + } +#endif + delete hstate; if (exclude_group) delete[] exclude_group; @@ -2573,7 +2592,9 @@ const char *scantype2str(stype scantype) { case BOUNCE_SCAN: return "Bounce Scan"; break; case SERVICE_SCAN: return "Service Scan"; break; case OS_SCAN: return "OS Scan"; break; + case SCRIPT_PRE_SCAN: return "Script Pre-Scan"; break; case SCRIPT_SCAN: return "Script Scan"; break; + case SCRIPT_POST_SCAN: return "Script Post-Scan"; break; case TRACEROUTE: return "Traceroute" ; break; default: assert(0); break; } @@ -2795,5 +2816,3 @@ int nmap_fetchfile(char *filename_returned, int bufferlen, const char *file) { return foundsomething; } - - diff --git a/nse_main.cc b/nse_main.cc index 06a48384a..a6e3911f9 100644 --- a/nse_main.cc +++ b/nse_main.cc @@ -22,6 +22,11 @@ #define NSE_MAIN "NSE_MAIN" /* the main function */ #define NSE_TRACEBACK "NSE_TRACEBACK" +/* Script Scan phases */ +#define NSE_PRE_SCAN "NSE_PRE_SCAN" +#define NSE_SCAN "NSE_SCAN" +#define NSE_POST_SCAN "NSE_POST_SCAN" + /* These are indices into the registry, for data shared with nse_main.lua. The definitions here must match those in nse_main.lua. */ #define NSE_YIELD "NSE_YIELD" @@ -37,6 +42,9 @@ extern NmapOps o; +/* global object to store Pre-Scan and Post-Scan script results */ +static ScriptResults script_scan_results; + static int timedOut (lua_State *L) { Target *target = get_target(L, 1); @@ -101,6 +109,15 @@ static int ports (lua_State *L) return 3; } +static int script_set_output (lua_State *L) +{ + ScriptResult sr; + sr.set_id(luaL_checkstring(L, 1)); + sr.set_output(luaL_checkstring(L, 2)); + script_scan_results.push_back(sr); + return 0; +} + static int host_set_output (lua_State *L) { ScriptResult sr; @@ -188,6 +205,7 @@ static void open_cnse (lua_State *L) {"startTimeOutClock", startTimeOutClock}, {"stopTimeOutClock", stopTimeOutClock}, {"ports", ports}, + {"script_set_output", script_set_output}, {"host_set_output", host_set_output}, {"port_set_output", port_set_output}, {NULL, NULL} @@ -231,6 +249,11 @@ std::string ScriptResult::get_id (void) const return id; } +ScriptResults *get_script_scan_results_obj (void) +{ + return &script_scan_results; +} + /* int panic (lua_State *L) * * Panic function set via lua_atpanic(). @@ -333,6 +356,7 @@ static int run_main (lua_State *L) /* New host group */ lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); lua_getfield(L, LUA_REGISTRYINDEX, NSE_TRACEBACK); /* index 1 */ @@ -363,8 +387,23 @@ static int run_main (lua_State *L) } lua_pop(L, 1); /* pop NSE_CURRENT_HOSTS */ - if (lua_pcall(L, 1, 0, 1) != 0) lua_error(L); /* we wanted a traceback */ + /* push script scan type phase */ + switch (o.current_scantype) + { + case SCRIPT_PRE_SCAN: + lua_pushstring(L, NSE_PRE_SCAN); + break; + case SCRIPT_SCAN: + lua_pushstring(L, NSE_SCAN); + break; + case SCRIPT_POST_SCAN: + lua_pushstring(L, NSE_POST_SCAN); + break; + default: + fatal("%s: failed to set the script scan phase.\n", SCRIPT_ENGINE); + } + if (lua_pcall(L, 2, 0, 1) != 0) lua_error(L); /* we wanted a traceback */ return 0; } @@ -495,18 +534,16 @@ void open_nse (void) } } -void script_scan (std::vector &targets) +void script_scan (std::vector &targets, stype scantype) { - o.current_scantype = SCRIPT_SCAN; + o.current_scantype = scantype; assert(L_NSE != NULL); lua_settop(L_NSE, 0); /* clear the stack */ if (lua_cpcall(L_NSE, run_main, (void *) &targets) != 0) - { error("%s: Script Engine Scan Aborted.\nAn error was thrown by the " "engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1)); - } } void close_nse (void) diff --git a/nse_main.h b/nse_main.h index 9cfc38ba0..f74c13b0a 100644 --- a/nse_main.h +++ b/nse_main.h @@ -13,6 +13,9 @@ extern "C" { #include "lauxlib.h" } +#include "nmap.h" +#include "global_structures.h" + class ScriptResult { private: @@ -27,6 +30,10 @@ class ScriptResult typedef std::list ScriptResults; +/* Call this to get a ScriptResults object which can be + * used to store Pre-Scan and Post-Scan script Results */ +ScriptResults *get_script_scan_results_obj (void); + class Target; @@ -39,7 +46,7 @@ void nse_selectedbyname (lua_State *); void nse_gettarget (lua_State *, int); void open_nse (void); -void script_scan (std::vector &targets); +void script_scan (std::vector &targets, stype scantype); void close_nse (void); #define SCRIPT_ENGINE "NSE" diff --git a/nse_main.lua b/nse_main.lua index 3f3000d6d..063a59ce9 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -32,6 +32,11 @@ local NAME = "NSE"; +-- Script Scan phases. +local NSE_PRE_SCAN = "NSE_PRE_SCAN"; +local NSE_SCAN = "NSE_SCAN"; +local NSE_POST_SCAN = "NSE_POST_SCAN"; + -- String keys into the registry (_R), for data shared with nse_main.cc. local YIELD = "NSE_YIELD"; local BASE = "NSE_BASE"; @@ -107,6 +112,14 @@ local stdnse = require "stdnse"; -- differentiate between yields initiated by NSE or regular coroutine yields. local NSE_YIELD_VALUE = {}; +-- Table of different supported rules. +local NSE_SCRIPT_RULES = { + prerule = "prerule", + hostrule = "hostrule", + portrule = "portrule", + postrule = "postrule", +}; + do -- This is the method by which we allow a script to have nested -- coroutines. If a sub-thread yields in an NSE function such as @@ -187,14 +200,79 @@ do -- Outputs debug information at level 1 or higher. -- Changes "%THREAD" with an appropriate identifier for the debug level function Thread:d (fmt, ...) - if debugging() > 1 then - print_debug(1, gsub(fmt, "%%THREAD", self.info), ...); + local against; + if self.host and self.port then + against = " against "..self.host.ip..":"..self.port.number; + elseif self.host then + against = " against "..self.host.ip; else - print_debug(1, gsub(fmt, "%%THREAD", self.short_basename), ...); + against = ""; + end + if debugging() > 1 then + fmt = gsub(fmt, "%%THREAD_AGAINST", self.info..against); + fmt = gsub(fmt, "%%THREAD", self.info); + else + fmt = gsub(fmt, "%%THREAD_AGAINST", self.short_basename..against); + fmt = gsub(fmt, "%%THREAD", self.short_basename); + end + print_debug(1, fmt, ...); + end + + -- Sets scripts output. Variable result is a string. + function Thread:set_output(result) + if self.type == "prerule" or self.type == "postrule" then + cnse.script_set_output(self.id, result); + elseif self.type == "hostrule" then + cnse.host_set_output(self.host, self.id, result); + elseif self.type == "portrule" then + cnse.port_set_output(self.host, self.port, self.id, result); end end - function Thread:close () + -- 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); + end + return nil; + end + + function Thread:start_time_out_clock () + if self.type == "hostrule" or self.type == "portrule" then + return cnse.startTimeOutClock(self.host); + end + return nil; + end + + function Thread:stop_time_out_clock () + if self.type == "hostrule" or self.type == "portrule" then + return cnse.stopTimeOutClock(self.host); + end + return nil; + end + + -- Register scripts in the timeouts list to track their timeouts. + function Thread:start (timeouts) + self:d("Starting %THREAD_AGAINST."); + if self.host then + timeouts[self.host] = timeouts[self.host] or {}; + timeouts[self.host][self.co] = true; + end + end + + -- Remove scripts from the timeouts list and call their + -- destructor handles. + function Thread:close (timeouts, result) + self.error = result; + if self.host then + timeouts[self.host][self.co] = nil; + -- Any more threads running for this script/host? + if not next(timeouts[self.host]) then + self:stop_time_out_clock(); + timeouts[self.host] = nil; + end + end local ch = self.close_handlers; for key, destructor_t in pairs(ch) do destructor_t.destructor(destructor_t.thread, key); @@ -210,11 +288,13 @@ do -- Returns: -- thread The thread (class) is returned, or nil. function Script:new_thread (rule, ...) - assert(rule == "hostrule" or rule == "portrule"); + local script_type = assert(NSE_SCRIPT_RULES[rule]); if not self[rule] then return nil end -- No rule for this script? local file_closure = self.file_closure; local env = setmetatable({ - filename = self.filename, + SCRIPT_PATH = self.filename, + SCRIPT_NAME = self.short_basename, + SCRIPT_TYPE = script_type, }, {__index = _G}); setfenv(file_closure, env); local unique_value = {}; -- to test valid yield @@ -238,7 +318,7 @@ do env = env, identifier = tostring(co), info = format("'%s' (%s)", self.short_basename, tostring(co)); - type = rule == "hostrule" and "host" or "port", + type = script_type, close_handlers = {}, }, { __metatable = Thread, @@ -291,10 +371,19 @@ do type(field).."', expected type '"..t.."'"); end end - -- Check one of two required rule functions exists - local hostrule, portrule = rawget(env, "hostrule"), rawget(env, "portrule"); - assert(type(hostrule) == "function" or type(portrule) == "function", - filename.." is missing a required function: 'hostrule' or 'portrule'"); + -- Check the required rule functions + local rules = {} + for rule in pairs(NSE_SCRIPT_RULES) do + local rulef = rawget(env, rule); + assert(type(rulef) == "function" or rulef == nil, + rule.." must be a function!"); + rules[rule] = rulef; + end + assert(next(rules), filename.." is missing required function: 'rule'"); + local prerule = rules.prerule; + local hostrule = rules.hostrule; + local portrule = rules.portrule; + local postrule = rules.postrule; -- Assert that categories is an array of strings for i, category in ipairs(rawget(env, "categories")) do assert(type(category) == "string", @@ -314,8 +403,10 @@ do filename, id = match(filename, "^.-[/\\]([^\\/]-)%.nse$") or filename, file_closure = file_closure, - hostrule = type(hostrule) == "function" and hostrule or nil, - portrule = type(portrule) == "function" and portrule or nil, + prerule = prerule, + hostrule = hostrule, + portrule = portrule, + postrule = postrule, args = {n = 0}; categories = rawget(env, "categories"), author = rawget(env, "author"), @@ -518,26 +609,24 @@ end -- The main loop function for NSE. It handles running all the script threads. -- Arguments: -- threads An array of threads (a runlevel) to run. -local function run (threads) +-- scantype A string that indicates the current script scan phase. +local function run (threads, scantype) -- running scripts may be resumed at any time. waiting scripts are -- yielded until Nsock wakes them. After being awakened with -- nse_restore, waiting threads become pending and later are moved all -- at once back to running. local running, waiting, pending = {}, {}, {}; local all = setmetatable({}, {__mode = "kv"}); -- base coroutine to Thread - -- hosts maps a host to a list of threads for that host. - local hosts, total = {}, 0; - local current; + local current; -- The currently running Thread. + local total = 0; -- Number of threads, for record keeping. + local timeouts = {}; -- A list to save and to track scripts timeout. local progress = cnse.scan_progress_meter(NAME); print_debug(1, "NSE Script Threads (%d) running:", #threads); while #threads > 0 do local thread = remove(threads); - thread:d("Starting %THREAD against %s%s.", thread.host.ip, - thread.port and ":"..thread.port.number or ""); all[thread.co], running[thread.co], total = thread, thread, total+1; - hosts[thread.host] = hosts[thread.host] or {}; - hosts[thread.host][thread.co] = true; + thread:start(timeouts); end -- Map of yielded threads to the base Thread @@ -586,9 +675,11 @@ local function run (threads) current.parent.info, tostring(co)); local thread = { co = co, + id = current.id, args = {n = select("#", ...), ...}, host = current.host, port = current.port, + type = current.type, parent = current.parent, info = format("'%s' worker (%s)", current.short_basename, tostring(co)); -- d = function(...) end, -- output no debug information @@ -633,28 +724,28 @@ local function run (threads) end end - -- Checked for timed-out hosts. + -- Checked for timed-out scripts and hosts. for co, thread in pairs(waiting) do - if cnse.timedOut(thread.host) then + if thread:timed_out() then waiting[co], all[co] = nil, nil; - thread:d("%THREAD %s%s timed out", thread.host.ip, - thread.port and ":"..thread.port.number or ""); - thread:close(); + thread:d("%THREAD %stimed out", thread.host + and format("%s%s ", thread.host.ip, + thread.port and ":"..thread.port.number or "") + or ""); + thread:close(timeouts, "timed out"); end end for co, thread in pairs(running) do current, running[co] = thread, nil; - cnse.startTimeOutClock(thread.host); + thread:start_time_out_clock(); local s, result = resume(co, unpack(thread.args, 1, thread.args.n)); if not s then -- script error... - hosts[thread.host][co], all[co] = nil, nil; - thread:d("%THREAD against %s%s threw an error!\n%s\n", - thread.host.ip, thread.port and ":"..thread.port.number or "", + all[co] = nil; + thread:d("%THREAD_AGAINST threw an error!\n%s\n", traceback(co, tostring(result))); - thread.error = result; - thread:close(); + thread:close(timeouts, result); elseif status(co) == "suspended" then if result == NSE_YIELD_VALUE then waiting[co] = thread; @@ -663,7 +754,7 @@ local function run (threads) thread:close(); end elseif status(co) == "dead" then - hosts[thread.host][co], all[co] = nil, nil; + all[co] = nil; if type(result) == "string" then -- Escape any character outside the range 32-126 except for tab, -- carriage return, and line feed. This makes the string safe for @@ -671,20 +762,10 @@ local function run (threads) result = gsub(result, "[^\t\r\n\032-\126]", function(a) return format("\\x%02X", byte(a)); end); - if thread.type == "host" then - cnse.host_set_output(thread.host, thread.id, result); - else - cnse.port_set_output(thread.host, thread.port, thread.id, result); - end + thread:set_output(result); end - thread:d("Finished %THREAD against %s%s.", thread.host.ip, - thread.port and ":"..thread.port.number or ""); - thread:close(); - end - - -- Any more threads running for this host? - if not next(hosts[thread.host]) then - cnse.stopTimeOutClock(thread.host); + thread:d("Finished %THREAD_AGAINST."); + thread:close(timeouts); end end @@ -804,45 +885,104 @@ for i, script in ipairs(chosen_scripts) do end -- main(hosts) --- This is the main function we return to NSE (on the C side) which actually --- runs a scan against an array of hosts. nse_main.cc gets this function --- by loading and executing nse_main.lua. +-- This is the main function we return to NSE (on the C side), nse_main.cc +-- gets this function by loading and executing nse_main.lua. This +-- function runs a script scan phase according to its arguments. -- Arguments: -- hosts An array of hosts to scan. -return function (hosts) - if #hosts > 1 then - print_verbose(1, "Script scanning %d hosts.", #hosts); - elseif #hosts == 1 then - print_verbose(1, "Script scanning %s.", hosts[1].ip); - end - - -- Set up the runlevels. +-- scantype A string that indicates the current script scan phase. +-- Possible string values are: +-- "SCRIPT_PRE_SCAN" +-- "SCRIPT_SCAN" +-- "SCRIPT_POST_SCAN" +return function (hosts, scantype) + -- Used to set up the runlevels. local threads, runlevels = {}, {}; - for j, host in ipairs(hosts) do - -- Check hostrules for this host. + + -- Every script thread has a table that is used in the run function + -- (the main loop of NSE). + -- This is the list of the thread table key/value pairs: + -- Key Value + -- type A string that indicates the rule type of the script. + -- co A thread object to identify the coroutine. + -- parent A table that contains the parent thread table (it self). + -- close_handlers + -- A table that contains the thread destructor handlers. + -- info A string that contains the script name and the thread + -- debug information. + -- args A table that contains the arguments passed to scripts, + -- arguments can be host and port tables. + -- env A table that contains the global script environment: + -- categories, description, author, license, nmap table, + -- action function, rule functions, SCRIPT_PATH, + -- SCRIPT_NAME, SCRIPT_TYPE (pre|host|port|post rule). + -- identifier + -- A string to identify the thread address. + -- host A table that contains the target host information. This + -- will be nil for Pre-scanning and Post-scanning scripts. + -- port A table that contains the target port information. This + -- will be nil for Pre-scanning and Post-scanning scripts. + + -- activate prerule scripts + if (scantype == NSE_PRE_SCAN) then + print_verbose(1, "Script Pre-scanning."); for i, script in ipairs(chosen_scripts) do - local thread = script:new_thread("hostrule", tcopy(host)); + local thread = script:new_thread("prerule"); if thread then local runlevel = thread.runlevel; if threads[runlevel] == nil then insert(runlevels, runlevel); end threads[runlevel] = threads[runlevel] or {}; insert(threads[runlevel], thread); - thread.args, thread.host = {n = 1, tcopy(host)}, host; + thread.args = {n = 0}; end end - -- Check portrules for this host. - for port in cnse.ports(host) do + -- activate hostrule and portrule scripts + elseif (scantype == NSE_SCAN) then + if #hosts > 1 then + print_verbose(1, "Script scanning %d hosts.", #hosts); + elseif #hosts == 1 then + print_verbose(1, "Script scanning %s.", hosts[1].ip); + end + + -- Check hostrules for this host. + for j, host in ipairs(hosts) do for i, script in ipairs(chosen_scripts) do - local thread = script:new_thread("portrule", tcopy(host), tcopy(port)); + local thread = script:new_thread("hostrule", tcopy(host)); if thread then local runlevel = thread.runlevel; if threads[runlevel] == nil then insert(runlevels, runlevel); end threads[runlevel] = threads[runlevel] or {}; insert(threads[runlevel], thread); - thread.args, thread.host, thread.port = - {n = 2, tcopy(host), tcopy(port)}, host, port; + thread.args, thread.host = {n = 1, tcopy(host)}, host; end end + -- Check portrules for this host. + for port in cnse.ports(host) do + for i, script in ipairs(chosen_scripts) do + local thread = script:new_thread("portrule", tcopy(host), tcopy(port)); + if thread then + local runlevel = thread.runlevel; + if threads[runlevel] == nil then insert(runlevels, runlevel); end + threads[runlevel] = threads[runlevel] or {}; + insert(threads[runlevel], thread); + thread.args, thread.host, thread.port = + {n = 2, tcopy(host), tcopy(port)}, host, port; + end + end + end + end + -- activate postrule scripts + elseif (scantype == NSE_POST_SCAN) then + print_verbose(1, "Script Post-scanning."); + for i, script in ipairs(chosen_scripts) do + local thread = script:new_thread("postrule"); + if thread then + local runlevel = thread.runlevel; + if threads[runlevel] == nil then insert(runlevels, runlevel); end + threads[runlevel] = threads[runlevel] or {}; + insert(threads[runlevel], thread); + thread.args = {n = 0}; + end end end @@ -850,7 +990,7 @@ return function (hosts) for i, runlevel in ipairs(runlevels) do print_verbose(1, "Starting runlevel %u (of %u) scan.", runlevel, #runlevels); - run(threads[runlevel]); + run(threads[runlevel], scantype); end collectgarbage "collect"; diff --git a/output.cc b/output.cc index 2eb78f9db..10c2e91b6 100644 --- a/output.cc +++ b/output.cc @@ -1918,6 +1918,35 @@ void printserviceinfooutput(Target * currenths) { } #ifndef NOLUA +void printscriptresults(ScriptResults * scriptResults, stype scantype) { + ScriptResults::iterator iter; + char *script_output; + + if (scriptResults->size() > 0) { + if (scantype == SCRIPT_PRE_SCAN) { + xml_start_tag("prescript"); + log_write(LOG_PLAIN, "Pre-scan script results:\n"); + } + else { + xml_start_tag("postscript"); + log_write(LOG_PLAIN, "Post-scan script results:\n"); + } + + for (iter = scriptResults->begin(); + iter != scriptResults->end(); + iter++) { + xml_open_start_tag("script"); + xml_attribute("id", "%s", iter->get_id().c_str()); + xml_attribute("output", "%s", iter->get_output().c_str()); + xml_close_empty_tag(); + script_output = formatScriptOutput((*iter)); + log_write(LOG_PLAIN, "%s\n", script_output); + free(script_output); + } + xml_end_tag(); + } +} + void printhostscriptresults(Target * currenths) { ScriptResults::iterator iter; char *script_output; diff --git a/output.h b/output.h index c7fcab05f..347cbd3ab 100644 --- a/output.h +++ b/output.h @@ -213,6 +213,9 @@ void printosscanoutput(Target *currenths); service scan (if it was performed) */ void printserviceinfooutput(Target *currenths); +/* Use this function to report NSE_PRE_SCAN and NSE_POST_SCAN results */ +void printscriptresults(ScriptResults *scriptResults, stype scantype); + void printhostscriptresults(Target *currenths); /* Print a table with traceroute hops. */ diff --git a/scripts/asn-query.nse b/scripts/asn-query.nse index ab265fb32..5bdd329f9 100644 --- a/scripts/asn-query.nse +++ b/scripts/asn-query.nse @@ -209,7 +209,7 @@ function ip_to_asn( query ) local status, decoded_response = dns.query( query, options) if not status then - stdnse.print_debug( "%s Error from dns.query(): %s", filename, decoded_response ) + stdnse.print_debug( "%s Error from dns.query(): %s", SCRIPT_NAME, decoded_response ) end return status, decoded_response diff --git a/scripts/banner.nse b/scripts/banner.nse index f2ddd08b3..7b0be25db 100644 --- a/scripts/banner.nse +++ b/scripts/banner.nse @@ -56,7 +56,7 @@ function grab_banner(host, port) if not status then local errlvl = { ["EOF"]=3,["TIMEOUT"]=3,["ERROR"]=2 } stdnse.print_debug(errlvl[response] or 1, "%s failed for %s on %s port %s. Message: %s", - filename, host.ip, port.protocol, port.number, response or "No Message." ) + SCRIPT_NAME, host.ip, port.protocol, port.number, response or "No Message." ) return nil end @@ -87,8 +87,7 @@ function output( out ) if type(out) ~= "string" or out == "" then return nil end - -- convert filename from full filepath to filename -extn - local filename = filename:match( "[\\/]([^\\/]+)\.nse$" ) + local filename = SCRIPT_NAME local line_len = 75 -- The character width of command/shell prompt window. local fline_offset = 5 -- number of chars excluding script id not available to the script on the first line diff --git a/scripts/http-favicon.nse b/scripts/http-favicon.nse index 8cb4beb65..8c476bc7c 100644 --- a/scripts/http-favicon.nse +++ b/scripts/http-favicon.nse @@ -57,7 +57,8 @@ action = function(host, port) end if not pcall(require,'openssl') then - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return end diff --git a/scripts/http-userdir-enum.nse b/scripts/http-userdir-enum.nse index c50c4b7e0..6e405f045 100644 --- a/scripts/http-userdir-enum.nse +++ b/scripts/http-userdir-enum.nse @@ -150,13 +150,12 @@ end -- @return nil function init() - local filename = filename and filename:match( "[\\/]([^\\/]+)\.nse$" ) or "" local customlist = nmap.registry.args.users or (nmap.registry.args.userdir and nmap.registry.args.userdir.users) or nmap.registry.args['userdir.users'] local read, usernames = datafiles.parse_file(customlist or "nselib/data/usernames.lst", {}) if not read then - stdnse.print_debug(1, "%s %s", filename, + stdnse.print_debug(1, "%s %s", SCRIPT_NAME, usernames or "Unknown Error reading usernames list.") nmap.registry.userdir = {} return nil @@ -164,7 +163,7 @@ function init() -- random dummy username to catch false positives (not necessary) -- if #usernames > 0 then table.insert(usernames, 1, randomstring()) end nmap.registry.userdir = usernames - stdnse.print_debug(1, "%s Testing %d usernames.", filename, #usernames) + stdnse.print_debug(1, "%s Testing %d usernames.", SCRIPT_NAME, #usernames) return nil end diff --git a/scripts/imap-capabilities.nse b/scripts/imap-capabilities.nse index c755c6cd4..23d8123e0 100644 --- a/scripts/imap-capabilities.nse +++ b/scripts/imap-capabilities.nse @@ -34,7 +34,7 @@ action = function(host, port) end return stdnse.strjoin(" ", capstrings) elseif type(err) == "string" then - stdnse.print_debug(1, "%s: '%s' for %s", filename, err, host.ip) + stdnse.print_debug(1, "%s: '%s' for %s", SCRIPT_NAME, err, host.ip) return else return "server doesn't support CAPABILITIES" diff --git a/scripts/mysql-brute.nse b/scripts/mysql-brute.nse index e18c08941..28cd90e20 100644 --- a/scripts/mysql-brute.nse +++ b/scripts/mysql-brute.nse @@ -28,7 +28,8 @@ require 'unpwdb' if not pcall(require,"openssl") then portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/mysql-databases.nse b/scripts/mysql-databases.nse index 002bcbcaf..287143695 100644 --- a/scripts/mysql-databases.nse +++ b/scripts/mysql-databases.nse @@ -35,7 +35,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"} if not pcall(require,"openssl") then portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/mysql-users.nse b/scripts/mysql-users.nse index 1da4dd805..03de44ca0 100644 --- a/scripts/mysql-users.nse +++ b/scripts/mysql-users.nse @@ -41,7 +41,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"} if not pcall(require,"openssl") then portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/mysql-variables.nse b/scripts/mysql-variables.nse index 72b34b26b..fafb91400 100644 --- a/scripts/mysql-variables.nse +++ b/scripts/mysql-variables.nse @@ -49,7 +49,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"} if not pcall(require,"openssl") then portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/pgsql-brute.nse b/scripts/pgsql-brute.nse index c9bc1b2de..f5fbc4b10 100644 --- a/scripts/pgsql-brute.nse +++ b/scripts/pgsql-brute.nse @@ -43,7 +43,8 @@ if pcall(require,"openssl") then else portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/pop3-capabilities.nse b/scripts/pop3-capabilities.nse index 0d15d3be6..2d7943f80 100644 --- a/scripts/pop3-capabilities.nse +++ b/scripts/pop3-capabilities.nse @@ -44,7 +44,7 @@ action = function(host, port) end return stdnse.strjoin(" ", capstrings) elseif type(err) == "string" then - stdnse.print_debug(1, "%s: '%s' for %s", filename, err, host.ip) + stdnse.print_debug(1, "%s: '%s' for %s", SCRIPT_NAME, err, host.ip) return else return "server doesn't support CAPA" diff --git a/scripts/sql-injection.nse b/scripts/sql-injection.nse index d458e3b80..b3315e956 100644 --- a/scripts/sql-injection.nse +++ b/scripts/sql-injection.nse @@ -233,7 +233,7 @@ action = function(host, port) end if #injectable > 0 then - stdnse.print_debug(1, "%s: Testing %d suspicious URLs", filename, #injectable ) + stdnse.print_debug(1, "%s: Testing %d suspicious URLs", SCRIPT_NAME, #injectable ) -- test all potentially vulnerable queries injectableQs = build_injection_vector(injectable) local responses = inject(host, port, injectableQs) diff --git a/scripts/ssh-hostkey.nse b/scripts/ssh-hostkey.nse index 0726cb40a..187f9af5c 100644 --- a/scripts/ssh-hostkey.nse +++ b/scripts/ssh-hostkey.nse @@ -50,7 +50,8 @@ if pcall(require,"openssl") then else portrule = function() return false end action = function() end - stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", filename ) + stdnse.print_debug( 3, "Skipping %s script because OpenSSL is missing.", + SCRIPT_NAME) return; end diff --git a/scripts/whois.nse b/scripts/whois.nse index d06342323..c7250a7b8 100644 --- a/scripts/whois.nse +++ b/scripts/whois.nse @@ -95,7 +95,7 @@ hostrule = function( host ) local is_private, err = ipOps.isPrivate( host.ip ) if is_private == nil then - stdnse.print_debug( "%s Error in Hostrule: %s.", filename, err ) + stdnse.print_debug( "%s Error in Hostrule: %s.", SCRIPT_NAME, err ) return false end @@ -190,7 +190,7 @@ action = function( host ) status, retval = pcall( get_next_action, tracking, host.ip ) if not status then - stdnse.print_debug( "%s %s pcall caught an exception in get_next_action: %s.", filename, host.ip, retval ) + stdnse.print_debug( "%s %s pcall caught an exception in get_next_action: %s.", SCRIPT_NAME, host.ip, retval ) else tracking = retval end if tracking.this_db then @@ -201,13 +201,13 @@ action = function( host ) -- analyse data status, retval = pcall( analyse_response, tracking, host.ip, response, data ) if not status then - stdnse.print_debug( "%s %s pcall caught an exception in analyse_response: %s.", filename, host.ip, retval ) + stdnse.print_debug( "%s %s pcall caught an exception in analyse_response: %s.", SCRIPT_NAME, host.ip, retval ) else data = retval end -- get next action status, retval = pcall( get_next_action, tracking, host.ip ) if not status then - stdnse.print_debug( "%s %s pcall caught an exception in get_next_action: %s.", filename, host.ip, retval ) + stdnse.print_debug( "%s %s pcall caught an exception in get_next_action: %s.", SCRIPT_NAME, host.ip, retval ) if not tracking.last_db then tracking.last_db, tracking.this_db = tracking.this_db or tracking.next_db, nil end else tracking = retval end end @@ -340,7 +340,7 @@ function check_response_cache( ip ) -- record found in cache return true, nil else - stdnse.print_debug( 1, "%s %s Error in check_response_cache: Empty Cache Entry was found.", filename, ip ) + stdnse.print_debug( 1, "%s %s Error in check_response_cache: Empty Cache Entry was found.", SCRIPT_NAME, ip ) end return false, nil @@ -461,7 +461,7 @@ function get_db_from_assignments( ip ) end if not nmap.registry.whois.local_assignments_data or not nmap.registry.whois.local_assignments_data[af] then - stdnse.print_debug( 1, "%s Error in get_db_from_assignments: Missing assignments data in registry.", filename ) + stdnse.print_debug( 1, "%s Error in get_db_from_assignments: Missing assignments data in registry.", SCRIPT_NAME ) return nil end @@ -488,14 +488,14 @@ end function do_query(db, ip) if type( db ) ~= "string" or not nmap.registry.whois.whoisdb[db] then - stdnse.print_debug("%s %s Error in do_query: %s is not a defined Whois service.", filename, ip, db) + stdnse.print_debug("%s %s Error in do_query: %s is not a defined Whois service.", SCRIPT_NAME, ip, db) return nil end local service = nmap.registry.whois.whoisdb[db] if type( service.hostname ) ~= "string" or service.hostname == "" then - stdnse.print_debug("%s %s Error in do_query: Invalid hostname for %s.", filename, ip, db) + stdnse.print_debug("%s %s Error in do_query: Invalid hostname for %s.", SCRIPT_NAME, ip, db) return nil end @@ -511,7 +511,7 @@ function do_query(db, ip) local socket = nmap.new_socket() local catch = function() - stdnse.print_debug( "%s %s Connection to %s failed or was aborted! No Output for this Target.", filename, ip, db ) + stdnse.print_debug( "%s %s Connection to %s failed or was aborted! No Output for this Target.", SCRIPT_NAME, ip, db ) nmap.registry.whois.mutex[db] "done" socket:close() end @@ -534,7 +534,7 @@ function do_query(db, ip) socket:close() - stdnse.print_debug(3, "%s %s Ended Query at %s.", filename, ip, db) + stdnse.print_debug(3, "%s %s Ended Query at %s.", SCRIPT_NAME, ip, db) if #result == 0 then return nil @@ -587,13 +587,13 @@ function analyse_response( tracking, ip, response, data ) if type( meta ) == "table" and type( meta.fieldreq ) == "table" and type( meta.fieldreq.ob_exist ) == "string" then have_objects = response:match( meta.fieldreq.ob_exist ) else - stdnse.print_debug( 2, "%s %s Could not check for objects, problem with meta data.", filename, ip ) + stdnse.print_debug( 2, "%s %s Could not check for objects, problem with meta data.", SCRIPT_NAME, ip ) have_objects = false end -- if we do not recognize objects check for an known error/non-object message if not have_objects then - stdnse.print_debug( 4, "%s %s %s has not responded with the expected objects.", filename, ip, this_db ) + stdnse.print_debug( 4, "%s %s %s has not responded with the expected objects.", SCRIPT_NAME, ip, this_db ) local tmp, msg -- may have found our record saying something similar to "No Record Found" for _, pattern in ipairs( nmap.registry.whois.m_none ) do @@ -601,7 +601,7 @@ function analyse_response( tracking, ip, response, data ) local pattern_u = pattern:gsub( "$addr", ip:upper() ) msg = response:match( pattern_l ) or response:match( pattern_u ) if msg then - stdnse.print_debug( 4, "%s %s %s responded with a message which is assumed to be authoritative (but may not be).", filename, ip, this_db ) + stdnse.print_debug( 4, "%s %s %s responded with a message which is assumed to be authoritative (but may not be).", SCRIPT_NAME, ip, this_db ) break end end @@ -610,7 +610,7 @@ function analyse_response( tracking, ip, response, data ) for _, pattern in ipairs( nmap.registry.whois.m_err ) do msg = response:match( pattern ) if msg then - stdnse.print_debug( 4, "%s %s %s responded with an ERROR message.", filename, ip, this_db ) + stdnse.print_debug( 4, "%s %s %s responded with an ERROR message.", SCRIPT_NAME, ip, this_db ) break end end @@ -629,7 +629,7 @@ function analyse_response( tracking, ip, response, data ) for setname, set in pairs( nmap.registry.whois.fields_meta ) do if set ~= nmap.registry.whois.whoisdb[this_db].fieldreq and response:match(set.ob_exist) then foreign_obj = setname - stdnse.print_debug( 4, "%s %s %s seems to have responded using the set of objects named: %s.", filename, ip, this_db, foreign_obj ) + stdnse.print_debug( 4, "%s %s %s seems to have responded using the set of objects named: %s.", SCRIPT_NAME, ip, this_db, foreign_obj ) break end end @@ -638,7 +638,7 @@ function analyse_response( tracking, ip, response, data ) meta = nmap.registry.whois.whoisdb.ripe meta.redirects = nil have_objects = true - stdnse.print_debug( 4, "%s %s %s will use the display properties of ripe.", filename, ip, this_db ) + stdnse.print_debug( 4, "%s %s %s will use the display properties of ripe.", SCRIPT_NAME, ip, this_db ) elseif foreign_obj then -- find a display to match the objects. for some_db, db_props in pairs( nmap.registry.whois.whoisdb ) do @@ -647,7 +647,7 @@ function analyse_response( tracking, ip, response, data ) meta = nmap.registry.whois.whoisdb[some_db] meta.redirects = nil have_objects = true - stdnse.print_debug( 4, "%s %s %s will use the display properties of %s.", filename, ip, this_db, some_db ) + stdnse.print_debug( 4, "%s %s %s will use the display properties of %s.", SCRIPT_NAME, ip, this_db, some_db ) break end end @@ -656,7 +656,7 @@ function analyse_response( tracking, ip, response, data ) -- extract fields from the entire response for record/redirect discovery if have_objects then - stdnse.print_debug( 4, "%s %s Parsing Query response from %s.", filename, ip, this_db ) + stdnse.print_debug( 4, "%s %s Parsing Query response from %s.", SCRIPT_NAME, ip, this_db ) data[this_db] = extract_objects_from_response( response, this_db, ip, meta ) end @@ -664,7 +664,7 @@ function analyse_response( tracking, ip, response, data ) -- do record/redirect discovery, cache found redirect if not nmap.registry.whois.nofollow and have_objects and meta.redirects then - stdnse.print_debug( 4, "%s %s Testing response for redirection.", filename, ip ) + stdnse.print_debug( 4, "%s %s Testing response for redirection.", SCRIPT_NAME, ip ) found, nextdb, data.iana = redirection_rules( this_db, ip, data, meta ) end @@ -672,7 +672,7 @@ function analyse_response( tracking, ip, response, data ) -- modify the data table depending on whether we're redirecting or quitting if have_objects then - stdnse.print_debug( 5, "%s %s Extracting Fields from response.", filename, ip ) + stdnse.print_debug( 5, "%s %s Extracting Fields from response.", SCRIPT_NAME, ip ) -- optionally constrain response to a more focused area -- discarding previous extraction @@ -684,7 +684,7 @@ function analyse_response( tracking, ip, response, data ) end if offset > 1 and meta.unordered then -- fetch an object immediately in front of inetnum - stdnse.print_debug( 5, "%s %s %s Searching for an object group immediately before this range.", filename, ip, this_db ) + stdnse.print_debug( 5, "%s %s %s Searching for an object group immediately before this range.", SCRIPT_NAME, ip, this_db ) -- split objects from the record, up to offset. Last object should be the one we want. local obj_sel = stdnse.strsplit( "\r?\n\r?\n", response:sub( 1, offset ) ) response_chunk = "\n" .. obj_sel[#obj_sel] .. "\n" @@ -716,10 +716,10 @@ function analyse_response( tracking, ip, response, data ) end -- DEBUG - stdnse.print_debug( 6, "%s %s %s Fields captured :", filename, ip, this_db ) + stdnse.print_debug( 6, "%s %s %s Fields captured :", SCRIPT_NAME, ip, this_db ) for ob, t in pairs( data[this_db] ) do for fieldname, fieldvalue in pairs( t ) do - stdnse.print_debug( 6, "%s %s %s %s.%s %s.", filename, ip, this_db, ob, fieldname, fieldvalue ) + stdnse.print_debug( 6, "%s %s %s %s.%s %s.", SCRIPT_NAME, ip, this_db, ob, fieldname, fieldvalue ) end end @@ -807,15 +807,15 @@ function extract_objects_from_response( response_string, db, ip, meta, specific_ -- we either receive a table for one object or for all objects if type( specific_object ) == "string" and meta.fieldreq[specific_object] then objects_to_extract[specific_object] = meta.fieldreq[specific_object] - stdnse.print_debug( 5, "%s %s Extracting a single object: %s.", filename, ip, specific_object ) + stdnse.print_debug( 5, "%s %s Extracting a single object: %s.", SCRIPT_NAME, ip, specific_object ) else - stdnse.print_debug( 5, "%s %s Extracting all objects.", filename, ip ) + stdnse.print_debug( 5, "%s %s Extracting all objects.", SCRIPT_NAME, ip ) objects_to_extract = meta.fieldreq end for object_name, object in pairs( objects_to_extract ) do if object_name and object_name ~= "ob_exist" then - stdnse.print_debug(5, "%s %s Seeking object group: %s.", filename, ip, object_name) + stdnse.print_debug(5, "%s %s Seeking object group: %s.", SCRIPT_NAME, ip, object_name) extracted_objects[object_name] = {} extracted_objects[object_name].for_compare = {} -- this will allow us to compare two tables -- get a substr of response_string that corresponds to a single object @@ -824,7 +824,7 @@ function extract_objects_from_response( response_string, db, ip, meta, specific_ -- if we could not find the end, make the end EOF ob_end = ob_end or -1 if ob_start and ob_end then - stdnse.print_debug(5, "%s %s Capturing: %s with indices %s and %s.", filename, ip, object_name, ob_start, ob_end ) + stdnse.print_debug(5, "%s %s Capturing: %s with indices %s and %s.", SCRIPT_NAME, ip, object_name, ob_start, ob_end ) local obj_string = response_string:sub( ob_start, ob_end ) for fieldname, pattern in pairs( object ) do if fieldname ~= "ob_start" and fieldname ~= "ob_end" then @@ -897,19 +897,19 @@ function redirection_rules( db, ip, data, meta ) -- arin record points to iana so we won't follow and we assume we have our record if directed_to == iana and directed_from == arin then - stdnse.print_debug( 4, "%s %s %s Accept arin record (matched IANA).", filename, ip, directed_from ) + stdnse.print_debug( 4, "%s %s %s Accept arin record (matched IANA).", SCRIPT_NAME, ip, directed_from ) return true, nil, ( icnt+1 ) end -- non-arin record points to iana so we query arin next if directed_to == iana then - stdnse.print_debug( 4, "%s %s Redirecting to arin (matched IANA).", filename, ip ) + stdnse.print_debug( 4, "%s %s Redirecting to arin (matched IANA).", SCRIPT_NAME, ip ) return false, arin, ( icnt+1 ) end -- a redirect, but not to iana or to self, so we follow it. if directed_to ~= nmap.registry.whois.whoisdb[directed_from].id then - stdnse.print_debug( 4, "%s %s %s redirects us to %s.", filename, ip, directed_from, directed_to ) + stdnse.print_debug( 4, "%s %s %s redirects us to %s.", SCRIPT_NAME, ip, directed_from, directed_to ) return false, directed_to, icnt end @@ -925,14 +925,14 @@ function redirection_rules( db, ip, data, meta ) -- if a field has been captured for the given redirect info if data[db][obj] and data[db][obj][fld] then - stdnse.print_debug( 5, "%s %s Seek redirect in object: %s.%s for %s.", filename, ip, obj, fld, pattern ) + stdnse.print_debug( 5, "%s %s Seek redirect in object: %s.%s for %s.", SCRIPT_NAME, ip, obj, fld, pattern ) -- iterate over nmap.registry.whois.whoisdb to find pattern (from each service) in the designated field for member, mem_properties in pairs( nmap.registry.whois.whoisdb ) do -- if pattern if found in the field, we have a redirect to member if type( mem_properties[pattern] ) == "string" and string.lower( data[db][obj][fld] ):match( mem_properties[pattern] ) then - stdnse.print_debug( 5, "%s %s Matched %s in %s.%s.", filename, ip, pattern, obj, fld ) + stdnse.print_debug( 5, "%s %s Matched %s in %s.%s.", SCRIPT_NAME, ip, pattern, obj, fld ) return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count ) elseif type( mem_properties[pattern] ) == "table" then @@ -940,7 +940,7 @@ function redirection_rules( db, ip, data, meta ) -- pattern is an array of patterns for _, pattn in ipairs( mem_properties[pattern] ) do if type( pattn ) == "string" and string.lower( data[db][obj][fld] ):match( pattn ) then - stdnse.print_debug( 5, "%s %s Matched %s in %s.%s.", filename, ip, pattern, obj, fld ) + stdnse.print_debug( 5, "%s %s Matched %s in %s.%s.", SCRIPT_NAME, ip, pattern, obj, fld ) return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count ) end end @@ -994,7 +994,7 @@ function constrain_response( response, db, ip, meta ) if # mptr > 1 then -- find the closest one to host.ip and constrain the response to it - stdnse.print_debug( 5, "%s %s %s Focusing on the smallest of %s address ranges.", filename, ip, db, #mptr ) + stdnse.print_debug( 5, "%s %s %s Focusing on the smallest of %s address ranges.", SCRIPT_NAME, ip, db, #mptr ) -- sort the table mptr into nets ascending table.sort( mptr, smallest_range ) -- select the first net that includes host.ip @@ -1012,15 +1012,15 @@ function constrain_response( response, db, ip, meta ) if mptr[index+1] and ( mptr[index+1].pointer > mptr[index].pointer ) then bound = mptr[index+1].pointer end - stdnse.print_debug(5, "%s %s %s Smallest range containing target IP addr. is %s.", filename, ip, db, trim( str_net ) ) + stdnse.print_debug(5, "%s %s %s Smallest range containing target IP addr. is %s.", SCRIPT_NAME, ip, db, trim( str_net ) ) local dbg = "%s %s %s smallest range is offset from %s to %s." -- isolate inetnum and associated objects if bound then - stdnse.print_debug(5, dbg, filename, ip, db, ptr, bound) + stdnse.print_debug(5, dbg, SCRIPT_NAME, ip, db, ptr, bound) -- get from pointer to bound return response:sub(ptr,bound), ptr else - stdnse.print_debug(5, dbg, filename, ip, db, ptr, "the end") + stdnse.print_debug(5, dbg, SCRIPT_NAME, ip, db, ptr, "the end") -- or get the whole thing from the pointer onwards return response:sub(ptr), ptr end @@ -1062,7 +1062,7 @@ function not_short_prefix( ip, range, redirect ) first, last, err[#err+1] = ipOps.get_ips_from_range( range ) if #err > 0 then - stdnse.print_debug( 1, "%s Error in not_short_prefix: s%.", filename, table.concat( err, " " ) ) + stdnse.print_debug( 1, "%s Error in not_short_prefix: s%.", SCRIPT_NAME, table.concat( err, " " ) ) return nil end @@ -1106,7 +1106,7 @@ function add_to_cache( ip, range, redirect, data ) -- we need to cache some range so we'll cache the small assignment that includes ip. if type( range ) ~= "string" or type( get_prefix_length( range ) ) ~= "number" then range = get_assignment( ip, longest_prefix ) - stdnse.print_debug(5, "%s %s Caching an assumed Range: %s", filename, ip, range) + stdnse.print_debug(5, "%s %s Caching an assumed Range: %s", SCRIPT_NAME, ip, range) end nmap.registry.whois.cache[ip] = {} -- destroy any previous cache entry for this target. @@ -1196,13 +1196,13 @@ function output( ip, services_queried ) end if type( services_queried ) ~= "table" then - stdnse.print_debug( "%s %s Error in output(): No data found.", filename, ip ) + stdnse.print_debug( "%s %s Error in output(): No data found.", SCRIPT_NAME, ip ) return nil elseif #services_queried == 0 then - stdnse.print_debug( "%s %s Error in output(): No data found, no queries were completed.", filename, ip ) + stdnse.print_debug( "%s %s Error in output(): No data found, no queries were completed.", SCRIPT_NAME, ip ) return nil elseif #services_queried > 0 then - stdnse.print_debug( "%s %s Error in output(): No data found - could not understand query responses.", filename, ip ) + stdnse.print_debug( "%s %s Error in output(): No data found - could not understand query responses.", SCRIPT_NAME, ip ) return nil end @@ -1223,7 +1223,7 @@ function get_output_from_cache( ip ) local ip_key = get_cache_key( ip ) if not ip_key then - stdnse.print_debug( 1, "%s %s Error in get_output_from_cache().", filename, ip ) + stdnse.print_debug( 1, "%s %s Error in get_output_from_cache().", SCRIPT_NAME, ip ) return nil end @@ -1672,7 +1672,7 @@ function get_args() nmap.registry.whois.using_cache = false elseif ( db == "nofile" ) then nmap.registry.whois.using_local_assignments_file = false - stdnse.print_debug( 2, "%s: Not using local assignments data.", filename ) + stdnse.print_debug( 2, "%s: Not using local assignments data.", SCRIPT_NAME ) end elseif not ( string.match( table.concat( t, " " ), db ) ) then -- we have a unique valid whois db @@ -1683,18 +1683,18 @@ function get_args() if ( #t > 0 ) and nmap.registry.whois.using_local_assignments_file then -- "nofile" was not explicitly supplied, but it is implied by supplying custom whoisdb_default_order nmap.registry.whois.using_local_assignments_file = false - stdnse.print_debug(3, "%s: Not using local assignments data because custom whoisdb_default_order was supplied.", filename) + stdnse.print_debug(3, "%s: Not using local assignments data because custom whoisdb_default_order was supplied.", SCRIPT_NAME) end if ( #t > 1 ) and nmap.registry.whois.nofollow then -- using nofollow, we do not follow redirects and can only accept what we find as a record therefore we only accept the first db supplied t = {t[1]} - stdnse.print_debug( 1, "%s: Too many args supplied with 'nofollow', only using %s.", filename, t[1] ) + stdnse.print_debug( 1, "%s: Too many args supplied with 'nofollow', only using %s.", SCRIPT_NAME, t[1] ) end if ( #t > 0 ) then nmap.registry.whois.whoisdb_default_order = t - stdnse.print_debug( 2, "%s: whoisdb_default_order: %s.", filename, table.concat( t, " " ) ) + stdnse.print_debug( 2, "%s: whoisdb_default_order: %s.", SCRIPT_NAME, table.concat( t, " " ) ) end end @@ -1723,7 +1723,7 @@ function get_local_assignments_data() local fetchfile = "nmap-services" local directory_path, err = get_parentpath( fetchfile ) if err then - stdnse.print_debug( 1, "%s: Nmap.fetchfile() failed to get a path to %s: %s.", filename, fetchfile, err ) + stdnse.print_debug( 1, "%s: Nmap.fetchfile() failed to get a path to %s: %s.", SCRIPT_NAME, fetchfile, err ) return nil, err end @@ -1739,10 +1739,10 @@ function get_local_assignments_data() local file, exists = directory_path .. assignment_data_spec.local_resource exists, err = file_exists( file ) if not exists and err then - stdnse.print_debug( 1, "%s: Error accessing %s: %s.", filename, file, err ) + stdnse.print_debug( 1, "%s: Error accessing %s: %s.", SCRIPT_NAME, file, err ) elseif not exists then update_required = true - stdnse.print_debug( 2, "%s: %s does not exist or is empty. Fetching it now...", filename, file ) + stdnse.print_debug( 2, "%s: %s does not exist or is empty. Fetching it now...", SCRIPT_NAME, file ) elseif exists then update_required, modified_date, entity_tag = requires_updating( file ) end @@ -1751,7 +1751,7 @@ function get_local_assignments_data() -- read an existing and up-to-date file into file_content. if exists and not update_required then - stdnse.print_debug( 2, "%s: %s was cached less than %s ago. Reading...", filename, file, nmap.registry.whois.local_assignments_file_expiry ) + stdnse.print_debug( 2, "%s: %s was cached less than %s ago. Reading...", SCRIPT_NAME, file, nmap.registry.whois.local_assignments_file_expiry ) file_content = read_from_file( file ) end @@ -1760,10 +1760,10 @@ function get_local_assignments_data() if update_required then http_response = ( conditional_download( assignment_data_spec.remote_resource, modified_date, entity_tag ) ) if not http_response or type( http_response.status ) ~= "number" then - stdnse.print_debug( 1, "%s: Failed whilst requesting %s.", filename, assignment_data_spec.remote_resource ) + stdnse.print_debug( 1, "%s: Failed whilst requesting %s.", SCRIPT_NAME, assignment_data_spec.remote_resource ) elseif http_response.status == 200 then -- prepend our file header - stdnse.print_debug( 2, "%s: Retrieved %s.", filename, assignment_data_spec.remote_resource ) + stdnse.print_debug( 2, "%s: Retrieved %s.", SCRIPT_NAME, assignment_data_spec.remote_resource ) file_content = stdnse.strsplit( "\r?\n", http_response.body ) table.insert( file_content, 1, "** Do Not Alter This Line or The Following Line **" ) local hline = {} @@ -1773,19 +1773,19 @@ function get_local_assignments_data() table.insert( file_content, 2, table.concat( hline ) ) write_success, err = write_to_file( file, file_content ) if err then - stdnse.print_debug( 1, "%s: Error writing %s to %s: %s.", filename, assignment_data_spec.remote_resource, file, err ) + stdnse.print_debug( 1, "%s: Error writing %s to %s: %s.", SCRIPT_NAME, assignment_data_spec.remote_resource, file, err ) end elseif http_response.status == 304 then -- update our file header with a new timestamp - stdnse.print_debug( 1, "%s: %s is up-to-date.", filename, file ) + stdnse.print_debug( 1, "%s: %s is up-to-date.", SCRIPT_NAME, file ) file_content = read_from_file( file ) file_content[2] = file_content[2]:gsub("^<[\-\+]?%d+>(.*)$", "<" .. os.time() .. ">%1") write_success, err = write_to_file( file, file_content ) if err then - stdnse.print_debug( 1, "%s: Error writing to %s: %s.", filename, file, err ) + stdnse.print_debug( 1, "%s: Error writing to %s: %s.", SCRIPT_NAME, file, err ) end else - stdnse.print_debug( 1, "%s: HTTP %s whilst requesting %s.", filename, http_response.status, assignment_data_spec.remote_resource ) + stdnse.print_debug( 1, "%s: HTTP %s whilst requesting %s.", SCRIPT_NAME, http_response.status, assignment_data_spec.remote_resource ) end end @@ -1799,7 +1799,7 @@ function get_local_assignments_data() if #t == 0 or err then -- good header, but bad file? Kill the file! write_to_file( file, "" ) - stdnse.print_debug( 1, "%s: Problem with the data in %s.", filename, file ) + stdnse.print_debug( 1, "%s: Problem with the data in %s.", SCRIPT_NAME, file ) else for i, v in pairs( t ) do ret[address_family][#ret[address_family]+1] = v @@ -1818,7 +1818,7 @@ function get_local_assignments_data() for af, t in pairs( ret ) do if #t == 0 then ret[af] = nil - stdnse.print_debug( 1, "%s: Cannot use local assignments file for address family %s.", filename, af ) + stdnse.print_debug( 1, "%s: Cannot use local assignments file for address family %s.", SCRIPT_NAME, af ) end end @@ -1829,9 +1829,9 @@ end --- --- Uses nmap.fetchfile to get the path of the parent directory of the supplied Nmap datafile filename. +-- Uses nmap.fetchfile to get the path of the parent directory of the supplied Nmap datafile SCRIPT_NAME. -- @param fname String - Filename of an Nmap datafile. --- @return String - The filepath of the directory containing the supplied filename including the trailing slash (or nil in case of an error). +-- @return String - The filepath of the directory containing the supplied SCRIPT_NAME including the trailing slash (or nil in case of an error). -- @return Nil or error message in case of an error. function get_parentpath( fname ) @@ -1940,7 +1940,7 @@ function read_from_file( file ) local f, err, _ = io.open( file, "r" ) if not f then - stdnse.print_debug( 1, "%s: Error opening %s for reading: %s", filename, file, err ) + stdnse.print_debug( 1, "%s: Error opening %s for reading: %s", SCRIPT_NAME, file, err ) return nil, err end @@ -1998,7 +1998,7 @@ function conditional_download( url, mod_date, e_tag ) -- follow one redirection if request_response.status ~= 304 and ( tostring( request_response.status ):match( "30%d" ) and type( request_response.header.location ) == "string" and request_response.header.location ~= "" ) then - stdnse.print_debug( 2, "%s: HTTP Status:%d New Location: %s.", filename, request_response.status, request_response.header.location ) + stdnse.print_debug( 2, "%s: HTTP Status:%d New Location: %s.", SCRIPT_NAME, request_response.status, request_response.header.location ) request_response = http.get_url( request_response.header.location, request_options ) end @@ -2027,7 +2027,7 @@ function write_to_file( file, content ) local f, err, _ = io.open( file, "w" ) if not f then - stdnse.print_debug( 1, "%s: Error opening %s for writing: %s.", filename, file, err ) + stdnse.print_debug( 1, "%s: Error opening %s for writing: %s.", SCRIPT_NAME, file, err ) return nil, err end