nse_nsock.cc

来自「Ubuntu packages of security software。 相」· CC 代码 · 共 1,410 行 · 第 1/3 页

CC
1,410
字号
			inet_ntop_both(af, &local, ipstring_local), 			inet_port_both(af, &local), 			(direction == TO)? ">" : "<", 			inet_ntop_both(af, &remote, ipstring_remote), 			inet_port_both(af, &remote), 			message); 		free(ipstring_local);		free(ipstring_remote);	}else{ // is pcap device		log_write(LOG_STDOUT, "SCRIPT ENGINE: %s | %s\n", 			(direction == TO)? ">" : "<", 			message); 	}}char* inet_ntop_both(int af, const void* v_addr, char* ipstring) {//	char* ipstring = (char*) safe_malloc(sizeof(char) * INET6_ADDRSTRLEN);	if(af == AF_INET) {		inet_ntop(AF_INET, &((struct sockaddr_in*) v_addr)->sin_addr, 				ipstring, INET6_ADDRSTRLEN);		return ipstring;	} #ifdef HAVE_IPV6	else if(af == AF_INET6) {		inet_ntop(AF_INET6, &((struct sockaddr_in6*) v_addr)->sin6_addr, 				ipstring, INET6_ADDRSTRLEN);		return ipstring;	} #endif	else {		return "unknown protocol";	}}unsigned short inet_port_both(int af, const void* v_addr) {	int port;	if(af == AF_INET) {		port = ((struct sockaddr_in*) v_addr)->sin_port;		}#ifdef HAVE_IPV6	else if(af == AF_INET6) {		port = ((struct sockaddr_in6*) v_addr)->sin6_port;		}#endif	else {		port = 0;	}		return ntohs(port);}static int l_nsock_get_info(lua_State* l) {	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	int status;	int protocol; // tcp or udp	int af; // address family	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(udata->nsiod == NULL) {		lua_pushboolean(l, false);		lua_pushstring(l, "Trying to get info from a closed socket\n");		return 2;		}	status =  nsi_getlastcommunicationinfo(udata->nsiod, &protocol, &af,			&local, &remote, sizeof(sockaddr));	lua_pushboolean(l, true);	lua_pushstring(l, inet_ntop_both(af, &local, ipstring_local));	lua_pushnumber(l, inet_port_both(af, &local));	lua_pushstring(l, inet_ntop_both(af, &remote, ipstring_remote));	lua_pushnumber(l, inet_port_both(af, &remote));	free(ipstring_local);	free(ipstring_remote);	return 5;}static int l_nsock_gc(lua_State* l){	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	if(udata->nsiod == NULL) { //socket obviously got closed already - so no finalization needed		return 0;		}else{	//FIXME - check wheter close returned true!!		l_nsock_close(l);	}	return 0;}static int l_nsock_close(lua_State* l) {	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	/* Never ever collect nse-pcap connections. */	if(udata->ncap_socket){		return 0;	}		l_nsock_clear_buf(l, udata);	if(udata->nsiod == NULL) {		lua_pushboolean(l, false);		lua_pushstring(l, "Trying to close a closed socket\n");		return 2;		}	if(o.scriptTrace()) {		l_nsock_trace(udata->nsiod, "CLOSE", TO);	}#ifdef HAVE_OPENSSL	if (udata->ssl_session)		SSL_SESSION_free((SSL_SESSION*)udata->ssl_session);	udata->ssl_session=NULL;#endif	nsi_delete(udata->nsiod, NSOCK_PENDING_NOTIFY);	nsock_descriptors_used--;	/* handle threads that are waiting for free sockets*/	if(nsock_connect_queue.size()){		lua_State *nl = nsock_connect_queue.front();		nsock_connect_queue.pop_front();		/* we can't restore lua thread here. instead create timer event with		 * short timeout 0, and restore thread there*/		nsock_timer_create(nsp, l_nsock_connect_queued_handler, 0, (void*) nl);	}	udata->nsiod = NULL;	lua_pushboolean(l, true);	return 1;}static int l_nsock_set_timeout(lua_State* l) {	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	int timeout = (unsigned short) luaL_checkint(l, 2);	udata->timeout = timeout;	return 0;}/* buffered I/O */static int l_nsock_receive_buf(lua_State* l) {	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	if(lua_gettop(l)==2){ 		/*we were called with 2 arguments only - push the default third one*/		lua_pushboolean(l,true);	}	if(udata->nsiod == NULL) {		lua_pushboolean(l, false);		lua_pushstring(l, "Trying to receive through a closed socket\n");		return 2;		}	if(udata->bufused==0){		lua_pushstring(l,"");		udata->bufidx = luaL_ref(l, LUA_REGISTRYINDEX);		udata->bufused=1;		nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, l);	}else if(udata->bufused==-1){ /*error message is inside the buffer*/		lua_pushboolean(l,false); 		lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx);		return 2;	}else{ /*buffer contains already some data */		/*we keep track here of how many calls to receive_buf are made */		udata->bufused++; 		if(l_nsock_check_buf(l)==NSOCK_WRAPPER_BUFFER_MOREREAD){			/*if we didn't have enough data in the buffer another nsock_read()			 * was scheduled - its callback will put us in running state again			 */			return lua_yield(l,3);		}		return 2;	}	/*yielding with 3 arguments since we need them when the callback arrives */	return lua_yield(l, 3);}void l_nsock_receive_buf_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;	int tmpidx;	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	if(l_nsock_checkstatus(l, nse) == NSOCK_WRAPPER_SUCCESS) {				//l_nsock_checkstatus pushes true on the stack in case of success		// we do this on our own here		lua_pop(l,1);		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);		}		/* push the buffer and what we received from nsock on the stack and		 * concatenate both*/		lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx);		lua_pushlstring(l, rcvd_string, rcvd_len);		lua_concat (l, 2);		luaL_unref(l, LUA_REGISTRYINDEX, udata->bufidx);		udata->bufidx = luaL_ref(l, LUA_REGISTRYINDEX);		if(l_nsock_check_buf(l)==NSOCK_WRAPPER_BUFFER_MOREREAD){		/*if there wasn't enough data in the buffer and we've issued another		 * nsock_read() the next callback will schedule the script for running		 */			return;		}		process_waiting2running((lua_State*) lua_state, 2);	} else {		if(udata->bufused>1){ 		/*error occured after we read into some data into the buffer		 * behave as if there was no error and push the rest of the buffer 		 * and clean the buffer afterwards		 */			/*save the error message inside the buffer*/			tmpidx=luaL_ref(l, LUA_REGISTRYINDEX); 			/*pop the status (==false) of the stack*/			lua_pop(l,1);			lua_pushboolean(l, true);			lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx);			l_nsock_clear_buf(l, udata);			udata->bufidx=tmpidx;			udata->bufused=-1;			process_waiting2running((lua_State*) lua_state, 2);		}else{ /*buffer should be empty */			process_waiting2running((lua_State*) lua_state, 2);		}	}}int l_nsock_check_buf(lua_State* l ){	l_nsock_udata* udata;	size_t startpos, endpos, bufsize;	const char *tmpbuf;	int tmpidx;	int keeppattern;	/*should we return the string including the pattern or without it */	keeppattern= lua_toboolean(l,-1);	lua_pop(l,1);	udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	if(lua_isfunction(l,2)){		lua_pushvalue(l,2);		lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); /* the buffer is the only argument to the function */		if(lua_pcall(l,1,2,0)!=0){			lua_pushboolean(l,false);			lua_pushfstring(l,"Error inside splitting-function: %s\n", lua_tostring(l,-1));			return NSOCK_WRAPPER_BUFFER_OK;			//luaL_error(l,"Error inside splitting-function, given as argument to nsockobj:receive_buf: %s\n", lua_tostring(l,-1));		}	}else if(lua_isstring(l,2)){		lua_getglobal(l,"string");		lua_getfield(l,-1,"find");		lua_remove(l, -2); /*drop the string-table, since we don't need it! */		lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); 		lua_pushvalue(l,2); /*the pattern we are searching for */		if(lua_pcall(l,2,2,0)!=0){			lua_pushboolean(l,false);			lua_pushstring(l,"Error in string.find (nsockobj:receive_buf)!");			return NSOCK_WRAPPER_BUFFER_OK;		}	}else{			lua_pushboolean(l,false);			lua_pushstring(l,"Expected either a function or a string!");			return NSOCK_WRAPPER_BUFFER_OK;			//luaL_argerror(l,2,"expected either a function or a string!");	}	/*the stack contains on top the indices where we want to seperate */	if(lua_isnil(l,-1)){ /*not found anything try to read more data*/		lua_pop(l,2);		nsock_read(nsp, udata->nsiod, l_nsock_receive_buf_handler, udata->timeout, l);		lua_pushboolean(l,keeppattern);		return NSOCK_WRAPPER_BUFFER_MOREREAD;	}else{		startpos = (size_t) lua_tointeger(l, -2);		endpos = (size_t) lua_tointeger(l, -1);		lua_settop(l,0); /* clear the stack for returning */		if(startpos>endpos){			lua_pushboolean(l,false);			lua_pushstring(l,"Delimiter has negative size!");			return NSOCK_WRAPPER_BUFFER_OK;		}else if(startpos==endpos){			/* if the delimter has a size of zero we keep it, since otherwise 			 * retured string would be trucated			 */			keeppattern=1; 		}		lua_settop(l,0); /* clear the stack for returning */		lua_rawgeti(l, LUA_REGISTRYINDEX, udata->bufidx); 		tmpbuf = lua_tolstring(l, -1, &bufsize);		lua_pop(l,1); /* pop the buffer off the stack, should be safe since it 		it is still in the registry */		if(tmpbuf==NULL){		 fatal("%s: In: %s:%i The buffer is not a string?! - please report this to nmap-dev@insecure.org.", SCRIPT_ENGINE, __FILE__, __LINE__);		}		/*first push the remains of the buffer */		lua_pushlstring(l,tmpbuf+endpos,(bufsize-endpos));		tmpidx = luaL_ref(l,LUA_REGISTRYINDEX);		lua_pushboolean(l,true);		if(keeppattern){			lua_pushlstring(l,tmpbuf,endpos);		}else{			lua_pushlstring(l,tmpbuf,startpos-1);		}		luaL_unref(l,LUA_REGISTRYINDEX,udata->bufidx);		udata->bufidx=tmpidx;		//l_dumpStack(l);		return NSOCK_WRAPPER_BUFFER_OK;	}	assert(0);	return 1;//unreachable}void l_nsock_clear_buf(lua_State* l, l_nsock_udata* udata){	luaL_unref (l, LUA_REGISTRYINDEX, udata->bufidx); 	udata->bufidx=LUA_NOREF;	udata->bufused=0;}/****************** NCAP_SOCKET ***********************************************/ #ifdef WIN32/* From tcpip.cc. Gets pcap device name from dnet name. */bool DnetName2PcapName(const char *dnetdev, char *pcapdev, int pcapdevlen);#endif/* fuckin' C++ maps stuff *//* here we store ncap_sockets */std::map<std::string, struct ncap_socket*> ncap_socket_map;/* receive sthing from socket_map */struct ncap_socket *ncap_socket_map_get(char *key){	std::string skey = key;	return ncap_socket_map[skey];}/* set sthing on socket_map */void ncap_socket_map_set(char *key, struct ncap_socket *ns){	std::string skey = key;	ncap_socket_map[skey] = ns;	return;}/* receive sthing from socket_map */void ncap_socket_map_del(char *key){	std::string skey = key;	ncap_socket_map.erase(skey);	return;}/* (static) Dnet-like device name to Pcap-like name */char *dnet_to_pcap_device_name(const char *device){	static char pcapdev[128];	if( strcmp(device, "any") == 0 )		return strncpy(pcapdev, "any", sizeof(pcapdev));			#ifdef WIN32	/* Nmap normally uses device names obtained through dnet for interfaces, 	 * but Pcap has its own naming system.  So the conversion is done here */	if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) {		/* Oh crap -- couldn't find the corresponding dev apparently.  		 * Let's just go with what we have then ... */		strncpy(pcapdev, device, sizeof(pcapdev));	}	#else		strncpy(pcapdev, device, sizeof(pcapdev));	#endif	return pcapdev;}/* (LUA) Open nsock-pcap socket.  * 1)	device	- dnet-style network interface name, or "any" * 2)	snaplen	- maximum number of bytes to be captured for packet * 3)	promisc - should we set network car in promiscuous mode (0/1) * 4)	callback- callback function, that will create hash string from packet * 5)	bpf	- berkeley packet filter, see tcpdump(8)	 * */  static int l_nsock_ncap_open(lua_State* l){	l_nsock_udata* udata  = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	const char* device    = luaL_checkstring(l, 2);	int snaplen           = luaL_checkint(l, 3);	int promisc           = luaL_checkint(l, 4);	luaL_checktype(l, 5, LUA_TFUNCTION);		/* callback function that creates hash */	const char* bpf       = luaL_checkstring(l, 6);	if(udata->nsiod || udata->ncap_request || udata->ncap_socket) {		luaL_argerror(l, 1, "Trying to open nsock-pcap, but this connection is already opened");		return 0;	}	char *pcapdev = dnet_to_pcap_device_name(device);	if(!strlen(device) || !strlen(pcapdev)) {		luaL_argerror(l, 1, "Trying to open nsock-pcap, but you're passing empty or wrong device name.");		return 0;	}	lua_pop(l, 1);	// pop bpf	/* take func from top of stack and store it in the Registry */	int hash_func_ref = luaL_ref(l, LUA_REGISTRYINDEX);	/* push function on the registry-stack */	lua_rawgeti(l, LUA_REGISTRYINDEX, hash_func_ref); 		struct ncap_socket *ns;		/* create key */	char key[8192];	Snprintf(key, sizeof(key), "%s|%i|%i|%u|%s",					pcapdev,					snaplen, promisc,					(unsigned int)strlen(bpf),					bpf);	ns = ncap_socket_map_get(key);	if(ns == NULL){		ns = (struct ncap_socket*)safe_zalloc(sizeof(struct ncap_socket));		ns->nsiod 	= nsi_new(nsp, ns);		ns->key		= strdup(key);		/* error messages are passed here */ 		char *emsg = nsock_pcap_open(nsp, ns->nsiod, pcapdev, snaplen, promisc, bpf);		if(emsg){			luaL_argerror(l, 1, emsg);			return 0;		}		ncap_socket_map_set(key, ns);	}	ns->references++;	udata->nsiod		= ns->nsiod;	udata->ncap_socket	= ns;	udata->ncap_cback_ref	= hash_func_ref;	return 0;}/* (LUA) Close nsock-pcap socket.  * */  static int l_nsock_ncap_close(lua_State* l){	l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1);	struct ncap_socket *ns = udata->ncap_socket;	if(!udata->nsiod || !udata->ncap_socket) {		luaL_argerror(l, 1, "Trying to close nsock-pcap, but it was never opened.");		return 0;		}	if(udata->ncap_request) {		luaL_argerror(l, 1, "Trying to close nsock-pcap, but it has active event.");		return 0;		}	assert(ns->references > 0);	ns->references--;	if(ns->references == 0){		ncap_socket_map_del(ns->key);		if(ns->key) free(ns->key);				nsi_delete(ns->nsiod, NSOCK_PENDING_NOTIFY);		free(ns);	}	udata->nsiod 		= NULL;	udata->ncap_socket	= NULL;	lua_unref(l, udata->ncap_cback_ref);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?