#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; const 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(!( (nse_check_extension(SCRIPT_ENGINE_EXTENSION, entry.cFileName)) && !(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