diff options
Diffstat (limited to 'nse_utility.cc')
-rw-r--r-- | nse_utility.cc | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/nse_utility.cc b/nse_utility.cc new file mode 100644 index 0000000..0ccd2d7 --- /dev/null +++ b/nse_utility.cc @@ -0,0 +1,243 @@ +#include <stdlib.h> +#include <stdarg.h> +#include <math.h> + +#include "Target.h" +#include "portlist.h" + +#include "nse_main.h" +#include "nse_utility.h" + +#ifndef IPPROTO_SCTP +#include "libnetutil/netutil.h" +#endif + +int nseU_checkinteger (lua_State *L, int arg) +{ + lua_Number n = luaL_checknumber(L, arg); + int i; + if (!lua_numbertointeger(floor(n), &i)) { + return luaL_error(L, "Number cannot be converted to an integer"); + } + return i; +} + +int nseU_traceback (lua_State *L) +{ + if (lua_isstring(L, 1)) + luaL_traceback(L, L, lua_tostring(L, 1), 1); + return 1; +} + +int nseU_placeholder (lua_State *L) +{ + lua_pushnil(L); + return lua_error(L); +} + +size_t nseU_tablen (lua_State *L, int idx) +{ + size_t len = 0; + idx = lua_absindex(L, idx); + + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) + len++; + + return len; +} + +void nseU_setsfield (lua_State *L, int idx, const char *field, const char *what) +{ + idx = lua_absindex(L, idx); + lua_pushstring(L, what); /* what can be NULL */ + lua_setfield(L, idx, field); +} + +void nseU_setnfield (lua_State *L, int idx, const char *field, lua_Number n) +{ + idx = lua_absindex(L, idx); + lua_pushnumber(L, n); + lua_setfield(L, idx, field); +} + +void nseU_setifield (lua_State *L, int idx, const char *field, lua_Integer i) +{ + idx = lua_absindex(L, idx); + lua_pushinteger(L, i); + lua_setfield(L, idx, field); +} + +void nseU_setbfield (lua_State *L, int idx, const char *field, int b) +{ + idx = lua_absindex(L, idx); + lua_pushboolean(L, b); + lua_setfield(L, idx, field); +} + +void nseU_setpfield (lua_State *L, int idx, const char *field, void * p) +{ + idx = lua_absindex(L, idx); + lua_pushlightuserdata(L, p); + lua_setfield(L, idx, field); +} + +void nseU_appendfstr (lua_State *L, int idx, const char *fmt, ...) +{ + va_list va; + idx = lua_absindex(L, idx); + va_start(va, fmt); + lua_pushvfstring(L, fmt, va); + va_end(va); + lua_rawseti(L, idx, lua_rawlen(L, idx)+1); +} + +int nseU_success (lua_State *L) +{ + lua_pushboolean(L, true); + return 1; +} + +int nseU_safeerror (lua_State *L, const char *fmt, ...) +{ + va_list va; + lua_pushboolean(L, false); + va_start(va, fmt); + lua_pushvfstring(L, fmt, va); + va_end(va); + return 2; +} + +void nseU_weaktable (lua_State *L, int narr, int nrec, const char *mode) +{ + lua_createtable(L, narr, nrec); + lua_createtable(L, 0, 1); + lua_pushstring(L, mode); + lua_setfield(L, -2, "__mode"); + lua_setmetatable(L, -2); +} + +void nseU_typeerror (lua_State *L, int idx, const char *type) +{ + const char *msg = lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx)); + luaL_argerror(L, idx, msg); +} + +void *nseU_checkudata (lua_State *L, int idx, int upvalue, const char *name) +{ + idx = lua_absindex(L, idx); + + lua_getmetatable(L, idx); + if (!(lua_isuserdata(L, idx) && lua_rawequal(L, -1, upvalue))) + nseU_typeerror(L, idx, name); + lua_pop(L, 1); + return lua_touserdata(L, idx); +} + +void nseU_checktarget (lua_State *L, int idx, const char **address, const char **targetname) +{ + idx = lua_absindex(L, idx); + if (lua_istable(L, idx)) { + lua_getfield(L, idx, "ip"); + *address = lua_tostring(L, -1); + lua_getfield(L, idx, "targetname"); + *targetname = lua_tostring(L, -1); + if (*address == NULL && *targetname == NULL) + luaL_argerror(L, idx, "host table lacks 'ip' or 'targetname' fields"); + *address = *address ? *address : *targetname; + lua_pop(L, 2); /* no point replacing idx, need 2 only have 1 */ + } else { + *address = *targetname = luaL_checkstring(L, idx); + } +} + +void nseU_opttarget (lua_State *L, int idx, const char **address, const char **targetname) +{ + if (lua_isnoneornil(L, idx)) { + *address = NULL; + *targetname = NULL; + return; + } else { + return nseU_checktarget(L, idx, address, targetname); + } +} + +uint16_t nseU_checkport (lua_State *L, int idx, const char **protocol) +{ + uint16_t port; + idx = lua_absindex(L, idx); + + if (lua_istable(L, idx)) { + lua_getfield(L, idx, "number"); + if (!lua_isinteger(L, -1)) + luaL_argerror(L, idx, "port table lacks integer 'number' field"); + port = (uint16_t) lua_tointeger(L, -1); + lua_getfield(L, idx, "protocol"); + if (lua_isstring(L, -1)) + *protocol = lua_tostring(L, -1); + lua_pop(L, 2); + } else { + port = (uint16_t) luaL_checkinteger(L, idx); + } + return port; +} + +Target *nseU_gettarget (lua_State *L, int idx) +{ + int top = lua_gettop(L); + Target *target; + idx = lua_absindex(L, idx); + luaL_checktype(L, idx, LUA_TTABLE); + lua_getfield(L, idx, "_Target"); + lua_getfield(L, idx, "targetname"); + lua_getfield(L, idx, "ip"); + if (!(lua_isstring(L, -2) || lua_isstring(L, -1))) + luaL_error(L, "host table does not have a 'ip' or 'targetname' field"); + if (lua_islightuserdata(L, -3)) /* _Target */ + { + lua_pop(L, 2); /* pop ip and targetname, leaving _Target on top */ + goto done; + } + /* IP is preferred to targetname because it is more unique. Really, though, a + * user can scan the same IP or targetname multiple times, and NSE will get + * all mixed up. */ + if (lua_isstring(L, -1)) /* ip */ + { + nse_gettarget(L, -1); /* use ip */ + if (lua_islightuserdata(L, -1)) + goto done; + else + lua_pop(L, 1); + } + if (lua_isstring(L, -2)) /* targetname */ + nse_gettarget(L, -2); /* use targetname */ + if (!lua_islightuserdata(L, -1)) + luaL_argerror(L, 1, "host is not being processed right now"); +done: + target = (Target *) lua_touserdata(L, -1); + lua_settop(L, top); /* reset stack */ + return target; +} + +Port *nseU_getport (lua_State *L, Target *target, Port *port, int idx) +{ + Port *p = NULL; + int portno, protocol; + idx = lua_absindex(L, idx); + luaL_checktype(L, idx, LUA_TTABLE); + lua_getfield(L, idx, "number"); + if (!lua_isinteger(L, -1)) + luaL_error(L, "port 'number' field must be an integer"); + lua_getfield(L, idx, "protocol"); + if (!lua_isstring(L, -1)) + luaL_error(L, "port 'protocol' field must be a string"); + portno = (int) lua_tointeger(L, -2); + protocol = strcmp(lua_tostring(L, -1), "tcp") == 0 ? IPPROTO_TCP : + strcmp(lua_tostring(L, -1), "udp") == 0 ? IPPROTO_UDP : + strcmp(lua_tostring(L, -1), "sctp") == 0 ? IPPROTO_SCTP : + luaL_error(L, "port 'protocol' field must be \"udp\", \"sctp\" or \"tcp\""); + while ((p = target->ports.nextPort(p, port, protocol, PORT_UNKNOWN)) != NULL) + if (p->portno == portno) + break; + lua_pop(L, 2); + return p; +} |