1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Merge r18689:r19511 from /nmap-exp/djalal/nse-rules.

o Add two new Script scan phases:
  Script Pre-scanning phase: before any Nmap scan operation, activated by the new "prerule".
  Script Post-scanning phase: after all Nmap scan operations, activated by the new "postrule".
o New environment variables:
  SCRIPT_PATH
  SCRIPT_NAME
  SCRIPT_TYPE: the type of the rule that activated the script.
This commit is contained in:
djalal
2010-08-06 16:40:03 +00:00
parent eb699270e9
commit f0c5e154c3
22 changed files with 403 additions and 160 deletions

View File

@@ -73,8 +73,9 @@
It represents to the topmost element of the output document. It represents to the topmost element of the output document.
--> -->
<!ELEMENT nmaprun (scaninfo*, verbose, debugging, <!ELEMENT nmaprun (scaninfo*, verbose, debugging,
((taskbegin, taskprogress*, taskend) | host | output)*, ((taskbegin, taskprogress*, taskend) |
runstats) > prescripts | postscripts | host | output)*,
runstats) >
<!ATTLIST nmaprun <!ATTLIST nmaprun
scanner (nmap) #REQUIRED scanner (nmap) #REQUIRED
args CDATA #IMPLIED args CDATA #IMPLIED
@@ -332,3 +333,5 @@
> >
<!ELEMENT hostscript ( script+ )> <!ELEMENT hostscript ( script+ )>
<!ELEMENT prescript ( script+ )>
<!ELEMENT postscript ( script+ )>

View File

@@ -244,6 +244,6 @@ struct scan_lists {
int prot_count; 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 */ #endif /*GLOBAL_STRUCTURES_H */

25
nmap.cc
View File

@@ -442,6 +442,10 @@ int nmap_main(int argc, char *argv[]) {
HostGroupState *hstate = NULL; HostGroupState *hstate = NULL;
char *endptr = NULL; char *endptr = NULL;
struct scan_lists ports = { 0 }; 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; TargetGroup *exclude_group = NULL;
char myname[MAXHOSTNAMELEN + 1]; char myname[MAXHOSTNAMELEN + 1];
#if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS)) #if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS))
@@ -1602,6 +1606,13 @@ int nmap_main(int argc, char *argv[]) {
o.scriptversion = 1; o.scriptversion = 1;
if (o.scriptversion || o.script || o.scriptupdatedb) if (o.scriptversion || o.script || o.scriptupdatedb)
open_nse(); 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 #endif
/* Time to create a hostgroup state object filled with all the requested /* 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 #ifndef NOLUA
if(o.script || o.scriptversion) { if(o.script || o.scriptversion) {
script_scan(Targets); script_scan(Targets, SCRIPT_SCAN);
} }
#endif #endif
@@ -1866,6 +1877,14 @@ int nmap_main(int argc, char *argv[]) {
o.numhosts_scanning = 0; o.numhosts_scanning = 0;
} while(!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned); } 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; delete hstate;
if (exclude_group) if (exclude_group)
delete[] exclude_group; delete[] exclude_group;
@@ -2573,7 +2592,9 @@ const char *scantype2str(stype scantype) {
case BOUNCE_SCAN: return "Bounce Scan"; break; case BOUNCE_SCAN: return "Bounce Scan"; break;
case SERVICE_SCAN: return "Service Scan"; break; case SERVICE_SCAN: return "Service Scan"; break;
case OS_SCAN: return "OS 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_SCAN: return "Script Scan"; break;
case SCRIPT_POST_SCAN: return "Script Post-Scan"; break;
case TRACEROUTE: return "Traceroute" ; break; case TRACEROUTE: return "Traceroute" ; break;
default: assert(0); break; default: assert(0); break;
} }
@@ -2795,5 +2816,3 @@ int nmap_fetchfile(char *filename_returned, int bufferlen, const char *file) {
return foundsomething; return foundsomething;
} }

View File

@@ -22,6 +22,11 @@
#define NSE_MAIN "NSE_MAIN" /* the main function */ #define NSE_MAIN "NSE_MAIN" /* the main function */
#define NSE_TRACEBACK "NSE_TRACEBACK" #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 /* These are indices into the registry, for data shared with nse_main.lua. The
definitions here must match those in nse_main.lua. */ definitions here must match those in nse_main.lua. */
#define NSE_YIELD "NSE_YIELD" #define NSE_YIELD "NSE_YIELD"
@@ -37,6 +42,9 @@
extern NmapOps o; 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) static int timedOut (lua_State *L)
{ {
Target *target = get_target(L, 1); Target *target = get_target(L, 1);
@@ -101,6 +109,15 @@ static int ports (lua_State *L)
return 3; 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) static int host_set_output (lua_State *L)
{ {
ScriptResult sr; ScriptResult sr;
@@ -188,6 +205,7 @@ static void open_cnse (lua_State *L)
{"startTimeOutClock", startTimeOutClock}, {"startTimeOutClock", startTimeOutClock},
{"stopTimeOutClock", stopTimeOutClock}, {"stopTimeOutClock", stopTimeOutClock},
{"ports", ports}, {"ports", ports},
{"script_set_output", script_set_output},
{"host_set_output", host_set_output}, {"host_set_output", host_set_output},
{"port_set_output", port_set_output}, {"port_set_output", port_set_output},
{NULL, NULL} {NULL, NULL}
@@ -231,6 +249,11 @@ std::string ScriptResult::get_id (void) const
return id; return id;
} }
ScriptResults *get_script_scan_results_obj (void)
{
return &script_scan_results;
}
/* int panic (lua_State *L) /* int panic (lua_State *L)
* *
* Panic function set via lua_atpanic(). * Panic function set via lua_atpanic().
@@ -333,6 +356,7 @@ static int run_main (lua_State *L)
/* New host group */ /* New host group */
lua_newtable(L); lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); lua_setfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS);
lua_getfield(L, LUA_REGISTRYINDEX, NSE_TRACEBACK); /* index 1 */ 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 */ 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; return 0;
} }
@@ -495,18 +534,16 @@ void open_nse (void)
} }
} }
void script_scan (std::vector<Target *> &targets) void script_scan (std::vector<Target *> &targets, stype scantype)
{ {
o.current_scantype = SCRIPT_SCAN; o.current_scantype = scantype;
assert(L_NSE != NULL); assert(L_NSE != NULL);
lua_settop(L_NSE, 0); /* clear the stack */ lua_settop(L_NSE, 0); /* clear the stack */
if (lua_cpcall(L_NSE, run_main, (void *) &targets) != 0) if (lua_cpcall(L_NSE, run_main, (void *) &targets) != 0)
{
error("%s: Script Engine Scan Aborted.\nAn error was thrown by the " error("%s: Script Engine Scan Aborted.\nAn error was thrown by the "
"engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1)); "engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1));
}
} }
void close_nse (void) void close_nse (void)

View File

@@ -13,6 +13,9 @@ extern "C" {
#include "lauxlib.h" #include "lauxlib.h"
} }
#include "nmap.h"
#include "global_structures.h"
class ScriptResult class ScriptResult
{ {
private: private:
@@ -27,6 +30,10 @@ class ScriptResult
typedef std::list<ScriptResult> ScriptResults; typedef std::list<ScriptResult> 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; class Target;
@@ -39,7 +46,7 @@ void nse_selectedbyname (lua_State *);
void nse_gettarget (lua_State *, int); void nse_gettarget (lua_State *, int);
void open_nse (void); void open_nse (void);
void script_scan (std::vector<Target *> &targets); void script_scan (std::vector<Target *> &targets, stype scantype);
void close_nse (void); void close_nse (void);
#define SCRIPT_ENGINE "NSE" #define SCRIPT_ENGINE "NSE"

View File

@@ -32,6 +32,11 @@
local NAME = "NSE"; 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. -- String keys into the registry (_R), for data shared with nse_main.cc.
local YIELD = "NSE_YIELD"; local YIELD = "NSE_YIELD";
local BASE = "NSE_BASE"; local BASE = "NSE_BASE";
@@ -107,6 +112,14 @@ local stdnse = require "stdnse";
-- differentiate between yields initiated by NSE or regular coroutine yields. -- differentiate between yields initiated by NSE or regular coroutine yields.
local NSE_YIELD_VALUE = {}; local NSE_YIELD_VALUE = {};
-- Table of different supported rules.
local NSE_SCRIPT_RULES = {
prerule = "prerule",
hostrule = "hostrule",
portrule = "portrule",
postrule = "postrule",
};
do do
-- This is the method by which we allow a script to have nested -- 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 -- 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. -- Outputs debug information at level 1 or higher.
-- Changes "%THREAD" with an appropriate identifier for the debug level -- Changes "%THREAD" with an appropriate identifier for the debug level
function Thread:d (fmt, ...) function Thread:d (fmt, ...)
if debugging() > 1 then local against;
print_debug(1, gsub(fmt, "%%THREAD", self.info), ...); 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 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
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; local ch = self.close_handlers;
for key, destructor_t in pairs(ch) do for key, destructor_t in pairs(ch) do
destructor_t.destructor(destructor_t.thread, key); destructor_t.destructor(destructor_t.thread, key);
@@ -210,11 +288,13 @@ do
-- Returns: -- Returns:
-- thread The thread (class) is returned, or nil. -- thread The thread (class) is returned, or nil.
function Script:new_thread (rule, ...) 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? if not self[rule] then return nil end -- No rule for this script?
local file_closure = self.file_closure; local file_closure = self.file_closure;
local env = setmetatable({ local env = setmetatable({
filename = self.filename, SCRIPT_PATH = self.filename,
SCRIPT_NAME = self.short_basename,
SCRIPT_TYPE = script_type,
}, {__index = _G}); }, {__index = _G});
setfenv(file_closure, env); setfenv(file_closure, env);
local unique_value = {}; -- to test valid yield local unique_value = {}; -- to test valid yield
@@ -238,7 +318,7 @@ do
env = env, env = env,
identifier = tostring(co), identifier = tostring(co),
info = format("'%s' (%s)", self.short_basename, tostring(co)); info = format("'%s' (%s)", self.short_basename, tostring(co));
type = rule == "hostrule" and "host" or "port", type = script_type,
close_handlers = {}, close_handlers = {},
}, { }, {
__metatable = Thread, __metatable = Thread,
@@ -291,10 +371,19 @@ do
type(field).."', expected type '"..t.."'"); type(field).."', expected type '"..t.."'");
end end
end end
-- Check one of two required rule functions exists -- Check the required rule functions
local hostrule, portrule = rawget(env, "hostrule"), rawget(env, "portrule"); local rules = {}
assert(type(hostrule) == "function" or type(portrule) == "function", for rule in pairs(NSE_SCRIPT_RULES) do
filename.." is missing a required function: 'hostrule' or 'portrule'"); 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 -- Assert that categories is an array of strings
for i, category in ipairs(rawget(env, "categories")) do for i, category in ipairs(rawget(env, "categories")) do
assert(type(category) == "string", assert(type(category) == "string",
@@ -314,8 +403,10 @@ do
filename, filename,
id = match(filename, "^.-[/\\]([^\\/]-)%.nse$") or filename, id = match(filename, "^.-[/\\]([^\\/]-)%.nse$") or filename,
file_closure = file_closure, file_closure = file_closure,
hostrule = type(hostrule) == "function" and hostrule or nil, prerule = prerule,
portrule = type(portrule) == "function" and portrule or nil, hostrule = hostrule,
portrule = portrule,
postrule = postrule,
args = {n = 0}; args = {n = 0};
categories = rawget(env, "categories"), categories = rawget(env, "categories"),
author = rawget(env, "author"), author = rawget(env, "author"),
@@ -518,26 +609,24 @@ end
-- The main loop function for NSE. It handles running all the script threads. -- The main loop function for NSE. It handles running all the script threads.
-- Arguments: -- Arguments:
-- threads An array of threads (a runlevel) to run. -- 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 -- running scripts may be resumed at any time. waiting scripts are
-- yielded until Nsock wakes them. After being awakened with -- yielded until Nsock wakes them. After being awakened with
-- nse_restore, waiting threads become pending and later are moved all -- nse_restore, waiting threads become pending and later are moved all
-- at once back to running. -- at once back to running.
local running, waiting, pending = {}, {}, {}; local running, waiting, pending = {}, {}, {};
local all = setmetatable({}, {__mode = "kv"}); -- base coroutine to Thread local all = setmetatable({}, {__mode = "kv"}); -- base coroutine to Thread
-- hosts maps a host to a list of threads for that host. local current; -- The currently running Thread.
local hosts, total = {}, 0; local total = 0; -- Number of threads, for record keeping.
local current; local timeouts = {}; -- A list to save and to track scripts timeout.
local progress = cnse.scan_progress_meter(NAME); local progress = cnse.scan_progress_meter(NAME);
print_debug(1, "NSE Script Threads (%d) running:", #threads); print_debug(1, "NSE Script Threads (%d) running:", #threads);
while #threads > 0 do while #threads > 0 do
local thread = remove(threads); 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; all[thread.co], running[thread.co], total = thread, thread, total+1;
hosts[thread.host] = hosts[thread.host] or {}; thread:start(timeouts);
hosts[thread.host][thread.co] = true;
end end
-- Map of yielded threads to the base Thread -- Map of yielded threads to the base Thread
@@ -586,9 +675,11 @@ local function run (threads)
current.parent.info, tostring(co)); current.parent.info, tostring(co));
local thread = { local thread = {
co = co, co = co,
id = current.id,
args = {n = select("#", ...), ...}, args = {n = select("#", ...), ...},
host = current.host, host = current.host,
port = current.port, port = current.port,
type = current.type,
parent = current.parent, parent = current.parent,
info = format("'%s' worker (%s)", current.short_basename, tostring(co)); info = format("'%s' worker (%s)", current.short_basename, tostring(co));
-- d = function(...) end, -- output no debug information -- d = function(...) end, -- output no debug information
@@ -633,28 +724,28 @@ local function run (threads)
end end
end end
-- Checked for timed-out hosts. -- Checked for timed-out scripts and hosts.
for co, thread in pairs(waiting) do for co, thread in pairs(waiting) do
if cnse.timedOut(thread.host) then if thread:timed_out() then
waiting[co], all[co] = nil, nil; waiting[co], all[co] = nil, nil;
thread:d("%THREAD %s%s timed out", thread.host.ip, thread:d("%THREAD %stimed out", thread.host
thread.port and ":"..thread.port.number or ""); and format("%s%s ", thread.host.ip,
thread:close(); thread.port and ":"..thread.port.number or "")
or "");
thread:close(timeouts, "timed out");
end end
end end
for co, thread in pairs(running) do for co, thread in pairs(running) do
current, running[co] = thread, nil; 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)); local s, result = resume(co, unpack(thread.args, 1, thread.args.n));
if not s then -- script error... if not s then -- script error...
hosts[thread.host][co], all[co] = nil, nil; all[co] = nil;
thread:d("%THREAD against %s%s threw an error!\n%s\n", thread:d("%THREAD_AGAINST threw an error!\n%s\n",
thread.host.ip, thread.port and ":"..thread.port.number or "",
traceback(co, tostring(result))); traceback(co, tostring(result)));
thread.error = result; thread:close(timeouts, result);
thread:close();
elseif status(co) == "suspended" then elseif status(co) == "suspended" then
if result == NSE_YIELD_VALUE then if result == NSE_YIELD_VALUE then
waiting[co] = thread; waiting[co] = thread;
@@ -663,7 +754,7 @@ local function run (threads)
thread:close(); thread:close();
end end
elseif status(co) == "dead" then elseif status(co) == "dead" then
hosts[thread.host][co], all[co] = nil, nil; all[co] = nil;
if type(result) == "string" then if type(result) == "string" then
-- Escape any character outside the range 32-126 except for tab, -- Escape any character outside the range 32-126 except for tab,
-- carriage return, and line feed. This makes the string safe for -- 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) result = gsub(result, "[^\t\r\n\032-\126]", function(a)
return format("\\x%02X", byte(a)); return format("\\x%02X", byte(a));
end); end);
if thread.type == "host" then thread:set_output(result);
cnse.host_set_output(thread.host, thread.id, result);
else
cnse.port_set_output(thread.host, thread.port, thread.id, result);
end
end end
thread:d("Finished %THREAD against %s%s.", thread.host.ip, thread:d("Finished %THREAD_AGAINST.");
thread.port and ":"..thread.port.number or ""); thread:close(timeouts);
thread:close();
end
-- Any more threads running for this host?
if not next(hosts[thread.host]) then
cnse.stopTimeOutClock(thread.host);
end end
end end
@@ -804,45 +885,104 @@ for i, script in ipairs(chosen_scripts) do
end end
-- main(hosts) -- main(hosts)
-- This is the main function we return to NSE (on the C side) which actually -- This is the main function we return to NSE (on the C side), nse_main.cc
-- runs a scan against an array of hosts. nse_main.cc gets this function -- gets this function by loading and executing nse_main.lua. This
-- by loading and executing nse_main.lua. -- function runs a script scan phase according to its arguments.
-- Arguments: -- Arguments:
-- hosts An array of hosts to scan. -- hosts An array of hosts to scan.
return function (hosts) -- scantype A string that indicates the current script scan phase.
if #hosts > 1 then -- Possible string values are:
print_verbose(1, "Script scanning %d hosts.", #hosts); -- "SCRIPT_PRE_SCAN"
elseif #hosts == 1 then -- "SCRIPT_SCAN"
print_verbose(1, "Script scanning %s.", hosts[1].ip); -- "SCRIPT_POST_SCAN"
end return function (hosts, scantype)
-- Used to set up the runlevels.
-- Set up the runlevels.
local threads, 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 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 if thread then
local runlevel = thread.runlevel; local runlevel = thread.runlevel;
if threads[runlevel] == nil then insert(runlevels, runlevel); end if threads[runlevel] == nil then insert(runlevels, runlevel); end
threads[runlevel] = threads[runlevel] or {}; threads[runlevel] = threads[runlevel] or {};
insert(threads[runlevel], thread); insert(threads[runlevel], thread);
thread.args, thread.host = {n = 1, tcopy(host)}, host; thread.args = {n = 0};
end end
end end
-- Check portrules for this host. -- activate hostrule and portrule scripts
for port in cnse.ports(host) do 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 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 if thread then
local runlevel = thread.runlevel; local runlevel = thread.runlevel;
if threads[runlevel] == nil then insert(runlevels, runlevel); end if threads[runlevel] == nil then insert(runlevels, runlevel); end
threads[runlevel] = threads[runlevel] or {}; threads[runlevel] = threads[runlevel] or {};
insert(threads[runlevel], thread); insert(threads[runlevel], thread);
thread.args, thread.host, thread.port = thread.args, thread.host = {n = 1, tcopy(host)}, host;
{n = 2, tcopy(host), tcopy(port)}, host, port;
end end
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
end end
@@ -850,7 +990,7 @@ return function (hosts)
for i, runlevel in ipairs(runlevels) do for i, runlevel in ipairs(runlevels) do
print_verbose(1, "Starting runlevel %u (of %u) scan.", runlevel, print_verbose(1, "Starting runlevel %u (of %u) scan.", runlevel,
#runlevels); #runlevels);
run(threads[runlevel]); run(threads[runlevel], scantype);
end end
collectgarbage "collect"; collectgarbage "collect";

View File

@@ -1918,6 +1918,35 @@ void printserviceinfooutput(Target * currenths) {
} }
#ifndef NOLUA #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) { void printhostscriptresults(Target * currenths) {
ScriptResults::iterator iter; ScriptResults::iterator iter;
char *script_output; char *script_output;

View File

@@ -213,6 +213,9 @@ void printosscanoutput(Target *currenths);
service scan (if it was performed) */ service scan (if it was performed) */
void printserviceinfooutput(Target *currenths); 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); void printhostscriptresults(Target *currenths);
/* Print a table with traceroute hops. */ /* Print a table with traceroute hops. */

View File

@@ -209,7 +209,7 @@ function ip_to_asn( query )
local status, decoded_response = dns.query( query, options) local status, decoded_response = dns.query( query, options)
if not status then 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 end
return status, decoded_response return status, decoded_response

View File

@@ -56,7 +56,7 @@ function grab_banner(host, port)
if not status then if not status then
local errlvl = { ["EOF"]=3,["TIMEOUT"]=3,["ERROR"]=2 } 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", 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 return nil
end end
@@ -87,8 +87,7 @@ function output( out )
if type(out) ~= "string" or out == "" then return nil end if type(out) ~= "string" or out == "" then return nil end
-- convert filename from full filepath to filename -extn local filename = SCRIPT_NAME
local filename = filename:match( "[\\/]([^\\/]+)\.nse$" )
local line_len = 75 -- The character width of command/shell prompt window. 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 local fline_offset = 5 -- number of chars excluding script id not available to the script on the first line

View File

@@ -57,7 +57,8 @@ action = function(host, port)
end end
if not pcall(require,'openssl') then 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 return
end end

View File

@@ -150,13 +150,12 @@ end
-- @return nil -- @return nil
function init() function init()
local filename = filename and filename:match( "[\\/]([^\\/]+)\.nse$" ) or ""
local customlist = nmap.registry.args.users or local customlist = nmap.registry.args.users or
(nmap.registry.args.userdir and nmap.registry.args.userdir.users) or (nmap.registry.args.userdir and nmap.registry.args.userdir.users) or
nmap.registry.args['userdir.users'] nmap.registry.args['userdir.users']
local read, usernames = datafiles.parse_file(customlist or "nselib/data/usernames.lst", {}) local read, usernames = datafiles.parse_file(customlist or "nselib/data/usernames.lst", {})
if not read then 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.") usernames or "Unknown Error reading usernames list.")
nmap.registry.userdir = {} nmap.registry.userdir = {}
return nil return nil
@@ -164,7 +163,7 @@ function init()
-- random dummy username to catch false positives (not necessary) -- random dummy username to catch false positives (not necessary)
-- if #usernames > 0 then table.insert(usernames, 1, randomstring()) end -- if #usernames > 0 then table.insert(usernames, 1, randomstring()) end
nmap.registry.userdir = usernames 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 return nil
end end

View File

@@ -34,7 +34,7 @@ action = function(host, port)
end end
return stdnse.strjoin(" ", capstrings) return stdnse.strjoin(" ", capstrings)
elseif type(err) == "string" then 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 return
else else
return "server doesn't support CAPABILITIES" return "server doesn't support CAPABILITIES"

View File

@@ -28,7 +28,8 @@ require 'unpwdb'
if not pcall(require,"openssl") then if not pcall(require,"openssl") then
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -35,7 +35,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"}
if not pcall(require,"openssl") then if not pcall(require,"openssl") then
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -41,7 +41,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"}
if not pcall(require,"openssl") then if not pcall(require,"openssl") then
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -49,7 +49,8 @@ dependencies = {"mysql-brute", "mysql-empty-password"}
if not pcall(require,"openssl") then if not pcall(require,"openssl") then
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -43,7 +43,8 @@ if pcall(require,"openssl") then
else else
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -44,7 +44,7 @@ action = function(host, port)
end end
return stdnse.strjoin(" ", capstrings) return stdnse.strjoin(" ", capstrings)
elseif type(err) == "string" then 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 return
else else
return "server doesn't support CAPA" return "server doesn't support CAPA"

View File

@@ -233,7 +233,7 @@ action = function(host, port)
end end
if #injectable > 0 then 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 -- test all potentially vulnerable queries
injectableQs = build_injection_vector(injectable) injectableQs = build_injection_vector(injectable)
local responses = inject(host, port, injectableQs) local responses = inject(host, port, injectableQs)

View File

@@ -50,7 +50,8 @@ if pcall(require,"openssl") then
else else
portrule = function() return false end portrule = function() return false end
action = function() 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; return;
end end

View File

@@ -95,7 +95,7 @@ hostrule = function( host )
local is_private, err = ipOps.isPrivate( host.ip ) local is_private, err = ipOps.isPrivate( host.ip )
if is_private == nil then 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 return false
end end
@@ -190,7 +190,7 @@ action = function( host )
status, retval = pcall( get_next_action, tracking, host.ip ) status, retval = pcall( get_next_action, tracking, host.ip )
if not status then 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 else tracking = retval end
if tracking.this_db then if tracking.this_db then
@@ -201,13 +201,13 @@ action = function( host )
-- analyse data -- analyse data
status, retval = pcall( analyse_response, tracking, host.ip, response, data ) status, retval = pcall( analyse_response, tracking, host.ip, response, data )
if not status then 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 else data = retval end
-- get next action -- get next action
status, retval = pcall( get_next_action, tracking, host.ip ) status, retval = pcall( get_next_action, tracking, host.ip )
if not status then 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 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 else tracking = retval end
end end
@@ -340,7 +340,7 @@ function check_response_cache( ip )
-- record found in cache -- record found in cache
return true, nil return true, nil
else 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 end
return false, nil return false, nil
@@ -461,7 +461,7 @@ function get_db_from_assignments( ip )
end end
if not nmap.registry.whois.local_assignments_data or not nmap.registry.whois.local_assignments_data[af] then 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 return nil
end end
@@ -488,14 +488,14 @@ end
function do_query(db, ip) function do_query(db, ip)
if type( db ) ~= "string" or not nmap.registry.whois.whoisdb[db] then 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 return nil
end end
local service = nmap.registry.whois.whoisdb[db] local service = nmap.registry.whois.whoisdb[db]
if type( service.hostname ) ~= "string" or service.hostname == "" then 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 return nil
end end
@@ -511,7 +511,7 @@ function do_query(db, ip)
local socket = nmap.new_socket() local socket = nmap.new_socket()
local catch = function() 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" nmap.registry.whois.mutex[db] "done"
socket:close() socket:close()
end end
@@ -534,7 +534,7 @@ function do_query(db, ip)
socket:close() 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 if #result == 0 then
return nil 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 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 ) have_objects = response:match( meta.fieldreq.ob_exist )
else 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 have_objects = false
end end
-- if we do not recognize objects check for an known error/non-object message -- if we do not recognize objects check for an known error/non-object message
if not have_objects then 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 local tmp, msg
-- may have found our record saying something similar to "No Record Found" -- may have found our record saying something similar to "No Record Found"
for _, pattern in ipairs( nmap.registry.whois.m_none ) do 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() ) local pattern_u = pattern:gsub( "$addr", ip:upper() )
msg = response:match( pattern_l ) or response:match( pattern_u ) msg = response:match( pattern_l ) or response:match( pattern_u )
if msg then 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 break
end end
end end
@@ -610,7 +610,7 @@ function analyse_response( tracking, ip, response, data )
for _, pattern in ipairs( nmap.registry.whois.m_err ) do for _, pattern in ipairs( nmap.registry.whois.m_err ) do
msg = response:match( pattern ) msg = response:match( pattern )
if msg then 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 break
end end
end end
@@ -629,7 +629,7 @@ function analyse_response( tracking, ip, response, data )
for setname, set in pairs( nmap.registry.whois.fields_meta ) do 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 if set ~= nmap.registry.whois.whoisdb[this_db].fieldreq and response:match(set.ob_exist) then
foreign_obj = setname 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 break
end end
end end
@@ -638,7 +638,7 @@ function analyse_response( tracking, ip, response, data )
meta = nmap.registry.whois.whoisdb.ripe meta = nmap.registry.whois.whoisdb.ripe
meta.redirects = nil meta.redirects = nil
have_objects = true 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 elseif foreign_obj then
-- find a display to match the objects. -- find a display to match the objects.
for some_db, db_props in pairs( nmap.registry.whois.whoisdb ) do 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 = nmap.registry.whois.whoisdb[some_db]
meta.redirects = nil meta.redirects = nil
have_objects = true 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 break
end end
end end
@@ -656,7 +656,7 @@ function analyse_response( tracking, ip, response, data )
-- extract fields from the entire response for record/redirect discovery -- extract fields from the entire response for record/redirect discovery
if have_objects then 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 ) data[this_db] = extract_objects_from_response( response, this_db, ip, meta )
end end
@@ -664,7 +664,7 @@ function analyse_response( tracking, ip, response, data )
-- do record/redirect discovery, cache found redirect -- do record/redirect discovery, cache found redirect
if not nmap.registry.whois.nofollow and have_objects and meta.redirects then 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 ) found, nextdb, data.iana = redirection_rules( this_db, ip, data, meta )
end end
@@ -672,7 +672,7 @@ function analyse_response( tracking, ip, response, data )
-- modify the data table depending on whether we're redirecting or quitting -- modify the data table depending on whether we're redirecting or quitting
if have_objects then 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 -- optionally constrain response to a more focused area
-- discarding previous extraction -- discarding previous extraction
@@ -684,7 +684,7 @@ function analyse_response( tracking, ip, response, data )
end end
if offset > 1 and meta.unordered then if offset > 1 and meta.unordered then
-- fetch an object immediately in front of inetnum -- 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. -- 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 ) ) local obj_sel = stdnse.strsplit( "\r?\n\r?\n", response:sub( 1, offset ) )
response_chunk = "\n" .. obj_sel[#obj_sel] .. "\n" response_chunk = "\n" .. obj_sel[#obj_sel] .. "\n"
@@ -716,10 +716,10 @@ function analyse_response( tracking, ip, response, data )
end end
-- DEBUG -- 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 ob, t in pairs( data[this_db] ) do
for fieldname, fieldvalue in pairs( t ) 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
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 -- we either receive a table for one object or for all objects
if type( specific_object ) == "string" and meta.fieldreq[specific_object] then if type( specific_object ) == "string" and meta.fieldreq[specific_object] then
objects_to_extract[specific_object] = meta.fieldreq[specific_object] 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 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 objects_to_extract = meta.fieldreq
end end
for object_name, object in pairs( objects_to_extract ) do for object_name, object in pairs( objects_to_extract ) do
if object_name and object_name ~= "ob_exist" then 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] = {}
extracted_objects[object_name].for_compare = {} -- this will allow us to compare two tables 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 -- 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 -- if we could not find the end, make the end EOF
ob_end = ob_end or -1 ob_end = ob_end or -1
if ob_start and ob_end then 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 ) local obj_string = response_string:sub( ob_start, ob_end )
for fieldname, pattern in pairs( object ) do for fieldname, pattern in pairs( object ) do
if fieldname ~= "ob_start" and fieldname ~= "ob_end" then 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 -- 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 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 ) return true, nil, ( icnt+1 )
end end
-- non-arin record points to iana so we query arin next -- non-arin record points to iana so we query arin next
if directed_to == iana then 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 ) return false, arin, ( icnt+1 )
end end
-- a redirect, but not to iana or to self, so we follow it. -- a redirect, but not to iana or to self, so we follow it.
if directed_to ~= nmap.registry.whois.whoisdb[directed_from].id then 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 return false, directed_to, icnt
end end
@@ -925,14 +925,14 @@ function redirection_rules( db, ip, data, meta )
-- if a field has been captured for the given redirect info -- if a field has been captured for the given redirect info
if data[db][obj] and data[db][obj][fld] then 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 -- 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 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 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 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 ) return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count )
elseif type( mem_properties[pattern] ) == "table" then elseif type( mem_properties[pattern] ) == "table" then
@@ -940,7 +940,7 @@ function redirection_rules( db, ip, data, meta )
-- pattern is an array of patterns -- pattern is an array of patterns
for _, pattn in ipairs( mem_properties[pattern] ) do for _, pattn in ipairs( mem_properties[pattern] ) do
if type( pattn ) == "string" and string.lower( data[db][obj][fld] ):match( pattn ) then 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 ) return redirection_validation( nmap.registry.whois.whoisdb[member].id, db, iana_count )
end end
end end
@@ -994,7 +994,7 @@ function constrain_response( response, db, ip, meta )
if # mptr > 1 then if # mptr > 1 then
-- find the closest one to host.ip and constrain the response to it -- 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 -- sort the table mptr into nets ascending
table.sort( mptr, smallest_range ) table.sort( mptr, smallest_range )
-- select the first net that includes host.ip -- 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 if mptr[index+1] and ( mptr[index+1].pointer > mptr[index].pointer ) then
bound = mptr[index+1].pointer bound = mptr[index+1].pointer
end 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." local dbg = "%s %s %s smallest range is offset from %s to %s."
-- isolate inetnum and associated objects -- isolate inetnum and associated objects
if bound then 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 -- get from pointer to bound
return response:sub(ptr,bound), ptr return response:sub(ptr,bound), ptr
else 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 -- or get the whole thing from the pointer onwards
return response:sub(ptr), ptr return response:sub(ptr), ptr
end end
@@ -1062,7 +1062,7 @@ function not_short_prefix( ip, range, redirect )
first, last, err[#err+1] = ipOps.get_ips_from_range( range ) first, last, err[#err+1] = ipOps.get_ips_from_range( range )
if #err > 0 then 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 return nil
end 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. -- 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 if type( range ) ~= "string" or type( get_prefix_length( range ) ) ~= "number" then
range = get_assignment( ip, longest_prefix ) 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 end
nmap.registry.whois.cache[ip] = {} -- destroy any previous cache entry for this target. nmap.registry.whois.cache[ip] = {} -- destroy any previous cache entry for this target.
@@ -1196,13 +1196,13 @@ function output( ip, services_queried )
end end
if type( services_queried ) ~= "table" then 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 return nil
elseif #services_queried == 0 then 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 return nil
elseif #services_queried > 0 then 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 return nil
end end
@@ -1223,7 +1223,7 @@ function get_output_from_cache( ip )
local ip_key = get_cache_key( ip ) local ip_key = get_cache_key( ip )
if not ip_key then 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 return nil
end end
@@ -1672,7 +1672,7 @@ function get_args()
nmap.registry.whois.using_cache = false nmap.registry.whois.using_cache = false
elseif ( db == "nofile" ) then elseif ( db == "nofile" ) then
nmap.registry.whois.using_local_assignments_file = false 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 end
elseif not ( string.match( table.concat( t, " " ), db ) ) then elseif not ( string.match( table.concat( t, " " ), db ) ) then
-- we have a unique valid whois db -- 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 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 -- "nofile" was not explicitly supplied, but it is implied by supplying custom whoisdb_default_order
nmap.registry.whois.using_local_assignments_file = false 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 end
if ( #t > 1 ) and nmap.registry.whois.nofollow then 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 -- 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]} 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 end
if ( #t > 0 ) then if ( #t > 0 ) then
nmap.registry.whois.whoisdb_default_order = t 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
end end
@@ -1723,7 +1723,7 @@ function get_local_assignments_data()
local fetchfile = "nmap-services" local fetchfile = "nmap-services"
local directory_path, err = get_parentpath( fetchfile ) local directory_path, err = get_parentpath( fetchfile )
if err then 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 return nil, err
end end
@@ -1739,10 +1739,10 @@ function get_local_assignments_data()
local file, exists = directory_path .. assignment_data_spec.local_resource local file, exists = directory_path .. assignment_data_spec.local_resource
exists, err = file_exists( file ) exists, err = file_exists( file )
if not exists and err then 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 elseif not exists then
update_required = true 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 elseif exists then
update_required, modified_date, entity_tag = requires_updating( file ) update_required, modified_date, entity_tag = requires_updating( file )
end end
@@ -1751,7 +1751,7 @@ function get_local_assignments_data()
-- read an existing and up-to-date file into file_content. -- read an existing and up-to-date file into file_content.
if exists and not update_required then 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 ) file_content = read_from_file( file )
end end
@@ -1760,10 +1760,10 @@ function get_local_assignments_data()
if update_required then if update_required then
http_response = ( conditional_download( assignment_data_spec.remote_resource, modified_date, entity_tag ) ) http_response = ( conditional_download( assignment_data_spec.remote_resource, modified_date, entity_tag ) )
if not http_response or type( http_response.status ) ~= "number" then 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 elseif http_response.status == 200 then
-- prepend our file header -- 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 ) file_content = stdnse.strsplit( "\r?\n", http_response.body )
table.insert( file_content, 1, "** Do Not Alter This Line or The Following Line **" ) table.insert( file_content, 1, "** Do Not Alter This Line or The Following Line **" )
local hline = {} local hline = {}
@@ -1773,19 +1773,19 @@ function get_local_assignments_data()
table.insert( file_content, 2, table.concat( hline ) ) table.insert( file_content, 2, table.concat( hline ) )
write_success, err = write_to_file( file, file_content ) write_success, err = write_to_file( file, file_content )
if err then 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 end
elseif http_response.status == 304 then elseif http_response.status == 304 then
-- update our file header with a new timestamp -- 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 = read_from_file( file )
file_content[2] = file_content[2]:gsub("^<[\-\+]?%d+>(.*)$", "<" .. os.time() .. ">%1") file_content[2] = file_content[2]:gsub("^<[\-\+]?%d+>(.*)$", "<" .. os.time() .. ">%1")
write_success, err = write_to_file( file, file_content ) write_success, err = write_to_file( file, file_content )
if err then 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 end
else 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
end end
@@ -1799,7 +1799,7 @@ function get_local_assignments_data()
if #t == 0 or err then if #t == 0 or err then
-- good header, but bad file? Kill the file! -- good header, but bad file? Kill the file!
write_to_file( 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 else
for i, v in pairs( t ) do for i, v in pairs( t ) do
ret[address_family][#ret[address_family]+1] = v ret[address_family][#ret[address_family]+1] = v
@@ -1818,7 +1818,7 @@ function get_local_assignments_data()
for af, t in pairs( ret ) do for af, t in pairs( ret ) do
if #t == 0 then if #t == 0 then
ret[af] = nil 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
end end
@@ -1829,9 +1829,9 @@ end
--- ---
-- Uses <code>nmap.fetchfile</code> to get the path of the parent directory of the supplied Nmap datafile filename. -- Uses <code>nmap.fetchfile</code> to get the path of the parent directory of the supplied Nmap datafile SCRIPT_NAME.
-- @param fname String - Filename of an Nmap datafile. -- @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. -- @return Nil or error message in case of an error.
function get_parentpath( fname ) function get_parentpath( fname )
@@ -1940,7 +1940,7 @@ function read_from_file( file )
local f, err, _ = io.open( file, "r" ) local f, err, _ = io.open( file, "r" )
if not f then 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 return nil, err
end end
@@ -1998,7 +1998,7 @@ function conditional_download( url, mod_date, e_tag )
-- follow one redirection -- follow one redirection
if request_response.status ~= 304 and ( tostring( request_response.status ):match( "30%d" ) and 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 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 ) request_response = http.get_url( request_response.header.location, request_options )
end end
@@ -2027,7 +2027,7 @@ function write_to_file( file, content )
local f, err, _ = io.open( file, "w" ) local f, err, _ = io.open( file, "w" )
if not f then 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 return nil, err
end end