mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Merge from /nmap-exp/patrick/nse-nsock-maintenance.
This is a maintenance fix for the NSE Nsock library binding. The patch focuses on code correctness and simplicity. The patch also brings some initial updates with an eye towards the upcoming Lua 5.2 release. See [1] for a post concerning this branch. [1] http://seclists.org/nmap-dev/2010/q3/710
This commit is contained in:
@@ -82,9 +82,9 @@ UNINSTALLZENMAP=@UNINSTALLZENMAP@
|
|||||||
UNINSTALLNPING=@UNINSTALLNPING@
|
UNINSTALLNPING=@UNINSTALLNPING@
|
||||||
|
|
||||||
ifneq (@LIBLUA_LIBS@,)
|
ifneq (@LIBLUA_LIBS@,)
|
||||||
NSE_SRC=nse_main.cc nse_nsock.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_binlib.cc nse_bit.cc
|
NSE_SRC=nse_main.cc nse_utility.cc nse_nsock.cc nse_dnet.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_binlib.cc nse_bit.cc
|
||||||
NSE_HDRS=nse_main.h nse_nsock.h nse_fs.h nse_nmaplib.h nse_debug.h nse_pcrelib.h nse_binlib.h nse_bit.h
|
NSE_HDRS=nse_main.h nse_utility.h nse_nsock.h nse_dnet.h nse_fs.h nse_nmaplib.h nse_debug.h nse_pcrelib.h nse_binlib.h nse_bit.h
|
||||||
NSE_OBJS=nse_main.o nse_nsock.o nse_fs.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_binlib.o nse_bit.o
|
NSE_OBJS=nse_main.o nse_utility.o nse_nsock.o nse_dnet.o nse_fs.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_binlib.o nse_bit.o
|
||||||
ifneq (@OPENSSL_LIBS@,)
|
ifneq (@OPENSSL_LIBS@,)
|
||||||
NSE_SRC+=nse_openssl.cc nse_ssl_cert.cc
|
NSE_SRC+=nse_openssl.cc nse_ssl_cert.cc
|
||||||
NSE_HDRS+=nse_openssl.h nse_ssl_cert.h
|
NSE_HDRS+=nse_openssl.h nse_ssl_cert.h
|
||||||
|
|||||||
@@ -278,6 +278,10 @@
|
|||||||
RelativePath="..\nse_main.cc"
|
RelativePath="..\nse_main.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\nse_utility.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_nmaplib.cc"
|
RelativePath="..\nse_nmaplib.cc"
|
||||||
>
|
>
|
||||||
@@ -286,6 +290,10 @@
|
|||||||
RelativePath="..\nse_nsock.cc"
|
RelativePath="..\nse_nsock.cc"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\nse_dnet.cc"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_openssl.cc"
|
RelativePath="..\nse_openssl.cc"
|
||||||
>
|
>
|
||||||
@@ -479,6 +487,10 @@
|
|||||||
RelativePath="..\nse_main.h"
|
RelativePath="..\nse_main.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\nse_utility.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_nmaplib.h"
|
RelativePath="..\nse_nmaplib.h"
|
||||||
>
|
>
|
||||||
@@ -487,6 +499,10 @@
|
|||||||
RelativePath="..\nse_nsock.h"
|
RelativePath="..\nse_nsock.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\nse_dnet.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\nse_openssl.h"
|
RelativePath="..\nse_openssl.h"
|
||||||
>
|
>
|
||||||
|
|||||||
313
nse_dnet.cc
Normal file
313
nse_dnet.cc
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
#include "nsock.h"
|
||||||
|
#include "nmap_error.h"
|
||||||
|
#include "NmapOps.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "tcpip.h"
|
||||||
|
#include "protocols.h"
|
||||||
|
#include "libnetutil/netutil.h"
|
||||||
|
|
||||||
|
#include "nse_main.h"
|
||||||
|
#include "nse_utility.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
extern NmapOps o;
|
||||||
|
|
||||||
|
/* Map of dnet userdata to ethernet device userdata */
|
||||||
|
#define ETH_CACHE_DNET_ETH 0
|
||||||
|
/* Map of ethernet device string identifier to ethernet device userdata */
|
||||||
|
#define ETH_CACHE_DEVICE_ETH 1
|
||||||
|
|
||||||
|
/* metatable entries in the registry */
|
||||||
|
#define DNET_METATABLE "DNET_METATABLE"
|
||||||
|
#define DNET_ETH_METATABLE "DNET_ETH_METATABLE"
|
||||||
|
|
||||||
|
typedef struct nse_dnet_udata
|
||||||
|
{
|
||||||
|
eth_t *eth;
|
||||||
|
int sock; /* raw ip socket */
|
||||||
|
int interface; /* integer reference in registry for interface string */
|
||||||
|
} nse_dnet_udata;
|
||||||
|
|
||||||
|
LUALIB_API int l_dnet_new (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata;
|
||||||
|
|
||||||
|
udata = (nse_dnet_udata *) lua_newuserdata(L, sizeof(nse_dnet_udata));
|
||||||
|
luaL_getmetatable(L, DNET_METATABLE);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
udata->eth = NULL;
|
||||||
|
udata->sock = -1;
|
||||||
|
udata->interface = LUA_NOREF;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LUALIB_API int l_dnet_get_interface_link (lua_State *L)
|
||||||
|
{
|
||||||
|
struct interface_info *ii = getInterfaceByName(luaL_checkstring(L, 1));
|
||||||
|
|
||||||
|
if (ii == NULL)
|
||||||
|
return luaL_argerror(L, 1, "bad interface");
|
||||||
|
|
||||||
|
switch (ii->device_type)
|
||||||
|
{
|
||||||
|
case devt_ethernet:
|
||||||
|
lua_pushliteral(L, "ethernet");
|
||||||
|
return 1;
|
||||||
|
case devt_loopback:
|
||||||
|
lua_pushliteral(L, "loopback");
|
||||||
|
return 1;
|
||||||
|
case devt_p2p:
|
||||||
|
lua_pushliteral(L, "p2p");
|
||||||
|
return 1;
|
||||||
|
case devt_other:
|
||||||
|
default:
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close_eth (lua_State *L)
|
||||||
|
{
|
||||||
|
eth_t **eth = (eth_t **) luaL_checkudata(L, 1, DNET_ETH_METATABLE);
|
||||||
|
assert(*eth != NULL);
|
||||||
|
eth_close(*eth);
|
||||||
|
*eth = NULL;
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static eth_t *open_eth_cached (lua_State *L, int dnet_index, const char *device)
|
||||||
|
{
|
||||||
|
eth_t **eth;
|
||||||
|
|
||||||
|
lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH);
|
||||||
|
lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DEVICE_ETH);
|
||||||
|
lua_getfield(L, -1, device);
|
||||||
|
if (!lua_isuserdata(L, -1))
|
||||||
|
{
|
||||||
|
eth = (eth_t **) lua_newuserdata(L, sizeof(eth_t *));
|
||||||
|
*eth = eth_open(device);
|
||||||
|
if (*eth == NULL)
|
||||||
|
luaL_error(L, "unable to open dnet on ethernet interface %s", device);
|
||||||
|
luaL_getmetatable(L, DNET_ETH_METATABLE);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_setfield(L, -4, device);
|
||||||
|
lua_replace(L, -2); /* replace nil */
|
||||||
|
}
|
||||||
|
eth = (eth_t **) lua_touserdata(L, -1);
|
||||||
|
|
||||||
|
lua_pushvalue(L, dnet_index);
|
||||||
|
lua_pushvalue(L, -2); /* eth_t userdata */
|
||||||
|
lua_rawset(L, -5); /* add to ETH_CACHE_DNET_ETH */
|
||||||
|
lua_pop(L, 3); /* ETH_CACHE_DNET_ETH, ETH_CACHE_DEVICE_ETH, eth_t userdata */
|
||||||
|
|
||||||
|
return *eth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ethernet_open (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
const char *interface_name = luaL_checkstring(L, 2);
|
||||||
|
struct interface_info *ii = getInterfaceByName(interface_name);
|
||||||
|
|
||||||
|
if (ii == NULL || ii->device_type != devt_ethernet)
|
||||||
|
return luaL_argerror(L, 2, "device is not valid ethernet interface");
|
||||||
|
|
||||||
|
udata->eth = open_eth_cached(L, 1, interface_name);
|
||||||
|
lua_pushvalue(L, 2);
|
||||||
|
udata->interface = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ethernet_close (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
|
||||||
|
udata->eth = NULL;
|
||||||
|
|
||||||
|
lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH);
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_pushnil(L);
|
||||||
|
lua_rawset(L, -3);
|
||||||
|
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, udata->interface);
|
||||||
|
udata->interface = LUA_NOREF;
|
||||||
|
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ethernet_send (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
if (udata->eth == NULL)
|
||||||
|
return luaL_error(L, "dnet ethernet interface is not open");
|
||||||
|
eth_send(udata->eth, luaL_checkstring(L, 2), lua_objlen(L, 2));
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ip_open (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
udata->sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||||
|
if (udata->sock == -1)
|
||||||
|
return luaL_error(L, "failed to open raw socket: %s (errno %d)",
|
||||||
|
socket_strerror(socket_errno()), socket_errno());
|
||||||
|
broadcast_socket(udata->sock);
|
||||||
|
#ifndef WIN32
|
||||||
|
sethdrinclude(udata->sock);
|
||||||
|
#endif
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ip_close (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
if (udata->sock == -1)
|
||||||
|
return safe_error(L, "raw socket already closed");
|
||||||
|
close(udata->sock);
|
||||||
|
udata->sock = -1;
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ip_send (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
const char *packet = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (udata->sock == -1)
|
||||||
|
return luaL_error(L, "raw socket not open to send");
|
||||||
|
|
||||||
|
if (lua_objlen(L, 2) < sizeof(struct ip))
|
||||||
|
return luaL_error(L, "ip packet too short");
|
||||||
|
|
||||||
|
if (o.sendpref & PACKET_SEND_ETH)
|
||||||
|
{
|
||||||
|
struct route_nfo route;
|
||||||
|
struct sockaddr_storage srcss, dstss, *nexthop;
|
||||||
|
struct sockaddr_in *srcsin = (struct sockaddr_in *) &srcss;
|
||||||
|
struct sockaddr_in *dstsin = (struct sockaddr_in *) &dstss;
|
||||||
|
struct ip *ip = (struct ip *) packet;
|
||||||
|
u8 dstmac[6];
|
||||||
|
eth_nfo eth;
|
||||||
|
|
||||||
|
/* build sockaddr for target from user packet and determine route */
|
||||||
|
memset(&dstss, 0, sizeof(dstss));
|
||||||
|
dstsin->sin_family = AF_INET;
|
||||||
|
dstsin->sin_addr.s_addr = ip->ip_dst.s_addr;
|
||||||
|
|
||||||
|
if (!nmap_route_dst(&dstss, &route))
|
||||||
|
goto usesock;
|
||||||
|
|
||||||
|
if (route.ii.device_type != devt_ethernet)
|
||||||
|
goto usesock;
|
||||||
|
|
||||||
|
/* above we fallback to using the raw socket if we can't find an (ethernet)
|
||||||
|
* route to the host. From here on out it's ethernet all the way.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* build sockaddr for source from user packet to determine next hop mac */
|
||||||
|
memset(&srcss, 0, sizeof(srcss));
|
||||||
|
srcsin->sin_family = AF_INET;
|
||||||
|
srcsin->sin_addr.s_addr = ip->ip_src.s_addr;
|
||||||
|
|
||||||
|
if (route.direct_connect)
|
||||||
|
nexthop = &dstss;
|
||||||
|
else
|
||||||
|
nexthop = &route.nexthop;
|
||||||
|
|
||||||
|
if (!getNextHopMAC(route.ii.devfullname, route.ii.mac, &srcss, nexthop, dstmac))
|
||||||
|
return luaL_error(L, "failed to determine next hop MAC address");
|
||||||
|
|
||||||
|
/* Use cached ethernet device, and use udata's eth and interface to keep
|
||||||
|
* track of if we're reusing the same device from the previous packet, and
|
||||||
|
* close the cached device if not.
|
||||||
|
*/
|
||||||
|
memset(ð, 0, sizeof(eth));
|
||||||
|
memcpy(eth.srcmac, route.ii.mac, sizeof(eth.srcmac));
|
||||||
|
memcpy(eth.dstmac, dstmac, sizeof(eth.dstmac));
|
||||||
|
|
||||||
|
/* close any current ethernet associated with this userdata */
|
||||||
|
lua_pushcfunction(L, ethernet_close);
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_call(L, 1, 0);
|
||||||
|
|
||||||
|
udata->eth = eth.ethsd = open_eth_cached(L, 1, route.ii.devname);
|
||||||
|
lua_pushstring(L, route.ii.devname);
|
||||||
|
udata->interface = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
ret = send_ip_packet(udata->sock, ð, (u8 *) packet, lua_objlen(L, 2));
|
||||||
|
} else {
|
||||||
|
usesock:
|
||||||
|
#ifdef WIN32
|
||||||
|
if (strlen(dev) > 0)
|
||||||
|
win32_warn_raw_sockets(dev);
|
||||||
|
#endif
|
||||||
|
ret = send_ip_packet(udata->sock, NULL, (u8 *) packet, lua_objlen(L, 2));
|
||||||
|
}
|
||||||
|
if (ret == -1)
|
||||||
|
return luaL_error(L, "error while sending: %s (errno %d)",
|
||||||
|
socket_strerror(socket_errno()), socket_errno());
|
||||||
|
|
||||||
|
return success(L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gc (lua_State *L)
|
||||||
|
{
|
||||||
|
nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE);
|
||||||
|
|
||||||
|
lua_pushcfunction(L, ip_close);
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_call(L, 1, 0);
|
||||||
|
lua_pushcfunction(L, ethernet_close);
|
||||||
|
lua_pushvalue(L, 1);
|
||||||
|
lua_call(L, 1, 0);
|
||||||
|
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, udata->interface);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LUALIB_API int luaopen_dnet (lua_State *L)
|
||||||
|
{
|
||||||
|
static const luaL_reg l_dnet[] = {
|
||||||
|
{"ethernet_open", ethernet_open},
|
||||||
|
{"ethernet_close", ethernet_close},
|
||||||
|
{"ethernet_send", ethernet_send},
|
||||||
|
{"ip_open", ip_open},
|
||||||
|
{"ip_close", ip_close},
|
||||||
|
{"ip_send", ip_send},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
lua_createtable(L, 2, 0);
|
||||||
|
lua_replace(L, LUA_ENVIRONINDEX);
|
||||||
|
weak_table(L, 0, 0, "k"); /* dnet udata weak, eth device strong */
|
||||||
|
lua_rawseti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH);
|
||||||
|
weak_table(L, 0, 0, "v"); /* eth_device weak */
|
||||||
|
lua_rawseti(L, LUA_ENVIRONINDEX, ETH_CACHE_DEVICE_ETH);
|
||||||
|
|
||||||
|
luaL_newmetatable(L, DNET_METATABLE);
|
||||||
|
lua_createtable(L, 0, 5);
|
||||||
|
luaL_register(L, NULL, l_dnet);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_setfield(L, -2, "__metatable");
|
||||||
|
lua_pushcfunction(L, gc);
|
||||||
|
lua_setfield(L, -2, "__gc");
|
||||||
|
|
||||||
|
luaL_newmetatable(L, DNET_ETH_METATABLE);
|
||||||
|
lua_pushcfunction(L, close_eth);
|
||||||
|
lua_setfield(L, -2, "__gc");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8
nse_dnet.h
Normal file
8
nse_dnet.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef NMAP_LUA_DNET_H
|
||||||
|
#define NMAP_LUA_DNET_H
|
||||||
|
|
||||||
|
LUALIB_API int l_dnet_new (lua_State *);
|
||||||
|
LUALIB_API int l_dnet_get_interface_link (lua_State *);
|
||||||
|
LUALIB_API int luaopen_dnet (lua_State *L);
|
||||||
|
|
||||||
|
#endif
|
||||||
51
nse_main.cc
51
nse_main.cc
@@ -1,15 +1,3 @@
|
|||||||
|
|
||||||
#include "nse_main.h"
|
|
||||||
|
|
||||||
#include "nse_fs.h"
|
|
||||||
#include "nse_nsock.h"
|
|
||||||
#include "nse_nmaplib.h"
|
|
||||||
#include "nse_bit.h"
|
|
||||||
#include "nse_binlib.h"
|
|
||||||
#include "nse_pcrelib.h"
|
|
||||||
#include "nse_openssl.h"
|
|
||||||
#include "nse_debug.h"
|
|
||||||
|
|
||||||
#include "nmap.h"
|
#include "nmap.h"
|
||||||
#include "nmap_error.h"
|
#include "nmap_error.h"
|
||||||
#include "portlist.h"
|
#include "portlist.h"
|
||||||
@@ -19,6 +7,17 @@
|
|||||||
#include "Target.h"
|
#include "Target.h"
|
||||||
#include "nmap_tty.h"
|
#include "nmap_tty.h"
|
||||||
|
|
||||||
|
#include "nse_main.h"
|
||||||
|
#include "nse_utility.h"
|
||||||
|
#include "nse_fs.h"
|
||||||
|
#include "nse_nsock.h"
|
||||||
|
#include "nse_nmaplib.h"
|
||||||
|
#include "nse_bit.h"
|
||||||
|
#include "nse_binlib.h"
|
||||||
|
#include "nse_pcrelib.h"
|
||||||
|
#include "nse_openssl.h"
|
||||||
|
#include "nse_debug.h"
|
||||||
|
|
||||||
#define NSE_MAIN "NSE_MAIN" /* the main function */
|
#define NSE_MAIN "NSE_MAIN" /* the main function */
|
||||||
#define NSE_TRACEBACK "NSE_TRACEBACK"
|
#define NSE_TRACEBACK "NSE_TRACEBACK"
|
||||||
|
|
||||||
@@ -130,7 +129,8 @@ static int host_set_output (lua_State *L)
|
|||||||
|
|
||||||
static int port_set_output (lua_State *L)
|
static int port_set_output (lua_State *L)
|
||||||
{
|
{
|
||||||
Port port, *p;
|
Port *p;
|
||||||
|
Port port;
|
||||||
ScriptResult sr;
|
ScriptResult sr;
|
||||||
Target *target = get_target(L, 1);
|
Target *target = get_target(L, 1);
|
||||||
p = get_port(L, target, &port, 2);
|
p = get_port(L, target, &port, 2);
|
||||||
@@ -406,6 +406,9 @@ static int run_main (lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lua 5.2 compatibility macro */
|
||||||
|
#define lua_yieldk(L,n,ctx,k) lua_yield(L,n)
|
||||||
|
|
||||||
/* int nse_yield (lua_State *L) [-?, +?, e]
|
/* int nse_yield (lua_State *L) [-?, +?, e]
|
||||||
*
|
*
|
||||||
* This function will yield the running thread back to NSE, even across script
|
* This function will yield the running thread back to NSE, even across script
|
||||||
@@ -413,12 +416,12 @@ static int run_main (lua_State *L)
|
|||||||
* correct and only way to call is as a tail call:
|
* correct and only way to call is as a tail call:
|
||||||
* return nse_yield(L);
|
* return nse_yield(L);
|
||||||
*/
|
*/
|
||||||
int nse_yield (lua_State *L)
|
int nse_yield (lua_State *L, int ctx, lua_CFunction k)
|
||||||
{
|
{
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, NSE_YIELD);
|
lua_getfield(L, LUA_REGISTRYINDEX, NSE_YIELD);
|
||||||
lua_pushthread(L);
|
lua_pushthread(L);
|
||||||
lua_call(L, 1, 1); /* returns NSE_YIELD_VALUE */
|
lua_call(L, 1, 1); /* returns NSE_YIELD_VALUE */
|
||||||
return lua_yield(L, 1); /* yield with NSE_YIELD_VALUE */
|
return lua_yieldk(L, 1, ctx, k); /* yield with NSE_YIELD_VALUE */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void nse_restore (lua_State *L, int number) [-, -, e]
|
/* void nse_restore (lua_State *L, int number) [-, -, e]
|
||||||
@@ -527,7 +530,14 @@ void open_nse (void)
|
|||||||
fatal("%s: failed to open a Lua state!", SCRIPT_ENGINE);
|
fatal("%s: failed to open a Lua state!", SCRIPT_ENGINE);
|
||||||
lua_atpanic(L_NSE, panic);
|
lua_atpanic(L_NSE, panic);
|
||||||
|
|
||||||
if (lua_cpcall(L_NSE, init_main, (void *) &o.chosenScripts) != 0)
|
#if 0
|
||||||
|
/* Lua 5.2 */
|
||||||
|
lua_pushcfunction(L_NSE, init_main);
|
||||||
|
lua_pushlightuserdata(L_NSE, &o.chosenScripts);
|
||||||
|
if (lua_pcall(L_NSE, 1, 0, 0))
|
||||||
|
#else
|
||||||
|
if (lua_cpcall(L_NSE, init_main, &o.chosenScripts))
|
||||||
|
#endif
|
||||||
fatal("%s: failed to initialize the script engine:\n%s\n", SCRIPT_ENGINE,
|
fatal("%s: failed to initialize the script engine:\n%s\n", SCRIPT_ENGINE,
|
||||||
lua_tostring(L_NSE, -1));
|
lua_tostring(L_NSE, -1));
|
||||||
}
|
}
|
||||||
@@ -540,7 +550,14 @@ void script_scan (std::vector<Target *> &targets, stype scantype)
|
|||||||
assert(L_NSE != NULL);
|
assert(L_NSE != NULL);
|
||||||
lua_settop(L_NSE, 0); /* clear the stack */
|
lua_settop(L_NSE, 0); /* clear the stack */
|
||||||
|
|
||||||
if (lua_cpcall(L_NSE, run_main, (void *) &targets) != 0)
|
#if 0
|
||||||
|
/* Lua 5.2 */
|
||||||
|
lua_pushcfunction(L_NSE, run_main);
|
||||||
|
lua_pushlightuserdata(L_NSE, &targets);
|
||||||
|
if (lua_pcall(L_NSE, 1, 0, 0))
|
||||||
|
#else
|
||||||
|
if (lua_cpcall(L_NSE, run_main, &targets))
|
||||||
|
#endif
|
||||||
error("%s: Script Engine Scan Aborted.\nAn error was thrown by the "
|
error("%s: Script Engine Scan Aborted.\nAn error was thrown by the "
|
||||||
"engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1));
|
"engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lualib.h"
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "nmap.h"
|
#include "nmap.h"
|
||||||
@@ -38,7 +38,7 @@ class Target;
|
|||||||
|
|
||||||
|
|
||||||
/* API */
|
/* API */
|
||||||
int nse_yield (lua_State *);
|
int nse_yield (lua_State *, int, lua_CFunction);
|
||||||
void nse_restore (lua_State *, int);
|
void nse_restore (lua_State *, int);
|
||||||
void nse_destructor (lua_State *, char);
|
void nse_destructor (lua_State *, char);
|
||||||
void nse_base (lua_State *);
|
void nse_base (lua_State *);
|
||||||
|
|||||||
109
nse_nmaplib.cc
109
nse_nmaplib.cc
@@ -2,6 +2,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -19,37 +20,15 @@ extern "C" {
|
|||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
|
|
||||||
#include "nse_nmaplib.h"
|
#include "nse_nmaplib.h"
|
||||||
|
#include "nse_utility.h"
|
||||||
#include "nse_nsock.h"
|
#include "nse_nsock.h"
|
||||||
|
#include "nse_dnet.h"
|
||||||
|
|
||||||
extern NmapOps o;
|
extern NmapOps o;
|
||||||
|
|
||||||
static const char *NSE_PROTOCOL_OP[] = {"tcp", "udp", "sctp", NULL};
|
static const char *NSE_PROTOCOL_OP[] = {"tcp", "udp", "sctp", NULL};
|
||||||
static const int NSE_PROTOCOL[] = {IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP};
|
static const int NSE_PROTOCOL[] = {IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP};
|
||||||
|
|
||||||
static void setsfield (lua_State *L, int idx, const char *field, const char *what)
|
|
||||||
{
|
|
||||||
lua_pushvalue(L, idx);
|
|
||||||
lua_pushstring(L, what); /* what can be NULL */
|
|
||||||
lua_setfield(L, -2, field);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setnfield (lua_State *L, int idx, const char *field, lua_Number n)
|
|
||||||
{
|
|
||||||
lua_pushvalue(L, idx);
|
|
||||||
lua_pushnumber(L, n);
|
|
||||||
lua_setfield(L, -2, field);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setbfield (lua_State *L, int idx, const char *field, int b)
|
|
||||||
{
|
|
||||||
lua_pushvalue(L, idx);
|
|
||||||
lua_pushboolean(L, b);
|
|
||||||
lua_setfield(L, -2, field);
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_version (lua_State *L, const struct serviceDeductions *sd)
|
void set_version (lua_State *L, const struct serviceDeductions *sd)
|
||||||
{
|
{
|
||||||
setsfield(L, -1, "name", sd->name);
|
setsfield(L, -1, "name", sd->name);
|
||||||
@@ -245,7 +224,7 @@ static int aux_mutex (lua_State *L)
|
|||||||
}
|
}
|
||||||
lua_pushthread(L);
|
lua_pushthread(L);
|
||||||
lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1);
|
lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1);
|
||||||
return nse_yield(L);
|
return nse_yield(L, 0, NULL);
|
||||||
case DONE:
|
case DONE:
|
||||||
lua_pushthread(L);
|
lua_pushthread(L);
|
||||||
if (!lua_equal(L, -1, lua_upvalueindex(2)))
|
if (!lua_equal(L, -1, lua_upvalueindex(2)))
|
||||||
@@ -341,7 +320,7 @@ static int aux_condvar (lua_State *L)
|
|||||||
case WAIT:
|
case WAIT:
|
||||||
lua_pushthread(L);
|
lua_pushthread(L);
|
||||||
lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1);
|
lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1);
|
||||||
return nse_yield(L);
|
return nse_yield(L, 0, NULL);
|
||||||
case SIGNAL:
|
case SIGNAL:
|
||||||
n = lua_objlen(L, lua_upvalueindex(1));
|
n = lua_objlen(L, lua_upvalueindex(1));
|
||||||
break;
|
break;
|
||||||
@@ -398,56 +377,6 @@ static int l_condvar (lua_State *L)
|
|||||||
return 1; // condition variable closure
|
return 1; // condition variable closure
|
||||||
}
|
}
|
||||||
|
|
||||||
Target *get_target (lua_State *L, int index)
|
|
||||||
{
|
|
||||||
int top = lua_gettop(L);
|
|
||||||
Target *target;
|
|
||||||
luaL_checktype(L, index, LUA_TTABLE);
|
|
||||||
lua_getfield(L, index, "targetname");
|
|
||||||
lua_getfield(L, index, "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_isstring(L, -2)) /* targetname */
|
|
||||||
{
|
|
||||||
nse_gettarget(L, -2); /* use targetname */
|
|
||||||
if (lua_islightuserdata(L, -1))
|
|
||||||
goto done;
|
|
||||||
else
|
|
||||||
lua_pop(L, 1);
|
|
||||||
}
|
|
||||||
if (lua_isstring(L, -1)) /* ip */
|
|
||||||
nse_gettarget(L, -1); /* use ip */
|
|
||||||
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 *get_port (lua_State *L, Target *target, Port *port, int index)
|
|
||||||
{
|
|
||||||
Port *p = NULL;
|
|
||||||
int portno, protocol;
|
|
||||||
luaL_checktype(L, index, LUA_TTABLE);
|
|
||||||
lua_getfield(L, index, "number");
|
|
||||||
if (!lua_isnumber(L, -1))
|
|
||||||
luaL_error(L, "port 'number' field must be a number");
|
|
||||||
lua_getfield(L, index, "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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generates an array of port data for the given host and leaves it on
|
/* Generates an array of port data for the given host and leaves it on
|
||||||
* the top of the stack
|
* the top of the stack
|
||||||
*/
|
*/
|
||||||
@@ -457,7 +386,8 @@ static int l_get_ports (lua_State *L)
|
|||||||
"open|filtered", "closed|filtered", NULL};
|
"open|filtered", "closed|filtered", NULL};
|
||||||
static const int states[] = {PORT_OPEN, PORT_FILTERED, PORT_UNFILTERED,
|
static const int states[] = {PORT_OPEN, PORT_FILTERED, PORT_UNFILTERED,
|
||||||
PORT_CLOSED, PORT_OPENFILTERED, PORT_CLOSEDFILTERED};
|
PORT_CLOSED, PORT_OPENFILTERED, PORT_CLOSEDFILTERED};
|
||||||
Port *p = NULL, port;
|
Port *p = NULL;
|
||||||
|
Port port; /* dummy Port for nextPort */
|
||||||
Target *target = get_target(L, 1);
|
Target *target = get_target(L, 1);
|
||||||
int protocol = NSE_PROTOCOL[luaL_checkoption(L, 3, NULL, NSE_PROTOCOL_OP)];
|
int protocol = NSE_PROTOCOL[luaL_checkoption(L, 3, NULL, NSE_PROTOCOL_OP)];
|
||||||
int state = states[luaL_checkoption(L, 4, NULL, state_op)];
|
int state = states[luaL_checkoption(L, 4, NULL, state_op)];
|
||||||
@@ -487,7 +417,8 @@ static int l_get_ports (lua_State *L)
|
|||||||
static int l_get_port_state (lua_State *L)
|
static int l_get_port_state (lua_State *L)
|
||||||
{
|
{
|
||||||
Target *target;
|
Target *target;
|
||||||
Port port, *p;
|
Port *p;
|
||||||
|
Port port; /* dummy Port */
|
||||||
target = get_target(L, 1);
|
target = get_target(L, 1);
|
||||||
p = get_port(L, target, &port, 2);
|
p = get_port(L, target, &port, 2);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
@@ -522,7 +453,8 @@ static int l_set_port_state (lua_State *L)
|
|||||||
static const int opstate[] = {PORT_OPEN, PORT_CLOSED};
|
static const int opstate[] = {PORT_OPEN, PORT_CLOSED};
|
||||||
static const char *op[] = {"open", "closed", NULL};
|
static const char *op[] = {"open", "closed", NULL};
|
||||||
Target *target;
|
Target *target;
|
||||||
Port port, *p;
|
Port *p;
|
||||||
|
Port port;
|
||||||
target = get_target(L, 1);
|
target = get_target(L, 1);
|
||||||
if ((p = get_port(L, target, &port, 2)) != NULL)
|
if ((p = get_port(L, target, &port, 2)) != NULL)
|
||||||
{
|
{
|
||||||
@@ -561,7 +493,8 @@ static int l_set_port_version (lua_State *L)
|
|||||||
"incomplete"
|
"incomplete"
|
||||||
};
|
};
|
||||||
Target *target;
|
Target *target;
|
||||||
Port port, *p;
|
Port *p;
|
||||||
|
Port port;
|
||||||
enum service_tunnel_type tunnel = SERVICE_TUNNEL_NONE;
|
enum service_tunnel_type tunnel = SERVICE_TUNNEL_NONE;
|
||||||
enum serviceprobestate probestate =
|
enum serviceprobestate probestate =
|
||||||
opversion[luaL_checkoption(L, 3, "hardmatched", ops)];
|
opversion[luaL_checkoption(L, 3, "hardmatched", ops)];
|
||||||
@@ -839,19 +772,11 @@ int luaopen_nmap (lua_State *L)
|
|||||||
lua_settop(L, 0); // clear stack
|
lua_settop(L, 0); // clear stack
|
||||||
luaL_register(L, "nmap", nmaplib);
|
luaL_register(L, "nmap", nmaplib);
|
||||||
|
|
||||||
lua_newtable(L);
|
weak_table(L, 0, 0, "v"); /* allow closures to be collected (see l_mutex) */
|
||||||
lua_createtable(L, 0, 1);
|
|
||||||
lua_pushliteral(L, "v");
|
|
||||||
lua_setfield(L, -2, "__mode");
|
|
||||||
lua_setmetatable(L, -2); // Allow closures to be collected (see l_mutex)
|
|
||||||
lua_pushcclosure(L, l_mutex, 1); /* mutex function */
|
lua_pushcclosure(L, l_mutex, 1); /* mutex function */
|
||||||
lua_setfield(L, -2, "mutex");
|
lua_setfield(L, -2, "mutex");
|
||||||
|
|
||||||
lua_newtable(L);
|
weak_table(L, 0, 0, "v"); /* allow closures to be collected (see l_condvar) */
|
||||||
lua_createtable(L, 0, 1);
|
|
||||||
lua_pushliteral(L, "v");
|
|
||||||
lua_setfield(L, -2, "__mode");
|
|
||||||
lua_setmetatable(L, -2); // Allow closures to be collected (see l_condvar)
|
|
||||||
lua_pushcclosure(L, l_condvar, 1); // condvar function
|
lua_pushcclosure(L, l_condvar, 1); // condvar function
|
||||||
lua_setfield(L, -2, "condvar");
|
lua_setfield(L, -2, "condvar");
|
||||||
|
|
||||||
@@ -862,6 +787,10 @@ int luaopen_nmap (lua_State *L)
|
|||||||
lua_pushliteral(L, "nsock");
|
lua_pushliteral(L, "nsock");
|
||||||
lua_call(L, 1, 0);
|
lua_call(L, 1, 0);
|
||||||
|
|
||||||
|
lua_pushcclosure(L, luaopen_dnet, 0);
|
||||||
|
lua_pushliteral(L, "dnet");
|
||||||
|
lua_call(L, 1, 0);
|
||||||
|
|
||||||
lua_settop(L, 1); // just nmap lib on stack
|
lua_settop(L, 1); // just nmap lib on stack
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
2736
nse_nsock.cc
2736
nse_nsock.cc
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,11 @@
|
|||||||
#ifndef NMAP_LUA_NSOCK_H
|
#ifndef NMAP_LUA_NSOCK_H
|
||||||
#define NMAP_LUA_NSOCK_H
|
#define NMAP_LUA_NSOCK_H
|
||||||
|
|
||||||
int luaopen_nsock(lua_State *);
|
#include "nse_main.h"
|
||||||
int l_nsock_new(lua_State *);
|
|
||||||
int l_nsock_sleep(lua_State *L);
|
|
||||||
|
|
||||||
int l_dnet_new(lua_State *);
|
LUALIB_API int luaopen_nsock (lua_State *);
|
||||||
int l_dnet_get_interface_link(lua_State *);
|
LUALIB_API int l_nsock_new (lua_State *);
|
||||||
|
LUALIB_API int l_nsock_sleep (lua_State *);
|
||||||
|
|
||||||
#define NSE_NSOCK_LOOP "NSOCK_LOOP"
|
#define NSE_NSOCK_LOOP "NSOCK_LOOP"
|
||||||
|
|
||||||
|
|||||||
180
nse_utility.cc
Normal file
180
nse_utility.cc
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Target.h"
|
||||||
|
#include "portlist.h"
|
||||||
|
|
||||||
|
#include "nse_main.h"
|
||||||
|
#include "nse_utility.h"
|
||||||
|
|
||||||
|
/* size_t table_length (lua_State *L, int index)
|
||||||
|
*
|
||||||
|
* Returns the length of the table at index index.
|
||||||
|
* This length is the number of elements, not just array elements.
|
||||||
|
*/
|
||||||
|
size_t table_length (lua_State *L, int index)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
lua_pushvalue(L, index);
|
||||||
|
lua_pushnil(L);
|
||||||
|
while (lua_next(L, -2))
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setsfield (lua_State *L, int idx, const char *field, const char *what)
|
||||||
|
{
|
||||||
|
lua_pushvalue(L, idx);
|
||||||
|
lua_pushstring(L, what); /* what can be NULL */
|
||||||
|
lua_setfield(L, -2, field);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setnfield (lua_State *L, int idx, const char *field, lua_Number n)
|
||||||
|
{
|
||||||
|
lua_pushvalue(L, idx);
|
||||||
|
lua_pushnumber(L, n);
|
||||||
|
lua_setfield(L, -2, field);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setbfield (lua_State *L, int idx, const char *field, int b)
|
||||||
|
{
|
||||||
|
lua_pushvalue(L, idx);
|
||||||
|
lua_pushboolean(L, b);
|
||||||
|
lua_setfield(L, -2, field);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int success (lua_State *L)
|
||||||
|
{
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int safe_error (lua_State *L, const char *message)
|
||||||
|
{
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
lua_pushstring(L, message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void weak_table (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* const char *check_target (lua_State *L, int idx)
|
||||||
|
*
|
||||||
|
* Check for a valid target specification at index idx.
|
||||||
|
* This function checks for a string at idx or a table containing
|
||||||
|
* the typical host table fields, 'ip' and 'targetname' in particular.
|
||||||
|
*/
|
||||||
|
void check_target (lua_State *L, int idx, const char **address, const char **targetname)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unsigned short check_port (lua_State *L, int idx)
|
||||||
|
*
|
||||||
|
* Check for a valid port specification at index idx.
|
||||||
|
*/
|
||||||
|
unsigned short check_port (lua_State *L, int idx, const char **protocol)
|
||||||
|
{
|
||||||
|
unsigned short port;
|
||||||
|
|
||||||
|
if (lua_istable(L, idx)) {
|
||||||
|
lua_getfield(L, idx, "number");
|
||||||
|
if (!lua_isnumber(L, -1))
|
||||||
|
luaL_argerror(L, idx, "port table lacks numeric 'number' field");
|
||||||
|
port = (unsigned short) lua_tointeger(L, -1);
|
||||||
|
lua_getfield(L, idx, "protocol");
|
||||||
|
*protocol = lua_tostring(L, -1);
|
||||||
|
lua_pop(L, 2);
|
||||||
|
} else {
|
||||||
|
port = (unsigned short) luaL_checkint(L, idx);
|
||||||
|
}
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Target *get_target (lua_State *L, int index)
|
||||||
|
*
|
||||||
|
* This function checks the value at index for a valid host table. It locates
|
||||||
|
* the associated Target (C++) class object associated with the host and
|
||||||
|
* returns it. If the Target is not being scanned then an error will be raised.
|
||||||
|
*/
|
||||||
|
Target *get_target (lua_State *L, int index)
|
||||||
|
{
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
Target *target;
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_getfield(L, index, "targetname");
|
||||||
|
lua_getfield(L, index, "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_isstring(L, -2)) /* targetname */
|
||||||
|
{
|
||||||
|
nse_gettarget(L, -2); /* use targetname */
|
||||||
|
if (lua_islightuserdata(L, -1))
|
||||||
|
goto done;
|
||||||
|
else
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
if (lua_isstring(L, -1)) /* ip */
|
||||||
|
nse_gettarget(L, -1); /* use ip */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Target *get_port (lua_State *L, Target *target, Port *port, int index)
|
||||||
|
*
|
||||||
|
* This function checks the value at index for a valid port table. It locates
|
||||||
|
* the associated Port (C++) class object associated with the host and
|
||||||
|
* returns it.
|
||||||
|
*/
|
||||||
|
Port *get_port (lua_State *L, Target *target, Port *port, int index)
|
||||||
|
{
|
||||||
|
Port *p = NULL;
|
||||||
|
int portno, protocol;
|
||||||
|
luaL_checktype(L, index, LUA_TTABLE);
|
||||||
|
lua_getfield(L, index, "number");
|
||||||
|
if (!lua_isnumber(L, -1))
|
||||||
|
luaL_error(L, "port 'number' field must be a number");
|
||||||
|
lua_getfield(L, index, "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;
|
||||||
|
}
|
||||||
19
nse_utility.h
Normal file
19
nse_utility.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef NMAP_NSE_UTILITY_H
|
||||||
|
#define NMAP_NSE_UTILITY_H
|
||||||
|
|
||||||
|
size_t table_length (lua_State *, int);
|
||||||
|
void setsfield (lua_State *, int, const char *, const char *);
|
||||||
|
void setnfield (lua_State *, int, const char *, lua_Number);
|
||||||
|
void setbfield (lua_State *, int, const char *, int);
|
||||||
|
void weak_table (lua_State *, int, int, const char *);
|
||||||
|
|
||||||
|
int success (lua_State *);
|
||||||
|
int safe_error (lua_State *, const char *);
|
||||||
|
|
||||||
|
void check_target (lua_State *, int, const char **, const char **);
|
||||||
|
unsigned short check_port (lua_State *, int, const char **);
|
||||||
|
|
||||||
|
Target *get_target (lua_State *, int);
|
||||||
|
Port *get_port (lua_State *, Target *, Port *, int);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -35,12 +35,6 @@ request_types_str[6] = "DHCPNAK"
|
|||||||
request_types_str[7] = "DHCPRELEASE"
|
request_types_str[7] = "DHCPRELEASE"
|
||||||
request_types_str[8] = "DHCPINFORM"
|
request_types_str[8] = "DHCPINFORM"
|
||||||
|
|
||||||
-- This pulls back 4 bytes in the packet that correspond to the transaction id. This should be randomly
|
|
||||||
-- generated and different for every instance of a script (to prevent collisions)
|
|
||||||
pcap_callback = function(packetsz, layer2, layer3)
|
|
||||||
return string.sub(layer3, 33, 36)
|
|
||||||
end
|
|
||||||
|
|
||||||
---Read an IP address or a list of IP addresses. Print an error if the length isn't a multiple of 4.
|
---Read an IP address or a list of IP addresses. Print an error if the length isn't a multiple of 4.
|
||||||
--
|
--
|
||||||
--@param data The packet.
|
--@param data The packet.
|
||||||
@@ -369,9 +363,8 @@ local function dhcp_send(interface, host, packet, transaction_id)
|
|||||||
-- Create a pcap socket to listen for the response. I used to consider this a hack, but
|
-- Create a pcap socket to listen for the response. I used to consider this a hack, but
|
||||||
-- it really isn't -- it's kinda how this has to be done.
|
-- it really isn't -- it's kinda how this has to be done.
|
||||||
local pcap = nmap.new_socket()
|
local pcap = nmap.new_socket()
|
||||||
pcap:pcap_open(interface, 590, 0, pcap_callback, "udp port 68")
|
pcap:pcap_open(interface, 590, false, "udp port 68")
|
||||||
pcap:set_timeout(5000)
|
pcap:set_timeout(5000)
|
||||||
pcap:pcap_register(transaction_id)
|
|
||||||
stdnse.print_debug(1, "dhcp: Starting listener")
|
stdnse.print_debug(1, "dhcp: Starting listener")
|
||||||
|
|
||||||
-- Create the UDP socket (TODO: enable SO_BROADCAST if we need to)
|
-- Create the UDP socket (TODO: enable SO_BROADCAST if we need to)
|
||||||
@@ -386,7 +379,12 @@ local function dhcp_send(interface, host, packet, transaction_id)
|
|||||||
socket:send(packet)
|
socket:send(packet)
|
||||||
|
|
||||||
-- Read the response
|
-- Read the response
|
||||||
local status, err, _, data = pcap:pcap_receive()
|
local status, length, layer2, layer3 = pcap:pcap_receive();
|
||||||
|
-- This pulls back 4 bytes in the packet that correspond to the transaction id. This should be randomly
|
||||||
|
-- generated and different for every instance of a script (to prevent collisions)
|
||||||
|
while status and layer3:sub(33, 36) ~= transaction_id do
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive();
|
||||||
|
end
|
||||||
if(status == false) then
|
if(status == false) then
|
||||||
stdnse.print_debug(1, "dhcp: Error calling pcap_receive(): %s", err)
|
stdnse.print_debug(1, "dhcp: Error calling pcap_receive(): %s", err)
|
||||||
return false, "Error calling pcap_receive(): " .. err
|
return false, "Error calling pcap_receive(): " .. err
|
||||||
|
|||||||
@@ -483,8 +483,7 @@ function receive_bytes(n)
|
|||||||
-- delimiter string (or matches the function passed in). This function
|
-- delimiter string (or matches the function passed in). This function
|
||||||
-- continues to read from the network until the delimiter is found or the
|
-- continues to read from the network until the delimiter is found or the
|
||||||
-- function times out. If data is read beyond the delimiter, that data is
|
-- function times out. If data is read beyond the delimiter, that data is
|
||||||
-- saved in a buffer for the next call to <code>receive_buf</code>. This
|
-- saved in a buffer for the next call to <code>receive_buf</code>.
|
||||||
-- buffer is cleared on subsequent calls to other Network I/O API functions.
|
|
||||||
--
|
--
|
||||||
-- The first argument may be either a pattern or a function. If a pattern, that
|
-- The first argument may be either a pattern or a function. If a pattern, that
|
||||||
-- pattern is used to separate the data. If a function, it must take exactly
|
-- pattern is used to separate the data. If a function, it must take exactly
|
||||||
@@ -501,12 +500,7 @@ function receive_bytes(n)
|
|||||||
--
|
--
|
||||||
-- On success the function returns true along with the received data. On failure
|
-- On success the function returns true along with the received data. On failure
|
||||||
-- the function returns <code>false</code> or <code>nil</code> along with an
|
-- the function returns <code>false</code> or <code>nil</code> along with an
|
||||||
-- error string. Possible error messages are the same as those that the other
|
-- receive error string. This function may also throw errors for incorrect usage.
|
||||||
-- receive functions can return, with the addition of
|
|
||||||
-- * <code>"Error inside splitting-function"</code>: The first argument was a function which caused an error while being called.
|
|
||||||
-- * <code>"Error in string.find (nsockobj:receive_buf)!"</code>: A string was provided as the first argument, and string.find() yielded an error while being called.
|
|
||||||
-- * <code>"Expected either a function or a string!"</code>: The first argument was neither a function nor a string.
|
|
||||||
-- * <code>"Delimiter has negative size!"</code>: The returned start offset is greater than the end offset.
|
|
||||||
-- @param delimiter A Lua pattern or a function with return values like those of
|
-- @param delimiter A Lua pattern or a function with return values like those of
|
||||||
-- <code>string.find</code>.
|
-- <code>string.find</code>.
|
||||||
-- @param keeppattern Whether to return the delimiter string with any returned
|
-- @param keeppattern Whether to return the delimiter string with any returned
|
||||||
@@ -565,37 +559,19 @@ function set_timeout(t)
|
|||||||
|
|
||||||
--- Opens a socket for raw packet capture.
|
--- Opens a socket for raw packet capture.
|
||||||
--
|
--
|
||||||
-- The callback function is a function that receives a packet with headers and
|
|
||||||
-- computes a "packet hash", some value derived from the packet. For example,
|
|
||||||
-- the callback function could extract the source IP address from a packet. The
|
|
||||||
-- hash of each packet received is compared against all the strings registered
|
|
||||||
-- with the <code>pcap_register</code> function.
|
|
||||||
-- @param device The dnet-style interface name of the device you want to capture
|
-- @param device The dnet-style interface name of the device you want to capture
|
||||||
-- from.
|
-- from.
|
||||||
-- @param snaplen The length of each packet you want to capture (similar to the
|
-- @param snaplen The length of each packet you want to capture (similar to the
|
||||||
-- <code>-s</code> option to tcpdump)
|
-- <code>-s</code> option to tcpdump)
|
||||||
-- @param promisc Set to 1 if the interface should activate promiscuous mode,
|
-- @param promisc Set to 1 if the interface should activate promiscuous mode,
|
||||||
-- and 0 otherwise.
|
-- and 0 otherwise.
|
||||||
-- @param test_function Callback function used to compute the packet hash.
|
|
||||||
-- @param bpf A string describing a Berkeley Packet Filter expression (like
|
-- @param bpf A string describing a Berkeley Packet Filter expression (like
|
||||||
-- those provided to tcpdump).
|
-- those provided to tcpdump).
|
||||||
-- @see new_socket, pcap_register, pcap_receive
|
-- @see new_socket, pcap_receive
|
||||||
-- @usage
|
-- @usage
|
||||||
-- local socket = nmap.new_socket()
|
-- local socket = nmap.new_socket()
|
||||||
-- socket:pcap_open("eth0", 64, 0, callback, "tcp")
|
-- socket:pcap_open("eth0", 64, false, "tcp")
|
||||||
function pcap_open(device, snaplen, promisc, test_function, bpf)
|
function pcap_open(device, snaplen, promisc, bpf)
|
||||||
|
|
||||||
--- Starts listening for incoming packets.
|
|
||||||
--
|
|
||||||
-- The provided <code>packet_hash</code> is a binary string which has to match
|
|
||||||
-- the hash returned by the <code>test_function</code> parameter provided to
|
|
||||||
-- <code>pcap_open</code>. If you want to receive all packets, just provide
|
|
||||||
-- the empty string (<code>""</code>). There has to be a call to
|
|
||||||
-- <code>pcap_register</code> before a call to <code>pcap_receive</code>.
|
|
||||||
-- @param packet_hash A binary string that is compared against packet hashes.
|
|
||||||
-- @see pcap_open, pcap_receive
|
|
||||||
-- @usage socket:pcap_register("")
|
|
||||||
function pcap_register(packet_hash)
|
|
||||||
|
|
||||||
--- Receives a captured packet.
|
--- Receives a captured packet.
|
||||||
--
|
--
|
||||||
@@ -609,7 +585,7 @@ function pcap_register(packet_hash)
|
|||||||
-- @return Data from the second OSI layer (e.g. ethernet headers).
|
-- @return Data from the second OSI layer (e.g. ethernet headers).
|
||||||
-- @return Data from the third OSI layer (e.g. IPv4 headers).
|
-- @return Data from the third OSI layer (e.g. IPv4 headers).
|
||||||
-- @return Packet capture time, as floating point seconds since the epoch
|
-- @return Packet capture time, as floating point seconds since the epoch
|
||||||
-- @see pcap_open, pcap_register
|
-- @see pcap_open
|
||||||
-- @usage status, plen, l2_data, l3_data, time = socket:pcap_receive()
|
-- @usage status, plen, l2_data, l3_data, time = socket:pcap_receive()
|
||||||
function pcap_receive()
|
function pcap_receive()
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,14 @@ require "openssl"
|
|||||||
-- @return packet_length, packet_length or nil
|
-- @return packet_length, packet_length or nil
|
||||||
-- the return is similar to the lua function string:find()
|
-- the return is similar to the lua function string:find()
|
||||||
check_packet_length = function( buffer )
|
check_packet_length = function( buffer )
|
||||||
|
if #buffer < 4 then return nil end
|
||||||
local payload_length, packet_length, offset
|
local payload_length, packet_length, offset
|
||||||
offset, payload_length = bin.unpack( ">I", buffer )
|
offset, payload_length = bin.unpack( ">I", buffer )
|
||||||
local padding = 8 - payload_length % 8
|
local padding = 8 - payload_length % 8
|
||||||
assert(payload_length)
|
assert(payload_length)
|
||||||
packet_length = buffer:len()
|
local total = 4+payload_length+padding;
|
||||||
if payload_length + 4 + padding > packet_length then return nil end
|
if total > #buffer then return nil end
|
||||||
return packet_length, packet_length
|
return total, total;
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Receives a complete SSH packet, even if fragmented
|
--- Receives a complete SSH packet, even if fragmented
|
||||||
@@ -43,7 +44,7 @@ end
|
|||||||
-- @return status True or false
|
-- @return status True or false
|
||||||
-- @return packet The packet received
|
-- @return packet The packet received
|
||||||
receive_ssh_packet = function( socket )
|
receive_ssh_packet = function( socket )
|
||||||
local status, packet = socket:receive_buf(check_packet_length)
|
local status, packet = socket:receive_buf(check_packet_length, true)
|
||||||
return status, packet
|
return status, packet
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ fetch_host_key = function(host, port)
|
|||||||
padding = 8 - packet_length % 8
|
padding = 8 - packet_length % 8
|
||||||
offset = offset + padding
|
offset = offset + padding
|
||||||
|
|
||||||
if padding + packet_length + 4 == data:len() then
|
if padding + packet_length + 4 == #data then
|
||||||
-- seems to be a proper SSH1 packet
|
-- seems to be a proper SSH1 packet
|
||||||
local msg_code,host_key_bits,exp,mod,length,fp_input
|
local msg_code,host_key_bits,exp,mod,length,fp_input
|
||||||
offset, msg_code = bin.unpack( ">c", data, offset )
|
offset, msg_code = bin.unpack( ">c", data, offset )
|
||||||
|
|||||||
@@ -29,11 +29,12 @@ local SSH2
|
|||||||
-- @return packet_length, packet_length or nil
|
-- @return packet_length, packet_length or nil
|
||||||
-- the return is similar to the lua function string:find()
|
-- the return is similar to the lua function string:find()
|
||||||
check_packet_length = function( buffer )
|
check_packet_length = function( buffer )
|
||||||
|
if #buffer < 4 then return nil end -- not enough data in buffer for int
|
||||||
local packet_length, offset
|
local packet_length, offset
|
||||||
offset, packet_length = bin.unpack( ">I", buffer )
|
offset, packet_length = bin.unpack( ">I", buffer )
|
||||||
assert(packet_length)
|
assert(packet_length)
|
||||||
if packet_length + 4 > buffer:len() then return nil end
|
if packet_length + 4 > buffer:len() then return nil end
|
||||||
return packet_length, packet_length
|
return packet_length+4, packet_length+4
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Receives a complete SSH packet, even if fragmented
|
--- Receives a complete SSH packet, even if fragmented
|
||||||
@@ -45,7 +46,7 @@ end
|
|||||||
-- @return status True or false
|
-- @return status True or false
|
||||||
-- @return packet The packet received
|
-- @return packet The packet received
|
||||||
transport.receive_packet = function( socket )
|
transport.receive_packet = function( socket )
|
||||||
local status, packet = socket:receive_buf(check_packet_length)
|
local status, packet = socket:receive_buf(check_packet_length, true)
|
||||||
return status, packet
|
return status, packet
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -78,7 +79,9 @@ end
|
|||||||
-- @return Payload of the SSH-2 packet.
|
-- @return Payload of the SSH-2 packet.
|
||||||
transport.payload = function( packet )
|
transport.payload = function( packet )
|
||||||
local packet_length, padding_length, payload_length, payload, offset
|
local packet_length, padding_length, payload_length, payload, offset
|
||||||
offset, packet_length, padding_length = bin.unpack( ">Ic", packet )
|
offset, packet_length = bin.unpack( ">I", packet )
|
||||||
|
packet = packet:sub(offset);
|
||||||
|
offset, padding_length = bin.unpack( ">c", packet )
|
||||||
assert(packet_length and padding_length)
|
assert(packet_length and padding_length)
|
||||||
payload_length = packet_length - padding_length - 1
|
payload_length = packet_length - padding_length - 1
|
||||||
if packet_length ~= packet:len() then
|
if packet_length ~= packet:len() then
|
||||||
|
|||||||
@@ -84,13 +84,6 @@ local checkpkt = function(reply, orig)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--- pcap callback
|
|
||||||
-- @return destination ip address, the ip protocol and icmp type
|
|
||||||
local callback = function(size, layer2, layer3)
|
|
||||||
local ip = packet.Packet:new(layer3, layer3:len())
|
|
||||||
return bin.pack('ACC', ip.ip_bin_dst, ip.ip_p, ip.icmp_type)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- set destination port and ip ttl to a generic tcp packet
|
--- set destination port and ip ttl to a generic tcp packet
|
||||||
-- @param ip the ip object
|
-- @param ip the ip object
|
||||||
-- @param dport the layer 4 destination port
|
-- @param dport the layer 4 destination port
|
||||||
@@ -274,6 +267,13 @@ local portrange = function(ports)
|
|||||||
return stdnse.strjoin(",", strrange)
|
return stdnse.strjoin(",", strrange)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- pcap check function
|
||||||
|
-- @return destination ip address, the ip protocol and icmp type
|
||||||
|
local function check (size, layer2, layer3)
|
||||||
|
local ip = packet.Packet:new(layer3, layer3:len())
|
||||||
|
return bin.pack('ACC', ip.ip_bin_dst, ip.ip_p, ip.icmp_type)
|
||||||
|
end
|
||||||
|
|
||||||
-- main firewalking logic
|
-- main firewalking logic
|
||||||
action = function(host)
|
action = function(host)
|
||||||
local sock = nmap.new_dnet()
|
local sock = nmap.new_dnet()
|
||||||
@@ -290,7 +290,7 @@ action = function(host)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- filter for incoming icmp time exceeded replies
|
-- filter for incoming icmp time exceeded replies
|
||||||
pcap:pcap_open(host.interface, 104, 0, callback, "icmp and dst host " .. saddr)
|
pcap:pcap_open(host.interface, 104, false, "icmp and dst host " .. saddr)
|
||||||
|
|
||||||
try(sock:ip_open())
|
try(sock:ip_open())
|
||||||
|
|
||||||
@@ -309,11 +309,14 @@ action = function(host)
|
|||||||
while retry < MAX_RETRIES do
|
while retry < MAX_RETRIES do
|
||||||
try(sock:ip_send(pkt.buf))
|
try(sock:ip_send(pkt.buf))
|
||||||
|
|
||||||
pcap:pcap_register(bin.pack('ACC', pkt.ip_bin_src, packet.IPPROTO_ICMP, ICMP_TIME_EXCEEDED))
|
local status, length, layer2, layer3 = pcap:pcap_receive();
|
||||||
local status, _, _, rep = pcap:pcap_receive()
|
local test = bin.pack('ACC', pkt.ip_bin_src, packet.IPPROTO_ICMP, ICMP_TIME_EXCEEDED);
|
||||||
|
while status and test ~= check(length, layer2, layer3) do
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive();
|
||||||
|
end
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
if checkpkt(rep, pkt) then
|
if checkpkt(layer3, pkt) then
|
||||||
stdnse.print_debug(1, "Firewalk: discovered fwd port " .. port)
|
stdnse.print_debug(1, "Firewalk: discovered fwd port " .. port)
|
||||||
table.insert(fwdports, port)
|
table.insert(fwdports, port)
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ require 'packet'
|
|||||||
|
|
||||||
local NUMPROBES = 6
|
local NUMPROBES = 6
|
||||||
|
|
||||||
--- Pcap callback
|
--- Pcap check function
|
||||||
-- @return Destination and source IP addresses and TCP ports
|
-- @return Destination and source IP addresses and TCP ports
|
||||||
local callback = function(size, layer2, layer3)
|
local function check (size, layer2, layer3)
|
||||||
local ip = packet.Packet:new(layer3, layer3:len())
|
local ip = packet.Packet:new(layer3, layer3:len())
|
||||||
return bin.pack('AA=S=S', ip.ip_bin_dst, ip.ip_bin_src, ip.tcp_dport, ip.tcp_sport)
|
return bin.pack('AA=S=S', ip.ip_bin_dst, ip.ip_bin_src, ip.tcp_dport, ip.tcp_sport)
|
||||||
end
|
end
|
||||||
@@ -222,7 +222,7 @@ action = function(host)
|
|||||||
|
|
||||||
try = nmap.new_try(function() sock:ip_close() end)
|
try = nmap.new_try(function() sock:ip_close() end)
|
||||||
|
|
||||||
pcap:pcap_open(host.interface, 104, 0, callback, "tcp and dst host " .. saddr .. " and src host " .. daddr .. " and src port " .. port)
|
pcap:pcap_open(host.interface, 104, false, "tcp and dst host " .. saddr .. " and src host " .. daddr .. " and src port " .. port)
|
||||||
|
|
||||||
pcap:set_timeout(host.times.timeout * 1000)
|
pcap:set_timeout(host.times.timeout * 1000)
|
||||||
|
|
||||||
@@ -231,12 +231,14 @@ action = function(host)
|
|||||||
while i <= NUMPROBES do
|
while i <= NUMPROBES do
|
||||||
try(sock:ip_send(tcp.buf))
|
try(sock:ip_send(tcp.buf))
|
||||||
|
|
||||||
pcap:pcap_register(bin.pack('AA=S=S', tcp.ip_bin_src, tcp.ip_bin_dst, tcp.tcp_sport, tcp.tcp_dport))
|
local status, len, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
local test = bin.pack('AA=S=S', tcp.ip_bin_src, tcp.ip_bin_dst, tcp.tcp_sport, tcp.tcp_dport)
|
||||||
local status, len, _, pkt = pcap:pcap_receive()
|
while status and test ~= check(len, layer2, layer3) do
|
||||||
|
status, len, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
end
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
table.insert(ipids, packet.u16(pkt, 4))
|
table.insert(ipids, packet.u16(layer3, 4))
|
||||||
end
|
end
|
||||||
|
|
||||||
updatepkt(tcp)
|
updatepkt(tcp)
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ end
|
|||||||
|
|
||||||
-- This is all we can use since we can get various protocols back from
|
-- This is all we can use since we can get various protocols back from
|
||||||
-- different hosts
|
-- different hosts
|
||||||
local callback = function(size, layer2, layer3)
|
local function check (size, layer2, layer3)
|
||||||
local ip = packet.Packet:new(layer3, layer3:len())
|
local ip = packet.Packet:new(layer3, layer3:len())
|
||||||
return bin.pack('A', ip.ip_bin_dst)
|
return bin.pack('A', ip.ip_bin_dst)
|
||||||
end
|
end
|
||||||
@@ -306,7 +306,7 @@ action = function(host)
|
|||||||
|
|
||||||
try = nmap.new_try(function() sock:ip_close() end)
|
try = nmap.new_try(function() sock:ip_close() end)
|
||||||
|
|
||||||
pcap:pcap_open(host.interface, 104, 0, callback, "dst host " .. saddr .. " and (icmp or (" .. proto .. " and src host " .. daddr .. " and src port " .. port .. "))")
|
pcap:pcap_open(host.interface, 104, false, "dst host " .. saddr .. " and (icmp or (" .. proto .. " and src host " .. daddr .. " and src port " .. port .. "))")
|
||||||
|
|
||||||
-- Since we're sending potentially large amounts of data per packet,
|
-- Since we're sending potentially large amounts of data per packet,
|
||||||
-- simply bump up the host's calculated timeout value. Most replies
|
-- simply bump up the host's calculated timeout value. Most replies
|
||||||
@@ -337,12 +337,14 @@ action = function(host)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
pcap:pcap_register(bin.pack('A', pkt.ip_bin_src))
|
local test = bin.pack('A', pkt.ip_bin_src)
|
||||||
|
local status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
status, _, _, ip = pcap:pcap_receive()
|
while status and test ~= check(length, layer2, layer3) do
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
end
|
||||||
|
|
||||||
if status then
|
if status then
|
||||||
local t, v = checkpkt(ip, pkt)
|
local t, v = checkpkt(layer3, pkt)
|
||||||
if t == "gotreply" then
|
if t == "gotreply" then
|
||||||
gotit = true
|
gotit = true
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -157,9 +157,9 @@ local tstat = function(n1, n2, u1, u2, v1, v2)
|
|||||||
return math.abs(u1 - u2) / math.sqrt(a * (b / dof))
|
return math.abs(u1 - u2) / math.sqrt(a * (b / dof))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Pcap callback
|
--- Pcap check
|
||||||
-- @return Destination and source IP addresses and TCP ports
|
-- @return Destination and source IP addresses and TCP ports
|
||||||
local callback = function(size, layer2, layer3)
|
local function check (size, layer2, layer3)
|
||||||
local ip = packet.Packet:new(layer3, layer3:len())
|
local ip = packet.Packet:new(layer3, layer3:len())
|
||||||
return bin.pack('AA=S=S', ip.ip_bin_dst, ip.ip_bin_src, ip.tcp_dport, ip.tcp_sport)
|
return bin.pack('AA=S=S', ip.ip_bin_dst, ip.ip_bin_src, ip.tcp_dport, ip.tcp_sport)
|
||||||
end
|
end
|
||||||
@@ -418,7 +418,7 @@ action = function(host)
|
|||||||
|
|
||||||
local conf, delay, numtrips = try(getopts())
|
local conf, delay, numtrips = try(getopts())
|
||||||
|
|
||||||
pcap:pcap_open(host.interface, 104, 0, callback, "tcp and dst host " .. saddr .. " and src host " .. daddr)
|
pcap:pcap_open(host.interface, 104, false, "tcp and dst host " .. saddr .. " and src host " .. daddr)
|
||||||
|
|
||||||
try(sock:ip_open())
|
try(sock:ip_open())
|
||||||
|
|
||||||
@@ -452,15 +452,17 @@ action = function(host)
|
|||||||
stats[j].fam = -1
|
stats[j].fam = -1
|
||||||
end
|
end
|
||||||
|
|
||||||
pcap:pcap_register(bin.pack('AA=S=S', tcp.ip_bin_src, tcp.ip_bin_dst, tcp.tcp_sport, tcp.tcp_dport))
|
|
||||||
|
|
||||||
start = stdnse.clock_us()
|
start = stdnse.clock_us()
|
||||||
|
|
||||||
try(sock:ip_send(tcp.buf))
|
try(sock:ip_send(tcp.buf))
|
||||||
|
|
||||||
stats[j].sent = stats[j].sent + 1
|
stats[j].sent = stats[j].sent + 1
|
||||||
|
|
||||||
local status, len, _, pkt, stop = pcap:pcap_receive()
|
local test = bin.pack('AA=S=S', tcp.ip_bin_src, tcp.ip_bin_dst, tcp.tcp_sport, tcp.tcp_dport)
|
||||||
|
local status, length, layer2, layer3, stop = pcap:pcap_receive()
|
||||||
|
while status and test ~= check(length, layer2, layer3) do
|
||||||
|
status, length, layer2, layer3, stop = pcap:pcap_receive()
|
||||||
|
end
|
||||||
|
|
||||||
if not stop then
|
if not stop then
|
||||||
-- probably a timeout, just grab current time
|
-- probably a timeout, just grab current time
|
||||||
|
|||||||
@@ -24,14 +24,13 @@ hostrule = function(host)
|
|||||||
nmap.get_interface_link(host.interface) == 'ethernet'
|
nmap.get_interface_link(host.interface) == 'ethernet'
|
||||||
end
|
end
|
||||||
|
|
||||||
callback = function(packetsz, layer2, layer3)
|
local function check (packetsz, layer2, layer3)
|
||||||
return string.sub(layer2, 0, 12)
|
return string.sub(layer2, 0, 12)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do_test = function(dnet, pcap, host, test)
|
do_test = function(dnet, pcap, host, test)
|
||||||
local _
|
local status, length, layer2, layer3
|
||||||
local status
|
|
||||||
local i = 0
|
local i = 0
|
||||||
|
|
||||||
-- ARP requests are send with timeouts: 10ms, 40ms, 90ms
|
-- ARP requests are send with timeouts: 10ms, 40ms, 90ms
|
||||||
@@ -41,15 +40,21 @@ do_test = function(dnet, pcap, host, test)
|
|||||||
-- flush buffers :), wait quite long.
|
-- flush buffers :), wait quite long.
|
||||||
repeat
|
repeat
|
||||||
pcap:set_timeout(100)
|
pcap:set_timeout(100)
|
||||||
pcap:pcap_register(host.mac_addr_src .. host.mac_addr)
|
local test = host.mac_addr_src .. host.mac_addr
|
||||||
status ,_,_,_ = pcap:pcap_receive()
|
status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
while status and test ~= check(length, layer2, layer3) do
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
end
|
||||||
until status ~= true
|
until status ~= true
|
||||||
pcap:set_timeout(10 * i*i)
|
pcap:set_timeout(10 * i*i)
|
||||||
pcap:pcap_register(host.mac_addr_src .. host.mac_addr)
|
|
||||||
|
|
||||||
dnet:ethernet_send(test)
|
dnet:ethernet_send(test)
|
||||||
|
|
||||||
status ,_,_,_ = pcap:pcap_receive()
|
local test = host.mac_addr_src .. host.mac_addr
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
while status and test ~= check(length, layer2, layer3) do
|
||||||
|
status, length, layer2, layer3 = pcap:pcap_receive()
|
||||||
|
end
|
||||||
if status == true then
|
if status == true then
|
||||||
-- the basic idea, was to inform user about time, when we got packet
|
-- the basic idea, was to inform user about time, when we got packet
|
||||||
-- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms)
|
-- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms)
|
||||||
@@ -79,7 +84,7 @@ action = function(host)
|
|||||||
}
|
}
|
||||||
dnet:ethernet_open(host.interface)
|
dnet:ethernet_open(host.interface)
|
||||||
|
|
||||||
pcap:pcap_open(host.interface, 64, 0, callback, "arp")
|
pcap:pcap_open(host.interface, 64, false, "arp")
|
||||||
|
|
||||||
local test_static = host.mac_addr_src ..
|
local test_static = host.mac_addr_src ..
|
||||||
string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) ..
|
string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) ..
|
||||||
|
|||||||
Reference in New Issue
Block a user