From d0bc640db88f37c16befbab9edb1763762c40690 Mon Sep 17 00:00:00 2001 From: batrick Date: Sat, 31 May 2008 02:39:27 +0000 Subject: [PATCH] Large recode of nse_init.cc Now does most of it's work through Lua: From Nmap-dev: "Many of the changes consist of changing how Nmap interfaces with Lua that were sometimes awkward or inflexible. Most of the functions have been made to be callable directly by Lua which offers many technical advantages: stack management is alleviated, errors are handled cleanly and are more descriptive, and there is increased reusability." Additionally: -- Moved all lua_State * symbols from "l" to "L". This is to maintain consistency with other Lua libraries (convention) and to make our macros portable. -- Moved file system manipulation over to nse_fs.cc (from nse_init.cc) --- Makefile.in | 6 +- mswin32/nmap.vcproj | 10 +- nmap.cc | 4 +- nmap.h | 2 +- nse_debug.cc | 40 +- nse_fs.cc | 190 ++++++ nse_fs.h | 22 + nse_init.cc | 1369 +++++++++++++++++++------------------------ nse_init.h | 11 +- nse_macros.h | 5 +- nse_main.cc | 375 +++++++----- nse_nmaplib.cc | 353 ++++++----- nse_nmaplib.h | 2 +- nse_nsock.cc | 572 +++++++++--------- 14 files changed, 1568 insertions(+), 1393 deletions(-) create mode 100644 nse_fs.cc create mode 100644 nse_fs.h diff --git a/Makefile.in b/Makefile.in index b7097dadab..1fa6530c14 100644 --- a/Makefile.in +++ b/Makefile.in @@ -60,9 +60,9 @@ INSTALLZENMAP=@INSTALLZENMAP@ UNINSTALLZENMAP=@UNINSTALLZENMAP@ ifneq (@LIBLUA_LIBS@,) -NSE_SRC=nse_main.cc nse_nsock.cc nse_init.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_string.cc -NSE_HDRS=nse_main.h nse_nsock.h nse_init.h nse_nmaplib.h nse_debug.h nse_macros.h nse_pcrelib.h nse_string.h -NSE_OBJS=nse_main.o nse_nsock.o nse_init.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_string.o +NSE_SRC=nse_main.cc nse_nsock.cc nse_init.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_string.cc +NSE_HDRS=nse_main.h nse_nsock.h nse_init.h nse_fs.h nse_nmaplib.h nse_debug.h nse_macros.h nse_pcrelib.h nse_string.h +NSE_OBJS=nse_main.o nse_nsock.o nse_init.o nse_fs.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_string.o NSESTDLIB=nsestdlib endif diff --git a/mswin32/nmap.vcproj b/mswin32/nmap.vcproj index 234bb250be..21193bb29d 100644 --- a/mswin32/nmap.vcproj +++ b/mswin32/nmap.vcproj @@ -259,6 +259,10 @@ RelativePath="..\nse_init.cc" > + + @@ -433,15 +437,15 @@ > = 0 - stack_height; i--) { log_write(LOG_PLAIN, "%d: ", i); - l_dumpValue(l, i); + l_dumpValue(L, i); } log_write(LOG_PLAIN, "-== Stack Dump End ==-\n"); } -void l_dumpValue(lua_State* l, int i) { - switch (lua_type(l, i)) +void l_dumpValue(lua_State *L, int i) { + switch (lua_type(L, i)) { case LUA_TTABLE: - l_dumpTable(l, i); + l_dumpTable(L, i); break; case LUA_TFUNCTION: - l_dumpFunction(l, i); + l_dumpFunction(L, i); break; case LUA_TSTRING: - log_write(LOG_PLAIN, "string '%s'\n", lua_tostring(l, i)); + log_write(LOG_PLAIN, "string '%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: log_write(LOG_PLAIN, "boolean: %s\n", - lua_toboolean(l, i) ? "true" : "false"); + lua_toboolean(L, i) ? "true" : "false"); break; case LUA_TNUMBER: - log_write(LOG_PLAIN, "number: %g\n", lua_tonumber(l, i)); + log_write(LOG_PLAIN, "number: %g\n", lua_tonumber(L, i)); break; default: - log_write(LOG_PLAIN, "%s\n", lua_typename(l, lua_type(l, i))); + log_write(LOG_PLAIN, "%s\n", lua_typename(L, lua_type(L, i))); } } -void l_dumpTable(lua_State *l, int index) { +void l_dumpTable(lua_State *L, int index) { log_write(LOG_PLAIN, "table\n"); - lua_pushnil(l); + lua_pushnil(L); if (index<0) --index; - while(lua_next(l, index) != 0) + while(lua_next(L, index) != 0) { - l_dumpValue(l, -2); - l_dumpValue(l, -1); - lua_pop(l, 1); + l_dumpValue(L, -2); + l_dumpValue(L, -1); + lua_pop(L, 1); } } -void l_dumpFunction(lua_State* l, int index) { +void l_dumpFunction(lua_State *L, int index) { // lua_Debug ar; log_write(LOG_PLAIN, "function\n"); -// lua_pushvalue(l, index); -// lua_getinfo(l, ">n", &ar); +// lua_pushvalue(L, index); +// lua_getinfo(L, ">n", &ar); // // log_write(LOG_PLAIN, "\tname: %s %s\n", ar.namewhat, ar.name); fflush(stdout); diff --git a/nse_fs.cc b/nse_fs.cc new file mode 100644 index 0000000000..03d30aa965 --- /dev/null +++ b/nse_fs.cc @@ -0,0 +1,190 @@ +#ifndef WIN32 + #include "dirent.h" +#endif + +#include "errno.h" +#include "nse_macros.h" +#include "nse_fs.h" +#include "nmap.h" +#include "nmap_error.h" +#include "NmapOps.h" + +extern NmapOps o; + +static bool filename_is_absolute(const char *file) { + if (file[0] == '/') + return true; +#ifdef WIN32 + if ((file[0] != '\0' && file[1] == ':') || file[0] == '\\') + return true; +#endif + return false; +} + +/* This is simply the most portable way to check + * if a file has a given extension. + * The portability comes at the price of reduced + * flexibility. + */ +int nse_check_extension (const char* ext, const char* path) +{ + int pathlen = strlen(path); + int extlen = strlen(ext); + if (extlen > pathlen || pathlen > MAX_FILENAME_LEN) + return 0; + else + return strcmp(path + pathlen - extlen, ext) == 0; +} + +int nse_fetchfile(char *path, size_t path_len, const char *file) { + int type = nmap_fetchfile(path, path_len, file); + + // lets look in /scripts too + if(type == 0) { + std::string alt_path = std::string(SCRIPT_ENGINE_LUA_DIR) + std::string(file); + type = nmap_fetchfile(path, path_len, alt_path.c_str()); + } + + return type; +} + +/* This is a modification of nse_fetchfile that first looks for an + * absolute file name. + */ +int nse_fetchfile_absolute(char *path, size_t path_len, const char *file) { + if (filename_is_absolute(file)) { + if (o.debugging > 1) + log_write(LOG_STDOUT, "%s: Trying absolute path %s\n", SCRIPT_ENGINE, file); + Strncpy(path, file, path_len); + return nmap_fileexistsandisreadable(file); + } + + return nse_fetchfile(path, path_len, file); +} + +#ifdef WIN32 + +int nse_scandir (lua_State *L) + HANDLE dir; + WIN32_FIND_DATA entry; + std::string path; + BOOL morefiles = FALSE; + char *dirname = luaL_checkstring(L, 1); + int files_or_dirs = luaL_checkint(L, 2); + + lua_createtable(L, 100, 0); // 100 files average + + dir = FindFirstFile((std::string(dirname) + "\\*").c_str(), &entry); + + if (dir == INVALID_HANDLE_VALUE) + { + error("%s: No files in '%s\\*'", SCRIPT_ENGINE, dirname); + return SCRIPT_ENGINE_ERROR; + } + + while(!(morefiles == FALSE && GetLastError() == ERROR_NO_MORE_FILES)) { + // if we are looking for files and this file doesn't end with .nse or + // is a directory, then we don't look further at it + if(files_or_dirs == FILES) { + if(!( + (check_extension(SCRIPT_ENGINE_EXTENSION, entry.cFileName) == MATCH) + && !(entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + )) { + morefiles = FindNextFile(dir, &entry); + continue; + } + + // if we are looking for dirs and this dir + // isn't a directory, then we don't look further at it + } else if(files_or_dirs == DIRS) { + if(!( + (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + )) { + morefiles = FindNextFile(dir, &entry); + continue; + } + + // they have passed an invalid value for files_or_dirs + } else { + fatal("%s: In: %s:%i This should never happen.", + SCRIPT_ENGINE, __FILE__, __LINE__); + } + + // otherwise we add it to the results + // we assume that dirname ends with a directory separator of some kind + path = std::string(dirname) + "\\" + std::string(entry.cFileName); + lua_pushstring(L, path.c_str()); + lua_rawseti(L, -2, lua_objlen(L, -2) + 1); + morefiles = FindNextFile(dir, &entry); + } + + + return 1; +} + +#else + +int nse_scandir (lua_State *L) { + DIR* dir; + struct dirent* entry; + struct stat stat_entry; + const char *dirname = luaL_checkstring(L, 1); + int files_or_dirs = luaL_checkint(L, 2); + + lua_createtable(L, 100, 0); // 100 files average + + dir = opendir(dirname); + if(dir == NULL) { + error("%s: Could not open directory '%s'.", SCRIPT_ENGINE, dirname); + return SCRIPT_ENGINE_ERROR; + } + + // note that if there is a symlink in the dir, we have to rely on + // the .nse extension + // if they provide a symlink to a dir which ends with .nse, things + // break :/ + while((entry = readdir(dir)) != NULL) { + std::string path = std::string(dirname) + "/" + std::string(entry->d_name); + + if(stat(path.c_str(), &stat_entry) != 0) + fatal("%s: In: %s:%i This should never happen.", + SCRIPT_ENGINE, __FILE__, __LINE__); + + // if we are looking for files and this file doesn't end with .nse and + // isn't a file or a link, then we don't look further at it + if(files_or_dirs == FILES) { + if(!( + (nse_check_extension(SCRIPT_ENGINE_EXTENSION, entry->d_name)) + && (S_ISREG(stat_entry.st_mode) + || S_ISLNK(stat_entry.st_mode)) + )) { + continue; + } + + // if we are looking for dirs and this dir + // isn't a dir or a link, then we don't look further at it + } else if(files_or_dirs == DIRS) { + if(!( + (S_ISDIR(stat_entry.st_mode) + || S_ISLNK(stat_entry.st_mode)) + )) { + continue; + } + + // they have passed an invalid value for files_or_dirs + } else { + fatal("%s: In: %s:%i This should never happen.", + SCRIPT_ENGINE, __FILE__, __LINE__); + } + + // otherwise we add it to the results + lua_pushstring(L, path.c_str()); + lua_rawseti(L, -2, lua_objlen(L, -2) + 1); + } + + closedir(dir); + + return 1; +} + +#endif diff --git a/nse_fs.h b/nse_fs.h new file mode 100644 index 0000000000..204c04d45a --- /dev/null +++ b/nse_fs.h @@ -0,0 +1,22 @@ +#ifndef NSE_FS +#define NSE_FS + +extern "C" { + #include "lua.h" + #include "lualib.h" + #include "lauxlib.h" +} + +#include +#include +#include + +int nse_check_extension (const char* ext, const char* path); + +int nse_fetchfile(char *path, size_t path_len, const char *file); + +int nse_fetchfile_absolute(char *path, size_t path_len, const char *file); + +int nse_scandir (lua_State *L); + +#endif diff --git a/nse_init.cc b/nse_init.cc index 5d97113c23..e437f54953 100644 --- a/nse_init.cc +++ b/nse_init.cc @@ -2,6 +2,7 @@ #include "nse_nmaplib.h" #include "nse_macros.h" #include "nse_debug.h" +#include "nse_fs.h" // 3rd Party libs #include "nse_pcrelib.h" @@ -12,801 +13,669 @@ #include "nmap_error.h" #include "NmapOps.h" -#ifndef WIN32 - #include "dirent.h" -#endif - #include "errno.h" #include -int init_setlualibpath(lua_State* l); -int init_setargs(lua_State *l); -int init_parseargs(lua_State* l); -int init_loadfile(lua_State* l, char* filename); -int init_loaddir(lua_State* l, char* dirname); -int init_loadcategories(lua_State* l, std::vector categories, std::vector &unusedTags); -int init_scandir(char* dirname, std::vector& result, int files_or_dirs); -int init_fetchfile(char *result, size_t result_max_len, char* file); -int init_fetchfile_absolute(char *path, size_t path_len, char *file); -int init_updatedb(lua_State* l); -int init_pick_default_categories(std::vector& chosenScripts); - -int check_extension(const char* ext, const char* path); extern NmapOps o; -/* open the standard libs */ -int init_lua(lua_State* l) { // FIXME: Use cpcall, let Lua error normally. - static const luaL_Reg lualibs[] = { - {"", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {NSE_PCRELIBNAME, luaopen_pcrelib}, - {NULL, NULL} - }; - - const luaL_Reg* lib; - for (lib = lualibs; lib->func; lib++) { - lua_pushcfunction(l, lib->func); - lua_pushstring(l, lib->name); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 1, 0, 0)); - } - - - /* publish the nmap bindings to the script */ - lua_newtable(l); - SCRIPT_ENGINE_TRY(set_nmaplib(l)); - lua_setglobal(l, "nmap"); - SCRIPT_ENGINE_TRY(init_setlualibpath(l)); - return SCRIPT_ENGINE_SUCCESS; +extern int current_hosts; +extern int errfunc; + +/* TODO: keep? +// Error function if a user script attempts to create a new global +static int global_error(lua_State *L) +{ + lua_pushvalue(L, lua_upvalueindex(1)); + lua_pushvalue(L, 2); + if (!lua_tostring(L, -1)) + { + lua_pushliteral(L, "? (of type "); + lua_pushstring(L, lua_typename(L, lua_type(L, -2))); + lua_pushliteral(L, ")"); + lua_concat(L, 3); + lua_replace(L, -2); + } + lua_pushvalue(L, lua_upvalueindex(2)); + lua_concat(L, 3); + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + return lua_error(L); +} */ + +/* int error_function (lua_State *L) + * + * Arguments: + * -- error_message (passed by Lua) + * + * This function is for use with lua_pcall as the error handler. + * Because the stack is not unwound when this is called, + * we are able to obtain a traceback of the current stack frame. + * We use debug.traceback (an upvalue set in init_lua) for the real work. + */ +static int error_function (lua_State *L) // for use with lua_pcall +{ + luaL_where(L, 1); + lua_insert(L, 1); + lua_pushvalue(L, lua_upvalueindex(1)); // debug.traceback + lua_pushthread(L); + lua_pushliteral(L, ""); + lua_pushinteger(L, 2); + lua_call(L, 3, 1); + lua_concat(L, 3); + return 1; } -/*sets two variables, which control where lua looks for modules (implemented in C or lua */ -int init_setlualibpath(lua_State* l){ - char path[MAX_FILENAME_LEN]; - char cpath[MAX_FILENAME_LEN]; - - const char*oldpath, *oldcpath; - std::string luapath, luacpath; - /* set the path lua searches for modules*/ - if(nmap_fetchfile(path, MAX_FILENAME_LEN, SCRIPT_ENGINE_LIB_DIR)!=2){ - /*SCRIPT_ENGINE_LIB_DIR is not a directory - error */ - error("%s: %s not a directory", SCRIPT_ENGINE, SCRIPT_ENGINE_LIB_DIR); - return SCRIPT_ENGINE_ERROR; - } - - if(nmap_fetchfile(cpath, MAX_FILENAME_LEN, SCRIPT_ENGINE_LIBEXEC_DIR)!=2){ - error("%s: %s not a directory", SCRIPT_ENGINE, SCRIPT_ENGINE_LIBEXEC_DIR); - return SCRIPT_ENGINE_ERROR; - } - - /* the path lua uses to search for modules is setted to the - * SCRIPT_ENGINE_LIBDIR/ *.lua with the default path - * (which is read from the package-module) appended - - * the path for C-modules is as above but it searches for shared libs (*.so) */ - luapath= std::string(path) + "?.lua;"; +/* load an nmap-lua script + * create a new closure to store the script + * tell the closure where to find the standard + * lua libs and the nmap bindings + * we do some error checking to make sure that + * the script is well formed + * the script is then added to either the hostrules + * or the portrules + * */ + +/* int loadfile (lua_State *L) + * + * Arguments + * -- filename File to load + * + * This function loads a file as a new script. + * The file is loaded with it's own environment that has access to the Global + * Environment. The function is tested to be sure it set a global with a valid + * required_fields[?] ("action", "description", ...), port or host rule. + * If it did, the script's environment (table) is saved in the global PORTTESTS + * or HOSTTESTS table. + */ +static int loadfile (lua_State *L) +{ + int i; + const char *filename = luaL_checkstring(L, 1); + static const char *required_fields[] = {ACTION, DESCRIPTION}; + lua_settop(L, 1); // removes other arguments + + lua_createtable(L, 0, 11); // Environment for script + + lua_pushvalue(L, 1); // tell the script about its filename + lua_setfield(L, -2, "filename"); + + lua_pushnumber(L, 1.0); // set a default RUNLEVEL + lua_setfield(L, -2, RUNLEVEL); + + lua_createtable(L, 0, 1); // script gets access to global env + lua_pushvalue(L, LUA_GLOBALSINDEX); // We may want to use G(L)->mainthread + // later if this function becomes + // exposed. See lstate.h + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + + // TODO: Allow scripts to modify globals? + /* finally we make sure nobody tampers with the global name space any more + * and prepare for runlevel sorting + */ + /* lua_getmetatable(L, -1); + + lua_pushliteral(L, "Attempted to change the global '"); + lua_pushliteral(L, "' in "); + lua_pushstring(L, filename); + lua_pushliteral(L, " - use nmap.registry if you really want to share " + "data between scripts."); + lua_concat(L, 3); + lua_pushcclosure(L, global_error, 2); + lua_setfield(L, -2, "__newindex"); + lua_pop(L, 1); */ + + if (luaL_loadfile(L, filename) != 0) // load the file + luaL_error(L, "'%s' could not be loaded!", filename); + lua_pushvalue(L, -2); // push environment table + lua_setfenv(L, -2); // set it + lua_call(L, 0, 0); // Call the function (loads globals) + + /* Check some required fields */ + for (i = 0; i < ARRAY_LEN(required_fields); i++) + { + lua_pushstring(L, required_fields[i]); + lua_gettable(L, -2); + if (lua_isnil(L, -1)) + luaL_error(L, "No '%s' field in script '%s'.", required_fields[i], + filename); + lua_pop(L, 1); + } + /* store the initialized test in either + * the hosttests or the porttests + */ + lua_getfield(L, -1, PORTRULE); // script's portrule + lua_getfield(L, -2, HOSTRULE); // script's hostrule + + /* if we are looking at a portrule then store it in the porttestsets table, + * else if it is a hostrule, then it goes into the hosttestsets table, + * otherwise we fail if there. + */ + if (!lua_isnil(L, -2)) + { + lua_pop(L, 2); // pop port/host rules + lua_getglobal(L, PORTTESTS); // Get global PORTTESTS table + lua_pushvalue(L, -2); // script's environment + lua_rawseti(L, -2, lua_objlen(L, -2) + 1); // add it + lua_pop(L, 1); // pop the porttests table + } + else if (!lua_isnil(L, -1)) + { + lua_pop(L, 2); + lua_getglobal(L, HOSTTESTS); + lua_pushvalue(L, -2); + lua_rawseti(L, -2, lua_objlen(L, -2) + 1); + lua_pop(L, 1); // pop the hosttests table + } + else + luaL_error(L, "No rules in script '%s'.", filename); + return 0; +} + +/* int loaddir (lua_State *L) + * + * Arguments + * -- directory Directory (string) to load. + * + * Loads all the scripts (files with a .nse extension), using loadfile. + */ +static int loaddir(lua_State *L) +{ + int i; + luaL_checkstring(L, 1); // directory to load + + lua_pushcclosure(L, nse_scandir, 0); + lua_pushvalue(L, 1); + lua_pushinteger(L, FILES); + lua_call(L, 2, 1); + + lua_pushcclosure(L, loadfile, 0); + for (i = 1; i <= (int) lua_objlen(L, -2); i++) + { + lua_pushvalue(L, -1); // loadfile closure + lua_rawgeti(L, -3, i); // filename + lua_call(L, 1, 0); // load it + } + return 0; +} + +/* int init_setpath (lua_State *L) + * + * Sets the search path of require function to include: + * ./nselib/ For Lua Path (.lua files) + * ./nselib-bin/ For C Path (.so files) + */ +static int init_setpath (lua_State *L) +{ + char path[MAX_FILENAME_LEN], cpath[MAX_FILENAME_LEN]; + + /* set the path lua searches for modules*/ + if (nmap_fetchfile(path, MAX_FILENAME_LEN, SCRIPT_ENGINE_LIB_DIR) != 2) + luaL_error(L, "'%s' not a directory", SCRIPT_ENGINE_LIB_DIR); + if (nmap_fetchfile(cpath, MAX_FILENAME_LEN, SCRIPT_ENGINE_LIBEXEC_DIR) != 2) + luaL_error(L, "'%s' not a directory", SCRIPT_ENGINE_LIBEXEC_DIR); + + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, -1, LUA_LOADLIBNAME); /* "package" */ + lua_pushstring(L, cpath); #ifdef WIN32 - luacpath= std::string(cpath) + "?.dll;"; + lua_pushliteral(L, "?.dll;"); #else - luacpath= std::string(cpath) + "?.so;"; + lua_pushliteral(L, "?.so;"); #endif - - lua_getglobal(l,"package"); - if(!lua_istable(l,-1)){ - error("%s: the lua global-variable package is not a table?!", SCRIPT_ENGINE); - return SCRIPT_ENGINE_ERROR; - } - lua_getfield(l,-1, "path"); - lua_getfield(l,-2, "cpath"); - if(!lua_isstring(l,-1)||!lua_isstring(l,-2)){ - error("%s: no default paths setted in package table (needed in %s at line %d) -- probably a problem of the lua-configuration?!", SCRIPT_ENGINE, __FILE__, __LINE__); - return SCRIPT_ENGINE_ERROR; - } - oldcpath= lua_tostring(l,-1); - oldpath = lua_tostring(l,-2); - luacpath= luacpath + oldcpath; - luapath= luapath + oldpath; - lua_pop(l,2); - lua_pushstring(l, luapath.c_str()); - lua_setfield(l, -2, "path"); - lua_pushstring(l, luacpath.c_str()); - lua_setfield(l, -2, "cpath"); - lua_getfield(l,-1, "path"); - lua_getfield(l,-2, "cpath"); - SCRIPT_ENGINE_DEBUGGING(log_write(LOG_STDOUT, "%s: Using %s to search for C-modules and %s for Lua-modules\n", SCRIPT_ENGINE, lua_tostring(l,-1), lua_tostring(l,-2));) - /*pop the two strings (luapath and luacpath) and the package table off - * the stack */ - lua_pop(l,3); - return SCRIPT_ENGINE_SUCCESS; + lua_getfield(L, -3, "cpath"); /* package.cpath */ + lua_concat(L, 3); + lua_setfield(L, -2, "cpath"); + + lua_pushstring(L, path); + lua_pushliteral(L, "?.lua;"); + lua_getfield(L, -3, "path"); /* package.path */ + lua_concat(L, 3); + lua_setfield(L, -2, "path"); + + return 0; } -/* parses the argument provided to --script-args and leaves the processed - * string on the stack, after this it only has to be prepended with - * "={" and appended by "}", before it can be called by - * luaL_loadbuffer() +/* int init_lua (lua_State *L) + * + * Initializes the Lua State. + * Opens standard libraries as well as nmap and pcre. + * Sets an error function for use by pcall. + * Sets the path for require. */ -int init_parseargs(lua_State* l){ - //FIXME - free o.script-args after we're finished!!! - - if (o.scriptargs==NULL) - return SCRIPT_ENGINE_SUCCESS; //if no arguments are provided we're done - - lua_pushstring(l, o.scriptargs); - luaL_getmetafield(l, -1, "__index"); - lua_getfield(l, -1, "gsub"); - lua_pushvalue(l, -3); - lua_pushliteral(l, "=([^{},]+)"); - lua_pushliteral(l, "=\"%1\""); - SCRIPT_ENGINE_TRY(lua_pcall(l,3,1,0)); - lua_replace(l, 1); - lua_settop(l,1); //clear stack - - return SCRIPT_ENGINE_SUCCESS; +int init_lua (lua_State *L) +{ + int i; + static const luaL_Reg libs[] = { + {NSE_PCRELIBNAME, luaopen_pcrelib}, // pcre library + {"nmap", luaopen_nmap} // nmap bindings + }; + + luaL_openlibs(L); // opens all standard libraries + + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); /* Loaded libraries */ + for (i = 0; i < ARRAY_LEN(libs); i++) // for each in libs + { + lua_pushstring(L, libs[i].name); + lua_pushcclosure(L, libs[i].func, 0); + lua_pushvalue(L, -2); + lua_call(L, 1, 1); + if (lua_isnil(L, -1)) + { + lua_pushboolean(L, 1); + lua_replace(L, -2); + } + lua_settable(L, -3); + } + lua_getfield(L, -1, "debug"); // _LOADED.debug + lua_getfield(L, -1, "traceback"); + lua_pushcclosure(L, error_function, 1); + errfunc = luaL_ref(L, LUA_REGISTRYINDEX); + + lua_pushcclosure(L, init_setpath, 0); + lua_call(L, 0, 0); + + lua_newtable(L); + current_hosts = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; } -/* set the arguments inside the nmap.registry, for use by scripts + +/* int init_parseargs (lua_State *L) + * + * Arguments + * args Arguments passed through --script-args + * Returns + * function Function that returns a table with the arguments, or an error + * message describing why the arguments could not be parsed. */ -int init_setargs(lua_State *l){ - const char *argbuf; - size_t argbuflen; - if(o.scriptargs==NULL){ - return SCRIPT_ENGINE_SUCCESS; - } - /* we'll concatenate the stuff we need to prepend and append to the - * processed using lua's functionality - */ - SCRIPT_ENGINE_TRY(init_parseargs(l)); - lua_pushliteral(l,"nmap.registry.args={"); - lua_insert(l,-2); - lua_pushliteral(l,"}"); - lua_concat(l,3); - argbuf=lua_tolstring(l,-1,&argbuflen); - luaL_loadbuffer(l,argbuf,argbuflen, "Script-Arguments"); - lua_replace(l, -2); // remove argbuf string - if(lua_pcall(l,0,0,0)!=0){ - error("error loading --script-args: %s",lua_tostring(l,-1)); - return SCRIPT_ENGINE_ERROR; - } - return SCRIPT_ENGINE_SUCCESS; -} -/* if there were no command line arguments specifying - * which scripts should be run, a default script set is - * chosen - * otherwise the script locators given at the command line - * (either directories with lua files or lua files) are - * loaded - * */ -int init_rules(lua_State* l, std::vector chosenScripts) { - char path[MAX_FILENAME_LEN]; - int type; - char* c_iter; - std::vector unusedTags; - - lua_newtable(l); - lua_setglobal(l, PORTTESTS); - - lua_newtable(l); - lua_setglobal(l, HOSTTESTS); - - SCRIPT_ENGINE_TRY(init_pick_default_categories(chosenScripts)); - - // we try to interpret the choices as categories - SCRIPT_ENGINE_TRY(init_loadcategories(l, chosenScripts, unusedTags)); - - // if there's more, we try to interpret as directory or file - std::vector::iterator iter; - bool extension_not_matched = false; - for(iter = unusedTags.begin(); iter != unusedTags.end(); iter++) { - - c_iter = strdup((*iter).c_str()); - type = init_fetchfile_absolute(path, sizeof(path), c_iter); - free(c_iter); - - if (type == 0) { - c_iter = strdup((*iter + std::string(SCRIPT_ENGINE_EXTENSION)).c_str()); - type = init_fetchfile_absolute(path, sizeof(path), c_iter); - free(c_iter); - } - - switch(type) { - case 0: // no such path - error("%s: No such category, file or directory: '%s'", SCRIPT_ENGINE, (*iter).c_str()); - return SCRIPT_ENGINE_ERROR; - break; - case 1: // nmap_fetchfile returned a file - if(check_extension(SCRIPT_ENGINE_EXTENSION, path) != MATCH - && extension_not_matched == false) { - error("%s: Warning: Loading '%s' - the recommended file extension is '.nse'.", - SCRIPT_ENGINE, path); - extension_not_matched = true; - } - SCRIPT_ENGINE_TRY(init_loadfile(l, path)); - break; - case 2: // nmap_fetchfile returned a dir - SCRIPT_ENGINE_TRY(init_loaddir(l, path)); - break; - default: - fatal("%s: In: %s:%i This should never happen.", - SCRIPT_ENGINE, __FILE__, __LINE__); - } - } - - // Compute some stats - SCRIPT_ENGINE_DEBUGGING( - int rules_count; - - lua_getglobal(l, HOSTTESTS); - rules_count = lua_objlen(l, -1); - - lua_getglobal(l, PORTTESTS); - rules_count += lua_objlen(l, -1); - lua_pop(l, 2); - log_write(LOG_STDOUT, "%s: Initialized %d rules\n", SCRIPT_ENGINE, rules_count); - ) - - return SCRIPT_ENGINE_SUCCESS; -} +int init_parseargs (lua_State *L) +{ + const char *arg; + size_t len; + + luaL_checkstring(L, 1); + luaL_getmetafield(L, 1, "__index"); // string library + lua_getfield(L, -1, "gsub"); // string.gsub + lua_pushvalue(L, 1); + lua_pushliteral(L, "=([^{},]+)"); // make strings quoted + lua_pushliteral(L, "=\"%1\""); + lua_call(L, 3, 1); + + lua_pushliteral(L, "return {"); + lua_insert(L, -2); + lua_pushliteral(L, "}"); + lua_concat(L, 3); + arg = lua_tolstring(L, -1, &len); + luaL_loadbuffer(L, arg, len, "Script-Args"); -class ExtensionalCategory { -public: - std::string category; - int option; - - ExtensionalCategory(std::string _category, int _option) { - category = _category; - option = _option; - } -}; - -int init_pick_default_categories(std::vector& chosenScripts) { - std::vector reserved_categories; - std::vector::iterator rcat_iter; - - reserved_categories.push_back(ExtensionalCategory(std::string("version"), o.scriptversion)); - - // if they tried to explicitely select an implicit category, we complain - if(o.script) { - for( rcat_iter = reserved_categories.begin(); - rcat_iter != reserved_categories.end(); - rcat_iter++) { - if( (*rcat_iter).option == 0 - && std::find( - chosenScripts.begin(), - chosenScripts.end(), - (*rcat_iter).category) != chosenScripts.end()) - fatal("%s: specifying the \"%s\" category explicitly is not allowed.", - SCRIPT_ENGINE, (*rcat_iter).category.c_str()); - } - } - - // if no scripts were chosen, we use a default set - if( (o.script == 1 - && chosenScripts.size() == 0) ) - { - chosenScripts.push_back(std::string("default")); - } - - // we append the implicitely selected categories - for( rcat_iter = reserved_categories.begin(); - rcat_iter != reserved_categories.end(); - rcat_iter++) { - if((*rcat_iter).option == 1) - chosenScripts.push_back((*rcat_iter).category); - } - - return SCRIPT_ENGINE_SUCCESS; + return 1; // return function from luaL_loadbuffer or error message returned } -int init_updatedb(lua_State* l) { - char path[MAX_FILENAME_LEN]; - FILE* scriptdb; - std::vector files; - std::vector::iterator iter; - char* c_iter; - - if(nmap_fetchfile(path, sizeof(path)-sizeof(SCRIPT_ENGINE_DATABASE)-1, SCRIPT_ENGINE_LUA_DIR) == 0) { - error("%s: Couldn't find '%s'", SCRIPT_ENGINE, SCRIPT_ENGINE_LUA_DIR); - return SCRIPT_ENGINE_ERROR; - } - - SCRIPT_ENGINE_TRY(init_scandir(path, files, FILES)); - - // we rely on the fact that nmap_fetchfile returned a string which leaves enough room - // to append the db filename (see call to nmap_fetchfile above) - strncat(path, SCRIPT_ENGINE_DATABASE, MAX_FILENAME_LEN-1); - - scriptdb = fopen(path, "w"); - if(scriptdb == NULL) { - error("%s: Could not open '%s' for writing: %s", - SCRIPT_ENGINE, path, strerror(errno)); - return SCRIPT_ENGINE_ERROR; - } - - SCRIPT_ENGINE_DEBUGGING( - log_write(LOG_STDOUT, "%s: Trying to add %d scripts to the database.\n", - SCRIPT_ENGINE, (int) files.size()); - ) - - lua_newtable(l); - /*give the script global namespace access*/ - lua_newtable(l); - lua_pushvalue(l, LUA_GLOBALSINDEX); - lua_setfield(l, -2, "__index"); - lua_setmetatable(l, -2); - - std::sort(files.begin(), files.end()); - - for(iter = files.begin(); iter != files.end(); iter++) { - c_iter = strdup((*iter).c_str()); - if(check_extension(SCRIPT_ENGINE_EXTENSION, c_iter) == MATCH - && strstr(c_iter, SCRIPT_ENGINE_DATABASE) == NULL) { - - SCRIPT_ENGINE_LUA_TRY(luaL_loadfile(l, c_iter)); - lua_pushvalue(l, -2); - lua_setfenv(l, -2); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 0, 0, 0)); - - lua_getfield(l, -1, "categories"); - if(lua_isnil(l, -1)) { - error("%s: Script '%s' does not contain any category categories.", SCRIPT_ENGINE, c_iter); - return SCRIPT_ENGINE_ERROR; - } - - lua_pushnil(l); - while(lua_next(l, -2) != 0) { - char *filename = path_get_basename(c_iter); - if (filename == NULL) { - error("%s: Could not allocate temporary memory.", SCRIPT_ENGINE); - return SCRIPT_ENGINE_ERROR; - } - fprintf(scriptdb, - "Entry{ category = \"%s\", filename = \"%s\" }\n", - lua_tostring(l, -1), filename); - free(filename); - lua_pop(l, 1); - } - lua_pop(l, 1); // pop the categories table - } - - free(c_iter); - } - lua_pop(l, 1); // pop the closure - - if(fclose(scriptdb) != 0) { - error("%s: Could not close %s: %s", SCRIPT_ENGINE, path, strerror(errno)); - return SCRIPT_ENGINE_ERROR; - } - - return SCRIPT_ENGINE_SUCCESS; -} +/* int init_setargs (lua_State *L) + * + * Takes the function returned by init_parseargs(), calls it, and puts + * the returned table in nmap.registry.args + */ +int init_setargs (lua_State *L) +{ + if (o.scriptargs == NULL) + return 0; -int init_loadcategories(lua_State* l, std::vector categories, std::vector &unusedTags) { - std::vector::iterator iter; - std::vector files; - std::string dbpath = std::string(SCRIPT_ENGINE_LUA_DIR) + std::string(SCRIPT_ENGINE_DATABASE); - char* c_dbpath_buf; - char c_dbpath[MAX_FILENAME_LEN]; - const char* stub = "\ -files = {}\n\ -Entry = function(e)\n\ - if (categories[e.category] ~= nil) then\n\ - categories[e.category] = categories[e.category] + 1\n\ - files[e.filename] = true\n\ - end\n\ - if (categories[\"all\"] ~= nil and e.category ~= \"version\") then\n\ - categories[\"all\"] = categories[\"all\"] + 1\n\ - files[e.filename] = true\n\ - end\n\ -end\n"; - int categories_usage; - char* c_iter; - char script_path[MAX_FILENAME_LEN]; - int type; - - // closure - lua_newtable(l); - - // categories table - lua_newtable(l); - for(iter = categories.begin(); iter != categories.end(); iter++) { - lua_pushinteger(l, 0); - lua_setfield(l, -2, (*iter).c_str()); - } - lua_setfield(l, -2, "categories"); - - // we load the stub - // the strlen is safe in this case because the stub is a constant string - SCRIPT_ENGINE_LUA_TRY(luaL_loadbuffer(l, stub, strlen(stub), "Database Stub")); - lua_pushvalue(l, -2); - lua_setfenv(l, -2); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 0, 0, 0)); - - // if we can't find the database we try to create it - c_dbpath_buf = strdup(dbpath.c_str()); - if(nmap_fetchfile(c_dbpath, sizeof(c_dbpath), c_dbpath_buf) == 0) { - SCRIPT_ENGINE_TRY(init_updatedb(l)); - } - free(c_dbpath_buf); - - SCRIPT_ENGINE_LUA_TRY(luaL_loadfile(l, c_dbpath)); - lua_pushvalue(l, -2); - lua_setfenv(l, -2); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 0, 0, 0)); - - // retrieve the filenames produced by the stub - lua_getfield(l, -1, "files"); - lua_pushnil(l); - while(lua_next(l, -2) != 0) { - if(lua_isstring(l, -2)) - files.push_back(std::string(lua_tostring(l, -2))); - else { - error("%s: One of the filenames in '%s' is not a string?!", - SCRIPT_ENGINE, - SCRIPT_ENGINE_DATABASE); - return SCRIPT_ENGINE_ERROR; - } - lua_pop(l, 1); - } - lua_pop(l, 1); - - // find out which categories didn't produce any filenames - lua_getfield(l, -1, "categories"); - lua_pushnil(l); - while(lua_next(l, -2) != 0) { - categories_usage = lua_tointeger(l, -1); - if(categories_usage == 0) { - unusedTags.push_back(std::string(lua_tostring(l, -2))); - } - lua_pop(l, 1); - } - lua_pop(l, 2); - - // load all the files we have found for the given categories - for(iter = files.begin(); iter != files.end(); iter++) { - c_iter = strdup((*iter).c_str()); - type = init_fetchfile(script_path, sizeof(script_path), c_iter); - - if(type != 1) { - error("%s: %s is not a file.", SCRIPT_ENGINE, c_iter); - return SCRIPT_ENGINE_ERROR; - } - - free(c_iter); - - SCRIPT_ENGINE_TRY(init_loadfile(l, script_path)); - } - - return SCRIPT_ENGINE_SUCCESS; -} + lua_getglobal(L, "nmap"); + lua_getfield(L, -1, "registry"); -int init_fetchfile(char *path, size_t path_len, char* file) { - int type; + lua_pushcclosure(L, init_parseargs, 0); + lua_pushstring(L, o.scriptargs); + lua_call(L, 1, 1); - type = nmap_fetchfile(path, path_len, file); + if (!lua_isfunction(L, -1)) + luaL_error(L, "Bad script arguments!\n\t%s", lua_tostring(L, -1)); - // lets look in /scripts too - if(type == 0) { - char* alt_path = strdup((std::string(SCRIPT_ENGINE_LUA_DIR) + std::string(file)).c_str()); - type = nmap_fetchfile(path, path_len, alt_path); - free(alt_path); - - } + lua_call(L, 0, 1); /* get returned table */ - return type; + lua_setfield(L, -2, "args"); + + return 0; } -static bool filename_is_absolute(const char *file) { - if (file[0] == '/') - return true; -#ifdef WIN32 - if ((file[0] != '\0' && file[1] == ':') || file[0] == '\\') - return true; -#endif - return false; +/* int init_updatedb (lua_State *L) + * + * Loads all the files in ./scripts and puts them in the database. + * Each file is loaded and for each of its categories, an entry in the + * database is made in the following format: + * Entry{ category = "category1", filename = "somefile" }\n" + * Entry{ category = "category2", filename = "somefile" }\n" + * Each file will have an entry per category. + */ +int init_updatedb (lua_State *L) +{ + int i; + char path[MAX_FILENAME_LEN]; + FILE *scriptdb; + lua_settop(L, 0); // clear all args + + if (nmap_fetchfile(path, sizeof(path) - sizeof(SCRIPT_ENGINE_DATABASE), + SCRIPT_ENGINE_LUA_DIR) == 0) + luaL_error(L, "Couldn't find '%s'", SCRIPT_ENGINE_LUA_DIR); + + lua_pushcclosure(L, nse_scandir, 0); + lua_pushstring(L, path); + lua_pushinteger(L, FILES); + lua_call(L, 2, 1); // get all the .nse files in ./scripts + + // we rely on the fact that nmap_fetchfile returned a string which leaves enough room + // to append the db filename (see call to nmap_fetchfile above) + strncat(path, SCRIPT_ENGINE_DATABASE, MAX_FILENAME_LEN-1); + + scriptdb = fopen(path, "w"); + if (scriptdb == NULL) + luaL_error(L, "Could not open file '%s' for writing.", path); + + SCRIPT_ENGINE_DEBUGGING( + log_write(LOG_STDOUT, "%s: Trying to add %u scripts to the database.\n", + SCRIPT_ENGINE, lua_objlen(L, 1)); + ) + + // give the script global namespace access + lua_createtable(L, 0, 1); // metatable + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); + + for (i = 1; i <= (int) lua_objlen(L, 1); i++) + { + const char *file; + lua_rawgeti(L, 1, i); // integer key from scan_dir() table + file = lua_tostring(L, -1); + if (nse_check_extension(SCRIPT_ENGINE_EXTENSION, file) && + strstr(file, SCRIPT_ENGINE_DATABASE) == NULL) + { + char *filebase = path_get_basename(file); + lua_newtable(L); // script environment + lua_pushvalue(L, -3); // script metatable + lua_setmetatable(L, -2); // set it + luaL_loadfile(L, file); // load file + lua_pushvalue(L, -2); // push environment + lua_setfenv(L, -2); // set it + lua_call(L, 0, 0); + + lua_getfield(L, -1, "categories"); + if (lua_isnil(L, -1)) + luaL_error(L, "Script, '%s', being added to the database " + "has no categories.", file); + + if (filebase == NULL) + luaL_error(L, "filename basename could not be generated"); + + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + fprintf(scriptdb, "Entry{ category = \"%s\", filename = \"%s\" }\n", + lua_tostring(L, -1), filebase); + lua_pop(L, 1); + } + lua_pop(L, 2); // script environment and categories + free(filebase); + } + lua_pop(L, 1); // filename + } + + if (fclose(scriptdb) != 0) + luaL_error(L, "Could not close script.db: %s.", strerror(errno)); + + return 0; } -/* This is a modification of init_fetchfile that first looks for an - * absolute file name. +typedef struct extensional_category { + char *category; + int option; +} extensional_category; + +/* int pick_default_categories (lua_State *L) + * + * The function is passed all the scripts/directories/categories passed + * through --scripts argument. For each of these, we check if a reserved + * category (currently "version") has been chosen, and raise a fatal error + * if so. Finally the reserved categories are added. Basically, explicitly + * adding the reserved categories is illegal. */ -int init_fetchfile_absolute(char *path, size_t path_len, char *file) { - if (filename_is_absolute(file)) { - if (o.debugging > 1) - log_write(LOG_STDOUT, "%s: Trying absolute path %s\n", SCRIPT_ENGINE, file); - Strncpy(path, file, path_len); - return nmap_fileexistsandisreadable(file); - } - - return init_fetchfile(path, path_len, file); +static int pick_default_categories (lua_State *L) +{ + int i, top = lua_gettop(L); + extensional_category reserved_categories[] = { + {"version", o.scriptversion}, + }; + + if (top > 0) + { + // if they tried to explicitely select an implicit category, we complain + // ... for each in reserved_categories + for (i = 0; i < ARRAY_LEN(reserved_categories); i++) + { + int j; + lua_pushstring(L, reserved_categories[i].category); + for (j = 1; j <= top; j++) + if (lua_equal(L, j, -1)) + { + fatal("%s: specifying the \"%s\" category explicitly is not allowed.", + SCRIPT_ENGINE, lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + else if (o.script == 1) + { + // default set of categories + lua_pushliteral(L, "default"); + } + + // for each in reserved_categories + for (i = 0; i < ARRAY_LEN(reserved_categories); i++) + if (reserved_categories[i].option == 1) + lua_pushstring(L, reserved_categories[i].category); + + return lua_gettop(L); } -/* This is simply the most portable way to check - * if a file has a given extension. - * The portability comes at the price of reduced - * flexibility. +/* int entry (lua_State *L) + * + * This function is called from the script.db file. It has two upvalues: + * [1] Categories The categories/files/directories passed via --script. + * [2] Files The Files currently loaded (initially an empty table). + * A table is passed from the script database with a category and filename. + * The function tests if either the script's (filename's) category was chosen + * by checking [1]. Or, it loads the file if [1] has the 'category' "all" and + * the script's category is not "version". */ -int check_extension(const char* ext, const char* path) { - int pathlen = strlen(path); - int extlen = strlen(ext); - const char* offset; - - if( extlen > pathlen - || pathlen > MAX_FILENAME_LEN) - return -1; - - offset = path + pathlen - extlen; - - if(strcmp(offset, ext) != MATCH) - return 1; - else - return MATCH; +static int entry (lua_State *L) +{ + char script_path[MAX_FILENAME_LEN]; + int not_all; + + luaL_checktype(L, 1, LUA_TTABLE); // Sole argument is a table + lua_settop(L, 1); + lua_getfield(L, 1, "category"); // index 2 + lua_getfield(L, 1, "filename"); // index 3 + if (!(lua_isstring(L, 2) && lua_isstring(L, 3))) + luaL_error(L, "bad entry in script database"); + lua_pushvalue(L, 3); // filename + lua_gettable(L, lua_upvalueindex(2)); // already loaded? + if (!lua_isnil(L, -1)) + return 0; + lua_pushvalue(L, 2); // category + lua_gettable(L, lua_upvalueindex(1)); // check 1 + lua_pushliteral(L, "version"); // check 2 + lua_getfield(L, lua_upvalueindex(1), "all"); // check 3 + + // if category chosen OR category != "version" and [1].all exists + if ((not_all = (!lua_isnil(L, -3))) || + (!(lua_isnil(L, -1) || lua_equal(L, 2, -2)))) + { + if (not_all) + lua_pushvalue(L, 2); + else + lua_pushliteral(L, "all"); + lua_pushboolean(L, 1); // set category to true + lua_settable(L, lua_upvalueindex(1)); + + if (nse_fetchfile(script_path, sizeof(script_path), + lua_tostring(L, 3)) != 1) + luaL_error(L, "%s: %s is not a file!", lua_tostring(L, 3)); + + lua_pushvalue(L, 3); // filename + lua_pushboolean(L, 1); + lua_settable(L, lua_upvalueindex(2)); // loaded + lua_pushcclosure(L, loadfile, 0); + lua_pushstring(L, script_path); + lua_call(L, 1, 0); + } + return 0; } -int init_loaddir(lua_State* l, char* dirname) { - std::vector files; - char* c_iter; +/* int loadcategories (lua_State *L) + * + * This function takes all the categories/scripts/directories + * passed to it and puts them in a table. + * This table along with an empty one are used as upvalues to the + * Entry closure (see entry above). Finally, the ./scripts/script.db + * file is loaded and it's environment set to only include the Entry + * closure. The entry function will do the work to load all script files with + * chosen categories. After the script database is executed. Any remainining + * fields (files/directories and possibly unused categories) are left in the + * table to be handled later. + */ +static int loadcategories (lua_State *L) +{ + int i, top = lua_gettop(L); + char c_dbpath[MAX_FILENAME_LEN]; + static const char *dbpath = SCRIPT_ENGINE_LUA_DIR SCRIPT_ENGINE_DATABASE; - SCRIPT_ENGINE_TRY(init_scandir(dirname, files, FILES)); - - std::vector::iterator iter; - for(iter = files.begin(); iter != files.end(); iter++) { - c_iter = strdup((*iter).c_str()); - SCRIPT_ENGINE_TRY(init_loadfile(l, c_iter)); - free(c_iter); - } + if (nmap_fetchfile(c_dbpath, sizeof(c_dbpath), dbpath) == 0) + { + lua_pushcclosure(L, init_updatedb, 0); + lua_call(L, 0, 0); + } - return SCRIPT_ENGINE_SUCCESS; -} + lua_createtable(L, 0, top); // categories table + for (i = 1; i <= top; i++) + { + lua_pushvalue(L, i); // category/files/directory + lua_pushboolean(L, 0); // false (not used) + lua_settable(L, -3); + } -#ifdef WIN32 + luaL_loadfile(L, c_dbpath); + lua_createtable(L, 0, 1); + lua_pushliteral(L, "Entry"); + lua_pushvalue(L, -4); // categories table + lua_newtable(L); // files loaded + lua_pushcclosure(L, entry, 2); + lua_settable(L, -3); + lua_setfenv(L, -2); + lua_call(L, 0, 0); // Let errors go through + + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + if (lua_toboolean(L, -1)) // category was used? + { + lua_pushvalue(L, -2); + lua_pushnil(L); + lua_settable(L, -5); // remove the category + } + lua_pop(L, 1); + } -int init_scandir(char* dirname, std::vector& result, int files_or_dirs) { - HANDLE dir; - WIN32_FIND_DATA entry; - std::string path; - BOOL morefiles = FALSE; - - dir = FindFirstFile((std::string(dirname) + "\\*").c_str(), &entry); - - if (dir == INVALID_HANDLE_VALUE) - { - error("%s: No files in '%s\\*'", SCRIPT_ENGINE, dirname); - return SCRIPT_ENGINE_ERROR; - } - - while(!(morefiles == FALSE && GetLastError() == ERROR_NO_MORE_FILES)) { - // if we are looking for files and this file doesn't end with .nse or - // is a directory, then we don't look further at it - if(files_or_dirs == FILES) { - if(!( - (check_extension(SCRIPT_ENGINE_EXTENSION, entry.cFileName) == MATCH) - && !(entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - )) { - morefiles = FindNextFile(dir, &entry); - continue; - } - - // if we are looking for dirs and this dir - // isn't a directory, then we don't look further at it - } else if(files_or_dirs == DIRS) { - if(!( - (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - )) { - morefiles = FindNextFile(dir, &entry); - continue; - } - - // they have passed an invalid value for files_or_dirs - } else { - fatal("%s: In: %s:%i This should never happen.", - SCRIPT_ENGINE, __FILE__, __LINE__); - } - - // otherwise we add it to the results - // we assume that dirname ends with a directory separator of some kind - path = std::string(dirname) + "\\" + std::string(entry.cFileName); - result.push_back(path); - morefiles = FindNextFile(dir, &entry); - } - - - return SCRIPT_ENGINE_SUCCESS; + return 1; // unused tags (what's left in categories table) } -#else +/* int init_rules (lua_State *L) + * + * Arguments + * ... All the categories/scripts/directories passed via --script + * + * This function adds the PORTTESTS and HOSTTESTS globals to the main state. + * Then it calls pick_default_categories to check for illegally passed implicit + * categories (which it will add otherwise). Next, loadcategories is called + * to load all the viable files for which a category was chosen. The unused + * tags (files/directories, and possibly unused or invalid categories) are + * then each loaded (attempted). If any do not load then an error is raised. + */ +int init_rules (lua_State *L) +{ + int top = lua_gettop(L); // number of categories/scripts -int init_scandir(char* dirname, std::vector& result, int files_or_dirs) { - DIR* dir; - struct dirent* entry; - std::string path; - struct stat stat_entry; - - dir = opendir(dirname); - if(dir == NULL) { - error("%s: Could not open directory '%s'.", SCRIPT_ENGINE, dirname); - return SCRIPT_ENGINE_ERROR; - } - - // note that if there is a symlink in the dir, we have to rely on - // the .nse extension - // if they provide a symlink to a dir which ends with .nse, things - // break :/ - while((entry = readdir(dir)) != NULL) { - path = std::string(dirname) + "/" + std::string(entry->d_name); - - if(stat(path.c_str(), &stat_entry) != 0) - fatal("%s: In: %s:%i This should never happen.", - SCRIPT_ENGINE, __FILE__, __LINE__); - - // if we are looking for files and this file doesn't end with .nse and - // isn't a file or a link, then we don't look further at it - if(files_or_dirs == FILES) { - if(!( - (check_extension(SCRIPT_ENGINE_EXTENSION, entry->d_name) == MATCH) - && (S_ISREG(stat_entry.st_mode) - || S_ISLNK(stat_entry.st_mode)) - )) { - continue; - } - - // if we are looking for dirs and this dir - // isn't a dir or a link, then we don't look further at it - } else if(files_or_dirs == DIRS) { - if(!( - (S_ISDIR(stat_entry.st_mode) - || S_ISLNK(stat_entry.st_mode)) - )) { - continue; - } - - // they have passed an invalid value for files_or_dirs - } else { - fatal("%s: In: %s:%i This should never happen.", - SCRIPT_ENGINE, __FILE__, __LINE__); - } - - // otherwise we add it to the results - result.push_back(path); - } - - closedir(dir); - - return SCRIPT_ENGINE_SUCCESS; -} + lua_newtable(L); + lua_setglobal(L, PORTTESTS); -#endif + lua_newtable(L); + lua_setglobal(L, HOSTTESTS); -/* Error function if a user script attempts to create a new global */ -/* TODO: Why wasn't _changing_ globals handled? */ -static int global_error(lua_State *L) -{ - lua_pushvalue(L, lua_upvalueindex(1)); - lua_pushvalue(L, 2); - if (!lua_tostring(L, -1)) + lua_pushcclosure(L, pick_default_categories, 0); + lua_insert(L, 1); + lua_call(L, top, LUA_MULTRET); + top = lua_gettop(L); // new number of categories & scripts + + lua_pushcclosure(L, loadcategories, 0); + lua_insert(L, 1); + lua_call(L, top, 1); // returns unused tags table + + lua_pushcclosure(L, loadfile, 0); + lua_pushnil(L); + while (lua_next(L, -3) != 0) { - lua_pushliteral(L, "? (of type "); - lua_pushstring(L, lua_typename(L, lua_type(L, -2))); - lua_pushliteral(L, ")"); - lua_concat(L, 3); - lua_replace(L, -2); + char path[MAX_FILENAME_LEN]; + int type = nse_fetchfile_absolute(path, sizeof(path), + lua_tostring(L, -2)); + + if (type == 0) + { + lua_pushvalue(L, -2); // copy of key + lua_pushliteral(L, SCRIPT_ENGINE_EXTENSION); + lua_concat(L, 2); + lua_replace(L, -2); // remove value + type = nse_fetchfile_absolute(path, sizeof(path), lua_tostring(L, -1)); + } + + switch (type) + { + case 0: // no such path + luaL_error(L, "No such category, file or directory: '%s'", + lua_tostring(L, -2)); + case 1: // nmap_fetchfile returned a file + if (!nse_check_extension(SCRIPT_ENGINE_EXTENSION, path)) + { + error("%s: Warning: Loading '%s' - the recommended file extension is '.nse'.", + SCRIPT_ENGINE, path); + } + lua_pushvalue(L, -3); // loadfile closure + lua_pushstring(L, path); + lua_call(L, 1, 0); + break; + case 2: // nmap_fetchfile returned a dir + lua_pushcclosure(L, loaddir, 0); + lua_pushstring(L, path); + lua_call(L, 1, 0); + break; + default: + fatal("%s: In: %s:%i This should never happen.", + SCRIPT_ENGINE, __FILE__, __LINE__); + } + lua_pop(L, 1); } - lua_pushvalue(L, lua_upvalueindex(2)); - lua_concat(L, 3); - fprintf(stderr, "%s\n", lua_tostring(L, -1)); - return lua_error(L); -} -/* load an nmap-lua script - * create a new closure to store the script - * tell the closure where to find the standard - * lua libs and the nmap bindings - * we do some error checking to make sure that - * the script is well formed - * the script is then added to either the hostrules - * or the portrules - * */ -int init_loadfile(lua_State* l, char* filename) { - int rule_count; - - /* create a closure for encapsuled execution - * give the closure access to the global enviroment - */ - lua_newtable(l); - - /* tell the script about its filename */ - lua_pushstring(l, filename); - lua_setfield(l, -2, "filename"); - - /* we give the script access to the global name space - * */ - lua_newtable(l); - lua_pushvalue(l, LUA_GLOBALSINDEX); - lua_setfield(l, -2, "__index"); - lua_setmetatable(l, -2); - - /* load the *.nse file, set the closure and execute (init) the test - * */ - SCRIPT_ENGINE_LUA_TRY(luaL_loadfile(l, filename)); - lua_pushvalue(l, -2); - lua_setfenv(l, -2); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 0, 0, 0)); - - /* look at the runlevel, if it is not set, we set it to 1.0 - * */ - lua_getfield(l, -1, RUNLEVEL); - if(lua_isnil(l, -1)) { - lua_pushnumber(l, 1.0); - lua_setfield(l, -3, RUNLEVEL); - } - lua_pop(l, 1); - - /* finally we make sure nobody tampers with the global name space any more - * and prepare for runlevel sorting - * */ - lua_getmetatable(l, -1); - - lua_pushliteral(l, "Attempted to change the global '"); - lua_pushliteral(l, "' in "); - lua_pushstring(l, filename); - lua_pushliteral(l, " - use nmap.registry if you really want to share " - "data between scripts."); - lua_concat(l, 3); - lua_pushcclosure(l, global_error, 2); - lua_setfield(l, -2, "__newindex"); - - lua_setmetatable(l, -2); - - /* store the initialized test in either - * the hosttests or the porttests - * */ - lua_getfield(l, -1, PORTRULE); - lua_getfield(l, -2, HOSTRULE); - - /* if we are looking at a portrule then store it in the porttestsets table - * if it is a hostrule, then it goes into the hosttestsets table - * otherwise we fail - * if there is no action in the script we also fail - * */ - if(lua_isnil(l, -2) == 0) { - lua_pop(l, 2); - lua_getglobal(l, PORTTESTS); - rule_count = lua_objlen(l, -1); - lua_pushvalue(l, -2); - lua_rawseti(l, -2, (rule_count + 1)); - lua_pop(l, 1); // pop the porttests table - } else if(lua_isnil(l, -1) == 0) { - lua_pop(l, 2); - lua_getglobal(l, HOSTTESTS); - rule_count = lua_objlen(l, -1); - lua_pushvalue(l, -2); - lua_rawseti(l, -2, (rule_count + 1)); - lua_pop(l, 1); // pop the hosttests table - } else { - error("%s: No rules in script '%s'.", SCRIPT_ENGINE, filename); - return SCRIPT_ENGINE_ERROR; - } - - std::vector required_fields; - required_fields.push_back(std::string(ACTION)); - required_fields.push_back(std::string(DESCRIPTION)); - - std::vector::iterator iter; - for(iter = required_fields.begin(); iter != required_fields.end(); iter++) { - lua_getfield(l, -1, (*iter).c_str()); - if(lua_isnil(l, -1) == 1) { - error("%s: No '%s' field in script '%s'.", SCRIPT_ENGINE, (*iter).c_str(), filename); - return SCRIPT_ENGINE_ERROR; - } - lua_pop(l, 1); // pop the action - } - - - lua_pop(l, 1); // pop the closure - - return SCRIPT_ENGINE_SUCCESS; + // Compute some stats + SCRIPT_ENGINE_DEBUGGING( + int rules_count; + + lua_getglobal(L, HOSTTESTS); + rules_count = lua_objlen(L, -1); + + lua_getglobal(L, PORTTESTS); + rules_count += lua_objlen(L, -1); + lua_pop(L, 2); + log_write(LOG_STDOUT, "%s: Initialized %d rules\n", SCRIPT_ENGINE, rules_count); + ) + return 0; } - diff --git a/nse_init.h b/nse_init.h index 83d1d4f3fc..ac9f52dcf6 100644 --- a/nse_init.h +++ b/nse_init.h @@ -13,19 +13,18 @@ extern "C" { // initialize the lua state // opens the standard libraries and the nmap lua library -int init_lua(lua_State* l); +int init_lua(lua_State* L); //takes the script arguments provided to nmap through --script-args and //processes and checks them - leaves the processed string on the stack -int init_parseargs(lua_State* l); +int init_parseargs(lua_State* L); //sets the previously parsed args inside nmap.registry -int init_setargs(lua_State* l); +int init_setargs(lua_State* L); // you give it a description of scripts to run and it // populates the tables 'hosttests' and 'porttests' in l with // activation records for tests -int init_rules(lua_State* l, std::vector chosenScripts); -int init_updatedb(lua_State* l); +int init_rules(lua_State *L); +int init_updatedb(lua_State* L); #endif - diff --git a/nse_macros.h b/nse_macros.h index 07e89d132a..e099a24793 100644 --- a/nse_macros.h +++ b/nse_macros.h @@ -32,7 +32,7 @@ #define SCRIPT_ENGINE_EXTENSION ".nse" #define SCRIPT_ENGINE_LUA_TRY(func) if (func != 0) {\ - error("LUA INTERPRETER in %s:%d: %s", __FILE__, __LINE__, (char *)lua_tostring(l, -1));\ + error("LUA INTERPRETER in %s:%d: %s", __FILE__, __LINE__, (char *)lua_tostring(L, -1));\ return SCRIPT_ENGINE_LUA_ERROR;\ } @@ -40,10 +40,11 @@ return SCRIPT_ENGINE_ERROR;\ } +#define ARRAY_LEN(a) ((int)(sizeof(a) / sizeof(a[0]))) + #define SCRIPT_ENGINE_VERBOSE(msg) if (o.debugging || o.verbose > 0) {msg}; #define SCRIPT_ENGINE_DEBUGGING(msg) if (o.debugging) {msg}; -#define MATCH 0 #define MAX_FILENAME_LEN 4096 #define NOT_PRINTABLE '.' diff --git a/nse_main.cc b/nse_main.cc index 1c04fa6d32..c6b4435cc9 100644 --- a/nse_main.cc +++ b/nse_main.cc @@ -39,7 +39,8 @@ struct thread_record { run_record* rr; }; -std::map current_hosts; +int current_hosts = 0; +int errfunc = 0; std::list > torun_scripts; std::list running_scripts; std::list waiting_scripts; @@ -53,88 +54,118 @@ class CompareRunlevels { // prior execution int process_preparerunlevels(std::list torun_threads); -int process_preparehost(lua_State* l, Target* target, std::list& torun_threads); -int process_preparethread(lua_State* l, struct run_record rr, struct thread_record* tr); +int process_preparehost(lua_State* L, Target* target, std::list& torun_threads); +int process_preparethread(lua_State* L, struct run_record rr, struct thread_record* tr); // helper functions -int process_getScriptId(lua_State* l, struct script_scan_result* ssr); +int process_getScriptId(lua_State* L, struct script_scan_result* ssr); int process_pickScriptsForPort( - lua_State* l, + lua_State* L, Target* target, Port* port, std::vector& torun); // execution -int process_mainloop(lua_State* l); -int process_waiting2running(lua_State* l, int resume_arguments); -int process_finalize(lua_State* l, unsigned int registry_idx); - -int script_updatedb() { - int status; - lua_State* l; - - SCRIPT_ENGINE_VERBOSE( - log_write(LOG_STDOUT, "%s: Updating rule database.\n", - SCRIPT_ENGINE); - ) - - l = luaL_newstate(); - if(l == NULL) { - error("%s: Failed luaL_newstate()", SCRIPT_ENGINE); - return 0; - } - - status = init_lua(l); - if(status != SCRIPT_ENGINE_SUCCESS) { - goto finishup; - } - - status = init_updatedb(l); - if(status != SCRIPT_ENGINE_SUCCESS) { - goto finishup; - } - - log_write(LOG_STDOUT, "NSE script database updated successfully.\n"); +int process_mainloop(lua_State* L); +int process_waiting2running(lua_State* L, int resume_arguments); +int process_finalize(lua_State* L, unsigned int registry_idx); + +static int panic (lua_State *L) +{ + const char *err = lua_tostring(L, 1); + fatal("Unprotected error in Lua:\n%s\n", err); + return 0; +} -finishup: - lua_close(l); - if(status != SCRIPT_ENGINE_SUCCESS) { - error("%s: Aborting database update.\n", SCRIPT_ENGINE); - return SCRIPT_ENGINE_ERROR; - } else { - return SCRIPT_ENGINE_SUCCESS; - } +int script_updatedb (void) +{ + int status; + int ret; + lua_State *L; + + SCRIPT_ENGINE_VERBOSE( + log_write(LOG_STDOUT, "%s: Updating rule database.\n", + SCRIPT_ENGINE); + ) + + L = luaL_newstate(); + if (L == NULL) + { + error("%s: Failed luaL_newstate()", SCRIPT_ENGINE); + return 0; + } + 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)); + ret = SCRIPT_ENGINE_ERROR; + goto finishup; + } + + lua_settop(L, 0); // safety, is 0 anyway + lua_rawgeti(L, LUA_REGISTRYINDEX, errfunc); // index 1 + + lua_pushcclosure(L, init_updatedb, 0); + status = lua_pcall(L, 0, 0, 1); + if(status != 0) + { + error("%s: error while updating Script Database:\n%s\n", + SCRIPT_ENGINE, lua_tostring(L, -1)); + ret = SCRIPT_ENGINE_ERROR; + goto finishup; + } + + log_write(LOG_STDOUT, "NSE script database updated successfully.\n"); + + finishup: + lua_close(L); + if (ret != SCRIPT_ENGINE_SUCCESS) + { + error("%s: Aborting database update.\n", SCRIPT_ENGINE); + return SCRIPT_ENGINE_ERROR; + } + else + return SCRIPT_ENGINE_SUCCESS; } -//int check_scripts(){ -//} /* check the script-arguments provided to nmap (--script-args) before * scanning starts - otherwise the whole scan will run through and be * aborted before script-scanning */ -int script_check_args(){ - lua_State* l; - const char *argbuf; - size_t argbuflen; - - l= luaL_newstate(); - if(l==NULL){ - fatal("Error opening lua, for checking arguments\n"); - } - /* set all global libraries (we'll need the string-lib) */ - SCRIPT_ENGINE_TRY(init_lua(l)); - SCRIPT_ENGINE_TRY(init_parseargs(l)); - lua_pushstring(l,"t={"); - lua_insert(l,-2); - lua_pushstring(l,"}"); - lua_concat(l,3); - argbuf=lua_tolstring(l,-1,&argbuflen); - luaL_loadbuffer(l,argbuf,argbuflen,"Script-Arguments-prerun"); - SCRIPT_ENGINE_TRY(lua_pcall(l,0,0,0)); - - lua_close(l); - return SCRIPT_ENGINE_SUCCESS; +int script_check_args (void) +{ + int ret = SCRIPT_ENGINE_SUCCESS, status; + lua_State* L = luaL_newstate(); + + if (L == NULL) + fatal("Error opening lua, for checking arguments\n"); + lua_atpanic(L, panic); + + /* set all global libraries (we'll need the string-lib) */ + 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)); + ret = SCRIPT_ENGINE_ERROR; + goto finishup; + } + + lua_pushcclosure(L, init_parseargs, 0); + lua_pushstring(L, o.scriptargs); + lua_pcall(L, 1, 1, 0); + + if (!lua_isfunction(L, -1)) + ret = SCRIPT_ENGINE_ERROR; + + finishup: + lua_close(L); + return ret; } + /* open a lua instance * open the lua standard libraries * open all the scripts and prepare them for execution @@ -147,7 +178,8 @@ int script_scan(std::vector &targets) { std::list >::iterator runlevel_iter; std::list::iterator thr_iter; std::list torun_threads; - lua_State* l; + std::vector::iterator script_iter; + lua_State* L; o.current_scantype = SCRIPT_SCAN; @@ -166,34 +198,66 @@ int script_scan(std::vector &targets) { SCRIPT_ENGINE, (*targets.begin())->NameIP(targetstr, sizeof(targetstr))); ) - l = luaL_newstate(); - if(l == NULL) { + L = luaL_newstate(); + if(L == NULL) { error("%s: Failed luaL_newstate()", SCRIPT_ENGINE); - return 0; + return SCRIPT_ENGINE_ERROR; } + lua_atpanic(L, panic); - status = init_lua(l); - if(status != SCRIPT_ENGINE_SUCCESS) { - goto finishup; - } - //set the arguments - if provided - status = init_setargs(l); - if(status != SCRIPT_ENGINE_SUCCESS) { - goto finishup; - } + 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; + } - status = init_rules(l, o.chosenScripts); - if(status != SCRIPT_ENGINE_SUCCESS) { - 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; + } + + lua_settop(L, 0); // safety, is 0 anyway + lua_rawgeti(L, LUA_REGISTRYINDEX, errfunc); // index 1 + + if (!lua_checkstack(L, o.chosenScripts.size() + 1)) + { + error("%s: stack overflow at %s:%d", SCRIPT_ENGINE, __FILE__, __LINE__); + status = SCRIPT_ENGINE_ERROR; + goto finishup; + } + lua_pushcclosure(L, init_rules, 0); + for (script_iter = o.chosenScripts.begin(); + script_iter != o.chosenScripts.end(); + script_iter++) + lua_pushstring(L, script_iter->c_str()); + 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; + } SCRIPT_ENGINE_DEBUGGING(log_write(LOG_STDOUT, "%s: Matching rules.\n", SCRIPT_ENGINE);) for(target_iter = targets.begin(); target_iter != targets.end(); target_iter++) { std::string key = ((Target*) (*target_iter))->targetipstr(); - current_hosts[key] = (Target*) *target_iter; + lua_rawgeti(L, LUA_REGISTRYINDEX, current_hosts); + lua_pushstring(L, key.c_str()); + lua_pushlightuserdata(L, (void *) *target_iter); + lua_settable(L, -3); + lua_pop(L, 1); - status = process_preparehost(l, *target_iter, torun_threads); + status = process_preparehost(L, *target_iter, torun_threads); if(status != SCRIPT_ENGINE_SUCCESS){ goto finishup; } @@ -222,7 +286,7 @@ int script_scan(std::vector &targets) { if (!thr_iter->rr->host->timeOutClockRunning()) thr_iter->rr->host->startTimeOutClock(NULL); - status = process_mainloop(l); + status = process_mainloop(L); if(status != SCRIPT_ENGINE_SUCCESS){ goto finishup; } @@ -233,8 +297,7 @@ int script_scan(std::vector &targets) { SCRIPT_ENGINE_DEBUGGING( log_write(LOG_STDOUT, "%s: Script scanning completed.\n", SCRIPT_ENGINE); ) - lua_close(l); - current_hosts.clear(); + lua_close(L); torun_scripts.clear(); if(status != SCRIPT_ENGINE_SUCCESS) { error("%s: Aborting script scan.", SCRIPT_ENGINE); @@ -244,7 +307,7 @@ int script_scan(std::vector &targets) { } } -int process_mainloop(lua_State* l) { +int process_mainloop(lua_State *L) { int state; int unfinished = running_scripts.size() + waiting_scripts.size(); struct script_scan_result ssr; @@ -333,8 +396,8 @@ int process_mainloop(lua_State* l) { lua_pop(current.thread, 2); } - SCRIPT_ENGINE_TRY(process_finalize(l, current.registry_idx)); - SCRIPT_ENGINE_TRY(lua_gc(l, LUA_GCCOLLECT, 0)); + SCRIPT_ENGINE_TRY(process_finalize(L, current.registry_idx)); + SCRIPT_ENGINE_TRY(lua_gc(L, LUA_GCCOLLECT, 0)); } else { // this script returned because of an error // print the failing reason if the verbose level is high enough @@ -342,7 +405,7 @@ int process_mainloop(lua_State* l) { const char* errmsg = lua_tostring(current.thread, -1); log_write(LOG_STDOUT, "%s: %s\n", SCRIPT_ENGINE, errmsg); ) - SCRIPT_ENGINE_TRY(process_finalize(l, current.registry_idx)); + SCRIPT_ENGINE_TRY(process_finalize(L, current.registry_idx)); } } // while } @@ -368,8 +431,8 @@ int has_target_finished(Target *target) { return 1; } -int process_finalize(lua_State* l, unsigned int registry_idx) { - luaL_unref(l, LUA_REGISTRYINDEX, registry_idx); +int process_finalize(lua_State* L, unsigned int registry_idx) { + luaL_unref(L, LUA_REGISTRYINDEX, registry_idx); struct thread_record thr = running_scripts.front(); running_scripts.pop_front(); @@ -380,12 +443,12 @@ int process_finalize(lua_State* l, unsigned int registry_idx) { return SCRIPT_ENGINE_SUCCESS; } -int process_waiting2running(lua_State* l, int resume_arguments) { +int process_waiting2running(lua_State* L, int resume_arguments) { std::list::iterator iter; // find the lua state which has received i/o for( iter = waiting_scripts.begin(); - (*iter).thread != l; + (*iter).thread != L; iter++) { // It is very unlikely that a thread which @@ -417,23 +480,23 @@ int process_waiting2running(lua_State* l, int resume_arguments) { * if no 'id' field is found, the filename field is used which we set in the * setup phase. If someone changed the filename field to a nonstring we complain * */ -int process_getScriptId(lua_State* l, struct script_scan_result *ssr) { +int process_getScriptId(lua_State* L, struct script_scan_result *ssr) { - lua_getfield(l, -2, "id"); - lua_getfield(l, -3, "filename"); + lua_getfield(L, -2, "id"); + lua_getfield(L, -3, "filename"); - if(lua_isstring(l, -2)) { - ssr->id = strdup(lua_tostring (l, -2)); - } else if(lua_isstring(l, -1)) { - ssr->id = strdup(lua_tostring (l, -1)); + if(lua_isstring(L, -2)) { + ssr->id = strdup(lua_tostring (L, -2)); + } else if(lua_isstring(L, -1)) { + ssr->id = strdup(lua_tostring (L, -1)); } else { error("%s: The script has no 'id' entry, the 'filename' entry was changed to:", SCRIPT_ENGINE); - l_dumpValue(l, -1); + l_dumpValue(L, -1); return SCRIPT_ENGINE_ERROR; } - lua_pop(l, 2); + lua_pop(L, 2); return SCRIPT_ENGINE_SUCCESS; } @@ -444,7 +507,7 @@ int process_getScriptId(lua_State* l, struct script_scan_result *ssr) { * which want to run * process all scripts in the list * */ -int process_preparehost(lua_State* l, Target* target, std::list& torun_threads) { +int process_preparehost(lua_State* L, Target* target, std::list& torun_threads) { PortList* plist = &(target->ports); Port* current = NULL; size_t rules_count; @@ -455,20 +518,20 @@ int process_preparehost(lua_State* l, Target* target, std::listtargetipstr()); - lua_pop(l, 1); + lua_pop(L, 1); ) } - lua_pop(l, 2); + lua_pop(L, 2); } /* find the matching port rules * */ - lua_getglobal(l, PORTTESTS); + lua_getglobal(L, PORTTESTS); /* we only publish hostinfo once per portrule */ - lua_newtable(l); - set_hostinfo(l, target); + lua_newtable(L); + set_hostinfo(L, target); /* because of the port iteration API we need to awkwardly iterate * over the kinds of ports we're interested in explictely. * */ current = NULL; while((current = plist->nextPort(current, TCPANDUDP, PORT_OPEN)) != NULL) { - SCRIPT_ENGINE_TRY(process_pickScriptsForPort(l, target, current, torun)); + SCRIPT_ENGINE_TRY(process_pickScriptsForPort(L, target, current, torun)); } while((current = plist->nextPort(current, TCPANDUDP, PORT_OPENFILTERED)) != NULL) { - SCRIPT_ENGINE_TRY(process_pickScriptsForPort(l, target, current, torun)); + SCRIPT_ENGINE_TRY(process_pickScriptsForPort(L, target, current, torun)); } while((current = plist->nextPort(current, TCPANDUDP, PORT_UNFILTERED)) != NULL) { - SCRIPT_ENGINE_TRY(process_pickScriptsForPort(l, target, current, torun)); + SCRIPT_ENGINE_TRY(process_pickScriptsForPort(L, target, current, torun)); } // pop the hostinfo, we don't need it anymore - lua_pop(l, 1); + lua_pop(L, 1); /* ok, let's setup threads for the scripts which said they'd like * to run @@ -531,14 +594,14 @@ int process_preparehost(lua_State* l, Target* target, std::list torun_threads) { } /* Because we can't iterate over all ports of interest in one go - * we need to du port matching in a separate function (unlike host + * we need to do port matching in a separate function (unlike host * rule matching) * Note that we assume that at -2 on the stack we can find the portrules * and at -1 the hostinfo table * */ int process_pickScriptsForPort( - lua_State* l, + lua_State* L, Target* target, Port* port, std::vector& torun) { - size_t rules_count = lua_objlen(l, -2); + size_t rules_count = lua_objlen(L, -2); struct run_record rr; unsigned int i; for(i = 1; i <= rules_count; i++) { - lua_rawgeti(l, -2, i); + lua_rawgeti(L, -2, i); - lua_getfield(l, -1, PORTRULE); + lua_getfield(L, -1, PORTRULE); - lua_pushvalue(l, -3); + lua_pushvalue(L, -3); - lua_newtable(l); - set_portinfo(l, port); + lua_newtable(L); + set_portinfo(L, port); - SCRIPT_ENGINE_LUA_TRY(lua_pcall(l, 2, 1, 0)); + SCRIPT_ENGINE_LUA_TRY(lua_pcall(L, 2, 1, 0)); - if(lua_isboolean (l, -1) && lua_toboolean(l, -1)) { + if(lua_isboolean (L, -1) && lua_toboolean(L, -1)) { rr.type = 1; rr.index = i; rr.port = port; @@ -613,23 +676,23 @@ int process_pickScriptsForPort( torun.push_back(rr); SCRIPT_ENGINE_DEBUGGING( - lua_getfield(l, -2, "filename"); + lua_getfield(L, -2, "filename"); log_write(LOG_STDOUT, "%s: Will run %s against %s:%d\n", SCRIPT_ENGINE, - lua_tostring(l, -1), + lua_tostring(L, -1), target->targetipstr(), port->portno); - lua_pop(l, 1); + lua_pop(L, 1); ) - } else if(!lua_isboolean (l, -1)) { - lua_getfield(l, -2, "filename"); + } else if(!lua_isboolean (L, -1)) { + lua_getfield(L, -2, "filename"); error("%s: Rule in %s returned %s but boolean was expected.", SCRIPT_ENGINE, - lua_tostring(l, -1), - lua_typename(l, lua_type(l, -2))); + lua_tostring(L, -1), + lua_typename(L, lua_type(L, -2))); return SCRIPT_ENGINE_LUA_ERROR; } - lua_pop(l, 2); + lua_pop(L, 2); } return SCRIPT_ENGINE_SUCCESS; @@ -639,14 +702,14 @@ int process_pickScriptsForPort( * we store target info in the thread so that the mainloop * knows where to put the script result * */ -int process_preparethread(lua_State* l, struct run_record rr, struct thread_record* tr){ +int process_preparethread(lua_State* L, struct run_record rr, struct thread_record* tr){ - lua_State *thread = lua_newthread(l); + lua_State *thread = lua_newthread(L); - lua_rawgeti(l, -2, rr.index); // get the script closure + lua_rawgeti(L, -2, rr.index); // get the script closure // move the script closure into the thread - lua_xmove(l, thread, 1); + lua_xmove(L, thread, 1); // store the target of this thread in the thread struct run_record *rr_thread = (struct run_record*) safe_malloc(sizeof(struct run_record)); @@ -674,7 +737,7 @@ int process_preparethread(lua_State* l, struct run_record rr, struct thread_reco // we store the thread in the registry to prevent // garbage collection + - tr->registry_idx = luaL_ref(l, LUA_REGISTRYINDEX); + tr->registry_idx = luaL_ref(L, LUA_REGISTRYINDEX); /* if this is a host rule we don't have * a port state diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc index 22eb8d64b2..3f33c6f99f 100644 --- a/nse_nmaplib.cc +++ b/nse_nmaplib.cc @@ -14,40 +14,41 @@ #define SCRIPT_ENGINE_GETSTRING(name) \ char* name; \ - lua_getfield(l, -1, #name); \ - if(lua_isnil(l, -1)) \ + lua_getfield(L, -1, #name); \ + if(lua_isnil(L, -1)) \ name = NULL; \ else \ - name = strdup(lua_tostring(l, -1)); \ - lua_pop(l, 1); \ + name = strdup(lua_tostring(L, -1)); \ + lua_pop(L, 1); \ #define SCRIPT_ENGINE_PUSHSTRING_NOTNULL(c_str, str) if(c_str != NULL) {\ - lua_pushstring(l, c_str); \ - lua_setfield(l, -2, str); \ + lua_pushstring(L, c_str); \ + lua_setfield(L, -2, str); \ } extern NmapOps o; -extern std::map current_hosts; +/* extern std::map current_hosts; */ +extern int current_hosts; -void set_version(lua_State* l, struct serviceDeductions sd); +void set_version(lua_State *L, struct serviceDeductions sd); -static int l_exc_newtry(lua_State *l); -static int l_port_accessor(lua_State* l); -static int l_print_debug_unformatted(lua_State *l); -static int l_get_port_state(lua_State* l, Target* target, Port* port); -static int l_set_port_state(lua_State* l, Target* target, Port* port); -static int l_set_port_version(lua_State* l, Target* target, Port* port); +static int l_exc_newtry(lua_State *L); +static int l_port_accessor(lua_State *L); +static int l_print_debug_unformatted(lua_State *L); +static int l_get_port_state(lua_State *L, Target* target, Port* port); +static int l_set_port_state(lua_State *L, Target* target, Port* port); +static int l_set_port_version(lua_State *L, Target* target, Port* port); static int l_get_verbosity(lua_State *); static int l_get_debugging(lua_State *); -static int l_get_have_ssl(lua_State *l); -static int l_fetchfile(lua_State *l); +static int l_get_have_ssl(lua_State *L); +static int l_fetchfile(lua_State *L); -int l_clock_ms(lua_State* l); +int l_clock_ms(lua_State *L); /* register the nmap lib * we assume that we can write to a table at -1 on the stack * */ -int set_nmaplib(lua_State* l) { +/* int set_nmaplib(lua_State *L) { static luaL_reg nmaplib [] = { {"get_port_state", l_port_accessor}, {"set_port_state", l_port_accessor}, @@ -67,52 +68,82 @@ int set_nmaplib(lua_State* l) { const luaL_Reg* lib; for (lib = nmaplib; lib->func; lib++) { - lua_pushcfunction(l, lib->func); - lua_setfield(l, -2, lib->name); + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); } - lua_newtable(l); - lua_setfield(l, -2, "registry"); + lua_newtable(L); + lua_setfield(L, -2, "registry"); - SCRIPT_ENGINE_TRY(l_nsock_open(l)); - SCRIPT_ENGINE_TRY(l_dnet_open(l)); + SCRIPT_ENGINE_TRY(l_nsock_open(L)); + SCRIPT_ENGINE_TRY(l_dnet_open(L)); return SCRIPT_ENGINE_SUCCESS; +} */ + +int luaopen_nmap (lua_State *L) +{ + static luaL_reg nmaplib [] = { + {"get_port_state", l_port_accessor}, + {"set_port_state", l_port_accessor}, + {"set_port_version", l_port_accessor}, + {"new_socket", l_nsock_new}, + {"new_dnet", l_dnet_new}, + {"get_interface_link", l_dnet_get_interface_link}, + {"clock_ms", l_clock_ms}, + {"print_debug_unformatted", l_print_debug_unformatted}, + {"new_try", l_exc_newtry}, + {"verbosity", l_get_verbosity}, + {"debugging", l_get_debugging}, + {"have_ssl", l_get_have_ssl}, + {"fetchfile", l_fetchfile}, + {NULL, NULL} + }; + + luaL_register(L, "nmap", nmaplib); + + lua_newtable(L); + lua_setfield(L, -2, "registry"); + + SCRIPT_ENGINE_TRY(l_nsock_open(L)); + SCRIPT_ENGINE_TRY(l_dnet_open(L)); + + return 0; } /* set some port state information onto the * table which is currently on the stack * */ -void set_portinfo(lua_State* l, Port* port) { +void set_portinfo(lua_State *L, Port* port) { struct serviceDeductions sd; port->getServiceDeductions(&sd); - lua_pushnumber(l, (double) port->portno); - lua_setfield(l, -2, "number"); + lua_pushnumber(L, (double) port->portno); + lua_setfield(L, -2, "number"); - lua_pushstring(l, sd.name); - lua_setfield(l, -2, "service"); + lua_pushstring(L, sd.name); + lua_setfield(L, -2, "service"); - lua_pushstring(l, (port->proto == IPPROTO_TCP)? "tcp": "udp"); - lua_setfield(l, -2, "protocol"); + lua_pushstring(L, (port->proto == IPPROTO_TCP)? "tcp": "udp"); + lua_setfield(L, -2, "protocol"); - lua_newtable(l); - set_version(l, sd); - lua_setfield(l, -2, "version"); + lua_newtable(L); + set_version(L, sd); + lua_setfield(L, -2, "version"); - lua_pushstring(l, statenum2str(port->state)); - lua_setfield(l, -2, "state"); + lua_pushstring(L, statenum2str(port->state)); + lua_setfield(L, -2, "state"); - lua_pushstring(l, reason_str(port->reason.reason_id, 1)); - lua_setfield(l, -2, "reason"); + lua_pushstring(L, reason_str(port->reason.reason_id, 1)); + lua_setfield(L, -2, "reason"); } -void set_version(lua_State* l, struct serviceDeductions sd) { +void set_version(lua_State *L, struct serviceDeductions sd) { SCRIPT_ENGINE_PUSHSTRING_NOTNULL(sd.name, "name"); - lua_pushnumber(l, sd.name_confidence); - lua_setfield(l, -2, "name_confidence"); + lua_pushnumber(L, sd.name_confidence); + lua_setfield(L, -2, "name_confidence"); SCRIPT_ENGINE_PUSHSTRING_NOTNULL(sd.product, "product"); SCRIPT_ENGINE_PUSHSTRING_NOTNULL(sd.version, "version"); @@ -169,14 +200,14 @@ void set_version(lua_State* l, struct serviceDeductions sd) { } if(sd.rpc_status == RPC_STATUS_GOOD_PROG) { - lua_pushnumber(l, sd.rpc_program); - lua_setfield(l, -2, "rpc_program"); + lua_pushnumber(L, sd.rpc_program); + lua_setfield(L, -2, "rpc_program"); - lua_pushnumber(l, sd.rpc_lowver); - lua_setfield(l, -2, "rpc_lowver"); + lua_pushnumber(L, sd.rpc_lowver); + lua_setfield(L, -2, "rpc_lowver"); - lua_pushnumber(l, sd.rpc_highver); - lua_setfield(l, -2, "rpc_highver"); + lua_pushnumber(L, sd.rpc_highver); + lua_setfield(L, -2, "rpc_highver"); } } @@ -189,47 +220,47 @@ void set_version(lua_State* l, struct serviceDeductions sd) { * if an os scan wasn't performed, the array * points to nil! * */ -void set_hostinfo(lua_State* l, Target *currenths) { +void set_hostinfo(lua_State *L, Target *currenths) { unsigned int i; char hostname[1024]; - lua_pushstring(l, strncpy(hostname, currenths->targetipstr(), 1024)); - lua_setfield(l, -2, "ip"); + lua_pushstring(L, strncpy(hostname, currenths->targetipstr(), 1024)); + lua_setfield(L, -2, "ip"); - lua_pushstring(l, strncpy(hostname, currenths->HostName(), 1024)); - lua_setfield(l, -2, "name"); + lua_pushstring(L, strncpy(hostname, currenths->HostName(), 1024)); + lua_setfield(L, -2, "name"); if ( currenths->TargetName() ) { // else nil - lua_pushstring(l, strncpy(hostname, currenths->TargetName(), 1024)); - lua_setfield(l, -2, "targetname"); + lua_pushstring(L, strncpy(hostname, currenths->TargetName(), 1024)); + lua_setfield(L, -2, "targetname"); } if(currenths->directlyConnectedOrUnset() != -1){ - lua_pushboolean(l, currenths->directlyConnected()); - lua_setfield(l, -2, "directly_connected"); + lua_pushboolean(L, currenths->directlyConnected()); + lua_setfield(L, -2, "directly_connected"); } if(currenths->MACAddress()){ // else nil - lua_pushlstring (l, (const char*)currenths->MACAddress() , 6); - lua_setfield(l, -2, "mac_addr"); + lua_pushlstring (L, (const char*)currenths->MACAddress() , 6); + lua_setfield(L, -2, "mac_addr"); } if(currenths->SrcMACAddress()){ // else nil - lua_pushlstring(l, (const char*)currenths->SrcMACAddress(), 6); - lua_setfield(l, -2, "mac_addr_src"); + lua_pushlstring(L, (const char*)currenths->SrcMACAddress(), 6); + lua_setfield(L, -2, "mac_addr_src"); } if(currenths->deviceName()){ - lua_pushstring(l, strncpy(hostname, currenths->deviceName(), 1024)); - lua_setfield(l, -2, "interface"); + lua_pushstring(L, strncpy(hostname, currenths->deviceName(), 1024)); + lua_setfield(L, -2, "interface"); } if( (u32)(currenths->v4host().s_addr) ){ struct in_addr adr = currenths->v4host(); - lua_pushlstring(l, (char*)&adr, 4); - lua_setfield(l, -2, "bin_ip"); + lua_pushlstring(L, (char*)&adr, 4); + lua_setfield(L, -2, "bin_ip"); } if( (u32)(currenths->v4source().s_addr) ){ struct in_addr adr = currenths->v4source(); - lua_pushlstring(l, (char*)&adr, 4); - lua_setfield(l, -2, "bin_ip_src"); + lua_pushlstring(L, (char*)&adr, 4); + lua_setfield(L, -2, "bin_ip_src"); } FingerPrintResults *FPR = NULL; @@ -246,22 +277,22 @@ void set_hostinfo(lua_State* l, Target *currenths) { FPR->num_perfect_matches > 0 && FPR->num_perfect_matches <= 8 ) { - lua_newtable(l); + lua_newtable(L); // this will run at least one time and at most 8 times, see if condition for(i = 0; FPR->accuracy[i] == 1; i++) { - lua_pushstring(l, FPR->prints[i]->OS_name); - lua_rawseti(l, -2, i); + lua_pushstring(L, FPR->prints[i]->OS_name); + lua_rawseti(L, -2, i); } - lua_setfield(l, -2, "os"); + lua_setfield(L, -2, "os"); } } -static int l_port_accessor(lua_State* l) { +static int l_port_accessor(lua_State *L) { int retvalues = 0; char* function_name; - char* target_ip; + const char *target_ip; int portno; int proto; @@ -270,36 +301,38 @@ static int l_port_accessor(lua_State* l) { Port* port; lua_Debug ldebug; - lua_getstack(l, 0, &ldebug); - lua_getinfo(l, "n", &ldebug); + lua_getstack(L, 0, &ldebug); + lua_getinfo(L, "n", &ldebug); function_name = strdup(ldebug.name); - luaL_checktype(l, 1, LUA_TTABLE); - luaL_checktype(l, 2, LUA_TTABLE); - - lua_getfield(l, 1, "ip"); - luaL_checktype(l, -1, LUA_TSTRING); - target_ip = strdup(lua_tostring(l, -1)); - lua_pop(l, 1); - - lua_getfield(l, 2, "number"); - luaL_checktype(l, -1, LUA_TNUMBER); - portno = lua_tointeger(l, -1); - lua_pop(l, 1); - - lua_getfield(l, 2, "protocol"); - luaL_checktype(l, -1, LUA_TSTRING); - proto = (strcmp(lua_tostring(l, -1), "tcp") == 0)? IPPROTO_TCP : IPPROTO_UDP; - lua_pop(l, 1); - - std::string key = std::string(target_ip); - std::map::iterator iter = current_hosts.find(key); - if(iter == current_hosts.end()) { - luaL_argerror (l, 1, "Host isn't being processed right now."); - return 0; - } else { - target = (Target*) iter->second; - } + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TTABLE); + + lua_getfield(L, 1, "ip"); + luaL_checktype(L, -1, LUA_TSTRING); + target_ip = lua_tostring(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 2, "number"); + luaL_checktype(L, -1, LUA_TNUMBER); + portno = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 2, "protocol"); + luaL_checktype(L, -1, LUA_TSTRING); + proto = (strcmp(lua_tostring(L, -1), "tcp") == 0)? IPPROTO_TCP : IPPROTO_UDP; + lua_pop(L, 1); + + lua_rawgeti(L, LUA_REGISTRYINDEX, current_hosts); + lua_pushstring(L, target_ip); + lua_gettable(L, -2); + if (lua_isnil(L, -1)) + return luaL_argerror(L, 1, "Host isn't being processed right now."); + else + { + target = (Target *) lua_touserdata(L, -1); + lua_pop(L, 2); + } plist = &(target->ports); port = NULL; @@ -311,22 +344,20 @@ static int l_port_accessor(lua_State* l) { // if the port wasn't scanned we return nil if(port == NULL) { - free(target_ip); free(function_name); return 0; } - if(strcmp(function_name, "set_port_state") == MATCH) - retvalues = l_set_port_state(l, target, port); - else if(strcmp(function_name, "set_port_version") == MATCH) - retvalues = l_set_port_version(l, target, port); - else if(strcmp(function_name, "get_port_state") == MATCH) - retvalues = l_get_port_state(l, target, port); + if(strcmp(function_name, "set_port_state") == 0) + retvalues = l_set_port_state(L, target, port); + else if(strcmp(function_name, "set_port_version") == 0) + retvalues = l_set_port_version(L, target, port); + else if(strcmp(function_name, "get_port_state") == 0) + retvalues = l_get_port_state(L, target, port); // remove host and port argument from the stack - lua_remove(l, 2); - lua_remove(l, 1); - free(target_ip); + lua_remove(L, 2); + lua_remove(L, 1); free(function_name); return retvalues; } @@ -341,9 +372,9 @@ static int l_port_accessor(lua_State* l) { * this function is useful if we want rules which want to know * the state of more than one port * */ -static int l_get_port_state(lua_State* l, Target* target, Port* port) { - lua_newtable(l); - set_portinfo(l, port); +static int l_get_port_state(lua_State *L, Target* target, Port* port) { + lua_newtable(L); + set_portinfo(L, port); return 1; } @@ -352,18 +383,18 @@ static int l_get_port_state(lua_State* l, Target* target, Port* port) { * if for example a udp port was seen by the script as open instead of * filtered, the script is free to say so. * */ -static int l_set_port_state(lua_State* l, Target* target, Port* port) { +static int l_set_port_state(lua_State *L, Target* target, Port* port) { char* state; PortList* plist = &(target->ports); - luaL_checktype(l, -1, LUA_TSTRING); - state = strdup(lua_tostring(l, -1)); - lua_pop(l, 1); + luaL_checktype(L, -1, LUA_TSTRING); + state = strdup(lua_tostring(L, -1)); + lua_pop(L, 1); switch(state[0]) { case 'o': if (strcmp(state, "open")) - luaL_argerror (l, 4, "Invalid port state."); + luaL_argerror (L, 4, "Invalid port state."); if (port->state == PORT_OPEN) goto noset; plist->addPort(port->portno, port->proto, NULL, PORT_OPEN); @@ -371,14 +402,14 @@ static int l_set_port_state(lua_State* l, Target* target, Port* port) { break; case 'c': if (strcmp(state, "closed")) - luaL_argerror (l, 4, "Invalid port state."); + luaL_argerror (L, 4, "Invalid port state."); if (port->state == PORT_CLOSED) goto noset; plist->addPort(port->portno, port->proto, NULL, PORT_CLOSED); port->state = PORT_CLOSED; break; default: - luaL_argerror (l, 4, "Invalid port state."); + luaL_argerror (L, 4, "Invalid port state."); } port->reason.reason_id = ER_SCRIPT; @@ -388,15 +419,15 @@ static int l_set_port_state(lua_State* l, Target* target, Port* port) { return 0; } -static int l_set_port_version(lua_State* l, Target* target, Port* port) { - luaL_checktype(l, 3, LUA_TSTRING); - char* c_probestate = strdup(lua_tostring(l, -1)); - lua_pop(l, 1); +static int l_set_port_version(lua_State *L, Target* target, Port* port) { + luaL_checktype(L, 3, LUA_TSTRING); + char* c_probestate = strdup(lua_tostring(L, -1)); + lua_pop(L, 1); enum service_tunnel_type tunnel = SERVICE_TUNNEL_NONE; enum serviceprobestate probestate = PROBESTATE_INITIAL; - lua_getfield(l, -1, "version"); + lua_getfield(L, -1, "version"); SCRIPT_ENGINE_GETSTRING(name); SCRIPT_ENGINE_GETSTRING(product); SCRIPT_ENGINE_GETSTRING(version); @@ -414,8 +445,8 @@ static int l_set_port_version(lua_State* l, Target* target, Port* port) { else if(strcmp(service_tunnel, "ssl") == 0) tunnel = SERVICE_TUNNEL_SSL; else - luaL_argerror(l, 2, "Invalid value for port.version.service_tunnel"); - lua_pop(l, 1); + luaL_argerror(L, 2, "Invalid value for port.version.service_tunnel"); + lua_pop(L, 1); if(c_probestate == NULL) probestate = PROBESTATE_INITIAL; @@ -430,7 +461,7 @@ static int l_set_port_version(lua_State* l, Target* target, Port* port) { else if(strcmp(c_probestate, "incomplete") == 0) probestate = PROBESTATE_INCOMPLETE; else - luaL_argerror(l, 3, "Invalid value for probestate."); + luaL_argerror(L, 3, "Invalid value for probestate."); // port->setServiceProbeResults(probestate, name, // tunnel, product, version, @@ -464,33 +495,33 @@ static int l_set_port_version(lua_State* l, Target* target, Port* port) { return 0; } -static int l_print_debug_unformatted(lua_State *l) { +static int l_print_debug_unformatted(lua_State *L) { int verbosity=1; const char *out; - if (lua_gettop(l) != 2) return luaL_error(l, "Incorrect number of arguments\n"); + if (lua_gettop(L) != 2) return luaL_error(L, "Incorrect number of arguments\n"); - verbosity = luaL_checkinteger(l, 1); + verbosity = luaL_checkinteger(L, 1); if (verbosity > o.verbose) return 0; - out = luaL_checkstring(l, 2); + out = luaL_checkstring(L, 2); log_write(LOG_STDOUT, "%s DEBUG: %s\n", SCRIPT_ENGINE, out); return 0; } -static int l_exc_finalize(lua_State *l) { - if (!lua_toboolean(l, 1)) { +static int l_exc_finalize(lua_State *L) { + if (!lua_toboolean(L, 1)) { /* false or nil. */ - lua_pushvalue(l, lua_upvalueindex(1)); - lua_call(l, 0, 0); - lua_settop(l, 2); - lua_error(l); + lua_pushvalue(L, lua_upvalueindex(1)); + lua_call(L, 0, 0); + lua_settop(L, 2); + lua_error(L); return 0; - } else if(lua_isboolean(l, 1) && lua_toboolean(l, 1)) { + } else if(lua_isboolean(L, 1) && lua_toboolean(L, 1)) { /* true. */ - lua_remove(l, 1); - return lua_gettop(l); + lua_remove(L, 1); + return lua_gettop(L); } else { fatal("%s: In: %s:%i Trying to finalize a non conforming function. Are you sure you return true on success followed by the remaining return values and nil on failure followed by an error string?", SCRIPT_ENGINE, __FILE__, __LINE__); @@ -499,44 +530,44 @@ static int l_exc_finalize(lua_State *l) { } } -static int l_exc_do_nothing(lua_State *l) { - (void) l; +static int l_exc_do_nothing(lua_State *L) { + (void) L; return 0; } -static int l_exc_newtry(lua_State *l) { - lua_settop(l, 1); - if (lua_isnil(l, 1)) - lua_pushcfunction(l, l_exc_do_nothing); - lua_pushcclosure(l, l_exc_finalize, 1); +static int l_exc_newtry(lua_State *L) { + lua_settop(L, 1); + if (lua_isnil(L, 1)) + lua_pushcfunction(L, l_exc_do_nothing); + lua_pushcclosure(L, l_exc_finalize, 1); return 1; } -static int l_get_verbosity(lua_State *l) +static int l_get_verbosity(lua_State *L) { - lua_pushnumber(l, o.verbose); + lua_pushnumber(L, o.verbose); return 1; } -static int l_get_debugging(lua_State *l) +static int l_get_debugging(lua_State *L) { - lua_pushnumber(l, o.debugging); + lua_pushnumber(L, o.debugging); return 1; } -static int l_get_have_ssl(lua_State *l) { +static int l_get_have_ssl(lua_State *L) { #if HAVE_OPENSSL - lua_pushboolean(l, true); + lua_pushboolean(L, true); #else - lua_pushboolean(l, false); + lua_pushboolean(L, false); #endif return 1; } -static int l_fetchfile(lua_State *l) +static int l_fetchfile(lua_State *L) { char buf[FILENAME_MAX]; - const char *req = lua_tostring(l, -1); + const char *req = lua_tostring(L, -1); if (!req) goto err; @@ -544,12 +575,12 @@ static int l_fetchfile(lua_State *l) if (nmap_fetchfile(buf, sizeof buf, (char *) req) != 1) goto err; - lua_pop(l, 1); - lua_pushstring(l, buf); + lua_pop(L, 1); + lua_pushstring(L, buf); return 1; err: - lua_pop(l, 1); - lua_pushnil(l); + lua_pop(L, 1); + lua_pushnil(L); return 0; } diff --git a/nse_nmaplib.h b/nse_nmaplib.h index fb612448d0..bfa014460d 100644 --- a/nse_nmaplib.h +++ b/nse_nmaplib.h @@ -10,7 +10,7 @@ extern "C" { class Target; class Port; -int set_nmaplib(lua_State* l); +int luaopen_nmap(lua_State* l); void set_hostinfo(lua_State* l, Target* currenths); void set_portinfo(lua_State* l, Port* port); diff --git a/nse_nsock.cc b/nse_nsock.cc index 3ba0ed17be..23ca643aa3 100644 --- a/nse_nsock.cc +++ b/nse_nsock.cc @@ -37,24 +37,24 @@ extern NmapOps o; // defined in nse_main.cc but also declared here // to keep the .h files clean -int process_waiting2running(lua_State* l, int resume_arguments); - -static int l_nsock_connect(lua_State* l); -static int l_nsock_connect_queued(lua_State* l); -static int l_nsock_send(lua_State* l); -static int l_nsock_receive(lua_State* l); -static int l_nsock_receive_lines(lua_State* l); -static int l_nsock_receive_bytes(lua_State* l); -static int l_nsock_get_info(lua_State* l); -static int l_nsock_gc(lua_State* l); -static int l_nsock_close(lua_State* l); -static int l_nsock_set_timeout(lua_State* l); -static int l_nsock_receive_buf(lua_State* l); - -static int l_nsock_ncap_open(lua_State* l); -static int l_nsock_ncap_close(lua_State* l); -static int l_nsock_ncap_register(lua_State *l); -static int l_nsock_pcap_receive(lua_State* l); +int process_waiting2running(lua_State *L, int resume_arguments); + +static int l_nsock_connect(lua_State *L); +static int l_nsock_connect_queued(lua_State *L); +static int l_nsock_send(lua_State *L); +static int l_nsock_receive(lua_State *L); +static int l_nsock_receive_lines(lua_State *L); +static int l_nsock_receive_bytes(lua_State *L); +static int l_nsock_get_info(lua_State *L); +static int l_nsock_gc(lua_State *L); +static int l_nsock_close(lua_State *L); +static int l_nsock_set_timeout(lua_State *L); +static int l_nsock_receive_buf(lua_State *L); + +static int l_nsock_ncap_open(lua_State *L); +static int l_nsock_ncap_close(lua_State *L); +static int l_nsock_ncap_register(lua_State *L); +static int l_nsock_pcap_receive(lua_State *L); void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *lua_state); @@ -62,9 +62,9 @@ void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state); void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state); void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_state); -int l_nsock_check_buf(lua_State* l); +int l_nsock_check_buf(lua_State *L); -int l_nsock_checkstatus(lua_State* l, nsock_event nse); +int l_nsock_checkstatus(lua_State *L, nsock_event nse); void l_nsock_trace(nsock_iod nsiod, const char* message, int direction); const char* inet_ntop_both(int af, const void* v_addr, char* ipstring); @@ -113,7 +113,7 @@ struct ncap_socket{ */ struct ncap_request{ int suspended; /* is the thread suspended? (lua_yield) */ - lua_State *l; /* lua_State of current process + lua_State *L; /* lua_State of current process * or NULL if process isn't suspended */ nsock_event_id nseid; /* nse for this specific lua_State */ struct timeval end_time; @@ -151,18 +151,18 @@ struct l_nsock_udata { int ncap_cback_ref; }; -void l_nsock_clear_buf(lua_State* l, l_nsock_udata* udata); +void l_nsock_clear_buf(lua_State *L, l_nsock_udata* udata); -int l_nsock_open(lua_State* l) { - luaL_newmetatable(l, "nsock"); - lua_createtable(l, 20, 0); - luaL_register(l, NULL, l_nsock); - lua_setfield(l, -2, "__index"); - lua_pushcclosure(l, l_nsock_gc, 0); - lua_setfield(l, -2, "__gc"); - lua_pushliteral(l, ""); - lua_setfield(l, -2, "__metatable"); // protect metatable - lua_pop(l, 1); +int l_nsock_open(lua_State *L) { + luaL_newmetatable(L, "nsock"); + lua_createtable(L, 0, 20); + luaL_register(L, NULL, l_nsock); + lua_setfield(L, -2, "__index"); + lua_pushcclosure(L, l_nsock_gc, 0); + lua_setfield(L, -2, "__gc"); + lua_pushliteral(L, ""); + lua_setfield(L, -2, "__metatable"); // protect metatable + lua_pop(L, 1); nsp = nsp_new(NULL); //nsp_settrace(nsp, o.debugging, o.getStartTime()); @@ -172,11 +172,11 @@ int l_nsock_open(lua_State* l) { return NSOCK_WRAPPER_SUCCESS; } -int l_nsock_new(lua_State* l) { +int l_nsock_new(lua_State *L) { struct l_nsock_udata* udata; - udata = (struct l_nsock_udata*) lua_newuserdata(l, sizeof(struct l_nsock_udata)); - luaL_getmetatable(l, "nsock"); - lua_setmetatable(l, -2); + udata = (struct l_nsock_udata*) lua_newuserdata(L, sizeof(struct l_nsock_udata)); + luaL_getmetatable(L, "nsock"); + lua_setmetatable(L, -2); udata->nsiod = NULL; udata->ssl_session = NULL; udata->timeout = DEFAULT_TIMEOUT; @@ -193,12 +193,12 @@ int l_nsock_loop(int tout) { return nsock_loop(nsp, tout); } -int l_nsock_checkstatus(lua_State* l, nsock_event nse) { +int l_nsock_checkstatus(lua_State *L, nsock_event nse) { enum nse_status status = nse_status(nse); switch (status) { case NSE_STATUS_SUCCESS: - lua_pushboolean(l, true); + lua_pushboolean(L, true); return NSOCK_WRAPPER_SUCCESS; break; case NSE_STATUS_ERROR: @@ -206,8 +206,8 @@ int l_nsock_checkstatus(lua_State* l, nsock_event nse) { case NSE_STATUS_CANCELLED: case NSE_STATUS_KILL: case NSE_STATUS_EOF: - lua_pushnil(l); - lua_pushstring(l, nse_status2str(status)); + lua_pushnil(L); + lua_pushstring(L, nse_status2str(status)); return NSOCK_WRAPPER_ERROR; break; case NSE_STATUS_NONE: @@ -222,7 +222,7 @@ int l_nsock_checkstatus(lua_State* l, nsock_event nse) { } -static int l_nsock_connect_queued(lua_State* l) { +static int l_nsock_connect_queued(lua_State *L) { /* We allow at least 10 even max_parallelism is 1 because a single script might open a few sockets at once and we don't want it to @@ -230,7 +230,7 @@ static int l_nsock_connect_queued(lua_State* l) { const int max_descriptors_allowed = MAX(o.max_parallelism, 10); - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); if(udata->nsiod!=NULL){ /*should a script try to connect a socket, which is already connected @@ -240,65 +240,65 @@ static int l_nsock_connect_queued(lua_State* l) { if(o.scriptTrace()){ log_write(LOG_STDOUT,"%s: Trying to connect already connected socket - closing!\n",SCRIPT_ENGINE); } - l_nsock_close(l); - lua_pop(l,1); + l_nsock_close(L); + lua_pop(L,1); } if(nsock_descriptors_used >= max_descriptors_allowed){ /* wait for free descriptor */ - nsock_connect_queue.push_back(l); + nsock_connect_queue.push_back(L); /* I must know how many arguments are passed to nsock_connect. * is there a better way? */ int arguments = 3; - const char *how = luaL_optstring(l, 4, ""); + const char *how = luaL_optstring(L, 4, ""); if(*how != '\0'){ arguments = 4; - int port = luaL_optinteger(l, 5, -1); + int port = luaL_optinteger(L, 5, -1); if(port!=-1) arguments = 5; } if(o.scriptTrace()) - log_write(LOG_STDOUT, "NSOCK_connect_queued: thread queued (%i args) %p\n", arguments, (void *)l); + log_write(LOG_STDOUT, "NSOCK_connect_queued: thread queued (%i args) %p\n", arguments, (void *)L); - return lua_yield(l, arguments); + return lua_yield(L, arguments); } - return l_nsock_connect(l); + return l_nsock_connect(L); } void l_nsock_connect_queued_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { - lua_State* l = (lua_State*) lua_state; + lua_State *L = (lua_State*) lua_state; /* well, this is really hackish, we can't just do process_waiting2running, because * nsock_connect() can do lua_yield(). * Instead, we first execute nsock_connect, and if it returns lua_yield() (ie. -1) * than we don't do process_waiting2running. * So, in summary we can do two lua_yield() on thread (one in l_nsock_connect_queued, * second in l_nsock_connect). But it works for me. */ - int r = l_nsock_connect(l); + int r = l_nsock_connect(L); if(r != -1) process_waiting2running((lua_State*) lua_state, 0); } -static int l_nsock_connect(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - const char* addr = luaL_checkstring(l, 2); - unsigned short port = (unsigned short) luaL_checkint(l, 3); - const char *how = luaL_optstring(l, 4, "tcp"); +static int l_nsock_connect(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + const char* addr = luaL_checkstring(L, 2); + unsigned short port = (unsigned short) luaL_checkint(L, 3); + const char *how = luaL_optstring(L, 4, "tcp"); const char* error; struct addrinfo *dest; int error_id; - l_nsock_clear_buf(l, udata); + l_nsock_clear_buf(L, udata); error_id = getaddrinfo(addr, NULL, NULL, &dest); if (error_id) { error = gai_strerror(error_id); - lua_pushboolean(l, false); - lua_pushstring(l, error); + lua_pushboolean(L, false); + lua_pushstring(L, error); return 2; } @@ -309,23 +309,23 @@ static int l_nsock_connect(lua_State* l) { case 't': if (strcmp(how, "tcp")) goto error; nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, - udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port); + udata->timeout, L, dest->ai_addr, dest->ai_addrlen, port); break; case 'u': if (strcmp(how, "udp")) goto error; nsock_connect_udp(nsp, udata->nsiod, l_nsock_connect_handler, - l, dest->ai_addr, dest->ai_addrlen, port); + L, dest->ai_addr, dest->ai_addrlen, port); break; case 's': if (strcmp(how, "ssl")) goto error; #ifdef HAVE_OPENSSL nsock_connect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, - udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port, + udata->timeout, L, dest->ai_addr, dest->ai_addrlen, port, udata->ssl_session); break; #else - lua_pushboolean(l, false); - lua_pushstring(l, "Sorry, you don't have OpenSSL\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Sorry, you don't have OpenSSL\n"); return 2; #endif default: @@ -334,39 +334,39 @@ static int l_nsock_connect(lua_State* l) { } freeaddrinfo(dest); - return lua_yield(l, 0); + return lua_yield(L, 0); error: freeaddrinfo(dest); - luaL_argerror(l, 4, "invalid connection method"); + luaL_argerror(L, 4, "invalid connection method"); return 0; } void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { - lua_State* l = (lua_State*) lua_state; + lua_State *L = (lua_State*) lua_state; if(o.scriptTrace()) { l_nsock_trace(nse_iod(nse), "CONNECT", TO); } - if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { + if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { process_waiting2running((lua_State*) lua_state, 1); } else { process_waiting2running((lua_State*) lua_state, 2); } } -static int l_nsock_send(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - const char* string = luaL_checkstring(l, 2); - size_t string_len = lua_objlen (l, 2); +static int l_nsock_send(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + const char* string = luaL_checkstring(L, 2); + size_t string_len = lua_objlen (L, 2); char* hexified; - l_nsock_clear_buf(l,udata); + l_nsock_clear_buf(L,udata); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to send through a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to send through a closed socket\n"); return 2; } @@ -376,76 +376,76 @@ static int l_nsock_send(lua_State* l) { free(hexified); } - nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, l, string, string_len); - return lua_yield(l, 0); + nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, L, string, string_len); + return lua_yield(L, 0); } void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { - lua_State* l = (lua_State*) lua_state; + lua_State *L = (lua_State*) lua_state; - if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { + if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { process_waiting2running((lua_State*) lua_state, 1); } else { process_waiting2running((lua_State*) lua_state, 2); } } -static int l_nsock_receive(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - l_nsock_clear_buf(l, udata); +static int l_nsock_receive(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + l_nsock_clear_buf(L, udata); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to receive through a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive through a closed socket\n"); return 2; } - nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l); + nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, L); - return lua_yield(l, 0); + return lua_yield(L, 0); } -static int l_nsock_receive_lines(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - int nlines = (int) luaL_checknumber(l, 2); +static int l_nsock_receive_lines(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + int nlines = (int) luaL_checknumber(L, 2); - l_nsock_clear_buf(l, udata); + l_nsock_clear_buf(L, udata); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to receive lines through a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive lines through a closed socket\n"); return 2; } - nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l, nlines); + nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, L, nlines); - return lua_yield(l, 0); + return lua_yield(L, 0); } -static int l_nsock_receive_bytes(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - int nbytes = (int) luaL_checknumber(l, 2); +static int l_nsock_receive_bytes(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + int nbytes = (int) luaL_checknumber(L, 2); - l_nsock_clear_buf(l, udata); + l_nsock_clear_buf(L, udata); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to receive bytes through a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive bytes through a closed socket\n"); return 2; } - nsock_readbytes(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l, nbytes); + nsock_readbytes(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, L, nbytes); - return lua_yield(l, 0); + return lua_yield(L, 0); } void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { - lua_State* l = (lua_State*) lua_state; + lua_State *L = (lua_State*) lua_state; char* rcvd_string; int rcvd_len = 0; char* hexified; - if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { + if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { rcvd_string = nse_readbuf(nse, &rcvd_len); if(o.scriptTrace()) { @@ -454,7 +454,7 @@ void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { free(hexified); } - lua_pushlstring(l, rcvd_string, rcvd_len); + lua_pushlstring(L, rcvd_string, rcvd_len); process_waiting2running((lua_State*) lua_state, 2); } else { process_waiting2running((lua_State*) lua_state, 2); @@ -532,8 +532,8 @@ unsigned short inet_port_both(int af, const void* v_addr) { return ntohs(port); } -static int l_nsock_get_info(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +static int l_nsock_get_info(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); int status; int protocol; // tcp or udp @@ -544,50 +544,50 @@ static int l_nsock_get_info(lua_State* l) { char* ipstring_remote = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to get info from a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to get info from a closed socket\n"); return 2; } status = nsi_getlastcommunicationinfo(udata->nsiod, &protocol, &af, &local, &remote, sizeof(sockaddr)); - lua_pushboolean(l, true); + lua_pushboolean(L, true); - lua_pushstring(l, inet_ntop_both(af, &local, ipstring_local)); - lua_pushnumber(l, inet_port_both(af, &local)); + lua_pushstring(L, inet_ntop_both(af, &local, ipstring_local)); + lua_pushnumber(L, inet_port_both(af, &local)); - lua_pushstring(l, inet_ntop_both(af, &remote, ipstring_remote)); - lua_pushnumber(l, inet_port_both(af, &remote)); + lua_pushstring(L, inet_ntop_both(af, &remote, ipstring_remote)); + lua_pushnumber(L, inet_port_both(af, &remote)); free(ipstring_local); free(ipstring_remote); return 5; } -static int l_nsock_gc(lua_State* l){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +static int l_nsock_gc(lua_State *L){ + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); if(udata->nsiod == NULL) { //socket obviously got closed already - so no finalization needed return 0; }else{ //FIXME - check wheter close returned true!! - l_nsock_close(l); + l_nsock_close(L); } return 0; } -static int l_nsock_close(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +static int l_nsock_close(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); /* Never ever collect nse-pcap connections. */ if(udata->ncap_socket){ return 0; } - l_nsock_clear_buf(l, udata); + l_nsock_clear_buf(L, udata); if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to close a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to close a closed socket\n"); return 2; } @@ -615,13 +615,13 @@ static int l_nsock_close(lua_State* l) { udata->nsiod = NULL; - lua_pushboolean(l, true); + lua_pushboolean(L, true); return 1; } -static int l_nsock_set_timeout(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - int timeout = (unsigned short) luaL_checkint(l, 2); +static int l_nsock_set_timeout(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + int timeout = (unsigned short) luaL_checkint(L, 2); udata->timeout = timeout; @@ -629,53 +629,53 @@ static int l_nsock_set_timeout(lua_State* l) { } /* buffered I/O */ -static int l_nsock_receive_buf(lua_State* l) { - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - if(lua_gettop(l)==2){ +static int l_nsock_receive_buf(lua_State *L) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + if(lua_gettop(L)==2){ /*we were called with 2 arguments only - push the default third one*/ - lua_pushboolean(l,true); + lua_pushboolean(L,true); } if(udata->nsiod == NULL) { - lua_pushboolean(l, false); - lua_pushstring(l, "Trying to receive through a closed socket\n"); + lua_pushboolean(L, false); + lua_pushstring(L, "Trying to receive through a closed socket\n"); return 2; } if(udata->bufused==0){ - lua_pushstring(l,""); - udata->bufidx = luaL_ref(l, LUA_REGISTRYINDEX); + lua_pushstring(L,""); + udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); udata->bufused=1; - nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, l); + nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, L); }else if(udata->bufused==-1){ /*error message is inside the buffer*/ - lua_pushboolean(l,false); - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); + lua_pushboolean(L,false); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); return 2; }else{ /*buffer contains already some data */ /*we keep track here of how many calls to receive_buf are made */ udata->bufused++; - if(l_nsock_check_buf(l)==NSOCK_WRAPPER_BUFFER_MOREREAD){ + if(l_nsock_check_buf(L)==NSOCK_WRAPPER_BUFFER_MOREREAD){ /*if we didn't have enough data in the buffer another nsock_read() * was scheduled - its callback will put us in running state again */ - return lua_yield(l,3); + return lua_yield(L,3); } return 2; } /*yielding with 3 arguments since we need them when the callback arrives */ - return lua_yield(l, 3); + return lua_yield(L, 3); } void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { - lua_State* l = (lua_State*) lua_state; + lua_State *L = (lua_State*) lua_state; char* rcvd_string; int rcvd_len = 0; char* hexified; int tmpidx; - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + if(l_nsock_checkstatus(L, nse) == NSOCK_WRAPPER_SUCCESS) { //l_nsock_checkstatus pushes true on the stack in case of success // we do this on our own here - lua_pop(l,1); + lua_pop(L,1); rcvd_string = nse_readbuf(nse, &rcvd_len); @@ -686,12 +686,12 @@ void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_stat } /* push the buffer and what we received from nsock on the stack and * concatenate both*/ - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); - lua_pushlstring(l, rcvd_string, rcvd_len); - lua_concat (l, 2); - luaL_unref(l, LUA_REGISTRYINDEX, udata->bufidx); - udata->bufidx = luaL_ref(l, LUA_REGISTRYINDEX); - if(l_nsock_check_buf(l)==NSOCK_WRAPPER_BUFFER_MOREREAD){ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + lua_pushlstring(L, rcvd_string, rcvd_len); + lua_concat (L, 2); + luaL_unref(L, LUA_REGISTRYINDEX, udata->bufidx); + udata->bufidx = luaL_ref(L, LUA_REGISTRYINDEX); + if(l_nsock_check_buf(L)==NSOCK_WRAPPER_BUFFER_MOREREAD){ /*if there wasn't enough data in the buffer and we've issued another * nsock_read() the next callback will schedule the script for running */ @@ -705,12 +705,12 @@ void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_stat * and clean the buffer afterwards */ /*save the error message inside the buffer*/ - tmpidx=luaL_ref(l, LUA_REGISTRYINDEX); + tmpidx=luaL_ref(L, LUA_REGISTRYINDEX); /*pop the status (==false) of the stack*/ - lua_pop(l,1); - lua_pushboolean(l, true); - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); - l_nsock_clear_buf(l, udata); + lua_pop(L,1); + lua_pushboolean(L, true); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + l_nsock_clear_buf(L, udata); udata->bufidx=tmpidx; udata->bufused=-1; process_waiting2running((lua_State*) lua_state, 2); @@ -720,55 +720,55 @@ void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_stat } } -int l_nsock_check_buf(lua_State* l ){ +int l_nsock_check_buf(lua_State *L ){ l_nsock_udata* udata; size_t startpos, endpos, bufsize; const char *tmpbuf; int tmpidx; int keeppattern; /*should we return the string including the pattern or without it */ - keeppattern= lua_toboolean(l,-1); - lua_pop(l,1); - udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - if(lua_isfunction(l,2)){ - lua_pushvalue(l,2); - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); /* the buffer is the only argument to the function */ - if(lua_pcall(l,1,2,0)!=0){ - lua_pushboolean(l,false); - lua_pushfstring(l,"Error inside splitting-function: %s\n", lua_tostring(l,-1)); + keeppattern= lua_toboolean(L,-1); + lua_pop(L,1); + udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + if(lua_isfunction(L,2)){ + lua_pushvalue(L,2); + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); /* the buffer is the only argument to the function */ + if(lua_pcall(L,1,2,0)!=0){ + lua_pushboolean(L,false); + lua_pushfstring(L,"Error inside splitting-function: %s\n", lua_tostring(L,-1)); return NSOCK_WRAPPER_BUFFER_OK; - //luaL_error(l,"Error inside splitting-function, given as argument to nsockobj:receive_buf: %s\n", lua_tostring(l,-1)); + //luaL_error(L,"Error inside splitting-function, given as argument to nsockobj:receive_buf: %s\n", lua_tostring(L,-1)); } - }else if(lua_isstring(l,2)){ - lua_getglobal(l,"string"); - lua_getfield(l,-1,"find"); - lua_remove(l, -2); /*drop the string-table, since we don't need it! */ - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); - lua_pushvalue(l,2); /*the pattern we are searching for */ - if(lua_pcall(l,2,2,0)!=0){ - lua_pushboolean(l,false); - lua_pushstring(l,"Error in string.find (nsockobj:receive_buf)!"); + }else if(lua_isstring(L,2)){ + lua_getglobal(L,"string"); + lua_getfield(L,-1,"find"); + lua_remove(L, -2); /*drop the string-table, since we don't need it! */ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + lua_pushvalue(L,2); /*the pattern we are searching for */ + if(lua_pcall(L,2,2,0)!=0){ + lua_pushboolean(L,false); + lua_pushstring(L,"Error in string.find (nsockobj:receive_buf)!"); return NSOCK_WRAPPER_BUFFER_OK; } }else{ - lua_pushboolean(l,false); - lua_pushstring(l,"Expected either a function or a string!"); + lua_pushboolean(L,false); + lua_pushstring(L,"Expected either a function or a string!"); return NSOCK_WRAPPER_BUFFER_OK; - //luaL_argerror(l,2,"expected either a function or a string!"); + //luaL_argerror(L,2,"expected either a function or a string!"); } /*the stack contains on top the indices where we want to seperate */ - if(lua_isnil(l,-1)){ /*not found anything try to read more data*/ - lua_pop(l,2); - nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, l); - lua_pushboolean(l,keeppattern); + if(lua_isnil(L,-1)){ /*not found anything try to read more data*/ + lua_pop(L,2); + nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, L); + lua_pushboolean(L,keeppattern); return NSOCK_WRAPPER_BUFFER_MOREREAD; }else{ - startpos = (size_t) lua_tointeger(l, -2); - endpos = (size_t) lua_tointeger(l, -1); - lua_settop(l,0); /* clear the stack for returning */ + startpos = (size_t) lua_tointeger(L, -2); + endpos = (size_t) lua_tointeger(L, -1); + lua_settop(L,0); /* clear the stack for returning */ if(startpos>endpos){ - lua_pushboolean(l,false); - lua_pushstring(l,"Delimiter has negative size!"); + lua_pushboolean(L,false); + lua_pushstring(L,"Delimiter has negative size!"); return NSOCK_WRAPPER_BUFFER_OK; }else if(startpos==endpos){ /* if the delimter has a size of zero we keep it, since otherwise @@ -776,34 +776,34 @@ int l_nsock_check_buf(lua_State* l ){ */ keeppattern=1; } - lua_settop(l,0); /* clear the stack for returning */ - lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); - tmpbuf = lua_tolstring(l, -1, &bufsize); - lua_pop(l,1); /* pop the buffer off the stack, should be safe since it + lua_settop(L,0); /* clear the stack for returning */ + lua_rawgeti(L, LUA_REGISTRYINDEX, udata->bufidx); + tmpbuf = lua_tolstring(L, -1, &bufsize); + lua_pop(L,1); /* pop the buffer off the stack, should be safe since it it is still in the registry */ if(tmpbuf==NULL){ fatal("%s: In: %s:%i The buffer is not a string?! - please report this to nmap-dev@insecure.org.", SCRIPT_ENGINE, __FILE__, __LINE__); } /*first push the remains of the buffer */ - lua_pushlstring(l,tmpbuf+endpos,(bufsize-endpos)); - tmpidx = luaL_ref(l,LUA_REGISTRYINDEX); - lua_pushboolean(l,true); + lua_pushlstring(L,tmpbuf+endpos,(bufsize-endpos)); + tmpidx = luaL_ref(L,LUA_REGISTRYINDEX); + lua_pushboolean(L,true); if(keeppattern){ - lua_pushlstring(l,tmpbuf,endpos); + lua_pushlstring(L,tmpbuf,endpos); }else{ - lua_pushlstring(l,tmpbuf,startpos-1); + lua_pushlstring(L,tmpbuf,startpos-1); } - luaL_unref(l,LUA_REGISTRYINDEX,udata->bufidx); + luaL_unref(L,LUA_REGISTRYINDEX,udata->bufidx); udata->bufidx=tmpidx; - //l_dumpStack(l); + //l_dumpStack(L); return NSOCK_WRAPPER_BUFFER_OK; } assert(0); return 1;//unreachable } -void l_nsock_clear_buf(lua_State* l, l_nsock_udata* udata){ - luaL_unref (l, LUA_REGISTRYINDEX, udata->bufidx); +void l_nsock_clear_buf(lua_State *L, l_nsock_udata* udata){ + luaL_unref (L, LUA_REGISTRYINDEX, udata->bufidx); udata->bufidx=LUA_NOREF; udata->bufused=0; } @@ -866,29 +866,29 @@ char *dnet_to_pcap_device_name(const char *device){ * 4) callback- callback function, that will create hash string from packet * 5) bpf - berkeley packet filter, see tcpdump(8) * */ -static int l_nsock_ncap_open(lua_State* l){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); - const char* device = luaL_checkstring(l, 2); - int snaplen = luaL_checkint(l, 3); - int promisc = luaL_checkint(l, 4); - luaL_checktype(l, 5, LUA_TFUNCTION); /* callback function that creates hash */ - const char* bpf = luaL_checkstring(l, 6); +static int l_nsock_ncap_open(lua_State *L){ + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); + const char* device = luaL_checkstring(L, 2); + int snaplen = luaL_checkint(L, 3); + int promisc = luaL_checkint(L, 4); + luaL_checktype(L, 5, LUA_TFUNCTION); /* callback function that creates hash */ + const char* bpf = luaL_checkstring(L, 6); if(udata->nsiod || udata->ncap_request || udata->ncap_socket) { - luaL_argerror(l, 1, "Trying to open nsock-pcap, but this connection is already opened"); + luaL_argerror(L, 1, "Trying to open nsock-pcap, but this connection is already opened"); return 0; } char *pcapdev = dnet_to_pcap_device_name(device); if(!strlen(device) || !strlen(pcapdev)) { - luaL_argerror(l, 1, "Trying to open nsock-pcap, but you're passing empty or wrong device name."); + luaL_argerror(L, 1, "Trying to open nsock-pcap, but you're passing empty or wrong device name."); return 0; } - lua_pop(l, 1); // pop bpf + lua_pop(L, 1); // pop bpf /* take func from top of stack and store it in the Registry */ - int hash_func_ref = luaL_ref(l, LUA_REGISTRYINDEX); + int hash_func_ref = luaL_ref(L, LUA_REGISTRYINDEX); /* push function on the registry-stack */ - lua_rawgeti(l, LUA_REGISTRYINDEX, hash_func_ref); + lua_rawgeti(L, LUA_REGISTRYINDEX, hash_func_ref); struct ncap_socket *ns; @@ -907,7 +907,7 @@ static int l_nsock_ncap_open(lua_State* l){ /* error messages are passed here */ char *emsg = nsock_pcap_open(nsp, ns->nsiod, pcapdev, snaplen, promisc, bpf); if(emsg){ - luaL_argerror(l, 1, emsg); + luaL_argerror(L, 1, emsg); return 0; } ncap_socket_map_set(key, ns); @@ -921,16 +921,16 @@ static int l_nsock_ncap_open(lua_State* l){ /* (LUA) Close nsock-pcap socket. * */ -static int l_nsock_ncap_close(lua_State* l){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +static int l_nsock_ncap_close(lua_State *L){ + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); struct ncap_socket *ns = udata->ncap_socket; if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(l, 1, "Trying to close nsock-pcap, but it was never opened."); + luaL_argerror(L, 1, "Trying to close nsock-pcap, but it was never opened."); return 0; } if(udata->ncap_request) { - luaL_argerror(l, 1, "Trying to close nsock-pcap, but it has active event."); + luaL_argerror(L, 1, "Trying to close nsock-pcap, but it has active event."); return 0; } @@ -946,10 +946,10 @@ static int l_nsock_ncap_close(lua_State* l){ udata->nsiod = NULL; udata->ncap_socket = NULL; - lua_unref(l, udata->ncap_cback_ref); + lua_unref(L, udata->ncap_cback_ref); udata->ncap_cback_ref = 0; - lua_pushboolean(l, true); + lua_pushboolean(L, true); return 1; } @@ -1010,19 +1010,19 @@ void ncap_request_map_add(char *key, struct ncap_request *nr){ * 1) hash - hash for packet that should be matched. or empty string if you * want to receive first packet * */ -static int l_nsock_ncap_register(lua_State *l){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +static int l_nsock_ncap_register(lua_State *L){ + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); size_t testdatasz; - const char* testdata = luaL_checklstring(l, 2, &testdatasz); + const char* testdata = luaL_checklstring(L, 2, &testdatasz); struct timeval now = *nsock_gettimeofday(); if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(l, 1, "You can't register to nsock-pcap if it wasn't opened."); + luaL_argerror(L, 1, "You can't register to nsock-pcap if it wasn't opened."); return 0; } if(udata->ncap_request){ - luaL_argerror(l, 1, "You are already registered to this socket."); + luaL_argerror(L, 1, "You are already registered to this socket."); return 0; } @@ -1033,7 +1033,7 @@ static int l_nsock_ncap_register(lua_State *l){ TIMEVAL_MSEC_ADD(nr->end_time, now, udata->timeout); nr->key = strdup(hex((char*)testdata, testdatasz)); - nr->l = l; + nr->L = L; nr->ncap_cback_ref = udata->ncap_cback_ref; /* always create new event. */ nr->nseid = nsock_pcap_read_packet(nsp, @@ -1052,14 +1052,14 @@ static int l_nsock_ncap_register(lua_State *l){ * * return values: status(true/false), capture_len/error_msg, layer2data, layer3data * */ -int l_nsock_pcap_receive(lua_State *l){ - l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(l, 1, "nsock"); +int l_nsock_pcap_receive(lua_State *L){ + l_nsock_udata* udata = (l_nsock_udata*) luaL_checkudata(L, 1, "nsock"); if(!udata->nsiod || !udata->ncap_socket) { - luaL_argerror(l, 1, "You can't receive to nsock-pcap if it wasn't opened."); + luaL_argerror(L, 1, "You can't receive to nsock-pcap if it wasn't opened."); return 0; } if(!udata->ncap_request){ - luaL_argerror(l, 1, "You can't it's not registered"); + luaL_argerror(L, 1, "You can't it's not registered"); return 0; } @@ -1075,26 +1075,26 @@ int l_nsock_pcap_receive(lua_State *l){ /* no data yet? suspend thread */ nr->suspended = 1; - return lua_yield(l, 0); + return lua_yield(L, 0); } /* (free) excute callback function from lua script */ -char* ncap_request_do_callback(nsock_event nse, lua_State *l, int ncap_cback_ref){ +char* ncap_request_do_callback(nsock_event nse, lua_State *L, int ncap_cback_ref){ const unsigned char *l2_data, *l3_data; size_t l2_len, l3_len, packet_len; nse_readpcap(nse, &l2_data, &l2_len, &l3_data, &l3_len, &packet_len, NULL); - lua_rawgeti(l, LUA_REGISTRYINDEX, ncap_cback_ref); - lua_pushnumber(l, packet_len); - lua_pushlstring(l, (char*)l2_data, l2_len); - lua_pushlstring(l, (char*)l3_data, l3_len); + lua_rawgeti(L, LUA_REGISTRYINDEX, ncap_cback_ref); + lua_pushnumber(L, packet_len); + lua_pushlstring(L, (char*)l2_data, l2_len); + lua_pushlstring(L, (char*)l3_data, l3_len); - lua_call(l, 3, 1); + lua_call(L, 3, 1); /* get string from top of the stack*/ size_t testdatasz; - const char* testdata = lua_tolstring(l, -1, &testdatasz); - // lua_pop(l, 1);/* just in case [nope, it's not needed]*/ + const char* testdata = lua_tolstring(L, -1, &testdatasz); + // lua_pop(L, 1);/* just in case [nope, it's not needed]*/ char *key = strdup(hex((char*)testdata, testdatasz)); return key; @@ -1110,7 +1110,7 @@ void l_nsock_pcap_receive_handler(nsock_pool nsp, nsock_event nse, void *userdat switch(nse_status(nse)) { case NSE_STATUS_SUCCESS:{ - char *key = ncap_request_do_callback(nse, nr->l, nr->ncap_cback_ref); + char *key = ncap_request_do_callback(nse, nr->L, nr->ncap_cback_ref); /* processes threads that receive every packet */ this_event_restored += ncap_request_set_results(nse, ""); @@ -1221,21 +1221,21 @@ void ncap_request_set_result(nsock_event nse, struct ncap_request *nr) { /* if lua thread was suspended, restore it. If it wasn't, just return results * (push them on the stack and return) */ int ncap_restore_lua(ncap_request *nr){ - lua_State *l = nr->l; + lua_State *L = nr->L; if(nr->r_success){ - lua_pushboolean(l, true); - lua_pushnumber(l, nr->packetsz); - lua_pushlstring(l, (char*)nr->r_layer2, nr->r_layer2_len); - lua_pushlstring(l, (char*)nr->r_layer3, nr->r_layer3_len); + lua_pushboolean(L, true); + lua_pushnumber(L, nr->packetsz); + lua_pushlstring(L, (char*)nr->r_layer2, nr->r_layer2_len); + lua_pushlstring(L, (char*)nr->r_layer3, nr->r_layer3_len); }else{ - lua_pushnil(l); - lua_pushstring(l, nr->r_status); - lua_pushnil(l); - lua_pushnil(l); + lua_pushnil(L); + lua_pushstring(L, nr->r_status); + lua_pushnil(L); + lua_pushnil(L); } bool suspended = nr->suspended; - nr->l = NULL; + nr->L = NULL; nr->ncap_cback_ref = 0; /* this ref is freed in different place (on udata->ncap_cback_ref) */ if(nr->key) free(nr->key); if(nr->r_status) free(nr->r_status); @@ -1245,7 +1245,7 @@ int ncap_restore_lua(ncap_request *nr){ free(nr); if(suspended) /* lua process is suspended */ - return process_waiting2running(l, 4); + return process_waiting2running(L, 4); else /* not suspended, just pass output */ return 4; } @@ -1254,9 +1254,9 @@ int ncap_restore_lua(ncap_request *nr){ /****************** DNET ******************************************************/ -static int l_dnet_open_ethernet(lua_State* l); -static int l_dnet_close_ethernet(lua_State* l); -static int l_dnet_send_ethernet(lua_State* l); +static int l_dnet_open_ethernet(lua_State *L); +static int l_dnet_close_ethernet(lua_State *L); +static int l_dnet_send_ethernet(lua_State *L); static luaL_reg l_dnet [] = { {"ethernet_open", l_dnet_open_ethernet}, @@ -1265,14 +1265,14 @@ static luaL_reg l_dnet [] = { {NULL, NULL} }; -int l_dnet_open(lua_State* l) { - luaL_newmetatable(l, "dnet"); - lua_createtable(l, 5, 0); - luaL_register(l, NULL, l_dnet); - lua_setfield(l, -2, "__index"); - lua_pushliteral(l, ""); - lua_setfield(l, -2, "__metatable"); // protect metatable - lua_pop(l, 1); +int l_dnet_open(lua_State *L) { + luaL_newmetatable(L, "dnet"); + lua_createtable(L, 0, 5); + luaL_register(L, NULL, l_dnet); + lua_setfield(L, -2, "__index"); + lua_pushliteral(L, ""); + lua_setfield(L, -2, "__metatable"); // protect metatable + lua_pop(L, 1); return NSOCK_WRAPPER_SUCCESS; } @@ -1281,23 +1281,23 @@ struct l_dnet_udata { eth_t *eth; }; -int l_dnet_new(lua_State* l) { +int l_dnet_new(lua_State *L) { struct l_dnet_udata* udata; - udata = (struct l_dnet_udata*) lua_newuserdata(l, sizeof(struct l_dnet_udata)); - luaL_getmetatable(l, "dnet"); - lua_setmetatable(l, -2); + udata = (struct l_dnet_udata*) lua_newuserdata(L, sizeof(struct l_dnet_udata)); + luaL_getmetatable(L, "dnet"); + lua_setmetatable(L, -2); udata->interface= NULL; udata->eth = NULL; return 1; } -int l_dnet_get_interface_link(lua_State* l) { - const char* interface_name = luaL_checkstring(l, 1); +int l_dnet_get_interface_link(lua_State *L) { + const char* interface_name = luaL_checkstring(L, 1); struct interface_info *ii = getInterfaceByName((char*)interface_name); if(!ii){ - lua_pushnil(l); + lua_pushnil(L); return 1; } const char *s= NULL; @@ -1317,9 +1317,9 @@ int l_dnet_get_interface_link(lua_State* l) { break; } if(s) - lua_pushstring(l, s); + lua_pushstring(L, s); else - lua_pushnil(l); + lua_pushnil(L); return 1; } @@ -1365,13 +1365,13 @@ void ldnet_eth_close_cached(const char *device) { return; } -static int l_dnet_open_ethernet(lua_State* l){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(l, 1, "dnet"); - const char* interface_name = luaL_checkstring(l, 2); +static int l_dnet_open_ethernet(lua_State *L){ + l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); + const char* interface_name = luaL_checkstring(L, 2); struct interface_info *ii = getInterfaceByName((char*)interface_name); if(!ii || ii->device_type!=devt_ethernet){ - luaL_argerror(l, 2, "device is not valid ethernet interface"); + luaL_argerror(L, 2, "device is not valid ethernet interface"); return 0; } udata->interface= strdup(interface_name); @@ -1380,10 +1380,10 @@ static int l_dnet_open_ethernet(lua_State* l){ return 0; } -static int l_dnet_close_ethernet(lua_State* l){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(l, 1, "dnet"); +static int l_dnet_close_ethernet(lua_State *L){ + l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); if(!udata->interface || !udata->eth){ - luaL_argerror(l, 1, "dnet is not valid opened ethernet interface"); + luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); return 0; } @@ -1394,20 +1394,20 @@ static int l_dnet_close_ethernet(lua_State* l){ return 0; } -static int l_dnet_send_ethernet(lua_State* l){ - l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(l, 1, "dnet"); +static int l_dnet_send_ethernet(lua_State *L){ + l_dnet_udata* udata = (l_dnet_udata*) luaL_checkudata(L, 1, "dnet"); size_t packetsz = 0; - const char* packet = luaL_checklstring(l, 2, &packetsz); + const char* packet = luaL_checklstring(L, 2, &packetsz); if(!udata->interface || !udata->eth){ - luaL_argerror(l, 1, "dnet is not valid opened ethernet interface"); + luaL_argerror(L, 1, "dnet is not valid opened ethernet interface"); return 0; } eth_send(udata->eth, packet, packetsz); return 0; } -int l_clock_ms(lua_State* l){ +int l_clock_ms(lua_State *L){ struct timeval tv; gettimeofday(&tv, NULL); // no rounding error @@ -1416,10 +1416,6 @@ int l_clock_ms(lua_State* l){ usec = tv.tv_sec*1000; usec += (int)(tv.tv_usec/1000); // make sure it's integer. - lua_pushnumber(l, usec); + lua_pushnumber(L, usec); return 1; } - - - -