diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | buffer.c | 2 | ||||
-rw-r--r-- | channel.h | 12 | ||||
-rw-r--r-- | chansession.h | 5 | ||||
-rw-r--r-- | circbuffer.c | 138 | ||||
-rw-r--r-- | circbuffer.h | 50 | ||||
-rw-r--r-- | cli-chansession.c | 36 | ||||
-rw-r--r-- | cli-main.c | 3 | ||||
-rw-r--r-- | cli-session.c | 5 | ||||
-rw-r--r-- | cli-tcpfwd.c | 2 | ||||
-rw-r--r-- | common-channel.c | 67 | ||||
-rw-r--r-- | common-session.c | 4 | ||||
-rw-r--r-- | dbutil.c | 3 | ||||
-rw-r--r-- | includes.h | 10 | ||||
-rw-r--r-- | session.h | 5 | ||||
-rw-r--r-- | svr-agentfwd.c | 2 | ||||
-rw-r--r-- | svr-chansession.c | 10 | ||||
-rw-r--r-- | svr-main.c | 7 | ||||
-rw-r--r-- | tcpfwd.h | 3 |
19 files changed, 302 insertions, 64 deletions
@@ -2,6 +2,8 @@ Current: Things which might need doing: +- exit with returned exit codes? + - errfd needs fixing - Make options.h generated from configure perhaps? @@ -1,5 +1,5 @@ /* - * Dropbear - a SSH2 server + * Dropbear SSH * * Copyright (c) 2002,2003 Matt Johnston * All rights reserved. @@ -45,16 +45,15 @@ /* Not a real type */ #define SSH_OPEN_IN_PROGRESS 99 -#define MAX_CHANNELS 60 /* simple mem restriction, includes each tcp/x11 +#define MAX_CHANNELS 100 /* simple mem restriction, includes each tcp/x11 connection, so can't be _too_ small */ #define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */ -#define RECV_MAXWINDOW 6000 /* tweak */ -#define RECV_WINDOWEXTEND (RECV_MAXWINDOW/2) /* We send a "window extend" every - RECV_WINDOWEXTEND bytes */ -#define RECV_MAXPACKET 1400 /* tweak */ -#define RECV_MINWINDOW 19000 /* when we get below this, we send a windowadjust */ +#define RECV_MAXWINDOW 4000 /* tweak */ +#define RECV_WINDOWEXTEND 500 /* We send a "window extend" every + RECV_WINDOWEXTEND bytes */ +#define RECV_MAXPACKET RECV_MAXWINDOW /* tweak */ struct ChanType; @@ -63,6 +62,7 @@ struct Channel { unsigned int index; /* the local channel index */ unsigned int remotechan; unsigned int recvwindow, transwindow; + unsigned int recvdonelen; unsigned int recvmaxpacket, transmaxpacket; void* typedata; /* a pointer to type specific data */ int infd; /* data to send over the wire */ diff --git a/chansession.h b/chansession.h index 3fb1901..84ca55a 100644 --- a/chansession.h +++ b/chansession.h @@ -68,11 +68,6 @@ struct ChildPid { }; -void chansessionrequest(struct Channel * channel); -void send_msg_chansess_exitstatus(struct Channel * channel, - struct ChanSess * chansess); -void send_msg_chansess_exitsignal(struct Channel * channel, - struct ChanSess * chansess); void addnewvar(const char* param, const char* var); void cli_send_chansess_request(); diff --git a/circbuffer.c b/circbuffer.c new file mode 100644 index 0000000..a2edcbb --- /dev/null +++ b/circbuffer.c @@ -0,0 +1,138 @@ +/* + * Dropbear SSH + * + * Copyright (c) 2002-2004 Matt Johnston + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * 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. */ + +#include "includes.h" +#include "dbutil.h" +#include "circbuffer.h" + +#define MAX_CBUF_SIZE 100000000 + +circbuffer * cbuf_new(unsigned int size) { + + circbuffer *cbuf = NULL; + + if (size > MAX_CBUF_SIZE) { + dropbear_exit("bad cbuf size"); + } + + cbuf = (circbuffer*)m_malloc(sizeof(circbuffer)); + cbuf->data = (unsigned char*)m_malloc(size); + cbuf->used = 0; + cbuf->readpos = 0; + cbuf->writepos = 0; + cbuf->size = size; + + return cbuf; +} + +void cbuf_free(circbuffer * cbuf) { + + m_free(cbuf->data); + m_free(cbuf); +} + +unsigned int cbuf_getused(circbuffer * cbuf) { + + return cbuf->used; + +} + +unsigned int cbuf_getavail(circbuffer * cbuf) { + + return cbuf->size - cbuf->used; + +} + +unsigned int cbuf_readlen(circbuffer *cbuf) { + + assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size); + assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size); + + if (cbuf->used == 0) { + TRACE(("cbuf_readlen: unused buffer")); + return 0; + } + + if (cbuf->readpos < cbuf->writepos) { + return cbuf->writepos - cbuf->readpos; + } + + return cbuf->size - cbuf->readpos; +} + +unsigned int cbuf_writelen(circbuffer *cbuf) { + + assert(cbuf->used <= cbuf->size); + assert(((2*cbuf->size)+cbuf->writepos-cbuf->readpos)%cbuf->size == cbuf->used%cbuf->size); + assert(((2*cbuf->size)+cbuf->readpos-cbuf->writepos)%cbuf->size == (cbuf->size-cbuf->used)%cbuf->size); + + if (cbuf->used == cbuf->size) { + TRACE(("cbuf_writelen: full buffer")); + return 0; /* full */ + } + + if (cbuf->writepos < cbuf->readpos) { + return cbuf->readpos - cbuf->writepos; + } + + return cbuf->size - cbuf->writepos; +} + +unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len) { + if (len > cbuf_readlen(cbuf)) { + dropbear_exit("bad cbuf read"); + } + + return &cbuf->data[cbuf->readpos]; +} + +unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len) { + + if (len > cbuf_writelen(cbuf)) { + dropbear_exit("bad cbuf write"); + } + + return &cbuf->data[cbuf->writepos]; +} + +void cbuf_incrwrite(circbuffer *cbuf, unsigned int len) { + if (len > cbuf_writelen(cbuf)) { + dropbear_exit("bad cbuf write"); + } + + cbuf->used += len; + assert(cbuf->used <= cbuf->size); + cbuf->writepos = (cbuf->writepos + len) % cbuf->size; +} + + +void cbuf_incrread(circbuffer *cbuf, unsigned int len) { + if (len > cbuf_readlen(cbuf)) { + dropbear_exit("bad cbuf read"); + } + + assert(cbuf->used >= len); + cbuf->used -= len; + cbuf->readpos = (cbuf->readpos + len) % cbuf->size; +} diff --git a/circbuffer.h b/circbuffer.h new file mode 100644 index 0000000..21c5134 --- /dev/null +++ b/circbuffer.h @@ -0,0 +1,50 @@ +/* + * Dropbear SSH + * + * Copyright (c) 2002-2004 Matt Johnston + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * 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 _CIRCBUFFER_H_ +#define _CIRCBUFFER_H_ +struct circbuf { + + unsigned int size; + unsigned int readpos; + unsigned int writepos; + unsigned int used; + unsigned char* data; +}; + +typedef struct circbuf circbuffer; + +circbuffer * cbuf_new(unsigned int size); +void cbuf_free(circbuffer * cbuf); + +unsigned int cbuf_getused(circbuffer * cbuf); /* how much data stored */ +unsigned int cbuf_getavail(circbuffer * cbuf); /* how much we can write */ +unsigned int cbuf_readlen(circbuffer *cbuf); /* max linear read len */ +unsigned int cbuf_writelen(circbuffer *cbuf); /* max linear write len */ + +unsigned char* cbuf_readptr(circbuffer *cbuf, unsigned int len); +unsigned char* cbuf_writeptr(circbuffer *cbuf, unsigned int len); +void cbuf_incrwrite(circbuffer *cbuf, unsigned int len); +void cbuf_incrread(circbuffer *cbuf, unsigned int len); +#endif diff --git a/cli-chansession.c b/cli-chansession.c index df6eb45..50226dd 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -32,9 +32,11 @@ #include "ssh.h" #include "runopts.h" #include "termcodes.h" +#include "chansession.h" static void cli_closechansess(struct Channel *channel); static int cli_initchansess(struct Channel *channel); +static void cli_chansessreq(struct Channel *channel); static void start_channel_request(struct Channel *channel, unsigned char *type); @@ -42,19 +44,43 @@ static void send_chansess_pty_req(struct Channel *channel); static void send_chansess_shell_req(struct Channel *channel); static void cli_tty_setup(); -void cli_tty_cleanup(); const struct ChanType clichansess = { 0, /* sepfds */ "session", /* name */ cli_initchansess, /* inithandler */ NULL, /* checkclosehandler */ - NULL, /* reqhandler */ + cli_chansessreq, /* reqhandler */ cli_closechansess, /* closehandler */ }; +static void cli_chansessreq(struct Channel *channel) { + + unsigned char* type = NULL; + int wantreply; + + TRACE(("enter cli_chansessreq")); + + type = buf_getstring(ses.payload, NULL); + wantreply = buf_getbyte(ses.payload); + + if (strcmp(type, "exit-status") != 0) { + TRACE(("unknown request '%s'", type)); + send_msg_channel_failure(channel); + goto out; + } + + /* We'll just trust what they tell us */ + cli_ses.retval = buf_getint(ses.payload); + TRACE(("got exit-status of '%d'", cli_ses.retval)); + +out: + m_free(type); +} + + /* If the main session goes, we close it up */ -static void cli_closechansess(struct Channel *channel) { +static void cli_closechansess(struct Channel *UNUSED(channel)) { /* This channel hasn't gone yet, so we have > 1 */ if (ses.chancount > 1) { @@ -228,7 +254,7 @@ static void put_winsize() { } -static void sigwinch_handler(int dummy) { +static void sigwinch_handler(int UNUSED(unused)) { cli_ses.winchange = 1; @@ -317,7 +343,7 @@ static int cli_initchansess(struct Channel *channel) { channel->infd = STDOUT_FILENO; channel->outfd = STDIN_FILENO; channel->errfd = STDERR_FILENO; - channel->extrabuf = buf_new(RECV_MAXWINDOW); + channel->extrabuf = cbuf_new(RECV_MAXWINDOW); if (cli_opts.wantpty) { send_chansess_pty_req(channel); @@ -96,7 +96,8 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) { exit(exitcode); } -static void cli_dropbear_log(int priority, const char* format, va_list param) { +static void cli_dropbear_log(int UNUSED(priority), + const char* format, va_list param) { char printbuf[1024]; diff --git a/cli-session.c b/cli-session.c index b51e20f..671735c 100644 --- a/cli-session.c +++ b/cli-session.c @@ -118,6 +118,9 @@ static void cli_session_init() { cli_ses.stdincopy = dup(STDIN_FILENO); cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0); + cli_ses.retval = EXIT_SUCCESS; /* Assume it's clean if we don't get a + specific exit status */ + /* Auth */ cli_ses.lastpubkey = NULL; cli_ses.lastauthtype = NULL; @@ -261,7 +264,7 @@ static void cli_finished() { common_session_cleanup(); fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, cli_opts.remotehost, cli_opts.remoteport); - exit(EXIT_SUCCESS); + exit(cli_ses.retval); } diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c index 747d8db..4dbef01 100644 --- a/cli-tcpfwd.c +++ b/cli-tcpfwd.c @@ -89,7 +89,7 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr, remoteport)); tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*)); - tcpinfo->sendaddr = remoteaddr; + tcpinfo->sendaddr = m_strdup(remoteaddr); tcpinfo->sendport = remoteport; tcpinfo->listenport = listenport; tcpinfo->chantype = &cli_chan_tcplocal; diff --git a/common-channel.c b/common-channel.c index 41a7208..a4cc44b 100644 --- a/common-channel.c +++ b/common-channel.c @@ -40,7 +40,7 @@ static void send_msg_channel_open_failure(unsigned int remotechan, int reason, static void send_msg_channel_open_confirmation(struct Channel* channel, unsigned int recvwindow, unsigned int recvmaxpacket); -static void writechannel(struct Channel *channel); +static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf); static void send_msg_channel_window_adjust(struct Channel *channel, unsigned int incr); static void send_msg_channel_data(struct Channel *channel, int isextended, @@ -151,6 +151,7 @@ struct Channel* newchannel(unsigned int remotechan, newchan->writebuf = cbuf_new(RECV_MAXWINDOW); newchan->extrabuf = NULL; /* The user code can set it up */ newchan->recvwindow = RECV_MAXWINDOW; + newchan->recvdonelen = 0; newchan->recvmaxpacket = RECV_MAXPACKET; ses.channels[i] = newchan; @@ -220,7 +221,13 @@ void channelio(fd_set *readfd, fd_set *writefd) { continue; /* Important not to use the channel after checkinitdone(), as it may be NULL */ } - writechannel(channel); + writechannel(channel, channel->infd, channel->writebuf); + } + + /* stderr for client mode */ + if (channel->extrabuf != NULL + && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefd)) { + writechannel(channel, channel->errfd, channel->extrabuf); } /* now handle any of the channel-closing type stuff */ @@ -350,33 +357,30 @@ static void send_msg_channel_eof(struct Channel *channel) { /* Called to write data out to the local side of the channel. * Only called when we know we can write to a channel, writes as much as * possible */ -static void writechannel(struct Channel* channel) { +static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) { int len, maxlen; - circbuffer *cbuf; TRACE(("enter writechannel")); - cbuf = channel->writebuf; maxlen = cbuf_readlen(cbuf); - TRACE(("maxlen = %d", maxlen)); - /* Write the data out */ - len = write(channel->infd, cbuf_readptr(cbuf, maxlen), maxlen); + len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen); if (len <= 0) { if (len < 0 && errno != EINTR) { - /* no more to write */ + /* no more to write - we close it even if the fd was stderr, since + * that's a nasty failure too */ closeinfd(channel); } TRACE(("leave writechannel: len <= 0")); return; } - TRACE(("len = %d", len)); cbuf_incrread(cbuf, len); + channel->recvdonelen += len; - if (len == maxlen && channel->recveof) { + if (fd == channel->infd && len == maxlen && channel->recveof) { /* Check if we're closing up */ closeinfd(channel); return; @@ -385,12 +389,17 @@ static void writechannel(struct Channel* channel) { } /* Window adjust handling */ - if (channel->recvwindow < (RECV_MAXWINDOW - RECV_WINDOWEXTEND)) { + if (channel->recvdonelen >= RECV_WINDOWEXTEND) { /* Set it back to max window */ - send_msg_channel_window_adjust(channel, RECV_MAXWINDOW - - channel->recvwindow); - channel->recvwindow = RECV_MAXWINDOW; + send_msg_channel_window_adjust(channel, channel->recvdonelen); + channel->recvwindow += channel->recvdonelen; + channel->recvdonelen = 0; } + + assert(channel->recvwindow <= RECV_MAXWINDOW); + assert(channel->recvwindow <= cbuf_getavail(channel->writebuf)); + assert(channel->extrabuf == NULL || + channel->recvwindow <= cbuf_getavail(channel->extrabuf)); TRACE(("leave writechannel")); @@ -424,6 +433,8 @@ void setchannelfds(fd_set *readfd, fd_set *writefd) { /* For checking FD status (ie closure etc) - we don't actually * read data from infd */ + TRACE(("infd = %d, outfd %d, bufused %d", channel->infd, channel->outfd, + cbuf_getused(channel->writebuf) )); if (channel->infd >= 0 && channel->infd != channel->outfd) { FD_SET(channel->infd, readfd); } @@ -435,12 +446,10 @@ void setchannelfds(fd_set *readfd, fd_set *writefd) { FD_SET(channel->infd, writefd); } - /* if (channel->extrabuf != NULL && channel->errfd >= 0 - && cbuf_getavail(channel->extrabuf) > 0 ) { + && cbuf_getused(channel->extrabuf) > 0 ) { FD_SET(channel->errfd, writefd); } - */ } /* foreach channel */ @@ -468,7 +477,9 @@ void recv_msg_channel_eof() { } channel->recveof = 1; - if (cbuf_getused(channel->writebuf) == 0) { + if (cbuf_getused(channel->writebuf) == 0 + && (channel->extrabuf == NULL + || cbuf_getused(channel->extrabuf) == 0)) { closeinfd(channel); } @@ -678,36 +689,34 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd, datalen = buf_getint(ses.payload); - TRACE(("datalen = %d", datalen)); - /* if the client is going to send us more data than we've allocated, then - * it has ignored the windowsize, so we "MAY ignore all extra data" */ maxdata = cbuf_getavail(cbuf); - TRACE(("maxdata = %d", maxdata)); + + /* Whilst the spec says we "MAY ignore data past the end" this could + * lead to corrupted file transfers etc (chunks missed etc). It's better to + * just die horribly */ if (datalen > maxdata) { - TRACE(("Warning: recv_msg_channel_data: extra data past window")); - datalen = maxdata; + dropbear_exit("Oversized packet"); } - /* We may have to run throught twice, if the buffer wraps around. Can't * just "leave it for next time" like with writechannel, since this * is payload data */ len = datalen; while (len > 0) { buflen = cbuf_writelen(cbuf); - TRACE(("buflen = %d", buflen)); buflen = MIN(buflen, len); - TRACE(("buflenmin = %d", buflen)); memcpy(cbuf_writeptr(cbuf, buflen), buf_getptr(ses.payload, buflen), buflen); cbuf_incrwrite(cbuf, buflen); + buf_incrpos(ses.payload, buflen); len -= buflen; - TRACE(("len = %d", buflen)); } + assert(channel->recvwindow > datalen); channel->recvwindow -= datalen; + assert(channel->recvwindow <= RECV_MAXWINDOW); TRACE(("leave recv_msg_channel_data")); } diff --git a/common-session.c b/common-session.c index 1888eb7..f220753 100644 --- a/common-session.c +++ b/common-session.c @@ -35,6 +35,8 @@ #include "channel.h" #include "atomicio.h" +static void checktimeouts(); +static int ident_readln(int fd, char* buf, int count); struct sshsession ses; /* GLOBAL */ @@ -46,8 +48,6 @@ int sessinitdone = 0; /* GLOBAL */ int exitflag = 0; /* GLOBAL */ -static void checktimeouts(); -static int ident_readln(int fd, char* buf, int count); /* called only at the start of a session, set up initial state */ void common_session_init(int sock, char* remotehost) { @@ -111,7 +111,7 @@ static void generic_dropbear_exit(int exitcode, const char* format, exit(exitcode); } -static void generic_dropbear_log(int priority, const char* format, +static void generic_dropbear_log(int UNUSED(priority), const char* format, va_list param) { char printbuf[1024]; @@ -146,7 +146,6 @@ void dropbear_trace(const char* format, ...) { fprintf(stderr, "TRACE: "); vfprintf(stderr, format, param); fprintf(stderr, "\n"); - fflush(stderr); va_end(param); } #endif /* DEBUG_TRACE */ @@ -128,4 +128,14 @@ typedef u_int16_t uint16_t; #define LOG_AUTHPRIV LOG_AUTH #endif +/* so we can avoid warnings about unused params (ie in signal handlers etc) */ +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + #endif /* _INCLUDES_H_ */ @@ -43,7 +43,6 @@ extern int exitflag; void common_session_init(int sock, char* remotehost); void session_loop(void(*loophandler)()); void common_session_cleanup(); -void checktimeouts(); void session_identification(); @@ -54,8 +53,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param); /* Client */ void cli_session(int sock, char *remotehost); -void cli_dropbear_exit(int exitcode, const char* format, va_list param); -void cli_dropbear_log(int priority, const char* format, va_list param); void cli_session_cleanup(); void cleantext(unsigned char* dirtytext); @@ -220,6 +217,8 @@ struct clientsession { int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD, for the last type of auth we tried */ struct PubkeyList *lastpubkey; + + int retval; /* What the command exit status was - we emulate it */ #if 0 TODO struct AgentkeyList *agentkeys; /* Keys to use for public-key auth */ diff --git a/svr-agentfwd.c b/svr-agentfwd.c index 4e9aa56..2674138 100644 --- a/svr-agentfwd.c +++ b/svr-agentfwd.c @@ -97,7 +97,7 @@ 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 */ -static void agentaccept(struct Listener * listener, int sock) { +static void agentaccept(struct Listener *UNUSED(listener), int sock) { int fd; diff --git a/svr-chansession.c b/svr-chansession.c index d56fb2c..8c9fa3b 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -55,6 +55,10 @@ static int newchansess(struct Channel *channel); static void chansessionrequest(struct Channel *channel); static void send_exitsignalstatus(struct Channel *channel); +static void send_msg_chansess_exitstatus(struct Channel * channel, + struct ChanSess * chansess); +static void send_msg_chansess_exitsignal(struct Channel * channel, + struct ChanSess * chansess); static int sesscheckclose(struct Channel *channel); static void get_termmodes(struct ChanSess *chansess); @@ -68,7 +72,7 @@ static int sesscheckclose(struct Channel *channel) { } /* handler for childs exiting, store the state for return to the client */ -static void sesssigchild_handler(int dummy) { +static void sesssigchild_handler(int UNUSED(dummy)) { int status; pid_t pid; @@ -498,7 +502,9 @@ static int sessionpty(struct ChanSess * chansess) { } /* allocate the pty */ - assert(chansess->master == -1); /* haven't already got one */ + if (chansess->master != -1) { + dropbear_exit("multiple pty requests"); + } if (pty_allocate(&chansess->master, &chansess->slave, namebuf, 64) == 0) { TRACE(("leave sessionpty: failed to allocate pty")); return DROPBEAR_FAILURE; @@ -123,7 +123,6 @@ void main_noinetd() { pid_t childpid; int childpipe[2]; - struct sigaction sa_chld; /* fork */ if (svr_opts.forkbg) { int closefds = 0; @@ -303,7 +302,7 @@ void main_noinetd() { /* catch + reap zombie children */ -static void sigchld_handler(int fish) { +static void sigchld_handler(int UNUSED(unused)) { struct sigaction sa_chld; while(waitpid(-1, NULL, WNOHANG) > 0); @@ -316,14 +315,14 @@ static void sigchld_handler(int fish) { } /* catch any segvs */ -static void sigsegv_handler(int fish) { +static void sigsegv_handler(int UNUSED(unused)) { fprintf(stderr, "Aiee, segfault! You should probably report " "this as a bug to the developer\n"); exit(EXIT_FAILURE); } /* catch ctrl-c or sigterm */ -static void sigintterm_handler(int fish) { +static void sigintterm_handler(int UNUSED(unused)) { exitflag = 1; } @@ -47,7 +47,7 @@ struct TCPListener { /* A link in a list of forwards */ struct TCPFwdList { - char* connectaddr; + const unsigned char* connectaddr; unsigned int connectport; unsigned int listenport; struct TCPFwdList * next; @@ -60,6 +60,7 @@ extern const struct ChanType svr_chan_tcpdirect; /* Client */ void setup_localtcp(); +void setup_remotetcp(); extern const struct ChanType cli_chan_tcpremote; /* Common */ |