extern "C" { #include "lua.h" #include "lauxlib.h" } #include "nmap.h" #include "nse_fs.h" #include "nmap_error.h" #include "NmapOps.h" #include #include #include #ifndef WIN32 #include "dirent.h" #endif #define DIR_METATABLE "dir" #ifndef MAXPATHLEN # define MAXPATHLEN 2048 #endif #ifndef MAX_DIR_LENGTH # define MAX_DIR_LENGTH 1024 #endif typedef struct dir_data { int closed; #ifdef WIN32 long hFile; char pattern[MAX_DIR_LENGTH+1]; #else DIR *dir; #endif } dir_data; 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; } static 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. */ static 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); } int fetchfile_absolute (lua_State *L) { char path[MAXPATHLEN]; switch (nse_fetchfile_absolute(path, sizeof(path), luaL_checkstring(L, 1))) { case 0: // no such path lua_pushnil(L); lua_pushfstring(L, "no path to file/directory: %s", lua_tostring(L, 1)); break; case 1: // file returned lua_pushliteral(L, "file"); lua_pushstring(L, path); break; case 2: // directory returned lua_pushliteral(L, "directory"); lua_pushstring(L, path); break; default: return luaL_error(L, "nse_fetchfile_absolute returned bad code"); } return 2; } /* LuaFileSystem directory iterator port. * * LuaFileSystem library: * by Roberto Ierusalimschy, Andre Carregal and Tomas Guisasola * as part of the Kepler Project. * LuaFileSystem is currently maintained by Fabio Mascarenhas. * * LuaFileSystem is a Lua library developed to complement the set * of functions related to file systems offered by the standard * Lua distribution. * LuaFileSystem offers a portable way to access the underlying * directory structure and file attributes. * * LuaFileSystem is free software and uses the same license as Lua 5.1. * * the most recent copy can be found at * http://www.keplerproject.org/luafilesystem/ * * Note: this is a port of the LuaFileSystem directory iterator for the * Nmap project http://nmap.org **/ /* ** Directory iterator */ static int dir_iter (lua_State *L) { #ifdef WIN32 struct _finddata_t c_file; #else struct dirent *entry; #endif dir_data *d = (dir_data *)luaL_checkudata(L, 1, DIR_METATABLE); luaL_argcheck(L, !d->closed, 1, "closed directory"); #ifdef WIN32 if (d->hFile == 0L) { /* first entry */ if ((d->hFile = _findfirst(d->pattern, &c_file)) == -1L) { lua_pushnil(L); lua_pushstring(L, strerror (errno)); return 2; } else { lua_pushstring(L, c_file.name); return 1; } } else { /* next entry */ if (_findnext(d->hFile, &c_file) == -1L) { /* no more entries => close directory */ _findclose(d->hFile); d->closed = 1; return 0; } else { lua_pushstring(L, c_file.name); return 1; } } #else if ((entry = readdir(d->dir)) != NULL) { lua_pushstring(L, entry->d_name); return 1; } else { /* no more entries => close directory */ closedir(d->dir); d->closed = 1; return 0; } #endif } /* ** Closes directory iterators */ static int dir_close (lua_State *L) { dir_data *d = (dir_data *)lua_touserdata(L, 1); #ifdef WIN32 if (!d->closed && d->hFile) { _findclose(d->hFile); d->closed = 1; } #else if (!d->closed && d->dir) { closedir(d->dir); d->closed = 1; } #endif return 0; } /* ** Factory of directory iterators */ int nse_readdir (lua_State *L) { const char *dirname = luaL_checkstring(L, 1); dir_data *d; lua_pushcfunction(L, dir_iter); d = (dir_data *)lua_newuserdata(L, sizeof(dir_data)); d->closed = 0; #ifdef WIN32 d->hFile = 0L; luaL_getmetatable(L, DIR_METATABLE); lua_setmetatable(L, -2); if (strlen(dirname) > MAX_DIR_LENGTH) luaL_error(L, "%s: Path too long '%s'.", SCRIPT_ENGINE, dirname); else Snprintf(d->pattern, MAX_DIR_LENGTH, "%s/*", dirname); #else luaL_getmetatable(L, DIR_METATABLE); lua_setmetatable(L, -2); d->dir = opendir(dirname); if (d->dir == NULL) luaL_error(L, "%s: Could not open directory '%s'.", SCRIPT_ENGINE, dirname); #endif return 2; } int luaopen_fs(lua_State *L) { /* create the dir metatable */ luaL_newmetatable(L, DIR_METATABLE); lua_pushstring(L, "__index"); lua_newtable(L); lua_pushstring(L, "next"); lua_pushcfunction(L, dir_iter); lua_settable(L, -3); lua_pushstring (L, "close"); lua_pushcfunction (L, dir_close); lua_settable(L, -3); lua_settable(L, -3); lua_pushstring(L, "__gc"); lua_pushcfunction (L, dir_close); lua_settable(L, -3); lua_pop(L, 1); return 0; }