summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--buffer.c2
-rw-r--r--channel.h12
-rw-r--r--chansession.h5
-rw-r--r--circbuffer.c138
-rw-r--r--circbuffer.h50
-rw-r--r--cli-chansession.c36
-rw-r--r--cli-main.c3
-rw-r--r--cli-session.c5
-rw-r--r--cli-tcpfwd.c2
-rw-r--r--common-channel.c67
-rw-r--r--common-session.c4
-rw-r--r--dbutil.c3
-rw-r--r--includes.h10
-rw-r--r--session.h5
-rw-r--r--svr-agentfwd.c2
-rw-r--r--svr-chansession.c10
-rw-r--r--svr-main.c7
-rw-r--r--tcpfwd.h3
19 files changed, 302 insertions, 64 deletions
diff --git a/TODO b/TODO
index 0af56c9..4ac3757 100644
--- a/TODO
+++ b/TODO
@@ -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?
diff --git a/buffer.c b/buffer.c
index df608d9..793eee1 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1,5 +1,5 @@
/*
- * Dropbear - a SSH2 server
+ * Dropbear SSH
*
* Copyright (c) 2002,2003 Matt Johnston
* All rights reserved.
diff --git a/channel.h b/channel.h
index 3afd9f1..8a494c7 100644
--- a/channel.h
+++ b/channel.h
@@ -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);
diff --git a/cli-main.c b/cli-main.c
index 659177e..34a1e42 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -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) {
diff --git a/dbutil.c b/dbutil.c
index 0896bc9..a1ec3ed 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -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 */
diff --git a/includes.h b/includes.h
index b37422b..ceeb561 100644
--- a/includes.h
+++ b/includes.h
@@ -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_ */
diff --git a/session.h b/session.h
index 6afca85..40889a1 100644
--- a/session.h
+++ b/session.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;
diff --git a/svr-main.c b/svr-main.c
index 55c4106..7dc3722 100644
--- a/svr-main.c
+++ b/svr-main.c
@@ -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;
}
diff --git a/tcpfwd.h b/tcpfwd.h
index 569d59d..504a8d3 100644
--- a/tcpfwd.h
+++ b/tcpfwd.h
@@ -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 */