diff --git a/agentfwd.h b/agentfwd.h index 0b42cb2..a0f675d 100644 --- a/agentfwd.h +++ b/agentfwd.h @@ -30,9 +30,8 @@ #include "channel.h" int agentreq(struct ChanSess * chansess); -int agentaccept(struct ChanSess * chansess); -void agentcleanup(struct ChanSess * chansess); void agentsetauth(struct ChanSess *chansess); +void agentcleanup(struct ChanSess * chansess); void agentset(struct ChanSess *chansess); #ifdef __hpux diff --git a/dbutil.c b/dbutil.c index e03d648..2494f38 100644 --- a/dbutil.c +++ b/dbutil.c @@ -158,7 +158,7 @@ char* getaddrhostname(struct sockaddr * addr) { retstring = host->h_name; } - return strdup(retstring); + return m_strdup(retstring); } #ifdef DEBUG_TRACE void printhex(unsigned char* buf, int len) { @@ -263,6 +263,16 @@ void * m_malloc(size_t size) { } +void * m_strdup(const char * str) { + char* ret; + + ret = strdup(str); + if (ret == NULL) { + dropbear_exit("m_strdup failed"); + } + return ret; +} + void __m_free(void* ptr) { if (ptr != NULL) { free(ptr); diff --git a/dbutil.h b/dbutil.h index d13b13e..3888452 100644 --- a/dbutil.h +++ b/dbutil.h @@ -51,6 +51,7 @@ int buf_readfile(buffer* buf, const char* filename); int m_close(int fd); void * m_malloc(size_t size); +void * m_strdup(const char * str); void * m_realloc(void* ptr, size_t size); #define m_free(X) __m_free(X); (X) = NULL; void __m_free(void* ptr); diff --git a/svr-agentfwd.c b/svr-agentfwd.c index f8af30e..4c49e45 100644 --- a/svr-agentfwd.c +++ b/svr-agentfwd.c @@ -38,45 +38,52 @@ #include "packet.h" #include "buffer.h" #include "random.h" +#include "listener.h" #define AGENTDIRPREFIX "/tmp/dropbear-" static int send_msg_channel_open_agent(int fd); -static int bindagent(struct ChanSess * chansess); +static int bindagent(int fd, struct ChanSess * chansess); +static void agentaccept(struct Listener * listener); /* Handles client requests to start agent forwarding, sets up listening socket. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ int agentreq(struct ChanSess * chansess) { - if (chansess->agentfd != -1) { + int fd; + + if (chansess->agentlistener != NULL) { return DROPBEAR_FAILURE; } /* create listening socket */ - chansess->agentfd = socket(PF_UNIX, SOCK_STREAM, 0); - if (chansess->agentfd < 0) { + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { goto fail; } /* create the unix socket dir and file */ - if (bindagent(chansess) == DROPBEAR_FAILURE) { + if (bindagent(fd, chansess) == DROPBEAR_FAILURE) { return DROPBEAR_FAILURE; } /* listen */ - if (listen(chansess->agentfd, 20) < 0) { + if (listen(fd, 20) < 0) { goto fail; } /* set non-blocking */ - if (fcntl(chansess->agentfd, 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 */ + /* pass if off to listener */ + chansess->agentlistener = new_listener( fd, 0, chansess, + agentaccept, NULL); - /* set the maxfd so that select() loop will notice it */ - ses.maxfd = MAX(ses.maxfd, chansess->agentfd); + if (chansess->agentlistener == NULL) { + goto fail; + } return DROPBEAR_SUCCESS; @@ -90,16 +97,18 @@ fail: /* accepts a connection on the forwarded socket and opens a new channel for it * back to the client */ /* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ -int agentaccept(struct ChanSess * chansess) { +static void agentaccept(struct Listener * listener) { int fd; - fd = accept(chansess->agentfd, NULL, NULL); + fd = accept(listener->sock, NULL, NULL); if (fd < 0) { - return DROPBEAR_FAILURE; + return; } - return send_msg_channel_open_agent(fd); + if (send_msg_channel_open_agent(listener->sock) != DROPBEAR_SUCCESS) { + close(fd); + } } @@ -110,7 +119,7 @@ void agentset(struct ChanSess * chansess) { char *path = NULL; int len; - if (chansess->agentfd == -1) { + if (chansess->agentlistener == NULL) { return; } @@ -131,46 +140,57 @@ void agentcleanup(struct ChanSess * chansess) { gid_t gid; int len; - if (chansess->agentfd == -1) { - return; + if (chansess->agentlistener != NULL) { + remove_listener(chansess->agentlistener); + chansess->agentlistener = NULL; } - close(chansess->agentfd); + if (chansess->agentfile && chansess->agentdir) { - /* Remove the dir as the user. That way they can't cause problems except - * for themselves */ - uid = getuid(); - gid = getgid(); - if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 || - (seteuid(svr_ses.authstate.pw->pw_uid)) < 0) { - dropbear_exit("failed to set euid"); + /* Remove the dir as the user. That way they can't cause problems except + * for themselves */ + uid = getuid(); + gid = getgid(); + if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 || + (seteuid(svr_ses.authstate.pw->pw_uid)) < 0) { + dropbear_exit("failed to set euid"); + } + + /* 2 for "/" and "\0" */ + len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; + + path = m_malloc(len); + snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile); + unlink(path); + m_free(path); + + rmdir(chansess->agentdir); + + if ((seteuid(uid)) < 0 || + (setegid(gid)) < 0) { + dropbear_exit("failed to revert euid"); + } + + m_free(chansess->agentfile); + m_free(chansess->agentdir); } - /* 2 for "/" and "\0" */ - len = strlen(chansess->agentdir) + strlen(chansess->agentfile) + 2; - - path = m_malloc(len); - snprintf(path, len, "%s/%s", chansess->agentdir, chansess->agentfile); - unlink(path); - m_free(path); - - rmdir(chansess->agentdir); - - if ((seteuid(uid)) < 0 || - (setegid(gid)) < 0) { - dropbear_exit("failed to revert euid"); - } - - m_free(chansess->agentfile); - m_free(chansess->agentdir); - } +static const struct ChanType chan_agent = { + 0, /* sepfds */ + "auth-agent@openssh.com", + NULL, + NULL, + NULL, + NULL +}; + + /* helper for accepting an agent request */ static int send_msg_channel_open_agent(int fd) { - if (send_msg_channel_open_init(fd, CHANNEL_ID_AGENT, - "auth-agent@openssh.com") == DROPBEAR_SUCCESS) { + if (send_msg_channel_open_init(fd, &chan_agent) == DROPBEAR_SUCCESS) { encrypt_packet(); return DROPBEAR_SUCCESS; } else { @@ -180,7 +200,7 @@ static int send_msg_channel_open_agent(int fd) { /* helper for creating the agent socket-file returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ -static int bindagent(struct ChanSess * chansess) { +static int bindagent(int fd, struct ChanSess * chansess) { struct sockaddr_un addr; unsigned int prefix; @@ -225,13 +245,13 @@ bindsocket: * between subsequent user processes reusing socket fds (odds are now * 1/(2^64) */ genrandom((unsigned char*)&prefix, sizeof(prefix)); - snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, - chansess->agentfd); + snprintf(sockfile, sizeof(sockfile), "auth-%.8x-%d", prefix, fd); + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", path, sockfile); - if (bind(chansess->agentfd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { - chansess->agentdir = strdup(path); - chansess->agentfile = strdup(sockfile); + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { + chansess->agentdir = m_strdup(path); + chansess->agentfile = m_strdup(sockfile); ret = DROPBEAR_SUCCESS; } diff --git a/svr-auth.c b/svr-auth.c index 46ca70a..f6adb05 100644 --- a/svr-auth.c +++ b/svr-auth.c @@ -151,7 +151,7 @@ void recv_msg_userauth_request() { if (methodlen == AUTH_METHOD_PASSWORD_LEN && strncmp(methodname, AUTH_METHOD_PASSWORD, AUTH_METHOD_PASSWORD_LEN) == 0) { - passwordauth(username, userlen); + passwordauth(); goto out; } } @@ -162,7 +162,7 @@ void recv_msg_userauth_request() { if (methodlen == AUTH_METHOD_PUBKEY_LEN && strncmp(methodname, AUTH_METHOD_PUBKEY, AUTH_METHOD_PUBKEY_LEN) == 0) { - pubkeyauth(username, userlen); + pubkeyauth(); goto out; } #endif @@ -200,7 +200,7 @@ static int checkusername(unsigned char *username, unsigned int userlen) { } authclear(); svr_ses.authstate.pw = getpwnam((char*)username); - svr_ses.authstate.username = strdup(username); + svr_ses.authstate.username = m_strdup(username); m_free(svr_ses.authstate.printableuser); } @@ -214,7 +214,7 @@ static int checkusername(unsigned char *username, unsigned int userlen) { } /* We can set it once we know its a real user */ - svr_ses.authstate.printableuser = strdup(svr_ses.authstate.pw->pw_name); + svr_ses.authstate.printableuser = m_strdup(svr_ses.authstate.pw->pw_name); /* check for non-root if desired */ if (ses.opts->norootlogin && svr_ses.authstate.pw->pw_uid == 0) { diff --git a/svr-chansession.c b/svr-chansession.c index 4dd4228..c6526dc 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -419,7 +419,7 @@ static int sessionpty(struct ChanSess * chansess) { return DROPBEAR_FAILURE; } - chansess->tty = (char*)strdup(namebuf); + chansess->tty = (char*)m_strdup(namebuf); if (!chansess->tty) { dropbear_exit("out of memory"); /* TODO disconnect */ } @@ -541,7 +541,7 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess, #ifdef SFTPSERVER_PATH if ((cmdlen == 4) && strncmp(chansess->cmd, "sftp", 4) == 0) { m_free(chansess->cmd); - chansess->cmd = strdup(SFTPSERVER_PATH); + chansess->cmd = m_strdup(SFTPSERVER_PATH); } else #endif { diff --git a/tcpfwd-direct.c b/tcpfwd-direct.c index 81cd415..1131602 100644 --- a/tcpfwd-direct.c +++ b/tcpfwd-direct.c @@ -9,7 +9,7 @@ static int newtcpdirect(struct Channel * channel); static int newtcp(const char * host, int port); const struct ChanType chan_tcpdirect = { - 0, /* sepfds */ + 1, /* sepfds */ "direct-tcpip", newtcpdirect, /* init */ NULL, /* checkclose */ diff --git a/tcpfwd-remote.c b/tcpfwd-remote.c index 9996dbd..880044f 100644 --- a/tcpfwd-remote.c +++ b/tcpfwd-remote.c @@ -71,7 +71,7 @@ out: } static const struct ChanType chan_tcpremote = { - 0, /* sepfds */ + 1, /* sepfds */ "forwarded-tcpip", NULL, NULL, diff --git a/x11fwd.c b/x11fwd.c index e1b6961..12a8f21 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -38,7 +38,6 @@ #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); @@ -167,7 +166,7 @@ void x11setauth(struct ChanSess *chansess) { } } -static void x11cleanup(struct Listener *listener) { +void x11cleanup(struct Listener *listener) { struct ChanSess *chansess = (struct ChanSess*)listener->typedata; diff --git a/x11fwd.h b/x11fwd.h index 6cf4b96..13cd11f 100644 --- a/x11fwd.h +++ b/x11fwd.h @@ -31,6 +31,7 @@ int x11req(struct ChanSess * chansess); void x11setauth(struct ChanSess *chansess); +void x11cleanup(struct Listener *listener); #endif /* DROPBEAR_X11FWD */ #endif /* _X11FWD_H_ */