mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	- Reworked non-channel fd handling to listener.c
- More channel cleaning up --HG-- extra : convert_revision : 385ec76d0304b93e277d1cc193383db5fd773703
This commit is contained in:
		
							parent
							
								
									513f947d62
								
							
						
					
					
						commit
						444dbb5364
					
				
							
								
								
									
										10
									
								
								Makefile.in
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile.in
									
									
									
									
									
								
							| @ -4,9 +4,9 @@ LTM=libtommath/libtommath.a | ||||
| COMMONOBJS=dbutil.o common-session.o common-packet.o common-algo.o buffer.o \
 | ||||
| 		common-kex.o dss.o bignum.o \
 | ||||
| 		signkey.o rsa.o random.o common-channel.o \
 | ||||
| 		common-chansession.o queue.o termcodes.o runopts.o \
 | ||||
| 		loginrec.o atomicio.o x11fwd.o agentfwd.o localtcpfwd.o compat.o \
 | ||||
| 		remotetcpfwd.o tcpfwd.o | ||||
| 		common-chansession.o queue.o termcodes.o  \
 | ||||
| 		loginrec.o atomicio.o x11fwd.o tcpfwd-direct.o compat.o \
 | ||||
| 		tcpfwd-remote.o listener.o | ||||
| 
 | ||||
| SVROBJS=svr-kex.o svr-packet.o svr-algo.o svr-auth.o sshpty.o \
 | ||||
| 		svr-authpasswd.o svr-authpubkey.o svr-session.o svr-service.o \
 | ||||
| @ -28,8 +28,8 @@ HEADERS=options.h dbutil.h session.h packet.h algo.h ssh.h buffer.h kex.h \ | ||||
| 		dss.h bignum.h signkey.h rsa.h random.h service.h auth.h authpasswd.h \
 | ||||
| 		debug.h channel.h chansession.h debug.h config.h queue.h sshpty.h \
 | ||||
| 		termcodes.h gendss.h genrsa.h authpubkey.h runopts.h includes.h \
 | ||||
| 		loginrec.h atomicio.h x11fwd.h agentfwd.h localtcpfwd.h compat.h \
 | ||||
| 		remotetcpfwd.h tcpfwd.h | ||||
| 		loginrec.h atomicio.h x11fwd.h agentfwd.h tcpfwd-direct.h compat.h \
 | ||||
| 		tcpfwd-remote.h listener.h | ||||
| 
 | ||||
| ALLOBJS=$(OBJS) $(DROPBEARKEYOBJS) $(DROPBEAROBJS) | ||||
| 
 | ||||
|  | ||||
| @ -114,8 +114,7 @@ void recv_msg_channel_close(); | ||||
| void recv_msg_channel_eof(); | ||||
| 
 | ||||
| #ifdef USE_LISTENERS | ||||
| int send_msg_channel_open_init(int fd, struct ChanType *type, | ||||
| 		const char * typestring); | ||||
| int send_msg_channel_open_init(int fd, const struct ChanType *type); | ||||
| void recv_msg_channel_open_confirmation(); | ||||
| void recv_msg_channel_open_failure(); | ||||
| #endif | ||||
|  | ||||
| @ -27,6 +27,7 @@ | ||||
| 
 | ||||
| #include "loginrec.h" | ||||
| #include "channel.h" | ||||
| #include "listener.h" | ||||
| 
 | ||||
| struct ChanSess { | ||||
| 
 | ||||
| @ -47,7 +48,7 @@ struct ChanSess { | ||||
| 	unsigned char exitcore; | ||||
| 	 | ||||
| #ifndef DISABLE_X11FWD | ||||
| 	int x11fd; /* set to -1 to indicate forwarding not established */ | ||||
| 	struct Listener * x11listener; | ||||
| 	int x11port; | ||||
| 	char * x11authprot; | ||||
| 	char * x11authcookie; | ||||
| @ -56,7 +57,7 @@ struct ChanSess { | ||||
| #endif | ||||
| 
 | ||||
| #ifndef DISABLE_AGENTFWD | ||||
| 	int agentfd; | ||||
| 	struct Listener * agentlistener; | ||||
| 	char * agentfile; | ||||
| 	char * agentdir; | ||||
| #endif | ||||
|  | ||||
| @ -32,9 +32,9 @@ | ||||
| #include "dbutil.h" | ||||
| #include "channel.h" | ||||
| #include "ssh.h" | ||||
| #include "localtcpfwd.h" | ||||
| #include "remotetcpfwd.h" | ||||
| #include "tcpfwd.h" | ||||
| #include "tcpfwd-direct.h" | ||||
| #include "tcpfwd-remote.h" | ||||
| #include "listener.h" | ||||
| 
 | ||||
| static void send_msg_channel_open_failure(unsigned int remotechan, int reason, | ||||
| 		const unsigned char *text, const unsigned char *lang); | ||||
| @ -70,8 +70,8 @@ void chaninitialise(const struct ChanType *chantypes[]) { | ||||
| 
 | ||||
| 	ses.chantypes = chantypes; | ||||
| 
 | ||||
| #ifdef USING_TCP_LISTENERS | ||||
| 	tcp_fwd_initialise(); | ||||
| #ifdef USING_LISTENERS | ||||
| 	listeners_initialise(); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| @ -219,9 +219,9 @@ void channelio(fd_set *readfd, fd_set *writefd) { | ||||
| 
 | ||||
| 	} /* foreach channel */ | ||||
| 
 | ||||
| 	/* Not channel specific */ | ||||
| #ifdef USING_TCP_LISTENERS | ||||
| 		handle_tcp_fwd(readfd); | ||||
| 	/* Listeners such as TCP, X11, agent-auth */ | ||||
| #ifdef USING_LISTENERS | ||||
| 	handle_listeners(readfd); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| @ -429,8 +429,8 @@ void setchannelfds(fd_set *readfd, fd_set *writefd) { | ||||
| 
 | ||||
| 	} /* foreach channel */ | ||||
| 
 | ||||
| #ifdef USING_TCP_LISTENERS | ||||
| 	set_tcp_fwd_fds(readfd); | ||||
| #ifdef USING_LISTENERS | ||||
| 	set_listener_fds(readfd); | ||||
| #endif | ||||
| 
 | ||||
| } | ||||
| @ -895,8 +895,7 @@ static void send_msg_channel_open_confirmation(struct Channel* channel, | ||||
|  * options, with the calling function calling encrypt_packet() after | ||||
|  * completion. It is mandatory for the caller to encrypt_packet() if | ||||
|  * DROPBEAR_SUCCESS is returned */ | ||||
| int send_msg_channel_open_init(int fd, struct ChanType *type, | ||||
| 		const char * typestring) { | ||||
| int send_msg_channel_open_init(int fd, const struct ChanType *type) { | ||||
| 
 | ||||
| 	struct Channel* chan; | ||||
| 
 | ||||
| @ -920,7 +919,7 @@ int send_msg_channel_open_init(int fd, struct ChanType *type, | ||||
| 	CHECKCLEARTOWRITE(); | ||||
| 
 | ||||
| 	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN); | ||||
| 	buf_putstring(ses.writepayload, typestring, strlen(typestring)); | ||||
| 	buf_putstring(ses.writepayload, type->name, strlen(type->name)); | ||||
| 	buf_putint(ses.writepayload, chan->index); | ||||
| 	buf_putint(ses.writepayload, RECV_MAXWINDOW); | ||||
| 	buf_putint(ses.writepayload, RECV_MAXPACKET); | ||||
|  | ||||
							
								
								
									
										123
									
								
								listener.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								listener.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,123 @@ | ||||
| #include "includes.h" | ||||
| #include "listener.h" | ||||
| #include "session.h" | ||||
| #include "dbutil.h" | ||||
| 
 | ||||
| void listener_initialise() { | ||||
| 
 | ||||
| 	/* just one slot to start with */ | ||||
| 	ses.listeners = (struct Listener**)m_malloc(sizeof(struct Listener*)); | ||||
| 	ses.listensize = 1; | ||||
| 	ses.listeners[0] = NULL; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void set_listener_fds(fd_set * readfds) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct Listener *listener; | ||||
| 
 | ||||
| 	/* check each in turn */ | ||||
| 	for (i = 0; i < ses.listensize; i++) { | ||||
| 		listener = ses.listeners[i]; | ||||
| 		if (listener != NULL) { | ||||
| 			FD_SET(listener->sock, readfds); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void handle_listeners(fd_set * readfds) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct Listener *listener; | ||||
| 
 | ||||
| 	/* check each in turn */ | ||||
| 	for (i = 0; i < ses.listensize; i++) { | ||||
| 		listener = ses.listeners[i]; | ||||
| 		if (listener != NULL) { | ||||
| 			if (FD_ISSET(listener->sock, readfds)) { | ||||
| 				listener->accepter(listener); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* accepter(int fd, void* typedata) is a function to accept connections, 
 | ||||
|  * cleanup(void* typedata) happens when cleaning up */ | ||||
| struct Listener* new_listener(int sock, int type, void* typedata,  | ||||
| 		void (*accepter)(struct Listener*),  | ||||
| 		void (*cleanup)(struct Listener*)) { | ||||
| 
 | ||||
| 	unsigned int i, j; | ||||
| 	struct Listener *newlisten = NULL; | ||||
| 	/* try get a new structure to hold it */ | ||||
| 	for (i = 0; i < ses.listensize; i++) { | ||||
| 		if (ses.listeners[i] == NULL) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* or create a new one */ | ||||
| 	if (i == ses.listensize) { | ||||
| 		if (ses.listensize > MAX_LISTENERS) { | ||||
| 			TRACE(("leave newlistener: too many already")); | ||||
| 			close(sock); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 		 | ||||
| 		ses.listeners = (struct Listener**)m_realloc(ses.listeners, | ||||
| 				(ses.listensize+LISTENER_EXTEND_SIZE) | ||||
| 				*sizeof(struct Listener*)); | ||||
| 
 | ||||
| 		ses.listensize += LISTENER_EXTEND_SIZE; | ||||
| 
 | ||||
| 		for (j = i; j < ses.listensize; j++) { | ||||
| 			ses.listeners[j] = NULL; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ses.maxfd = MAX(ses.maxfd, sock); | ||||
| 
 | ||||
| 	newlisten = (struct Listener*)m_malloc(sizeof(struct Listener)); | ||||
| 	newlisten->index = i; | ||||
| 	newlisten->type = type; | ||||
| 	newlisten->typedata = typedata; | ||||
| 	newlisten->sock = sock; | ||||
| 	newlisten->accepter = accepter; | ||||
| 	newlisten->cleanup = cleanup; | ||||
| 
 | ||||
| 	ses.listeners[i] = newlisten; | ||||
| 	return newlisten; | ||||
| } | ||||
| 
 | ||||
| /* Return the first listener which matches the type-specific comparison
 | ||||
|  * function. Particularly needed for global requests, like tcp */ | ||||
| struct Listener * get_listener(int type, void* typedata, | ||||
| 		int (*match)(void*, void*)) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct Listener* listener; | ||||
| 
 | ||||
| 	for (i = 0, listener = ses.listeners[i]; i < ses.listensize; i++) { | ||||
| 		if (listener->type == type | ||||
| 				&& match(typedata, listener->typedata)) { | ||||
| 			return listener; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void remove_listener(struct Listener* listener) { | ||||
| 
 | ||||
| 	if (listener->cleanup) { | ||||
| 		listener->cleanup(listener); | ||||
| 	} | ||||
| 
 | ||||
| 	close(listener->sock); | ||||
| 	ses.listeners[listener->index] = NULL; | ||||
| 	m_free(listener); | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										37
									
								
								listener.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								listener.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| #ifndef _LISTENER_H | ||||
| #define _LISTENER_H | ||||
| 
 | ||||
| #define MAX_LISTENERS 20 | ||||
| #define LISTENER_EXTEND_SIZE 1 | ||||
| 
 | ||||
| struct Listener { | ||||
| 
 | ||||
| 	int sock; | ||||
| 
 | ||||
| 	int index; /* index in the array of listeners */ | ||||
| 
 | ||||
| 	void (*accepter)(struct Listener*); | ||||
| 	void (*cleanup)(struct Listener*); | ||||
| 
 | ||||
| 	int type; /* CHANNEL_ID_X11, CHANNEL_ID_AGENT, 
 | ||||
| 				 CHANNEL_ID_TCPDIRECT (for clients), | ||||
| 				 CHANNEL_ID_TCPFORWARDED (for servers) */ | ||||
| 
 | ||||
| 	void *typedata; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| void listener_initialise(); | ||||
| void handle_listeners(fd_set * readfds); | ||||
| void set_listener_fds(fd_set * readfds); | ||||
| 
 | ||||
| struct Listener* new_listener(int sock, int type, void* typedata,  | ||||
| 		void (*accepter)(struct Listener*),  | ||||
| 		void (*cleanup)(struct Listener*)); | ||||
| 
 | ||||
| struct Listener * get_listener(int type, void* typedata, | ||||
| 		int (*match)(void*, void*)); | ||||
| 
 | ||||
| void remove_listener(struct Listener* listener); | ||||
| 
 | ||||
| #endif /* _LISTENER_H */ | ||||
| @ -296,7 +296,7 @@ | ||||
| #endif | ||||
| 
 | ||||
| #ifndef ENABLE_LOCALTCPFWD | ||||
| #define DISABLE_LOCALTCPFWD | ||||
| #define DISABLE_TCPDIRECT | ||||
| #endif | ||||
| 
 | ||||
| #ifndef ENABLE_REMOTETCPFWD | ||||
|  | ||||
| @ -33,7 +33,7 @@ | ||||
| #include "channel.h" | ||||
| #include "queue.h" | ||||
| #include "runopts.h" | ||||
| #include "remotetcpfwd.h" | ||||
| #include "listener.h" | ||||
| 
 | ||||
| extern int sessinitdone; /* Is set to 0 somewhere */ | ||||
| extern int exitflag; | ||||
| @ -139,8 +139,8 @@ struct sshsession { | ||||
| 	 | ||||
| 	/* TCP forwarding - where manage listeners */ | ||||
| #ifndef DISABLE_REMOTETCPFWD | ||||
| 	struct TCPListener ** tcplisteners; | ||||
| 	unsigned int tcplistensize; | ||||
| 	struct Listener ** listeners; | ||||
| 	unsigned int listensize; | ||||
| #endif | ||||
| 
 | ||||
| }; | ||||
|  | ||||
| @ -201,13 +201,13 @@ static int newchansess(struct Channel *channel) { | ||||
| 	channel->typedata = chansess; | ||||
| 
 | ||||
| #ifndef DISABLE_X11FWD | ||||
| 	chansess->x11fd = -1; | ||||
| 	chansess->x11listener = NULL; | ||||
| 	chansess->x11authprot = NULL; | ||||
| 	chansess->x11authcookie = NULL; | ||||
| #endif | ||||
| 
 | ||||
| #ifndef DISABLE_AGENTFWD | ||||
| 	chansess->agentfd = -1; | ||||
| 	chansess->agentlistener = NULL; | ||||
| 	chansess->agentfile = NULL; | ||||
| 	chansess->agentdir = NULL; | ||||
| #endif | ||||
| @ -881,7 +881,7 @@ static void execchild(struct ChanSess *chansess) { | ||||
| 	/* only reached on error */ | ||||
| 	dropbear_exit("child failed"); | ||||
| } | ||||
| 	 | ||||
| 
 | ||||
| const struct ChanType svrchansess = { | ||||
| 	0, /* sepfds */ | ||||
| 	"session", /* name */ | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
| #include "channel.h" | ||||
| #include "chansession.h" | ||||
| #include "atomicio.h" | ||||
| #include "localtcpfwd.h" | ||||
| #include "tcpfwd-direct.h" | ||||
| 
 | ||||
| static void svr_remoteclosed(); | ||||
| 
 | ||||
|  | ||||
| @ -2,9 +2,9 @@ | ||||
| #include "session.h" | ||||
| #include "dbutil.h" | ||||
| #include "channel.h" | ||||
| #include "localtcpfwd.h" | ||||
| #include "tcpfwd-direct.h" | ||||
| 
 | ||||
| #ifndef DISABLE_LOCALTCPFWD | ||||
| #ifndef DISABLE_TCPFWD_DIRECT | ||||
| static int newtcpdirect(struct Channel * channel); | ||||
| static int newtcp(const char * host, int port); | ||||
| 
 | ||||
| @ -18,7 +18,6 @@ const struct ChanType chan_tcpdirect = { | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Called upon creating a new direct tcp channel (ie we connect out to an
 | ||||
|  * address */ | ||||
| static int newtcpdirect(struct Channel * channel) { | ||||
| @ -152,4 +151,4 @@ static int newtcp(const char * host, int port) { | ||||
| 	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val)); | ||||
| 	return sock; | ||||
| } | ||||
| #endif /* DISABLE_LOCALTCPFWD */ | ||||
| #endif /* DISABLE_TCPFWD_DIRECT */ | ||||
| @ -21,9 +21,9 @@ | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. */ | ||||
| #ifndef _LOCALTCPFWD_H_ | ||||
| #define _LOCALTCPFWD_H_ | ||||
| #ifndef DISABLE_LOCALTCPFWD | ||||
| #ifndef _TCPFWD_DIRECT_H_ | ||||
| #define _TCPFWD_DIRECT_H_ | ||||
| #ifndef DISABLE_TCFWD_DIRECT | ||||
| 
 | ||||
| #include "includes.h" | ||||
| #include "channel.h" | ||||
| @ -1,11 +1,11 @@ | ||||
| #include "includes.h" | ||||
| #include "ssh.h" | ||||
| #include "remotetcpfwd.h" | ||||
| #include "tcpfwd-remote.h" | ||||
| #include "dbutil.h" | ||||
| #include "session.h" | ||||
| #include "buffer.h" | ||||
| #include "packet.h" | ||||
| #include "tcpfwd.h" | ||||
| #include "listener.h" | ||||
| 
 | ||||
| #ifndef DISABLE_REMOTETCPFWD | ||||
| 
 | ||||
| @ -20,8 +20,8 @@ static void send_msg_request_success(); | ||||
| static void send_msg_request_failure(); | ||||
| static int cancelremotetcp(); | ||||
| static int remotetcpreq(); | ||||
| static int newlistener(unsigned char* bindaddr, unsigned int port); | ||||
| static void acceptremote(struct TCPListener *listener); | ||||
| static int listen_tcpfwd(unsigned char* bindaddr, unsigned int port); | ||||
| static void acceptremote(struct Listener *listener); | ||||
| 
 | ||||
| /* At the moment this is completely used for tcp code (with the name reflecting
 | ||||
|  * that). If new request types are added, this should be replaced with code | ||||
| @ -70,7 +70,17 @@ out: | ||||
| 	TRACE(("leave recv_msg_global_request")); | ||||
| } | ||||
| 
 | ||||
| static void acceptremote(struct TCPListener *listener) { | ||||
| static const struct ChanType chan_tcpremote = { | ||||
| 	0, /* sepfds */ | ||||
| 	"forwarded-tcpip", | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL, | ||||
| 	NULL | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static void acceptremote(struct Listener *listener) { | ||||
| 
 | ||||
| 	int fd; | ||||
| 	struct sockaddr addr; | ||||
| @ -90,19 +100,22 @@ static void acceptremote(struct TCPListener *listener) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* XXX XXX XXX - type here needs fixing */ | ||||
| 	if (send_msg_channel_open_init(fd, CHANNEL_ID_TCPFORWARDED,  | ||||
| 				"forwarded-tcpip") == DROPBEAR_SUCCESS) { | ||||
| 	if (send_msg_channel_open_init(fd, &chan_tcpremote) == DROPBEAR_SUCCESS) { | ||||
| 
 | ||||
| 		buf_putstring(ses.writepayload, tcpinfo->addr, | ||||
| 				strlen(tcpinfo->addr)); | ||||
| 		buf_putint(ses.writepayload, tcpinfo->port); | ||||
| 		buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); | ||||
| 		buf_putint(ses.writepayload, atol(portstring)); | ||||
| 		encrypt_packet(); | ||||
| 
 | ||||
| 	} else { | ||||
| 		/* XXX debug? */ | ||||
| 		close(fd); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void cleanupremote(struct TCPListener *listener) { | ||||
| static void cleanupremote(struct Listener *listener) { | ||||
| 
 | ||||
| 	struct RemoteTCP *tcpinfo = (struct RemoteTCP*)(listener->typedata); | ||||
| 
 | ||||
| @ -141,7 +154,7 @@ static int cancelremotetcp() { | ||||
| 	unsigned char * bindaddr = NULL; | ||||
| 	unsigned int addrlen; | ||||
| 	unsigned int port; | ||||
| 	struct TCPListener * listener = NULL; | ||||
| 	struct Listener * listener = NULL; | ||||
| 	struct RemoteTCP tcpinfo; | ||||
| 
 | ||||
| 	TRACE(("enter cancelremotetcp")); | ||||
| @ -203,7 +216,7 @@ static int remotetcpreq() { | ||||
| 	} | ||||
| 	*/ | ||||
| 
 | ||||
| 	ret = newlistener(bindaddr, port); | ||||
| 	ret = listen_tcpfwd(bindaddr, port); | ||||
| 
 | ||||
| out: | ||||
| 	if (ret == DROPBEAR_FAILURE) { | ||||
| @ -215,16 +228,16 @@ out: | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int newlistener(unsigned char* bindaddr, unsigned int port) { | ||||
| static int listen_tcpfwd(unsigned char* bindaddr, unsigned int port) { | ||||
| 
 | ||||
| 	struct RemoteTCP * tcpinfo = NULL; | ||||
| 	char portstring[6]; /* "65535\0" */ | ||||
| 	struct addrinfo *res = NULL, *ai = NULL; | ||||
| 	struct addrinfo hints; | ||||
| 	int sock = -1; | ||||
| 	int ret = DROPBEAR_FAILURE; | ||||
| 	struct Listener *listener = NULL; | ||||
| 
 | ||||
| 	TRACE(("enter newlistener")); | ||||
| 	TRACE(("enter listen_tcpfwd")); | ||||
| 
 | ||||
| 	/* first we try to bind, so don't need to do so much cleanup on failure */ | ||||
| 	snprintf(portstring, sizeof(portstring), "%d", port); | ||||
| @ -234,7 +247,7 @@ static int newlistener(unsigned char* bindaddr, unsigned int port) { | ||||
| 	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; | ||||
| 
 | ||||
| 	if (getaddrinfo(bindaddr, portstring, &hints, &res) < 0) { | ||||
| 		TRACE(("leave newlistener: getaddrinfo failed: %s", | ||||
| 		TRACE(("leave listen_tcpfwd: getaddrinfo failed: %s", | ||||
| 					strerror(errno))); | ||||
| 		goto done; | ||||
| 	} | ||||
| @ -283,10 +296,10 @@ fail: | ||||
| 	tcpinfo->addr = bindaddr; | ||||
| 	tcpinfo->port = port; | ||||
| 
 | ||||
| 	ret = new_fwd(sock, CHANNEL_ID_TCPFORWARDED, tcpinfo,  | ||||
| 	listener = new_listener(sock, CHANNEL_ID_TCPFORWARDED, tcpinfo,  | ||||
| 			acceptremote, cleanupremote); | ||||
| 
 | ||||
| 	if (ret == DROPBEAR_FAILURE) { | ||||
| 	if (listener == NULL) { | ||||
| 		m_free(tcpinfo); | ||||
| 	} | ||||
| 
 | ||||
| @ -295,8 +308,12 @@ done: | ||||
| 		freeaddrinfo(res); | ||||
| 	} | ||||
| 	 | ||||
| 	TRACE(("leave newlistener")); | ||||
| 	return ret; | ||||
| 	TRACE(("leave listen_tcpfwd")); | ||||
| 	if (listener == NULL) { | ||||
| 		return DROPBEAR_FAILURE; | ||||
| 	} else { | ||||
| 		return DROPBEAR_SUCCESS; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #endif /* DISABLE_REMOTETCPFWD */ | ||||
							
								
								
									
										124
									
								
								tcpfwd.c
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								tcpfwd.c
									
									
									
									
									
								
							| @ -1,124 +0,0 @@ | ||||
| #include "includes.h" | ||||
| #include "tcpfwd.h" | ||||
| #include "session.h" | ||||
| #include "dbutil.h" | ||||
| 
 | ||||
| void tcp_fwd_initialise() { | ||||
| 
 | ||||
| 	/* just one slot to start with */ | ||||
| 	ses.tcplisteners =  | ||||
| 		(struct TCPListener**)m_malloc(sizeof(struct TCPListener*)); | ||||
| 	ses.tcplistensize = 1; | ||||
| 	ses.tcplisteners[0] = NULL; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void set_tcp_fwd_fds(fd_set * readfds) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct TCPListener *listener; | ||||
| 
 | ||||
| 	/* check each in turn */ | ||||
| 	for (i = 0; i < ses.tcplistensize; i++) { | ||||
| 		listener = ses.tcplisteners[i]; | ||||
| 		if (listener != NULL) { | ||||
| 			FD_SET(listener->sock, readfds); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void handle_tcp_fwd(fd_set * readfds) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct TCPListener *listener; | ||||
| 
 | ||||
| 	/* check each in turn */ | ||||
| 	for (i = 0; i < ses.tcplistensize; i++) { | ||||
| 		listener = ses.tcplisteners[i]; | ||||
| 		if (listener != NULL) { | ||||
| 			if (FD_ISSET(listener->sock, readfds)) { | ||||
| 				listener->accepter(listener); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* accepter(int fd, void* typedata) is a function to accept connections, 
 | ||||
|  * cleanup(void* typedata) happens when cleaning up */ | ||||
| int new_fwd(int sock, int type, void* typedata,  | ||||
| 		void (*accepter)(struct TCPListener*),  | ||||
| 		void (*cleanup)(struct TCPListener*)) { | ||||
| 
 | ||||
| 	unsigned int i, j; | ||||
| 	struct TCPListener *newtcp = NULL; | ||||
| 	/* try get a new structure to hold it */ | ||||
| 	for (i = 0; i < ses.tcplistensize; i++) { | ||||
| 		if (ses.tcplisteners[i] == NULL) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* or create a new one */ | ||||
| 	if (i == ses.tcplistensize) { | ||||
| 		if (ses.tcplistensize > MAX_TCPLISTENERS) { | ||||
| 			TRACE(("leave newlistener: too many already")); | ||||
| 			close(sock); | ||||
| 			return DROPBEAR_FAILURE; | ||||
| 		} | ||||
| 		 | ||||
| 		ses.tcplisteners = (struct TCPListener**)m_realloc(ses.tcplisteners, | ||||
| 				(ses.tcplistensize+TCP_EXTEND_SIZE) | ||||
| 				*sizeof(struct TCPListener*)); | ||||
| 
 | ||||
| 		ses.tcplistensize += TCP_EXTEND_SIZE; | ||||
| 
 | ||||
| 		for (j = i; j < ses.tcplistensize; j++) { | ||||
| 			ses.tcplisteners[j] = NULL; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ses.maxfd = MAX(ses.maxfd, sock); | ||||
| 
 | ||||
| 	newtcp = (struct TCPListener*)m_malloc(sizeof(struct TCPListener)); | ||||
| 	newtcp->index = i; | ||||
| 	newtcp->type = type; | ||||
| 	newtcp->typedata = typedata; | ||||
| 	newtcp->sock = sock; | ||||
| 	newtcp->accepter = accepter; | ||||
| 	newtcp->cleanup = cleanup; | ||||
| 
 | ||||
| 	ses.tcplisteners[i] = newtcp; | ||||
| 	return DROPBEAR_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| /* Return the first listener which matches the type-specific comparison
 | ||||
|  * function */ | ||||
| struct TCPListener * get_listener(int type, void* typedata, | ||||
| 		int (*match)(void*, void*)) { | ||||
| 
 | ||||
| 	unsigned int i; | ||||
| 	struct TCPListener* listener; | ||||
| 
 | ||||
| 	for (i = 0, listener = ses.tcplisteners[i]; i < ses.tcplistensize; i++) { | ||||
| 		if (listener->type == type | ||||
| 				&& match(typedata, listener->typedata)) { | ||||
| 			return listener; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void remove_listener(struct TCPListener* listener) { | ||||
| 
 | ||||
| 	if (listener->cleanup) { | ||||
| 		listener->cleanup(listener); | ||||
| 	} | ||||
| 
 | ||||
| 	close(listener->sock); | ||||
| 	ses.tcplisteners[listener->index] = NULL; | ||||
| 	m_free(listener); | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										37
									
								
								tcpfwd.h
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								tcpfwd.h
									
									
									
									
									
								
							| @ -1,37 +0,0 @@ | ||||
| #ifndef _TCPFWD_H | ||||
| #define _TCPFWD_H | ||||
| 
 | ||||
| #define MAX_TCPLISTENERS 20 | ||||
| #define TCP_EXTEND_SIZE 1 | ||||
| 
 | ||||
| struct TCPListener { | ||||
| 
 | ||||
| 	int sock; | ||||
| 
 | ||||
| 	int index; /* index in the array of listeners */ | ||||
| 
 | ||||
| 	void (*accepter)(struct TCPListener*); | ||||
| 	void (*cleanup)(struct TCPListener*); | ||||
| 
 | ||||
| 	int type; /* CHANNEL_ID_X11, CHANNEL_ID_AGENT, 
 | ||||
| 				 CHANNEL_ID_TCPDIRECT (for clients), | ||||
| 				 CHANNEL_ID_TCPFORWARDED (for servers) */ | ||||
| 
 | ||||
| 	void *typedata; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| void tcp_fwd_initialise(); | ||||
| void handle_tcp_fwd(fd_set * readfds); | ||||
| void set_tcp_fwd_fds(fd_set * readfds); | ||||
| 
 | ||||
| int new_fwd(int sock, int type, void* typedata,  | ||||
| 		void (*accepter)(struct TCPListener*),  | ||||
| 		void (*cleanup)(struct TCPListener*)); | ||||
| 
 | ||||
| struct TCPListener * get_listener(int type, void* typedata, | ||||
| 		int (*match)(void*, void*)); | ||||
| 
 | ||||
| void remove_listener(struct TCPListener* listener); | ||||
| 
 | ||||
| #endif /* _TCPFWD_H */ | ||||
							
								
								
									
										72
									
								
								x11fwd.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								x11fwd.c
									
									
									
									
									
								
							| @ -37,6 +37,8 @@ | ||||
| #define X11BASEPORT 6000 | ||||
| #define X11BINDBASE 6010 | ||||
| 
 | ||||
| static void x11accept(struct Listener* listener); | ||||
| static void x11cleanup(struct Listener *listener); | ||||
| static int bindport(int fd); | ||||
| static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr); | ||||
| 
 | ||||
| @ -44,8 +46,10 @@ static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr); | ||||
| /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ | ||||
| int x11req(struct ChanSess * chansess) { | ||||
| 
 | ||||
| 	int fd; | ||||
| 
 | ||||
| 	/* we already have an x11 connection */ | ||||
| 	if (chansess->x11fd != -1) { | ||||
| 	if (chansess->x11listener != NULL) { | ||||
| 		return DROPBEAR_FAILURE; | ||||
| 	} | ||||
| 
 | ||||
| @ -55,62 +59,71 @@ int x11req(struct ChanSess * chansess) { | ||||
| 	chansess->x11screennum = buf_getint(ses.payload); | ||||
| 
 | ||||
| 	/* create listening socket */ | ||||
| 	chansess->x11fd = socket(PF_INET, SOCK_STREAM, 0); | ||||
| 	if (chansess->x11fd < 0) { | ||||
| 	fd = socket(PF_INET, SOCK_STREAM, 0); | ||||
| 	if (fd < 0) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	/* allocate port and bind */ | ||||
| 	chansess->x11port = bindport(chansess->x11fd); | ||||
| 	chansess->x11port = bindport(fd); | ||||
| 	if (chansess->x11port < 0) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	/* listen */ | ||||
| 	if (listen(chansess->x11fd, 20) < 0) { | ||||
| 	if (listen(fd, 20) < 0) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	/* set non-blocking */ | ||||
| 	if (fcntl(chansess->x11fd, F_SETFL, O_NONBLOCK) < 0) { | ||||
| 	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	/* channel.c's channel fd code will handle the socket now */ | ||||
| 
 | ||||
| 	/* set the maxfd so that select() loop will notice it */ | ||||
| 	ses.maxfd = MAX(ses.maxfd, chansess->x11fd); | ||||
| 	/* listener code will handle the socket now.
 | ||||
| 	 * No cleanup handler needed, since listener_remove only happens | ||||
| 	 * from our cleanup anyway */ | ||||
| 	chansess->x11listener = new_listener( fd, 0, chansess, x11accept, NULL); | ||||
| 	if (chansess->x11listener == NULL) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 
 | ||||
| 	return DROPBEAR_SUCCESS; | ||||
| 
 | ||||
| fail: | ||||
| 	/* cleanup */ | ||||
| 	x11cleanup(chansess); | ||||
| 	m_free(chansess->x11authprot); | ||||
| 	m_free(chansess->x11authcookie); | ||||
| 	close(fd); | ||||
| 
 | ||||
| 	return DROPBEAR_FAILURE; | ||||
| } | ||||
| 
 | ||||
| /* accepts a new X11 socket */ | ||||
| /* returns DROPBEAR_FAILURE or DROPBEAR_SUCCESS */ | ||||
| int x11accept(struct ChanSess * chansess) { | ||||
| static void x11accept(struct Listener* listener) { | ||||
| 
 | ||||
| 	int fd; | ||||
| 	struct sockaddr_in addr; | ||||
| 	int len; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	len = sizeof(addr); | ||||
| 
 | ||||
| 	fd = accept(chansess->x11fd, (struct sockaddr*)&addr, &len); | ||||
| 	fd = accept(listener->sock, (struct sockaddr*)&addr, &len); | ||||
| 	if (fd < 0) { | ||||
| 		return DROPBEAR_FAILURE; | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* if single-connection we close it up */ | ||||
| 	if (chansess->x11singleconn) { | ||||
| 		x11cleanup(chansess); | ||||
| 	if (((struct ChanSess *)(listener->typedata))->x11singleconn) { | ||||
| 		x11cleanup(listener); | ||||
| 	} | ||||
| 
 | ||||
| 	return send_msg_channel_open_x11(fd, &addr); | ||||
| 	ret = send_msg_channel_open_x11(fd, &addr); | ||||
| 	if (ret == DROPBEAR_FAILURE) { | ||||
| 		close(fd); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* This is called after switching to the user, and sets up the xauth
 | ||||
| @ -121,7 +134,7 @@ void x11setauth(struct ChanSess *chansess) { | ||||
| 	FILE * authprog; | ||||
| 	int val; | ||||
| 
 | ||||
| 	if (chansess->x11fd == -1) { | ||||
| 	if (chansess->x11listener == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| @ -154,24 +167,31 @@ void x11setauth(struct ChanSess *chansess) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void x11cleanup(struct ChanSess * chansess) { | ||||
| static void x11cleanup(struct Listener *listener) { | ||||
| 
 | ||||
| 	if (chansess->x11fd == -1) { | ||||
| 		return; | ||||
| 	} | ||||
| 	struct ChanSess *chansess = (struct ChanSess*)listener->typedata; | ||||
| 
 | ||||
| 	m_free(chansess->x11authprot); | ||||
| 	m_free(chansess->x11authcookie); | ||||
| 	close(chansess->x11fd); | ||||
| 	chansess->x11fd = -1; | ||||
| 	remove_listener(listener); | ||||
| 	chansess->x11listener = NULL; | ||||
| } | ||||
| 
 | ||||
| static const struct ChanType chan_x11 = { | ||||
| 	0, /* sepfds */ | ||||
| 	"x11", | ||||
| 	NULL, /* inithandler */ | ||||
| 	NULL, /* checkclose */ | ||||
| 	NULL, /* reqhandler */ | ||||
| 	NULL /* closehandler */ | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static int send_msg_channel_open_x11(int fd, struct sockaddr_in* addr) { | ||||
| 
 | ||||
| 	char* ipstring; | ||||
| 
 | ||||
| 	if (send_msg_channel_open_init(fd, CHANNEL_ID_X11, "x11")  | ||||
| 			== DROPBEAR_SUCCESS) { | ||||
| 	if (send_msg_channel_open_init(fd, &chan_x11) == DROPBEAR_SUCCESS) { | ||||
| 		ipstring = inet_ntoa(addr->sin_addr); | ||||
| 		buf_putstring(ses.writepayload, ipstring, strlen(ipstring)); | ||||
| 		buf_putint(ses.writepayload, addr->sin_port); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user