- added circular buffering for channels

- added stderr support for the client
- cleaned up a bunch of "unused" warnings, duplicated header definitions
- added exit-status support for the client

--HG--
extra : convert_revision : 5bdf806d8b440c87f7235414662f4189195618f4
This commit is contained in:
Matt Johnston 2004-08-26 13:16:40 +00:00
parent 2dcd6b22d9
commit 51a74b4799
19 changed files with 303 additions and 65 deletions

2
TODO
View File

@ -2,6 +2,8 @@ Current:
Things which might need doing: Things which might need doing:
- exit with returned exit codes?
- errfd needs fixing - errfd needs fixing
- Make options.h generated from configure perhaps? - Make options.h generated from configure perhaps?

View File

@ -1,5 +1,5 @@
/* /*
* Dropbear - a SSH2 server * Dropbear SSH
* *
* Copyright (c) 2002,2003 Matt Johnston * Copyright (c) 2002,2003 Matt Johnston
* All rights reserved. * All rights reserved.

View File

@ -45,16 +45,15 @@
/* Not a real type */ /* Not a real type */
#define SSH_OPEN_IN_PROGRESS 99 #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 */ connection, so can't be _too_ small */
#define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */ #define CHAN_EXTEND_SIZE 3 /* how many extra slots to add when we need more */
#define RECV_MAXWINDOW 6000 /* tweak */ #define RECV_MAXWINDOW 4000 /* tweak */
#define RECV_WINDOWEXTEND (RECV_MAXWINDOW/2) /* We send a "window extend" every #define RECV_WINDOWEXTEND 500 /* We send a "window extend" every
RECV_WINDOWEXTEND bytes */ RECV_WINDOWEXTEND bytes */
#define RECV_MAXPACKET 1400 /* tweak */ #define RECV_MAXPACKET RECV_MAXWINDOW /* tweak */
#define RECV_MINWINDOW 19000 /* when we get below this, we send a windowadjust */
struct ChanType; struct ChanType;
@ -63,6 +62,7 @@ struct Channel {
unsigned int index; /* the local channel index */ unsigned int index; /* the local channel index */
unsigned int remotechan; unsigned int remotechan;
unsigned int recvwindow, transwindow; unsigned int recvwindow, transwindow;
unsigned int recvdonelen;
unsigned int recvmaxpacket, transmaxpacket; unsigned int recvmaxpacket, transmaxpacket;
void* typedata; /* a pointer to type specific data */ void* typedata; /* a pointer to type specific data */
int infd; /* data to send over the wire */ int infd; /* data to send over the wire */

View File

@ -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 addnewvar(const char* param, const char* var);
void cli_send_chansess_request(); void cli_send_chansess_request();

138
circbuffer.c Normal file
View File

@ -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;
}

50
circbuffer.h Normal file
View File

@ -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

View File

@ -32,9 +32,11 @@
#include "ssh.h" #include "ssh.h"
#include "runopts.h" #include "runopts.h"
#include "termcodes.h" #include "termcodes.h"
#include "chansession.h"
static void cli_closechansess(struct Channel *channel); static void cli_closechansess(struct Channel *channel);
static int cli_initchansess(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); 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 send_chansess_shell_req(struct Channel *channel);
static void cli_tty_setup(); static void cli_tty_setup();
void cli_tty_cleanup();
const struct ChanType clichansess = { const struct ChanType clichansess = {
0, /* sepfds */ 0, /* sepfds */
"session", /* name */ "session", /* name */
cli_initchansess, /* inithandler */ cli_initchansess, /* inithandler */
NULL, /* checkclosehandler */ NULL, /* checkclosehandler */
NULL, /* reqhandler */ cli_chansessreq, /* reqhandler */
cli_closechansess, /* closehandler */ 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 */ /* 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 */ /* This channel hasn't gone yet, so we have > 1 */
if (ses.chancount > 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; cli_ses.winchange = 1;
@ -317,7 +343,7 @@ static int cli_initchansess(struct Channel *channel) {
channel->infd = STDOUT_FILENO; channel->infd = STDOUT_FILENO;
channel->outfd = STDIN_FILENO; channel->outfd = STDIN_FILENO;
channel->errfd = STDERR_FILENO; channel->errfd = STDERR_FILENO;
channel->extrabuf = buf_new(RECV_MAXWINDOW); channel->extrabuf = cbuf_new(RECV_MAXWINDOW);
if (cli_opts.wantpty) { if (cli_opts.wantpty) {
send_chansess_pty_req(channel); send_chansess_pty_req(channel);

View File

@ -96,7 +96,8 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
exit(exitcode); 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]; char printbuf[1024];

View File

@ -118,6 +118,9 @@ static void cli_session_init() {
cli_ses.stdincopy = dup(STDIN_FILENO); cli_ses.stdincopy = dup(STDIN_FILENO);
cli_ses.stdinflags = fcntl(STDIN_FILENO, F_GETFL, 0); 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 */ /* Auth */
cli_ses.lastpubkey = NULL; cli_ses.lastpubkey = NULL;
cli_ses.lastauthtype = NULL; cli_ses.lastauthtype = NULL;
@ -261,7 +264,7 @@ static void cli_finished() {
common_session_cleanup(); common_session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username, fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport); cli_opts.remotehost, cli_opts.remoteport);
exit(EXIT_SUCCESS); exit(cli_ses.retval);
} }

View File

@ -89,7 +89,7 @@ static int cli_localtcp(unsigned int listenport, const char* remoteaddr,
remoteport)); remoteport));
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*)); tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener*));
tcpinfo->sendaddr = remoteaddr; tcpinfo->sendaddr = m_strdup(remoteaddr);
tcpinfo->sendport = remoteport; tcpinfo->sendport = remoteport;
tcpinfo->listenport = listenport; tcpinfo->listenport = listenport;
tcpinfo->chantype = &cli_chan_tcplocal; tcpinfo->chantype = &cli_chan_tcplocal;

View File

@ -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, static void send_msg_channel_open_confirmation(struct Channel* channel,
unsigned int recvwindow, unsigned int recvwindow,
unsigned int recvmaxpacket); 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, static void send_msg_channel_window_adjust(struct Channel *channel,
unsigned int incr); unsigned int incr);
static void send_msg_channel_data(struct Channel *channel, int isextended, 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->writebuf = cbuf_new(RECV_MAXWINDOW);
newchan->extrabuf = NULL; /* The user code can set it up */ newchan->extrabuf = NULL; /* The user code can set it up */
newchan->recvwindow = RECV_MAXWINDOW; newchan->recvwindow = RECV_MAXWINDOW;
newchan->recvdonelen = 0;
newchan->recvmaxpacket = RECV_MAXPACKET; newchan->recvmaxpacket = RECV_MAXPACKET;
ses.channels[i] = newchan; ses.channels[i] = newchan;
@ -220,7 +221,13 @@ void channelio(fd_set *readfd, fd_set *writefd) {
continue; /* Important not to use the channel after continue; /* Important not to use the channel after
checkinitdone(), as it may be NULL */ 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 */ /* 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. /* 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 * Only called when we know we can write to a channel, writes as much as
* possible */ * possible */
static void writechannel(struct Channel* channel) { static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
int len, maxlen; int len, maxlen;
circbuffer *cbuf;
TRACE(("enter writechannel")); TRACE(("enter writechannel"));
cbuf = channel->writebuf;
maxlen = cbuf_readlen(cbuf); maxlen = cbuf_readlen(cbuf);
TRACE(("maxlen = %d", maxlen));
/* Write the data out */ /* 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) {
if (len < 0 && errno != EINTR) { 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); closeinfd(channel);
} }
TRACE(("leave writechannel: len <= 0")); TRACE(("leave writechannel: len <= 0"));
return; return;
} }
TRACE(("len = %d", len));
cbuf_incrread(cbuf, 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 */ /* Check if we're closing up */
closeinfd(channel); closeinfd(channel);
return; return;
@ -385,13 +389,18 @@ static void writechannel(struct Channel* channel) {
} }
/* Window adjust handling */ /* Window adjust handling */
if (channel->recvwindow < (RECV_MAXWINDOW - RECV_WINDOWEXTEND)) { if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
/* Set it back to max window */ /* Set it back to max window */
send_msg_channel_window_adjust(channel, RECV_MAXWINDOW - send_msg_channel_window_adjust(channel, channel->recvdonelen);
channel->recvwindow); channel->recvwindow += channel->recvdonelen;
channel->recvwindow = RECV_MAXWINDOW; 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")); 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 /* For checking FD status (ie closure etc) - we don't actually
* read data from infd */ * 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) { if (channel->infd >= 0 && channel->infd != channel->outfd) {
FD_SET(channel->infd, readfd); FD_SET(channel->infd, readfd);
} }
@ -435,12 +446,10 @@ void setchannelfds(fd_set *readfd, fd_set *writefd) {
FD_SET(channel->infd, writefd); FD_SET(channel->infd, writefd);
} }
/*
if (channel->extrabuf != NULL && channel->errfd >= 0 if (channel->extrabuf != NULL && channel->errfd >= 0
&& cbuf_getavail(channel->extrabuf) > 0 ) { && cbuf_getused(channel->extrabuf) > 0 ) {
FD_SET(channel->errfd, writefd); FD_SET(channel->errfd, writefd);
} }
*/
} /* foreach channel */ } /* foreach channel */
@ -468,7 +477,9 @@ void recv_msg_channel_eof() {
} }
channel->recveof = 1; 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); closeinfd(channel);
} }
@ -678,17 +689,15 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
datalen = buf_getint(ses.payload); 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); maxdata = cbuf_getavail(cbuf);
TRACE(("maxdata = %d", maxdata));
if (datalen > maxdata) {
TRACE(("Warning: recv_msg_channel_data: extra data past window"));
datalen = 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) {
dropbear_exit("Oversized packet");
}
/* We may have to run throught twice, if the buffer wraps around. Can't /* 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 * just "leave it for next time" like with writechannel, since this
@ -696,18 +705,18 @@ void common_recv_msg_channel_data(struct Channel *channel, int fd,
len = datalen; len = datalen;
while (len > 0) { while (len > 0) {
buflen = cbuf_writelen(cbuf); buflen = cbuf_writelen(cbuf);
TRACE(("buflen = %d", buflen));
buflen = MIN(buflen, len); buflen = MIN(buflen, len);
TRACE(("buflenmin = %d", buflen));
memcpy(cbuf_writeptr(cbuf, buflen), memcpy(cbuf_writeptr(cbuf, buflen),
buf_getptr(ses.payload, buflen), buflen); buf_getptr(ses.payload, buflen), buflen);
cbuf_incrwrite(cbuf, buflen); cbuf_incrwrite(cbuf, buflen);
buf_incrpos(ses.payload, buflen);
len -= buflen; len -= buflen;
TRACE(("len = %d", buflen));
} }
assert(channel->recvwindow > datalen);
channel->recvwindow -= datalen; channel->recvwindow -= datalen;
assert(channel->recvwindow <= RECV_MAXWINDOW);
TRACE(("leave recv_msg_channel_data")); TRACE(("leave recv_msg_channel_data"));
} }

View File

@ -35,6 +35,8 @@
#include "channel.h" #include "channel.h"
#include "atomicio.h" #include "atomicio.h"
static void checktimeouts();
static int ident_readln(int fd, char* buf, int count);
struct sshsession ses; /* GLOBAL */ struct sshsession ses; /* GLOBAL */
@ -46,8 +48,6 @@ int sessinitdone = 0; /* GLOBAL */
int exitflag = 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 */ /* called only at the start of a session, set up initial state */
void common_session_init(int sock, char* remotehost) { void common_session_init(int sock, char* remotehost) {

View File

@ -111,7 +111,7 @@ static void generic_dropbear_exit(int exitcode, const char* format,
exit(exitcode); 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) { va_list param) {
char printbuf[1024]; char printbuf[1024];
@ -146,7 +146,6 @@ void dropbear_trace(const char* format, ...) {
fprintf(stderr, "TRACE: "); fprintf(stderr, "TRACE: ");
vfprintf(stderr, format, param); vfprintf(stderr, format, param);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fflush(stderr);
va_end(param); va_end(param);
} }
#endif /* DEBUG_TRACE */ #endif /* DEBUG_TRACE */

View File

@ -128,4 +128,14 @@ typedef u_int16_t uint16_t;
#define LOG_AUTHPRIV LOG_AUTH #define LOG_AUTHPRIV LOG_AUTH
#endif #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_ */ #endif /* _INCLUDES_H_ */

View File

@ -43,7 +43,6 @@ extern int exitflag;
void common_session_init(int sock, char* remotehost); void common_session_init(int sock, char* remotehost);
void session_loop(void(*loophandler)()); void session_loop(void(*loophandler)());
void common_session_cleanup(); void common_session_cleanup();
void checktimeouts();
void session_identification(); void session_identification();
@ -54,8 +53,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
/* Client */ /* Client */
void cli_session(int sock, char *remotehost); 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 cli_session_cleanup();
void cleantext(unsigned char* dirtytext); void cleantext(unsigned char* dirtytext);
@ -220,6 +217,8 @@ struct clientsession {
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD, int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
for the last type of auth we tried */ for the last type of auth we tried */
struct PubkeyList *lastpubkey; struct PubkeyList *lastpubkey;
int retval; /* What the command exit status was - we emulate it */
#if 0 #if 0
TODO TODO
struct AgentkeyList *agentkeys; /* Keys to use for public-key auth */ struct AgentkeyList *agentkeys; /* Keys to use for public-key auth */

View File

@ -97,7 +97,7 @@ fail:
/* accepts a connection on the forwarded socket and opens a new channel for it /* accepts a connection on the forwarded socket and opens a new channel for it
* back to the client */ * back to the client */
/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ /* 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; int fd;

View File

@ -55,6 +55,10 @@ static int newchansess(struct Channel *channel);
static void chansessionrequest(struct Channel *channel); static void chansessionrequest(struct Channel *channel);
static void send_exitsignalstatus(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 int sesscheckclose(struct Channel *channel);
static void get_termmodes(struct ChanSess *chansess); 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 */ /* 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; int status;
pid_t pid; pid_t pid;
@ -498,7 +502,9 @@ static int sessionpty(struct ChanSess * chansess) {
} }
/* allocate the pty */ /* 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) { if (pty_allocate(&chansess->master, &chansess->slave, namebuf, 64) == 0) {
TRACE(("leave sessionpty: failed to allocate pty")); TRACE(("leave sessionpty: failed to allocate pty"));
return DROPBEAR_FAILURE; return DROPBEAR_FAILURE;

View File

@ -123,7 +123,6 @@ void main_noinetd() {
pid_t childpid; pid_t childpid;
int childpipe[2]; int childpipe[2];
struct sigaction sa_chld;
/* fork */ /* fork */
if (svr_opts.forkbg) { if (svr_opts.forkbg) {
int closefds = 0; int closefds = 0;
@ -303,7 +302,7 @@ void main_noinetd() {
/* catch + reap zombie children */ /* catch + reap zombie children */
static void sigchld_handler(int fish) { static void sigchld_handler(int UNUSED(unused)) {
struct sigaction sa_chld; struct sigaction sa_chld;
while(waitpid(-1, NULL, WNOHANG) > 0); while(waitpid(-1, NULL, WNOHANG) > 0);
@ -316,14 +315,14 @@ static void sigchld_handler(int fish) {
} }
/* catch any segvs */ /* catch any segvs */
static void sigsegv_handler(int fish) { static void sigsegv_handler(int UNUSED(unused)) {
fprintf(stderr, "Aiee, segfault! You should probably report " fprintf(stderr, "Aiee, segfault! You should probably report "
"this as a bug to the developer\n"); "this as a bug to the developer\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* catch ctrl-c or sigterm */ /* catch ctrl-c or sigterm */
static void sigintterm_handler(int fish) { static void sigintterm_handler(int UNUSED(unused)) {
exitflag = 1; exitflag = 1;
} }

View File

@ -47,7 +47,7 @@ struct TCPListener {
/* A link in a list of forwards */ /* A link in a list of forwards */
struct TCPFwdList { struct TCPFwdList {
char* connectaddr; const unsigned char* connectaddr;
unsigned int connectport; unsigned int connectport;
unsigned int listenport; unsigned int listenport;
struct TCPFwdList * next; struct TCPFwdList * next;
@ -60,6 +60,7 @@ extern const struct ChanType svr_chan_tcpdirect;
/* Client */ /* Client */
void setup_localtcp(); void setup_localtcp();
void setup_remotetcp();
extern const struct ChanType cli_chan_tcpremote; extern const struct ChanType cli_chan_tcpremote;
/* Common */ /* Common */