mirror of
https://github.com/nmap/nmap.git
synced 2025-12-29 02:49:01 +00:00
Add connect-mode recv() and send() support.
This commit is contained in:
@@ -83,15 +83,19 @@ DATAFILES = certs/ca-bundle.crt
|
||||
endif
|
||||
|
||||
ifneq ($(HAVE_LUA),)
|
||||
LUA_SRCS = ncat_lua_exec.c ncat_lua.c ncat_lua_filters.c
|
||||
LUA_OBJS = ncat_lua_exec.o ncat_lua.o ncat_lua_filters.o
|
||||
LUA_SRCS = ncat_lua.c ncat_lua_exec.c ncat_lua_filters.c ncat_lua_connect.c
|
||||
LUA_OBJS = ncat_lua.o ncat_lua_exec.o ncat_lua_filters.o ncat_lua_connect.o
|
||||
LUA_LIBS = @LIBLUA_LIBS@ -lm
|
||||
LUA_CFLAGS += -DHAVE_LUA=1 -I../liblua
|
||||
# This is the result of lua_setup() pulling in recv/send routines, which
|
||||
# in turn pull a few other files.
|
||||
MORE_TEST_OBJS = http.o http_digest.o base64.o ncat_ssl.o ncat_connect.o
|
||||
else
|
||||
LUA_SRCS =
|
||||
LUA_OBJS =
|
||||
LUA_LIBS =
|
||||
LUA_CFLAGS =
|
||||
MORE_TEST_OBJS =
|
||||
endif
|
||||
|
||||
SRCS += $(LUA_SRCS)
|
||||
@@ -135,16 +139,16 @@ config.h:
|
||||
$(SHELL) ./config.status; \
|
||||
fi
|
||||
|
||||
test/addrset: test/addrset.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS)
|
||||
test/addrset: test/addrset.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(MORE_TEST_OBJS) $(LUA_OBJS)
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
|
||||
|
||||
test/test-uri: test/test-uri.o base64.o http.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS)
|
||||
test/test-uri: test/test-uri.o base64.o http.o ncat_core.o sys_wrap.o util.o ncat_posix.o $(MORE_TEST_OBJS) $(LUA_OBJS)
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
|
||||
|
||||
test/test-cmdline-split: test/test-cmdline-split.o ncat_posix.o ncat_core.o sys_wrap.o util.o $(LUA_OBJS)
|
||||
test/test-cmdline-split: test/test-cmdline-split.o ncat_posix.o ncat_core.o sys_wrap.o util.o $(MORE_TEST_OBJS) $(LUA_OBJS)
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
|
||||
|
||||
test/test-wildcard: test/test-wildcard.o ncat_core.o ncat_ssl.o sys_wrap.o util.o ncat_posix.o $(LUA_OBJS)
|
||||
test/test-wildcard: test/test-wildcard.o ncat_core.o ncat_ssl.o sys_wrap.o util.o ncat_posix.o $(MORE_TEST_OBJS) $(LUA_OBJS)
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(NSOCKLIB) $(NBASELIB) $(OPENSSL_LIBS) $(PCAP_LIBS) $(LUA_LIBS) $(LIBS)
|
||||
|
||||
.PHONY: uninstall all clean distclean
|
||||
|
||||
@@ -151,6 +151,11 @@
|
||||
#define SHUT_WR SD_SEND
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
#include "ncat_lua_filters.h"
|
||||
#include "ncat_lua_connect.h"
|
||||
#endif
|
||||
|
||||
struct conn_state {
|
||||
nsock_iod sock_nsi;
|
||||
nsock_iod stdin_nsi;
|
||||
@@ -169,7 +174,6 @@ static void connect_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void post_connect(nsock_pool nsp, nsock_iod iod);
|
||||
static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void idle_timer_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
static void refresh_idle_timer(nsock_pool nsp);
|
||||
|
||||
@@ -549,6 +553,10 @@ int ncat_connect(void)
|
||||
cs.sock_nsi = nsi_new(mypool, NULL);
|
||||
if (cs.sock_nsi == NULL)
|
||||
bye("Failed to create nsock_iod.");
|
||||
#ifdef HAVE_LUA
|
||||
if (o.script)
|
||||
lua_nsock_save(mypool, cs.sock_nsi);
|
||||
#endif
|
||||
|
||||
if (nsi_set_hostname(cs.sock_nsi, o.target) == -1)
|
||||
bye("Failed to set hostname on iod.");
|
||||
@@ -706,6 +714,10 @@ int ncat_connect(void)
|
||||
/* Create IOD for nsp->stdin */
|
||||
if ((cs.stdin_nsi = nsi_new2(mypool, 0, NULL)) == NULL)
|
||||
bye("Failed to create stdin nsiod.");
|
||||
#ifdef HAVE_LUA
|
||||
if (o.script)
|
||||
lua_nsock_save(mypool, cs.sock_nsi);
|
||||
#endif
|
||||
|
||||
post_connect(mypool, cs.sock_nsi);
|
||||
}
|
||||
@@ -792,8 +804,14 @@ static void post_connect(nsock_pool nsp, nsock_iod iod)
|
||||
|
||||
/* Start the initial reads. */
|
||||
|
||||
if (!o.sendonly)
|
||||
nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL);
|
||||
if (!o.sendonly) {
|
||||
#ifdef HAVE_LUA
|
||||
if (o.script)
|
||||
lua_nsock_read(0);
|
||||
else
|
||||
#endif
|
||||
nsock_read(nsp, cs.sock_nsi, read_socket_handler, -1, NULL);
|
||||
}
|
||||
|
||||
if (!o.recvonly)
|
||||
nsock_readbytes(nsp, cs.stdin_nsi, read_stdin_handler, -1, NULL, 0);
|
||||
@@ -845,7 +863,13 @@ static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
buf = tmp;
|
||||
}
|
||||
|
||||
nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, buf, nbytes);
|
||||
#ifdef HAVE_LUA
|
||||
if (o.script)
|
||||
lua_nsock_write(nsp, cs.sock_nsi, buf, nbytes);
|
||||
else
|
||||
#endif
|
||||
nsock_write(nsp, cs.sock_nsi, write_socket_handler, -1, NULL, buf, nbytes);
|
||||
|
||||
ncat_log_send(buf, nbytes);
|
||||
|
||||
if (tmp)
|
||||
@@ -854,12 +878,11 @@ static void read_stdin_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
refresh_idle_timer(nsp);
|
||||
}
|
||||
|
||||
static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
/* Handle nsock errors. */
|
||||
int check_nsock_error(nsock_pool nsp, nsock_event evt)
|
||||
{
|
||||
enum nse_status status = nse_status(evt);
|
||||
enum nse_type type = nse_type(evt);
|
||||
char *buf;
|
||||
int nbytes;
|
||||
|
||||
ncat_assert(type == NSE_TYPE_READ);
|
||||
|
||||
@@ -868,7 +891,7 @@ static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
/* In --recv-only mode or non-TCP mode, exit after EOF on the socket. */
|
||||
if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.recvonly))
|
||||
nsock_loop_quit(nsp);
|
||||
return;
|
||||
return 1;
|
||||
} else if (status == NSE_STATUS_ERROR) {
|
||||
loguser("%s.\n", socket_strerror(nse_errorcode(evt)));
|
||||
exit(1);
|
||||
@@ -876,29 +899,46 @@ static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
loguser("%s.\n", socket_strerror(ETIMEDOUT));
|
||||
exit(1);
|
||||
} else if (status == NSE_STATUS_CANCELLED || status == NSE_STATUS_KILL) {
|
||||
return;
|
||||
return 1;
|
||||
} else {
|
||||
ncat_assert(status == NSE_STATUS_SUCCESS);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = nse_readbuf(evt, &nbytes);
|
||||
|
||||
/* Handle some post-read activities. */
|
||||
void ncat_nsock_postread(nsock_pool nsp, nsock_event evt, const char *buf, int nbytes)
|
||||
{
|
||||
if (o.linedelay)
|
||||
ncat_delay_timer(o.linedelay);
|
||||
|
||||
if (o.telnet)
|
||||
dotelnet(nsi_getsd(nse_iod(evt)), (unsigned char *) buf, nbytes);
|
||||
if (nbytes > 0) {
|
||||
if (o.telnet)
|
||||
dotelnet(nsi_getsd(nse_iod(evt)), (unsigned char *) buf, nbytes);
|
||||
|
||||
/* Write socket data to stdout */
|
||||
Write(STDOUT_FILENO, buf, nbytes);
|
||||
ncat_log_recv(buf, nbytes);
|
||||
|
||||
nsock_readbytes(nsp, cs.sock_nsi, read_socket_handler, -1, NULL, 0);
|
||||
/* Write socket data to stdout */
|
||||
Write(STDOUT_FILENO, buf, nbytes);
|
||||
ncat_log_recv(buf, nbytes);
|
||||
}
|
||||
|
||||
refresh_idle_timer(nsp);
|
||||
}
|
||||
|
||||
static void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
static void read_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
{
|
||||
char *buf;
|
||||
int nbytes;
|
||||
|
||||
if (check_nsock_error(nsp, evt))
|
||||
return;
|
||||
|
||||
buf = nse_readbuf(evt, &nbytes);
|
||||
ncat_nsock_postread(nsp, evt, buf, nbytes);
|
||||
|
||||
nsock_readbytes(nsp, cs.sock_nsi, read_socket_handler, -1, NULL, 0);
|
||||
}
|
||||
|
||||
void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data)
|
||||
{
|
||||
enum nse_status status = nse_status(evt);
|
||||
enum nse_type type = nse_type(evt);
|
||||
|
||||
@@ -123,5 +123,13 @@
|
||||
|
||||
#include "nsock.h"
|
||||
|
||||
#ifdef HAVE_LUA
|
||||
#include "ncat_lua.h"
|
||||
#include "ncat_lua_connect.h"
|
||||
#endif
|
||||
|
||||
/* handle nsock-powered connections */
|
||||
extern int ncat_connect(void);
|
||||
int check_nsock_error(nsock_pool nsp, nsock_event evt);
|
||||
void ncat_nsock_postread(nsock_pool nsp, nsock_event evt, const char *buf, int nbytes);
|
||||
void write_socket_handler(nsock_pool nsp, nsock_event evt, void *data);
|
||||
|
||||
@@ -139,11 +139,17 @@ static void lua_create_supersocket()
|
||||
lua_newtable(filters_L);
|
||||
|
||||
lua_pushstring(filters_L, "recv");
|
||||
lua_pushcfunction(filters_L, lua_do_nothing);
|
||||
if (o.listen)
|
||||
lua_pushcfunction(filters_L, lua_do_nothing); /* TODO */
|
||||
else
|
||||
lua_pushcfunction(filters_L, lua_nsock_recv_raw);
|
||||
lua_settable(filters_L, -3);
|
||||
|
||||
lua_pushstring(filters_L, "send");
|
||||
lua_pushcfunction(filters_L, lua_do_nothing);
|
||||
if (o.listen)
|
||||
lua_pushcfunction(filters_L, lua_do_nothing);
|
||||
else
|
||||
lua_pushcfunction(filters_L, lua_nsock_write_raw);
|
||||
lua_settable(filters_L, -3);
|
||||
|
||||
lua_set_registry("socket");
|
||||
@@ -229,3 +235,109 @@ void lua_run_filter(char *cmdexec)
|
||||
lua_report(filters_L, cmdexec, 1);
|
||||
lua_set_registry("socket");
|
||||
}
|
||||
|
||||
/* Try to find the connection in the global table named "connections" with fd
|
||||
as the key. If it's not there, create it, find its topmost "super", set its
|
||||
"fd" to the given struct ncat_lua_state and save it in connection_supers.
|
||||
Leave the socket on the stack. If *fdn is NULL, we assume that fd=0 and
|
||||
we're in connect mode. Also, if *created is not NULL, it is set to 1 if
|
||||
the socket put on the stack was just created. */
|
||||
struct ncat_lua_state* get_connection(struct fdinfo *fdn, int *created)
|
||||
{
|
||||
struct ncat_lua_state *ret;
|
||||
int connections_key;
|
||||
if (fdn == NULL)
|
||||
connections_key = 0;
|
||||
else
|
||||
connections_key = fdn->fd;
|
||||
/* Try to access connections[fd]. Leave connections[] on the stack. */
|
||||
lua_fetch_registry("connections");
|
||||
lua_pushinteger(filters_L, connections_key);
|
||||
lua_gettable(filters_L, -2);
|
||||
|
||||
if (lua_isnil(filters_L, -1)) {
|
||||
|
||||
lua_pop(filters_L, 1); /* nil means we hadn't added the connection yet, pop it. */
|
||||
|
||||
/* Basically: connections[fd] = new_socket(socket) */
|
||||
lua_pushinteger(filters_L, connections_key);
|
||||
lua_pushvalue(filters_L, make_socket_function_idx);
|
||||
lua_pushvalue(filters_L, make_socket_function_idx);
|
||||
lua_fetch_registry("socket");
|
||||
if (lua_pcall(filters_L, 2, 1, error_handler_idx) != LUA_OK)
|
||||
lua_report(filters_L, "Error creating the socket", 1);
|
||||
lua_pushvalue(filters_L, -1); /* Make a copy of the connection we created. */
|
||||
lua_insert(filters_L, -4); /* Move it below connection, 5 and original table. */
|
||||
lua_settable(filters_L, -3);
|
||||
lua_pop(filters_L, 1); /* Get rid of connections[]. */
|
||||
|
||||
/* Make another copy of the table - we'll work on the current one
|
||||
looking for the topmost super. */
|
||||
lua_pushvalue(filters_L, -1);
|
||||
for(;;) {
|
||||
lua_pushvalue(filters_L, -1); /* Copy the current table */
|
||||
lua_pushstring(filters_L, "super");
|
||||
lua_gettable(filters_L, -2);
|
||||
lua_insert(filters_L, -2); /* Move the copy to the top, pop it */
|
||||
lua_pop(filters_L, 1);
|
||||
if (lua_isnil(filters_L, -1)) {
|
||||
lua_pop(filters_L, 1); /* Pop the nil */
|
||||
break; /* There's no super, we're at the top */
|
||||
}
|
||||
lua_insert(filters_L, -2); /* Get rid of the old table */
|
||||
lua_pop(filters_L, 1);
|
||||
}
|
||||
|
||||
ret = (struct ncat_lua_state *) Calloc(1, sizeof(*ret));
|
||||
if (fdn != NULL)
|
||||
ret->fdn = *fdn;
|
||||
|
||||
/* Set the "lua_state" to a pointer to ret. */
|
||||
lua_pushlightuserdata(filters_L, ret);
|
||||
lua_setfield(filters_L, -2, "lua_state");
|
||||
|
||||
lua_fetch_registry("connection_roots");
|
||||
lua_pushinteger(filters_L, connections_key);
|
||||
lua_pushvalue(filters_L, -3);
|
||||
lua_remove(filters_L, -4);
|
||||
lua_settable(filters_L, -3);
|
||||
lua_pop(filters_L, 1);
|
||||
|
||||
if (created != NULL)
|
||||
*created = 1;
|
||||
} else {
|
||||
lua_insert(filters_L, -2); /* Get rid of connections[]. */
|
||||
lua_pop(filters_L, 1);
|
||||
|
||||
/* Get the struct ncat_lua_state from connection_roots[fd].lua_state. */
|
||||
lua_fetch_registry("connection_roots");
|
||||
lua_pushinteger(filters_L, connections_key);
|
||||
lua_gettable(filters_L, -2);
|
||||
lua_getfield(filters_L, -1, "lua_state");
|
||||
ret = (struct ncat_lua_state *) lua_touserdata(filters_L, -1);
|
||||
lua_pop(filters_L, 3); /* Pop the userdata, the table and connection_roots. */
|
||||
|
||||
if (created != NULL)
|
||||
*created = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Read "lua_state" field from socket table available under stack index given
|
||||
as the second argument. If after the call *ret is set to a non-negative
|
||||
value, it must be returned. */
|
||||
struct ncat_lua_state* lua_fetch_userdata(lua_State *L, int idx, int *ret)
|
||||
{
|
||||
struct ncat_lua_state *nls;
|
||||
*ret = -1;
|
||||
lua_getfield(L, idx, "lua_state");
|
||||
nls = (struct ncat_lua_state *) lua_touserdata(L, -1);
|
||||
if (nls == NULL) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "Socket already closed");
|
||||
*ret = 2;
|
||||
}
|
||||
return nls;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,19 @@
|
||||
|
||||
struct ncat_lua_state {
|
||||
struct fdinfo fdn;
|
||||
|
||||
/* Only used in connect mode: */
|
||||
int in_send;
|
||||
|
||||
/* Needed for receiving */
|
||||
nsock_event evt;
|
||||
/* 1 if the next read should be performed by nsock_readbytes, 0 if
|
||||
nsock_read. */
|
||||
int readbytes;
|
||||
|
||||
/* Needed for sending */
|
||||
nsock_pool nsp;
|
||||
nsock_iod nsiod;
|
||||
};
|
||||
|
||||
void lua_fetch_registry(const char *key);
|
||||
|
||||
Reference in New Issue
Block a user