nse_nsock.cc
来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,410 行 · 第 1/3 页
CC
1,410 行
#include "nse_nsock.h"#include "nse_auxiliar.h"#include "nse_macros.h"#include "nse_string.h"#include "nse_debug.h"#include "nsock.h"#include "nmap_error.h"/* #include "osscan.h" */#include "NmapOps.h"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include "utils.h"#include "tcpip.h"#if HAVE_OPENSSL#include <openssl/ssl.h>#endif#define SCRIPT_ENGINE "SCRIPT ENGINE"#define NSOCK_WRAPPER "NSOCK WRAPPER"#define NSOCK_WRAPPER_SUCCESS 0 #define NSOCK_WRAPPER_ERROR 2 #define NSOCK_WRAPPER_BUFFER_OK 1#define NSOCK_WRAPPER_BUFFER_MOREREAD 2#define FROM 1#define TO 2#define DEFAULT_TIMEOUT 30000extern NmapOps o;// defined in nse_main.cc but also declared here// to keep the .h files cleanint process_waiting2running(lua_State* l, int resume_arguments);static int l_nsock_connect(lua_State* l);static int l_nsock_connect_queued(lua_State* l);static int l_nsock_send(lua_State* l);static int l_nsock_receive(lua_State* l);static int l_nsock_receive_lines(lua_State* l);static int l_nsock_receive_bytes(lua_State* l);static int l_nsock_get_info(lua_State* l);static int l_nsock_gc(lua_State* l);static int l_nsock_close(lua_State* l);static int l_nsock_set_timeout(lua_State* l);static int l_nsock_receive_buf(lua_State* l);static int l_nsock_ncap_open(lua_State* l);static int l_nsock_ncap_close(lua_State* l);static int l_nsock_ncap_register(lua_State *l);static int l_nsock_pcap_receive(lua_State* l);void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *lua_state);void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state);void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state);void l_nsock_receive_buf_handler(nsock_pool nsp, nsock_event nse, void *lua_state);int l_nsock_check_buf(lua_State* l);int l_nsock_checkstatus(lua_State* l, nsock_event nse);void l_nsock_trace(nsock_iod nsiod, char* message, int direction);char* inet_ntop_both(int af, const void* v_addr, char* ipstring);unsigned short inet_port_both(int af, const void* v_addr);static luaL_reg l_nsock [] = { {"connect", l_nsock_connect_queued}, {"send", l_nsock_send}, {"receive", l_nsock_receive}, {"receive_lines", l_nsock_receive_lines}, {"receive_bytes", l_nsock_receive_bytes}, {"receive_buf", l_nsock_receive_buf}, {"get_info", l_nsock_get_info}, {"close", l_nsock_close}, {"set_timeout", l_nsock_set_timeout}, {"__gc",l_nsock_gc}, {"pcap_open", l_nsock_ncap_open}, {"pcap_close", l_nsock_ncap_close}, {"pcap_register", l_nsock_ncap_register}, {"pcap_receive", l_nsock_pcap_receive},// {"callback_test", l_nsock_pcap_callback_test}, {NULL, NULL}};static nsock_pool nsp;/* There can't be more opened descriptors than max_descriptors_allowed * (search below) If there are no more free slots, lua thread is * freezed and saved to nsock_connect_queue. It's restored when when a * descriptor becomes availble (after nsock_close). */static int nsock_descriptors_used; /* nsock descriptors currently in use */std::list<lua_State* > nsock_connect_queue; /* list of freezed threads waiting for desc *//* * Structure with nsock pcap descriptor. * shared between many lua threads */struct ncap_socket{ nsock_iod nsiod; /* nsock pcap desc */ int references; /* how many lua threads use this */ char *key; /* (free) zero-terminated key used in map to * address this structure. */};/* * */ struct ncap_request{ int suspended; /* is the thread suspended? (lua_yield) */ lua_State *l; /* lua_State of current process * or NULL if process isn't suspended */ nsock_event_id nseid; /* nse for this specific lua_State */ struct timeval end_time; char *key; /* (free) zero-terminated key used in map to * address this structure (hexified 'test') */ bool received; /* are results ready? */ bool r_success; /* true-> okay,data ready to pass to user * flase-> this statusstring contains error description */ char * r_status; /* errorstring */ unsigned char *r_layer2; size_t r_layer2_len; unsigned char *r_layer3; size_t r_layer3_len; size_t packetsz; int ncap_cback_ref; /* just copy of udata->ncap_cback_ref * because we don't have access to udata in place * we need to use this. */ };struct l_nsock_udata { int timeout; nsock_iod nsiod; void *ssl_session; /*used for buffered reading */ int bufidx; /*index inside lua's registry */ int bufused; struct ncap_socket *ncap_socket; struct ncap_request *ncap_request; int ncap_cback_ref;};void l_nsock_clear_buf(lua_State* l, l_nsock_udata* udata);int l_nsock_open(lua_State* l) { auxiliar_newclass(l, "nsock", l_nsock); nsp = nsp_new(NULL); //nsp_settrace(nsp, o.debugging, o.getStartTime()); if (o.scriptTrace()) nsp_settrace(nsp, 5, o.getStartTime()); return NSOCK_WRAPPER_SUCCESS;}int l_nsock_new(lua_State* l) { struct l_nsock_udata* udata; udata = (struct l_nsock_udata*) lua_newuserdata(l, sizeof(struct l_nsock_udata)); auxiliar_setclass(l, "nsock", -1); udata->nsiod = NULL; udata->ssl_session = NULL; udata->timeout = DEFAULT_TIMEOUT; udata->bufidx = LUA_NOREF; udata->bufused= 0; udata->ncap_socket = NULL; udata->ncap_request = NULL; udata->ncap_cback_ref = 0; return 1;}int l_nsock_loop(int tout) { return nsock_loop(nsp, tout);}int l_nsock_checkstatus(lua_State* l, nsock_event nse) { enum nse_status status = nse_status(nse); switch (status) { case NSE_STATUS_SUCCESS: lua_pushboolean(l, true); return NSOCK_WRAPPER_SUCCESS; break; case NSE_STATUS_ERROR: case NSE_STATUS_TIMEOUT: case NSE_STATUS_CANCELLED: case NSE_STATUS_KILL: case NSE_STATUS_EOF: lua_pushnil(l); lua_pushstring(l, nse_status2str(status)); return NSOCK_WRAPPER_ERROR; break; case NSE_STATUS_NONE: default: fatal("%s: In: %s:%i This should never happen.", NSOCK_WRAPPER, __FILE__, __LINE__); break; } return -1;}static int l_nsock_connect_queued(lua_State* l) { /* We allow at least 10 even max_parallelism is 1 because a single script might open a few sockets at once and we don't want it to deadlock when it tries to open the 2nd one. */ const int max_descriptors_allowed = MAX(o.max_parallelism, 10); l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); if(udata->nsiod!=NULL){ /*should a script try to connect a socket, which is already connected * we close the old connection, since it would have no access to it * anyways */ if(o.scriptTrace()){ log_write(LOG_STDOUT,"%s: Trying to connect already connected socket - closing!\n",SCRIPT_ENGINE); } l_nsock_close(l); lua_pop(l,1); } if(nsock_descriptors_used >= max_descriptors_allowed){ /* wait for free descriptor */ nsock_connect_queue.push_back(l); /* I must know how many arguments are passed to nsock_connect. * is there a better way? */ int arguments = 3; const char *how = luaL_optstring(l, 4, ""); if(how != ""){ arguments = 4; int port = luaL_optinteger(l, 5, -1); if(port!=-1) arguments = 5; } if(o.scriptTrace()) log_write(LOG_STDOUT, "NSOCK_connect_queued: thread queued (%i args) %p\n", arguments, (void *)l); return lua_yield(l, arguments); } return l_nsock_connect(l);}void l_nsock_connect_queued_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { lua_State* l = (lua_State*) lua_state; /* well, this is really hackish, we can't just do process_waiting2running, because * nsock_connect() can do lua_yield(). * Instead, we first execute nsock_connect, and if it returns lua_yield() (ie. -1) * than we don't do process_waiting2running. * So, in summary we can do two lua_yield() on thread (one in l_nsock_connect_queued, * second in l_nsock_connect). But it works for me. */ int r = l_nsock_connect(l); if(r != -1) process_waiting2running((lua_State*) lua_state, 0);}static int l_nsock_connect(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); const char* addr = luaL_checkstring(l, 2); unsigned short port = (unsigned short) luaL_checkint(l, 3); const char *how = luaL_optstring(l, 4, "tcp"); const char* error; struct addrinfo *dest; int error_id; l_nsock_clear_buf(l, udata); error_id = getaddrinfo(addr, NULL, NULL, &dest); if (error_id) { error = gai_strerror(error_id); lua_pushboolean(l, false); lua_pushstring(l, error); return 2; } udata->nsiod = nsi_new(nsp, NULL); nsock_descriptors_used++; switch (how[0]) { case 't': if (strcmp(how, "tcp")) goto error; nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port); break; case 'u': if (strcmp(how, "udp")) goto error; nsock_connect_udp(nsp, udata->nsiod, l_nsock_connect_handler, l, dest->ai_addr, dest->ai_addrlen, port); break; case 's': if (strcmp(how, "ssl")) goto error;#ifdef HAVE_OPENSSL nsock_connect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port, udata->ssl_session); break;#else lua_pushboolean(l, false); lua_pushstring(l, "Sorry, you don't have OpenSSL\n"); return 2;#endif default: goto error; break; } freeaddrinfo(dest); return lua_yield(l, 0);error: freeaddrinfo(dest); luaL_argerror(l, 4, "invalid connection method"); return 0;}void l_nsock_connect_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { lua_State* l = (lua_State*) lua_state; if(o.scriptTrace()) { l_nsock_trace(nse_iod(nse), "CONNECT", TO); } if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { process_waiting2running((lua_State*) lua_state, 1); } else { process_waiting2running((lua_State*) lua_state, 2); }}static int l_nsock_send(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); const char* string = luaL_checkstring(l, 2); size_t string_len = lua_objlen (l, 2); char* hexified; l_nsock_clear_buf(l,udata); if(udata->nsiod == NULL) { lua_pushboolean(l, false); lua_pushstring(l, "Trying to send through a closed socket\n"); return 2; } if(o.scriptTrace()) { hexified = nse_hexify((const void*)string, string_len); l_nsock_trace(udata->nsiod, hexified, TO); free(hexified); } nsock_write(nsp, udata->nsiod, l_nsock_send_handler, udata->timeout, l, string, string_len); return lua_yield(l, 0);}void l_nsock_send_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { lua_State* l = (lua_State*) lua_state; if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { process_waiting2running((lua_State*) lua_state, 1); } else { process_waiting2running((lua_State*) lua_state, 2); }}static int l_nsock_receive(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); l_nsock_clear_buf(l, udata); if(udata->nsiod == NULL) { lua_pushboolean(l, false); lua_pushstring(l, "Trying to receive through a closed socket\n"); return 2; } nsock_read(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l); return lua_yield(l, 0);}static int l_nsock_receive_lines(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); int nlines = (int) luaL_checknumber(l, 2); l_nsock_clear_buf(l, udata); if(udata->nsiod == NULL) { lua_pushboolean(l, false); lua_pushstring(l, "Trying to receive lines through a closed socket\n"); return 2; } nsock_readlines(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l, nlines); return lua_yield(l, 0);}static int l_nsock_receive_bytes(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); int nbytes = (int) luaL_checknumber(l, 2); l_nsock_clear_buf(l, udata); if(udata->nsiod == NULL) { lua_pushboolean(l, false); lua_pushstring(l, "Trying to receive bytes through a closed socket\n"); return 2; } nsock_readbytes(nsp, udata->nsiod, l_nsock_receive_handler, udata->timeout, l, nbytes); return lua_yield(l, 0);}void l_nsock_receive_handler(nsock_pool nsp, nsock_event nse, void *lua_state) { lua_State* l = (lua_State*) lua_state; char* rcvd_string; int rcvd_len = 0; char* hexified; if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) { rcvd_string = nse_readbuf(nse, &rcvd_len); if(o.scriptTrace()) { hexified = nse_hexify((const void*) rcvd_string, (size_t) rcvd_len); l_nsock_trace(nse_iod(nse), hexified, FROM); free(hexified); } lua_pushlstring(l, rcvd_string, rcvd_len); process_waiting2running((lua_State*) lua_state, 2); } else { process_waiting2running((lua_State*) lua_state, 2); }}void l_nsock_trace(nsock_iod nsiod, char* message, int direction) { int status; int protocol; int af; struct sockaddr local; struct sockaddr remote; char* ipstring_local = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); char* ipstring_remote = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN); if(!nsi_is_pcap(nsiod)){ status = nsi_getlastcommunicationinfo(nsiod, &protocol, &af, &local, &remote, sizeof(sockaddr)); log_write(LOG_STDOUT, "SCRIPT ENGINE: %s %s:%d %s %s:%d | %s\n", (protocol == IPPROTO_TCP)? "TCP" : "UDP",
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?