mirror of
https://github.com/nmap/nmap.git
synced 2026-01-06 14:39:03 +00:00
Initialize one global Lua state for running script scans, and reuse it in calls
to script_scan. This makes the NSE registry persist though all host groups.
This commit is contained in:
1
nmap.cc
1
nmap.cc
@@ -1916,6 +1916,7 @@ void nmap_free_mem() {
|
||||
if (o.extra_payload) free(o.extra_payload);
|
||||
if (o.ipoptions) free(o.ipoptions);
|
||||
#ifndef NOLUA
|
||||
script_scan_free();
|
||||
free(o.scriptargs);
|
||||
#endif
|
||||
}
|
||||
|
||||
133
nse_main.cc
133
nse_main.cc
@@ -219,20 +219,69 @@ int script_check_args (void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize a global Lua state used to run scripts. This initializes the
|
||||
* state, parses script arguments from the command line, and loads port and host
|
||||
* rules. This only needs to be done once per execution of Nmap. */
|
||||
static int init_script_state(lua_State *L) {
|
||||
std::vector<std::string>::iterator script_iter;
|
||||
int status;
|
||||
|
||||
/* Call init_lua to load librarie, set up errfunc, and other things. */
|
||||
status = lua_cpcall(L, init_lua, NULL);
|
||||
if (status != 0) {
|
||||
error("%s: error while initializing Lua State:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
}
|
||||
|
||||
/* Set any script arguments. */
|
||||
status = lua_cpcall(L, init_setargs, NULL);
|
||||
if (status != 0) {
|
||||
error("%s: error while setting arguments for scripts:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
}
|
||||
|
||||
/* Get the error function to use with the lua_pcall of init_rules. */
|
||||
/* errfunc is stored in the registry by init_lua. */
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, errfunc);
|
||||
lua_pushcclosure(L, init_rules, 0);
|
||||
/* We need room for the list of scripts. */
|
||||
if (!lua_checkstack(L, o.chosenScripts.size())) {
|
||||
error("%s: stack overflow at %s:%d", SCRIPT_ENGINE, __FILE__, __LINE__);
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
}
|
||||
/* Push each of the selected scripts. */
|
||||
for (script_iter = o.chosenScripts.begin();
|
||||
script_iter != o.chosenScripts.end();
|
||||
script_iter++) {
|
||||
lua_pushstring(L, script_iter->c_str());
|
||||
}
|
||||
/* Call init_rules using the error function at index 1. */
|
||||
status = lua_pcall(L, o.chosenScripts.size(), 0, 1);
|
||||
if (status != 0) {
|
||||
error("%s: error while initializing script rules:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
}
|
||||
/* Pop the error function. */
|
||||
lua_pop(L, 1);
|
||||
|
||||
return SCRIPT_ENGINE_SUCCESS;
|
||||
}
|
||||
|
||||
/* The global Lua state in which scripts are run. It has file-level scope so it
|
||||
* and the NSE registry it contains can persist across calls to script_scan. */
|
||||
static lua_State* L = NULL;
|
||||
|
||||
/* open a lua instance
|
||||
* open the lua standard libraries
|
||||
* open all the scripts and prepare them for execution
|
||||
* (export nmap bindings, add them to host/port rulesets etc.)
|
||||
* apply all scripts on all hosts
|
||||
* */
|
||||
* apply all scripts on all hosts */
|
||||
int script_scan(std::vector<Target*> &targets) {
|
||||
int status;
|
||||
std::vector<Target*>::iterator target_iter;
|
||||
std::list<std::list<struct thread_record> >::iterator runlevel_iter;
|
||||
std::list<struct thread_record>::iterator thr_iter;
|
||||
std::list<struct thread_record> torun_threads;
|
||||
std::vector<std::string>::iterator script_iter;
|
||||
lua_State* L;
|
||||
|
||||
o.current_scantype = SCRIPT_SCAN;
|
||||
|
||||
@@ -251,58 +300,18 @@ int script_scan(std::vector<Target*> &targets) {
|
||||
SCRIPT_ENGINE, (*targets.begin())->NameIP(targetstr, sizeof(targetstr)));
|
||||
)
|
||||
|
||||
L = luaL_newstate();
|
||||
/* Initialize the script scanning state if it hasn't been already. */
|
||||
if (L == NULL) {
|
||||
error("%s: Failed luaL_newstate()", SCRIPT_ENGINE);
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
L = luaL_newstate();
|
||||
if (L == NULL) {
|
||||
error("%s: Failed luaL_newstate()", SCRIPT_ENGINE);
|
||||
return SCRIPT_ENGINE_ERROR;
|
||||
}
|
||||
lua_atpanic(L, panic);
|
||||
status = init_script_state(L);
|
||||
if (status != SCRIPT_ENGINE_SUCCESS)
|
||||
goto finishup;
|
||||
}
|
||||
lua_atpanic(L, panic);
|
||||
|
||||
status = lua_cpcall(L, init_lua, NULL);
|
||||
if (status != 0)
|
||||
{
|
||||
error("%s: error while initializing Lua State:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
status = SCRIPT_ENGINE_ERROR;
|
||||
goto finishup;
|
||||
}
|
||||
|
||||
//set the arguments - if provided
|
||||
status = lua_cpcall(L, init_setargs, NULL);
|
||||
if (status != 0)
|
||||
{
|
||||
error("%s: error while setting arguments for scripts:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
status = SCRIPT_ENGINE_ERROR;
|
||||
goto finishup;
|
||||
}
|
||||
|
||||
|
||||
/* Get the error function to use with the lua_pcall of init_rules. */
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, errfunc);
|
||||
lua_pushcclosure(L, init_rules, 0);
|
||||
/* We need room for the list of scripts. */
|
||||
if (!lua_checkstack(L, o.chosenScripts.size())) {
|
||||
error("%s: stack overflow at %s:%d", SCRIPT_ENGINE, __FILE__, __LINE__);
|
||||
status = SCRIPT_ENGINE_ERROR;
|
||||
goto finishup;
|
||||
}
|
||||
/* Push each of the selected scripts. */
|
||||
for (script_iter = o.chosenScripts.begin();
|
||||
script_iter != o.chosenScripts.end();
|
||||
script_iter++) {
|
||||
lua_pushstring(L, script_iter->c_str());
|
||||
}
|
||||
/* Call init_rules using the error function at index 1. */
|
||||
status = lua_pcall(L, o.chosenScripts.size(), 0, 1);
|
||||
if (status != 0) {
|
||||
error("%s: error while initializing script rules:\n%s\n",
|
||||
SCRIPT_ENGINE, lua_tostring(L, -1));
|
||||
status = SCRIPT_ENGINE_ERROR;
|
||||
goto finishup;
|
||||
}
|
||||
/* Pop the error function. */
|
||||
lua_pop(L, 1);
|
||||
|
||||
assert(lua_gettop(L) == 0);
|
||||
|
||||
@@ -337,8 +346,7 @@ int script_scan(std::vector<Target*> &targets) {
|
||||
running_scripts.front().runlevel);)
|
||||
|
||||
/* Start the time-out clocks for targets with scripts in this
|
||||
* runlevel. The clock is stopped in process_finalize().
|
||||
*/
|
||||
* runlevel. The clock is stopped in process_finalize(). */
|
||||
for (thr_iter = running_scripts.begin();
|
||||
thr_iter != running_scripts.end();
|
||||
thr_iter++)
|
||||
@@ -356,7 +364,6 @@ finishup:
|
||||
SCRIPT_ENGINE_DEBUGGING(
|
||||
log_write(LOG_STDOUT, "%s: Script scanning completed.\n", SCRIPT_ENGINE);
|
||||
)
|
||||
lua_close(L);
|
||||
torun_scripts.clear();
|
||||
if(status != SCRIPT_ENGINE_SUCCESS) {
|
||||
error("%s: Aborting script scan.", SCRIPT_ENGINE);
|
||||
@@ -366,6 +373,12 @@ finishup:
|
||||
}
|
||||
}
|
||||
|
||||
/* Free global resources associated with script scanning. */
|
||||
void script_scan_free() {
|
||||
if (L != NULL)
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
int process_mainloop(lua_State *L) {
|
||||
int state;
|
||||
int unfinished = running_scripts.size() + waiting_scripts.size();
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef std::vector<ScriptResult> ScriptResults;
|
||||
class Target;
|
||||
int script_scan(std::vector<Target *> &targets);
|
||||
int script_updatedb();
|
||||
void script_scan_free();
|
||||
|
||||
//parses the arguments provided to scripts via nmap's --script-args option
|
||||
int script_check_args();
|
||||
|
||||
Reference in New Issue
Block a user