mirror of
https://github.com/clearml/dropbear
synced 2025-03-12 06:41:20 +00:00
- 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:
parent
2dcd6b22d9
commit
51a74b4799
2
TODO
2
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?
|
||||
|
2
buffer.c
2
buffer.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
* Dropbear SSH
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
|
10
channel.h
10
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
|
||||
#define RECV_MAXWINDOW 4000 /* tweak */
|
||||
#define RECV_WINDOWEXTEND 500 /* 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_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 */
|
||||
|
@ -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();
|
||||
|
138
circbuffer.c
Normal file
138
circbuffer.c
Normal 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
50
circbuffer.h
Normal 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
|
@ -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];
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,13 +389,18 @@ 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,17 +689,15 @@ 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));
|
||||
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
|
||||
* 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;
|
||||
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"));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
3
dbutil.c
3
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 */
|
||||
|
10
includes.h
10
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_ */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
3
tcpfwd.h
3
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user