diff options
-rw-r--r-- | Makefile.in | 10 | ||||
-rw-r--r-- | channel.h | 3 | ||||
-rw-r--r-- | chansession.h | 5 | ||||
-rw-r--r-- | common-channel.c | 25 | ||||
-rw-r--r-- | listener.c | 123 | ||||
-rw-r--r-- | listener.h | 37 | ||||
-rw-r--r-- | options.h | 2 | ||||
-rw-r--r-- | session.h | 6 | ||||
-rw-r--r-- | svr-chansession.c | 6 | ||||
-rw-r--r-- | svr-session.c | 2 | ||||
-rw-r--r-- | tcpfwd-direct.c (renamed from localtcpfwd.c) | 7 | ||||
-rw-r--r-- | tcpfwd-direct.h (renamed from localtcpfwd.h) | 6 | ||||
-rw-r--r-- | tcpfwd-remote.c (renamed from remotetcpfwd.c) | 55 | ||||
-rw-r--r-- | tcpfwd-remote.h (renamed from remotetcpfwd.h) | 0 | ||||
-rw-r--r-- | tcpfwd.c | 124 | ||||
-rw-r--r-- | tcpfwd.h | 37 | ||||
-rw-r--r-- | x11fwd.c | 72 | ||||
-rw-r--r-- | x11fwd.h | 2 |
18 files changed, 277 insertions, 245 deletions
diff --git a/Makefile.in b/Makefile.in index 10d3cc1..cc3127a 100644 --- a/Makefile.in +++ b/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 diff --git a/chansession.h b/chansession.h index 85dc9c1..7879791 100644 --- a/chansession.h +++ b/chansession.h @@ -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 diff --git a/common-channel.c b/common-channel.c index 4643fc2..63ed275 100644 --- a/common-channel.c +++ b/common-channel.c @@ -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); diff --git a/listener.c b/listener.c new file mode 100644 index 0000000..df66629 --- /dev/null +++ b/listener.c @@ -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); + +} diff --git a/listener.h b/listener.h new file mode 100644 index 0000000..ab77351 --- /dev/null +++ b/listener.h @@ -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 }; diff --git a/svr-chansession.c b/svr-chansession.c index f5b4308..4dd4228 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -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 */ diff --git a/svr-session.c b/svr-session.c index 8e8eaea..2a97f94 100644 --- a/svr-session.c +++ b/svr-session.c @@ -35,7 +35,7 @@ #include "channel.h" #include "chansession.h" #include "atomicio.h" -#include "localtcpfwd.h" +#include "tcpfwd-direct.h" static void svr_remoteclosed(); diff --git a/localtcpfwd.c b/tcpfwd-direct.c index bf89fa0..81cd415 100644 --- a/localtcpfwd.c +++ b/tcpfwd-direct.c @@ -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 */ diff --git a/localtcpfwd.h b/tcpfwd-direct.h index 65efa6e..20cd278 100644 --- a/localtcpfwd.h +++ b/tcpfwd-direct.h @@ -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" diff --git a/remotetcpfwd.c b/tcpfwd-remote.c index 40a3a82..9996dbd 100644 --- a/remotetcpfwd.c +++ b/tcpfwd-remote.c @@ -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 */ diff --git a/remotetcpfwd.h b/tcpfwd-remote.h index 64dbed3..64dbed3 100644 --- a/remotetcpfwd.h +++ b/tcpfwd-remote.h diff --git a/tcpfwd.c b/tcpfwd.c deleted file mode 100644 index d95970a..0000000 --- a/tcpfwd.c +++ /dev/null @@ -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); - -} diff --git a/tcpfwd.h b/tcpfwd.h deleted file mode 100644 index 85d7373..0000000 --- a/tcpfwd.h +++ /dev/null @@ -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 */ @@ -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); @@ -30,8 +30,6 @@ #include "channel.h" int x11req(struct ChanSess * chansess); -int x11accept(struct ChanSess * chansess); -void x11cleanup(struct ChanSess * chansess); void x11setauth(struct ChanSess *chansess); #endif /* DROPBEAR_X11FWD */ |