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