mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
merge
--HG-- branch : coverity
This commit is contained in:
26
CHANGES
26
CHANGES
@@ -1,3 +1,29 @@
|
||||
2014.64 pending
|
||||
|
||||
- Fix compiling with ECDSA and DSS disabled
|
||||
|
||||
- Don't exit abruptly if too many outgoing packets are queued for writev(). Patch
|
||||
thanks to Ronny Meeus
|
||||
|
||||
- The -K keepalive option now behaves more like OpenSSH's "ServerAliveInterval".
|
||||
If no response is received after 3 keepalives then the session is terminated. This
|
||||
will close connections faster than waiting for a TCP timeout.
|
||||
|
||||
- Rework TCP priority setting. New settings are
|
||||
if (connecting || ptys || x11) tos = LOWDELAY
|
||||
else if (tcp_forwards) tos = 0
|
||||
else tos = BULK
|
||||
Thanks to Catalin Patulea for the suggestion.
|
||||
|
||||
- Improve handling of many concurrent new TCP forwarded connections, should now
|
||||
be able to handle as many as MAX_CHANNELS. Thanks to Eduardo Silva for reporting
|
||||
and investigating it.
|
||||
|
||||
- Make sure that exit messages from the client are printed, regression in 2013.57
|
||||
|
||||
- Use monotonic clock where available, timeouts won't be affected by system time
|
||||
changes
|
||||
|
||||
2014.63 - Wednesday 19 February 2014
|
||||
|
||||
- Fix ~. to terminate a client interactive session after waking a laptop
|
||||
|
||||
21
channel.h
21
channel.h
@@ -29,14 +29,6 @@
|
||||
#include "buffer.h"
|
||||
#include "circbuffer.h"
|
||||
|
||||
/* channel->type values */
|
||||
#define CHANNEL_ID_NONE 0
|
||||
#define CHANNEL_ID_SESSION 1
|
||||
#define CHANNEL_ID_X11 2
|
||||
#define CHANNEL_ID_AGENT 3
|
||||
#define CHANNEL_ID_TCPDIRECT 4
|
||||
#define CHANNEL_ID_TCPFORWARDED 5
|
||||
|
||||
#define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED 1
|
||||
#define SSH_OPEN_CONNECT_FAILED 2
|
||||
#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
|
||||
@@ -49,6 +41,13 @@
|
||||
|
||||
struct ChanType;
|
||||
|
||||
enum dropbear_channel_prio {
|
||||
DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */
|
||||
DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */
|
||||
DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */
|
||||
DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */
|
||||
};
|
||||
|
||||
struct Channel {
|
||||
|
||||
unsigned int index; /* the local channel index */
|
||||
@@ -87,6 +86,8 @@ struct Channel {
|
||||
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
|
||||
|
||||
const struct ChanType* type;
|
||||
|
||||
enum dropbear_channel_prio prio;
|
||||
};
|
||||
|
||||
struct ChanType {
|
||||
@@ -97,7 +98,6 @@ struct ChanType {
|
||||
int (*check_close)(struct Channel*);
|
||||
void (*reqhandler)(struct Channel*);
|
||||
void (*closehandler)(struct Channel*);
|
||||
|
||||
};
|
||||
|
||||
void chaninitialise(const struct ChanType *chantypes[]);
|
||||
@@ -129,4 +129,7 @@ void recv_msg_channel_open_confirmation();
|
||||
void recv_msg_channel_open_failure();
|
||||
#endif
|
||||
|
||||
void send_msg_request_success();
|
||||
void send_msg_request_failure();
|
||||
|
||||
#endif /* _CHANNEL_H_ */
|
||||
|
||||
10
cli-auth.c
10
cli-auth.c
@@ -174,11 +174,11 @@ void recv_msg_userauth_failure() {
|
||||
the "none" auth request, and then a response to the immediate auth request.
|
||||
We need to be careful handling them. */
|
||||
if (cli_ses.ignore_next_auth_response) {
|
||||
TRACE(("ignore next response, state set to USERAUTH_REQ_SENT"))
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
cli_ses.ignore_next_auth_response = 0;
|
||||
TRACE(("leave recv_msg_userauth_failure, ignored response, state set to USERAUTH_REQ_SENT"));
|
||||
return;
|
||||
} else {
|
||||
cli_ses.state = USERAUTH_FAIL_RCVD;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||
#ifdef ENABLE_CLI_PUBKEY_AUTH
|
||||
/* If it was a pubkey auth request, we should cross that key
|
||||
* off the list. */
|
||||
@@ -197,10 +197,10 @@ void recv_msg_userauth_failure() {
|
||||
cli_ses.auth_interact_failed = 1;
|
||||
}
|
||||
#endif
|
||||
cli_ses.state = USERAUTH_FAIL_RCVD;
|
||||
cli_ses.lastauthtype = AUTH_TYPE_NONE;
|
||||
}
|
||||
|
||||
cli_ses.ignore_next_auth_response = 0;
|
||||
|
||||
methods = buf_getstring(ses.payload, &methlen);
|
||||
|
||||
partial = buf_getbool(ses.payload);
|
||||
|
||||
@@ -41,7 +41,7 @@ static void cli_chansessreq(struct Channel *channel);
|
||||
static void send_chansess_pty_req(struct Channel *channel);
|
||||
static void send_chansess_shell_req(struct Channel *channel);
|
||||
static void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len);
|
||||
|
||||
static int cli_init_netcat(struct Channel *channel);
|
||||
|
||||
static void cli_tty_setup();
|
||||
|
||||
@@ -357,6 +357,11 @@ static int cli_init_stdpipe_sess(struct Channel *channel) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cli_init_netcat(struct Channel *channel) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
return cli_init_stdpipe_sess(channel);
|
||||
}
|
||||
|
||||
static int cli_initchansess(struct Channel *channel) {
|
||||
|
||||
cli_init_stdpipe_sess(channel);
|
||||
@@ -369,8 +374,9 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
|
||||
if (cli_opts.wantpty) {
|
||||
send_chansess_pty_req(channel);
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||
} else {
|
||||
set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||
}
|
||||
|
||||
send_chansess_shell_req(channel);
|
||||
@@ -389,7 +395,7 @@ static int cli_initchansess(struct Channel *channel) {
|
||||
static const struct ChanType cli_chan_netcat = {
|
||||
0, /* sepfds */
|
||||
"direct-tcpip",
|
||||
cli_init_stdpipe_sess, /* inithandler */
|
||||
cli_init_netcat, /* inithandler */
|
||||
NULL,
|
||||
NULL,
|
||||
cli_closechansess
|
||||
|
||||
@@ -75,9 +75,6 @@ int main(int argc, char ** argv) {
|
||||
int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
0, &error);
|
||||
sock_in = sock_out = sock;
|
||||
if (cli_opts.wantpty) {
|
||||
set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY);
|
||||
}
|
||||
}
|
||||
|
||||
if (sock_in < 0) {
|
||||
@@ -107,9 +104,10 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
|
||||
/* Do the cleanup first, since then the terminal will be reset */
|
||||
session_cleanup();
|
||||
/* Avoid printing onwards from terminal cruft */
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
@@ -121,7 +119,7 @@ static void cli_dropbear_log(int UNUSED(priority),
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
fprintf(stderr, "%s: %s\n", cli_opts.progname, printbuf);
|
||||
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void exec_proxy_cmd(void *user_data_cmd) {
|
||||
|
||||
@@ -163,6 +163,8 @@ void cli_getopts(int argc, char ** argv) {
|
||||
opts.ipv6 = 1;
|
||||
*/
|
||||
opts.recv_window = DEFAULT_RECV_WINDOW;
|
||||
opts.keepalive_secs = DEFAULT_KEEPALIVE;
|
||||
opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
|
||||
|
||||
fill_own_user();
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ static void cli_session_init();
|
||||
static void cli_finished();
|
||||
static void recv_msg_service_accept(void);
|
||||
static void cli_session_cleanup(void);
|
||||
static void recv_msg_global_request_cli(void);
|
||||
|
||||
struct clientsession cli_ses; /* GLOBAL */
|
||||
|
||||
@@ -68,6 +69,7 @@ static const packettype cli_packettypes[] = {
|
||||
{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
|
||||
{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
|
||||
{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
|
||||
{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_cli},
|
||||
#ifdef ENABLE_CLI_REMOTETCPFWD
|
||||
{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
|
||||
{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
|
||||
@@ -366,3 +368,9 @@ void cleantext(unsigned char* dirtytext) {
|
||||
/* Null terminate */
|
||||
dirtytext[j] = '\0';
|
||||
}
|
||||
|
||||
static void recv_msg_global_request_cli(void) {
|
||||
TRACE(("recv_msg_global_request_cli"))
|
||||
/* Send a proper rejection */
|
||||
send_msg_request_failure();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ static int cli_localtcp(const char* listenaddr,
|
||||
static const struct ChanType cli_chan_tcplocal = {
|
||||
1, /* sepfds */
|
||||
"direct-tcpip",
|
||||
NULL,
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
@@ -267,6 +267,8 @@ static int newtcpforwarded(struct Channel * channel) {
|
||||
* progress succeeds */
|
||||
channel->writefd = sock;
|
||||
channel->initconn = 1;
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
|
||||
@@ -174,6 +174,8 @@ static struct Channel* newchannel(unsigned int remotechan,
|
||||
newchan->recvdonelen = 0;
|
||||
newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
|
||||
|
||||
newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */
|
||||
|
||||
ses.channels[i] = newchan;
|
||||
ses.chancount++;
|
||||
|
||||
@@ -208,11 +210,14 @@ struct Channel* getchannel() {
|
||||
/* Iterate through the channels, performing IO if available */
|
||||
void channelio(fd_set *readfds, fd_set *writefds) {
|
||||
|
||||
/* Listeners such as TCP, X11, agent-auth */
|
||||
struct Channel *channel;
|
||||
unsigned int i;
|
||||
|
||||
/* foreach channel */
|
||||
for (i = 0; i < ses.chansize; i++) {
|
||||
/* Close checking only needs to occur for channels that had IO events */
|
||||
int do_check_close = 0;
|
||||
|
||||
channel = ses.channels[i];
|
||||
if (channel == NULL) {
|
||||
@@ -224,6 +229,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
|
||||
if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
|
||||
TRACE(("send normal readfd"))
|
||||
send_msg_channel_data(channel, 0);
|
||||
do_check_close = 1;
|
||||
}
|
||||
|
||||
/* read stderr data and send it over the wire */
|
||||
@@ -231,6 +237,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
|
||||
&& FD_ISSET(channel->errfd, readfds)) {
|
||||
TRACE(("send normal errfd"))
|
||||
send_msg_channel_data(channel, 1);
|
||||
do_check_close = 1;
|
||||
}
|
||||
|
||||
/* write to program/pipe stdin */
|
||||
@@ -242,20 +249,22 @@ void channelio(fd_set *readfds, fd_set *writefds) {
|
||||
check_in_progress(), as it may be NULL */
|
||||
}
|
||||
writechannel(channel, channel->writefd, channel->writebuf);
|
||||
do_check_close = 1;
|
||||
}
|
||||
|
||||
/* stderr for client mode */
|
||||
if (ERRFD_IS_WRITE(channel)
|
||||
&& channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
|
||||
writechannel(channel, channel->errfd, channel->extrabuf);
|
||||
do_check_close = 1;
|
||||
}
|
||||
|
||||
/* handle any channel closing etc */
|
||||
check_close(channel);
|
||||
|
||||
if (do_check_close) {
|
||||
check_close(channel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Listeners such as TCP, X11, agent-auth */
|
||||
#ifdef USING_LISTENERS
|
||||
handle_listeners(readfds);
|
||||
#endif
|
||||
@@ -567,14 +576,16 @@ static void remove_channel(struct Channel * channel) {
|
||||
}
|
||||
|
||||
|
||||
/* close the FDs in case they haven't been done
|
||||
* yet (they might have been shutdown etc) */
|
||||
TRACE(("CLOSE writefd %d", channel->writefd))
|
||||
close(channel->writefd);
|
||||
TRACE(("CLOSE readfd %d", channel->readfd))
|
||||
close(channel->readfd);
|
||||
TRACE(("CLOSE errfd %d", channel->errfd))
|
||||
close(channel->errfd);
|
||||
if (IS_DROPBEAR_SERVER || (channel->writefd != STDOUT_FILENO)) {
|
||||
/* close the FDs in case they haven't been done
|
||||
* yet (they might have been shutdown etc) */
|
||||
TRACE(("CLOSE writefd %d", channel->writefd))
|
||||
close(channel->writefd);
|
||||
TRACE(("CLOSE readfd %d", channel->readfd))
|
||||
close(channel->readfd);
|
||||
TRACE(("CLOSE errfd %d", channel->errfd))
|
||||
close(channel->errfd);
|
||||
}
|
||||
|
||||
if (!channel->close_handler_done
|
||||
&& channel->type->closehandler) {
|
||||
@@ -586,6 +597,8 @@ static void remove_channel(struct Channel * channel) {
|
||||
m_free(channel);
|
||||
ses.chancount--;
|
||||
|
||||
update_channel_prio();
|
||||
|
||||
TRACE(("leave remove_channel"))
|
||||
}
|
||||
|
||||
@@ -876,6 +889,10 @@ void recv_msg_channel_open() {
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||
}
|
||||
|
||||
chan_initwritebuf(channel);
|
||||
|
||||
/* success */
|
||||
@@ -889,6 +906,8 @@ failure:
|
||||
|
||||
cleanup:
|
||||
m_free(type);
|
||||
|
||||
update_channel_prio();
|
||||
|
||||
TRACE(("leave recv_msg_channel_open"))
|
||||
}
|
||||
@@ -1004,7 +1023,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
|
||||
* for X11, agent, tcp forwarding, and should be filled with channel-specific
|
||||
* options, with the calling function calling encrypt_packet() after
|
||||
* completion. It is mandatory for the caller to encrypt_packet() if
|
||||
* DROPBEAR_SUCCESS is returned */
|
||||
* a channel is returned. NULL is returned on failure. */
|
||||
int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
||||
|
||||
struct Channel* chan;
|
||||
@@ -1073,6 +1092,10 @@ void recv_msg_channel_open_confirmation() {
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||
}
|
||||
update_channel_prio();
|
||||
|
||||
TRACE(("leave recv_msg_channel_open_confirmation"))
|
||||
}
|
||||
@@ -1092,3 +1115,15 @@ void recv_msg_channel_open_failure() {
|
||||
remove_channel(channel);
|
||||
}
|
||||
#endif /* USING_LISTENERS */
|
||||
|
||||
void send_msg_request_success() {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
|
||||
encrypt_packet();
|
||||
}
|
||||
|
||||
void send_msg_request_failure() {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
|
||||
encrypt_packet();
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ static void kexinitialise() {
|
||||
|
||||
ses.kexstate.our_first_follows_matches = 0;
|
||||
|
||||
ses.kexstate.lastkextime = time(NULL);
|
||||
ses.kexstate.lastkextime = monotonic_now();
|
||||
|
||||
}
|
||||
|
||||
|
||||
127
common-session.c
127
common-session.c
@@ -51,6 +51,7 @@ int exitflag = 0; /* GLOBAL */
|
||||
|
||||
/* called only at the start of a session, set up initial state */
|
||||
void common_session_init(int sock_in, int sock_out) {
|
||||
time_t now;
|
||||
|
||||
TRACE(("enter session_init"))
|
||||
|
||||
@@ -58,9 +59,15 @@ void common_session_init(int sock_in, int sock_out) {
|
||||
ses.sock_out = sock_out;
|
||||
ses.maxfd = MAX(sock_in, sock_out);
|
||||
|
||||
ses.connect_time = 0;
|
||||
ses.last_trx_packet_time = 0;
|
||||
ses.last_packet_time = 0;
|
||||
ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
|
||||
/* Sets it to lowdelay */
|
||||
update_channel_prio();
|
||||
|
||||
now = monotonic_now();
|
||||
ses.last_packet_time_keepalive_recv = now;
|
||||
ses.last_packet_time_idle = now;
|
||||
ses.last_packet_time_any_sent = 0;
|
||||
ses.last_packet_time_keepalive_sent = 0;
|
||||
|
||||
if (pipe(ses.signal_pipe) < 0) {
|
||||
dropbear_exit("Signal pipe failed");
|
||||
@@ -186,13 +193,7 @@ void session_loop(void(*loophandler)()) {
|
||||
/* check for auth timeout, rekeying required etc */
|
||||
checktimeouts();
|
||||
|
||||
/* process session socket's incoming/outgoing data */
|
||||
if (ses.sock_out != -1) {
|
||||
if (FD_ISSET(ses.sock_out, &writefd) && !isempty(&ses.writequeue)) {
|
||||
write_packet();
|
||||
}
|
||||
}
|
||||
|
||||
/* process session socket's incoming data */
|
||||
if (ses.sock_in != -1) {
|
||||
if (FD_ISSET(ses.sock_in, &readfd)) {
|
||||
if (!ses.remoteident) {
|
||||
@@ -218,6 +219,14 @@ void session_loop(void(*loophandler)()) {
|
||||
* during rekeying ) */
|
||||
channelio(&readfd, &writefd);
|
||||
|
||||
/* process session socket's outgoing data */
|
||||
if (ses.sock_out != -1) {
|
||||
if (!isempty(&ses.writequeue)) {
|
||||
write_packet();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (loophandler) {
|
||||
loophandler();
|
||||
}
|
||||
@@ -385,11 +394,21 @@ static int ident_readln(int fd, char* buf, int count) {
|
||||
return pos+1;
|
||||
}
|
||||
|
||||
void send_msg_ignore() {
|
||||
static void send_msg_keepalive() {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_IGNORE);
|
||||
buf_putstring(ses.writepayload, "", 0);
|
||||
time_t old_time_idle = ses.last_packet_time_idle;
|
||||
/* Try to force a response from the other end. Some peers will
|
||||
reply with SSH_MSG_REQUEST_FAILURE, some will reply with SSH_MSG_UNIMPLEMENTED */
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
|
||||
/* A short string */
|
||||
buf_putstring(ses.writepayload, "k@dropbear.nl", 0);
|
||||
buf_putbyte(ses.writepayload, 1); /* want_reply */
|
||||
encrypt_packet();
|
||||
|
||||
ses.last_packet_time_keepalive_sent = monotonic_now();
|
||||
|
||||
/* keepalives shouldn't update idle timeout, reset it back */
|
||||
ses.last_packet_time_idle = old_time_idle;
|
||||
}
|
||||
|
||||
/* Check all timeouts which are required. Currently these are the time for
|
||||
@@ -397,13 +416,8 @@ void send_msg_ignore() {
|
||||
static void checktimeouts() {
|
||||
|
||||
time_t now;
|
||||
|
||||
now = time(NULL);
|
||||
now = monotonic_now();
|
||||
|
||||
if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
|
||||
dropbear_close("Timeout before auth");
|
||||
}
|
||||
|
||||
/* we can't rekey if we haven't done remote ident exchange yet */
|
||||
if (ses.remoteident == NULL) {
|
||||
return;
|
||||
@@ -416,13 +430,27 @@ static void checktimeouts() {
|
||||
send_msg_kexinit();
|
||||
}
|
||||
|
||||
if (opts.keepalive_secs > 0
|
||||
&& now - ses.last_trx_packet_time >= opts.keepalive_secs) {
|
||||
send_msg_ignore();
|
||||
if (opts.keepalive_secs > 0) {
|
||||
/* Send keepalives if we've been idle */
|
||||
if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
|
||||
send_msg_keepalive();
|
||||
}
|
||||
|
||||
/* Also send an explicit keepalive message to trigger a response
|
||||
if the remote end hasn't sent us anything */
|
||||
if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs
|
||||
&& now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) {
|
||||
send_msg_keepalive();
|
||||
}
|
||||
|
||||
if (now - ses.last_packet_time_keepalive_recv
|
||||
>= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) {
|
||||
dropbear_exit("Keepalive timeout");
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.idle_timeout_secs > 0 && ses.last_packet_time > 0
|
||||
&& now - ses.last_packet_time >= opts.idle_timeout_secs) {
|
||||
if (opts.idle_timeout_secs > 0
|
||||
&& now - ses.last_packet_time_idle >= opts.idle_timeout_secs) {
|
||||
dropbear_close("Idle timeout");
|
||||
}
|
||||
}
|
||||
@@ -433,12 +461,13 @@ static long select_timeout() {
|
||||
long ret = LONG_MAX;
|
||||
if (KEX_REKEY_TIMEOUT > 0)
|
||||
ret = MIN(KEX_REKEY_TIMEOUT, ret);
|
||||
if (AUTH_TIMEOUT > 0)
|
||||
/* AUTH_TIMEOUT is only relevant before authdone */
|
||||
if (ses.authstate.authdone != 1 && AUTH_TIMEOUT > 0)
|
||||
ret = MIN(AUTH_TIMEOUT, ret);
|
||||
if (opts.keepalive_secs > 0)
|
||||
ret = MIN(opts.keepalive_secs, ret);
|
||||
if (opts.idle_timeout_secs > 0)
|
||||
ret = MIN(opts.idle_timeout_secs, ret);
|
||||
if (opts.idle_timeout_secs > 0)
|
||||
ret = MIN(opts.idle_timeout_secs, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -487,3 +516,47 @@ void fill_passwd(const char* username) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when channels are modified */
|
||||
void update_channel_prio() {
|
||||
enum dropbear_prio new_prio;
|
||||
int any = 0;
|
||||
unsigned int i;
|
||||
|
||||
TRACE(("update_channel_prio"))
|
||||
|
||||
new_prio = DROPBEAR_PRIO_BULK;
|
||||
for (i = 0; i < ses.chansize; i++) {
|
||||
struct Channel *channel = ses.channels[i];
|
||||
if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||
if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||
TRACE(("update_channel_prio: early %d", channel->index))
|
||||
}
|
||||
continue;
|
||||
}
|
||||
any = 1;
|
||||
if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE)
|
||||
{
|
||||
TRACE(("update_channel_prio: lowdelay %d", channel->index))
|
||||
new_prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
break;
|
||||
} else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE
|
||||
&& new_prio == DROPBEAR_PRIO_BULK)
|
||||
{
|
||||
TRACE(("update_channel_prio: unknowable %d", channel->index))
|
||||
new_prio = DROPBEAR_PRIO_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
if (any == 0) {
|
||||
/* lowdelay during setup */
|
||||
TRACE(("update_channel_prio: not any"))
|
||||
new_prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
}
|
||||
|
||||
if (new_prio != ses.socket_prio) {
|
||||
TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio))
|
||||
set_sock_priority(ses.sock_out, new_prio);
|
||||
ses.socket_prio = new_prio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -361,6 +361,10 @@ AC_CHECK_FUNCS(endutxent getutxent getutxid getutxline pututxline )
|
||||
AC_CHECK_FUNCS(setutxent utmpxname)
|
||||
AC_CHECK_FUNCS(logout updwtmp logwtmp)
|
||||
|
||||
# OS X monotonic time
|
||||
AC_CHECK_HEADERS([mach/mach_time.h])
|
||||
AC_CHECK_FUNCS(mach_absolute_time)
|
||||
|
||||
AC_ARG_ENABLE(bundled-libtom,
|
||||
[ --enable-bundled-libtom Force using bundled libtomcrypt/libtommath even if a system version exists.
|
||||
--disable-bundled-libtom Force using system libtomcrypt/libtommath, fail if it does not exist.
|
||||
|
||||
45
dbutil.c
45
dbutil.c
@@ -48,6 +48,19 @@
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#define _GNU_SOURCE
|
||||
/* To call clock_gettime() directly */
|
||||
#include <sys/syscall.h>
|
||||
#endif /* __linux */
|
||||
|
||||
#ifdef HAVE_MACH_MACH_TIME_H
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
@@ -319,7 +332,7 @@ int dropbear_listen(const char* address, const char* port,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (listen(sock, 20) < 0) {
|
||||
if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) {
|
||||
err = errno;
|
||||
close(sock);
|
||||
TRACE(("listen() failed"))
|
||||
@@ -932,3 +945,33 @@ int constant_time_memcmp(const void* a, const void *b, size_t n)
|
||||
return c;
|
||||
}
|
||||
|
||||
time_t monotonic_now() {
|
||||
|
||||
#if defined(__linux__) && defined(SYS_clock_gettime)
|
||||
/* CLOCK_MONOTONIC_COARSE was added in Linux 2.6.32. Probably cheaper. */
|
||||
#ifndef CLOCK_MONOTONIC_COARSE
|
||||
#define CLOCK_MONOTONIC_COARSE 6
|
||||
#endif
|
||||
static clockid_t clock_source = CLOCK_MONOTONIC_COARSE;
|
||||
struct timespec ts;
|
||||
|
||||
if (syscall(SYS_clock_gettime, clock_source, &ts) == EINVAL) {
|
||||
clock_source = CLOCK_MONOTONIC;
|
||||
syscall(SYS_clock_gettime, CLOCK_MONOTONIC, &ts);
|
||||
}
|
||||
return ts.tv_sec;
|
||||
#elif defined(HAVE_MACH_ABSOLUTE_TIME)
|
||||
/* OS X, see https://developer.apple.com/library/mac/qa/qa1398/_index.html */
|
||||
static mach_timebase_info_data_t timebase_info;
|
||||
if (timebase_info.denom == 0) {
|
||||
mach_timebase_info(&timebase_info);
|
||||
}
|
||||
return mach_absolute_time() * timebase_info.numer / timebase_info.denom
|
||||
/ 1e9;
|
||||
#else
|
||||
/* Fallback for everything else - this will sometimes go backwards */
|
||||
return time(NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
11
dbutil.h
11
dbutil.h
@@ -62,9 +62,9 @@ extern int debug_trace;
|
||||
#endif
|
||||
|
||||
enum dropbear_prio {
|
||||
DROPBEAR_PRIO_DEFAULT,
|
||||
DROPBEAR_PRIO_LOWDELAY,
|
||||
DROPBEAR_PRIO_BULK,
|
||||
DROPBEAR_PRIO_DEFAULT = 'dffd',
|
||||
DROPBEAR_PRIO_LOWDELAY = 'lddl',
|
||||
DROPBEAR_PRIO_BULK = 'bllb',
|
||||
};
|
||||
|
||||
char * stripcontrol(const char * text);
|
||||
@@ -106,4 +106,9 @@ int m_str_to_uint(const char* str, unsigned int *val);
|
||||
/* Returns 0 if a and b have the same contents */
|
||||
int constant_time_memcmp(const void* a, const void *b, size_t n);
|
||||
|
||||
/* Returns a time in seconds that doesn't go backwards - does not correspond to
|
||||
a real-world clock */
|
||||
time_t monotonic_now();
|
||||
|
||||
|
||||
#endif /* _DBUTIL_H_ */
|
||||
|
||||
16
keyimport.c
16
keyimport.c
@@ -602,13 +602,18 @@ static sign_key *openssh_read(const char *filename, char * UNUSED(passphrase))
|
||||
*/
|
||||
blobbuf = buf_new(3000);
|
||||
|
||||
#ifdef DROPBEAR_DSS
|
||||
if (key->type == OSSH_DSA) {
|
||||
buf_putstring(blobbuf, "ssh-dss", 7);
|
||||
retkey->type = DROPBEAR_SIGNKEY_DSS;
|
||||
} else if (key->type == OSSH_RSA) {
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_RSA
|
||||
if (key->type == OSSH_RSA) {
|
||||
buf_putstring(blobbuf, "ssh-rsa", 7);
|
||||
retkey->type = DROPBEAR_SIGNKEY_RSA;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < num_integers; i++) {
|
||||
ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,
|
||||
@@ -831,7 +836,14 @@ static int openssh_write(const char *filename, sign_key *key,
|
||||
mp_int dmp1, dmq1, iqmp, tmpval; /* for rsa */
|
||||
#endif
|
||||
|
||||
if (key->type == DROPBEAR_SIGNKEY_RSA || key->type == DROPBEAR_SIGNKEY_DSS)
|
||||
if (
|
||||
#ifdef DROPBEAR_RSA
|
||||
key->type == DROPBEAR_SIGNKEY_RSA ||
|
||||
#endif
|
||||
#ifdef DROPBEAR_DSS
|
||||
key->type == DROPBEAR_SIGNKEY_DSS ||
|
||||
#endif
|
||||
0)
|
||||
{
|
||||
/*
|
||||
* Fetch the key blobs.
|
||||
|
||||
@@ -308,6 +308,11 @@ much traffic. */
|
||||
be overridden at runtime with -K. 0 disables keepalives */
|
||||
#define DEFAULT_KEEPALIVE 0
|
||||
|
||||
/* If this many KEEPALIVES are sent with no packets received from the
|
||||
other side, exit. Not run-time configurable - if you have a need
|
||||
for runtime configuration please mail the Dropbear list */
|
||||
#define DEFAULT_KEEPALIVE_LIMIT 3
|
||||
|
||||
/* Ensure that data is received within IDLE_TIMEOUT seconds. This can
|
||||
be overridden at runtime with -I. 0 disables idle timeouts */
|
||||
#define DEFAULT_IDLE_TIMEOUT 0
|
||||
|
||||
57
packet.c
57
packet.c
@@ -57,42 +57,52 @@ void write_packet() {
|
||||
|
||||
int len, written;
|
||||
buffer * writebuf = NULL;
|
||||
time_t now;
|
||||
unsigned packet_type;
|
||||
int all_ignore = 1;
|
||||
#ifdef HAVE_WRITEV
|
||||
struct iovec *iov = NULL;
|
||||
int i;
|
||||
struct Link *l;
|
||||
int iov_max_count;
|
||||
#endif
|
||||
|
||||
TRACE2(("enter write_packet"))
|
||||
dropbear_assert(!isempty(&ses.writequeue));
|
||||
|
||||
#ifdef HAVE_WRITEV
|
||||
iov = m_malloc(sizeof(*iov) * ses.writequeue.count);
|
||||
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
|
||||
|
||||
#ifndef IOV_MAX
|
||||
#define IOV_MAX UIO_MAXIOV
|
||||
#endif
|
||||
|
||||
/* Make sure the size of the iov is below the maximum allowed by the OS. */
|
||||
iov_max_count = ses.writequeue.count;
|
||||
if (iov_max_count > IOV_MAX)
|
||||
{
|
||||
iov_max_count = IOV_MAX;
|
||||
}
|
||||
|
||||
iov = m_malloc(sizeof(*iov) * iov_max_count);
|
||||
for (l = ses.writequeue.head, i = 0; l; l = l->link, i++)
|
||||
{
|
||||
writebuf = (buffer*)l->item;
|
||||
packet_type = writebuf->data[writebuf->len-1];
|
||||
len = writebuf->len - 1 - writebuf->pos;
|
||||
dropbear_assert(len > 0);
|
||||
all_ignore &= (packet_type == SSH_MSG_IGNORE);
|
||||
TRACE2(("write_packet writev #%d type %d len %d/%d", i, packet_type,
|
||||
len, writebuf->len-1))
|
||||
iov[i].iov_base = buf_getptr(writebuf, len);
|
||||
iov[i].iov_len = len;
|
||||
}
|
||||
written = writev(ses.sock_out, iov, ses.writequeue.count);
|
||||
written = writev(ses.sock_out, iov, iov_max_count);
|
||||
if (written < 0) {
|
||||
if (errno == EINTR) {
|
||||
m_free(iov);
|
||||
TRACE2(("leave writepacket: EINTR"))
|
||||
TRACE2(("leave write_packet: EINTR"))
|
||||
return;
|
||||
} else {
|
||||
dropbear_exit("Error writing");
|
||||
dropbear_exit("Error writing: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (written == 0) {
|
||||
ses.remoteclosed();
|
||||
@@ -113,8 +123,7 @@ void write_packet() {
|
||||
}
|
||||
|
||||
m_free(iov);
|
||||
|
||||
#else
|
||||
#else /* No writev () */
|
||||
/* Get the next buffer in the queue of encrypted packets to write*/
|
||||
writebuf = (buffer*)examine(&ses.writequeue);
|
||||
|
||||
@@ -131,10 +140,9 @@ void write_packet() {
|
||||
TRACE2(("leave writepacket: EINTR"))
|
||||
return;
|
||||
} else {
|
||||
dropbear_exit("Error writing");
|
||||
dropbear_exit("Error writing: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
all_ignore = (packet_type == SSH_MSG_IGNORE);
|
||||
|
||||
if (written == 0) {
|
||||
ses.remoteclosed();
|
||||
@@ -149,14 +157,7 @@ void write_packet() {
|
||||
/* More packet left to write, leave it in the queue for later */
|
||||
buf_incrpos(writebuf, written);
|
||||
}
|
||||
|
||||
#endif
|
||||
now = time(NULL);
|
||||
ses.last_trx_packet_time = now;
|
||||
|
||||
if (!all_ignore) {
|
||||
ses.last_packet_time = now;
|
||||
}
|
||||
#endif /* writev */
|
||||
|
||||
TRACE2(("leave write_packet"))
|
||||
}
|
||||
@@ -503,6 +504,8 @@ void encrypt_packet() {
|
||||
unsigned char packet_type;
|
||||
unsigned int len, encrypt_buf_size;
|
||||
unsigned char mac_bytes[MAX_MAC_LEN];
|
||||
|
||||
time_t now;
|
||||
|
||||
TRACE2(("enter encrypt_packet()"))
|
||||
|
||||
@@ -610,6 +613,18 @@ void encrypt_packet() {
|
||||
ses.kexstate.datatrans += writebuf->len;
|
||||
ses.transseq++;
|
||||
|
||||
now = monotonic_now();
|
||||
ses.last_packet_time_any_sent = now;
|
||||
/* idle timeout shouldn't be affected by responses to keepalives.
|
||||
send_msg_keepalive() itself also does tricks with
|
||||
ses.last_packet_idle_time - read that if modifying this code */
|
||||
if (packet_type != SSH_MSG_REQUEST_FAILURE
|
||||
&& packet_type != SSH_MSG_UNIMPLEMENTED
|
||||
&& packet_type != SSH_MSG_IGNORE) {
|
||||
ses.last_packet_time_idle = now;
|
||||
|
||||
}
|
||||
|
||||
TRACE2(("leave encrypt_packet()"))
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ void process_packet() {
|
||||
|
||||
unsigned char type;
|
||||
unsigned int i;
|
||||
time_t now;
|
||||
|
||||
TRACE2(("enter process_packet"))
|
||||
|
||||
@@ -52,7 +53,8 @@ void process_packet() {
|
||||
|
||||
ses.lastpacket = type;
|
||||
|
||||
ses.last_packet_time = time(NULL);
|
||||
now = monotonic_now();
|
||||
ses.last_packet_time_keepalive_recv = now;
|
||||
|
||||
/* These packets we can receive at any time */
|
||||
switch(type) {
|
||||
@@ -65,13 +67,21 @@ void process_packet() {
|
||||
case SSH_MSG_UNIMPLEMENTED:
|
||||
/* debugging XXX */
|
||||
TRACE(("SSH_MSG_UNIMPLEMENTED"))
|
||||
dropbear_exit("Received SSH_MSG_UNIMPLEMENTED");
|
||||
goto out;
|
||||
|
||||
case SSH_MSG_DISCONNECT:
|
||||
/* TODO cleanup? */
|
||||
dropbear_close("Disconnect received");
|
||||
}
|
||||
|
||||
/* Ignore these packet types so that keepalives don't interfere with
|
||||
idle detection. This is slightly incorrect since a tcp forwarded
|
||||
global request with failure won't trigger the idle timeout,
|
||||
but that's probably acceptable */
|
||||
if (!(type == SSH_MSG_GLOBAL_REQUEST || type == SSH_MSG_REQUEST_FAILURE)) {
|
||||
ses.last_packet_time_idle = now;
|
||||
}
|
||||
|
||||
/* This applies for KEX, where the spec says the next packet MUST be
|
||||
* NEWKEYS */
|
||||
if (ses.requirenext != 0) {
|
||||
|
||||
@@ -37,8 +37,8 @@ typedef struct runopts {
|
||||
int listen_fwd_all;
|
||||
#endif
|
||||
unsigned int recv_window;
|
||||
time_t keepalive_secs;
|
||||
time_t idle_timeout_secs;
|
||||
time_t keepalive_secs; /* Time between sending keepalives. 0 is off */
|
||||
time_t idle_timeout_secs; /* Exit if no traffic is sent/received in this time */
|
||||
|
||||
#ifndef DISABLE_ZLIB
|
||||
/* TODO: add a commandline flag. Currently this is on by default if compression
|
||||
|
||||
26
session.h
26
session.h
@@ -48,6 +48,8 @@ void session_cleanup();
|
||||
void send_session_identification();
|
||||
void send_msg_ignore();
|
||||
|
||||
void update_channel_prio();
|
||||
|
||||
const char* get_user_shell();
|
||||
void fill_passwd(const char* username);
|
||||
|
||||
@@ -104,10 +106,6 @@ struct sshsession {
|
||||
/* Is it a client or server? */
|
||||
unsigned char isserver;
|
||||
|
||||
time_t connect_time; /* time the connection was established
|
||||
(cleared after auth once we're not
|
||||
respecting AUTH_TIMEOUT any more) */
|
||||
|
||||
int sock_in;
|
||||
int sock_out;
|
||||
|
||||
@@ -146,11 +144,14 @@ struct sshsession {
|
||||
int signal_pipe[2]; /* stores endpoints of a self-pipe used for
|
||||
race-free signal handling */
|
||||
|
||||
time_t last_trx_packet_time; /* time of the last packet transmission, for
|
||||
keepalive purposes */
|
||||
/* time of the last packet send/receive, for keepalive. Not real-world clock */
|
||||
time_t last_packet_time_keepalive_sent;
|
||||
time_t last_packet_time_keepalive_recv;
|
||||
time_t last_packet_time_any_sent;
|
||||
|
||||
time_t last_packet_time; /* time of the last packet transmission or receive, for
|
||||
idle timeout purposes */
|
||||
time_t last_packet_time_idle; /* time of the last packet transmission or receive, for
|
||||
idle timeout purposes so ignores SSH_MSG_IGNORE
|
||||
or responses to keepalives. Not real-world clock */
|
||||
|
||||
|
||||
/* KEX/encryption related */
|
||||
@@ -187,7 +188,9 @@ struct sshsession {
|
||||
unsigned int chancount; /* the number of Channel*s in use */
|
||||
const struct ChanType **chantypes; /* The valid channel types */
|
||||
|
||||
|
||||
/* TCP priority level for the main "port 22" tcp socket */
|
||||
enum dropbear_prio socket_prio;
|
||||
|
||||
/* TCP forwarding - where manage listeners */
|
||||
struct Listener ** listeners;
|
||||
unsigned int listensize;
|
||||
@@ -217,6 +220,11 @@ struct serversession {
|
||||
/* The resolved remote address, used for lastlog etc */
|
||||
char *remotehost;
|
||||
|
||||
time_t connect_time; /* time the connection was established
|
||||
(cleared after auth once we're not
|
||||
respecting AUTH_TIMEOUT any more).
|
||||
A monotonic time, not realworld */
|
||||
|
||||
#ifdef USE_VFORK
|
||||
pid_t server_pid;
|
||||
#endif
|
||||
|
||||
@@ -106,6 +106,7 @@ enum signkey_type signkey_type_from_name(const char* name, unsigned int namelen)
|
||||
void **
|
||||
signkey_key_ptr(sign_key *key, enum signkey_type type) {
|
||||
switch (type) {
|
||||
#ifdef DROPBEAR_ECDSA
|
||||
#ifdef DROPBEAR_ECC_256
|
||||
case DROPBEAR_SIGNKEY_ECDSA_NISTP256:
|
||||
return (void**)&key->ecckey256;
|
||||
@@ -118,6 +119,7 @@ signkey_key_ptr(sign_key *key, enum signkey_type type) {
|
||||
case DROPBEAR_SIGNKEY_ECDSA_NISTP521:
|
||||
return (void**)&key->ecckey521;
|
||||
#endif
|
||||
#endif /* DROPBEAR_ECDSA */
|
||||
#ifdef DROPBEAR_RSA
|
||||
case DROPBEAR_SIGNKEY_RSA:
|
||||
return (void**)&key->rsakey;
|
||||
|
||||
@@ -392,8 +392,7 @@ void send_msg_userauth_success() {
|
||||
/* authdone must be set after encrypt_packet() for
|
||||
* delayed-zlib mode */
|
||||
ses.authstate.authdone = 1;
|
||||
ses.connect_time = 0;
|
||||
|
||||
svr_ses.connect_time = 0;
|
||||
|
||||
if (ses.authstate.pw_uid == 0) {
|
||||
ses.allowprivport = 1;
|
||||
|
||||
@@ -253,6 +253,8 @@ static int newchansess(struct Channel *channel) {
|
||||
chansess->agentdir = NULL;
|
||||
#endif
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -668,8 +670,11 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
||||
|
||||
if (chansess->term == NULL) {
|
||||
/* no pty */
|
||||
set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
|
||||
ret = noptycommand(channel, chansess);
|
||||
if (ret == DROPBEAR_SUCCESS) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||
update_channel_prio();
|
||||
}
|
||||
} else {
|
||||
/* want pty */
|
||||
ret = ptycommand(channel, chansess);
|
||||
|
||||
@@ -80,12 +80,22 @@ svr_session_cleanup(void)
|
||||
svr_pubkey_options_cleanup();
|
||||
}
|
||||
|
||||
static void
|
||||
svr_sessionloop() {
|
||||
if (svr_ses.connect_time != 0
|
||||
&& monotonic_now() - svr_ses.connect_time >= AUTH_TIMEOUT) {
|
||||
dropbear_close("Timeout before auth");
|
||||
}
|
||||
}
|
||||
|
||||
void svr_session(int sock, int childpipe) {
|
||||
char *host, *port;
|
||||
size_t len;
|
||||
|
||||
common_session_init(sock, sock);
|
||||
|
||||
svr_ses.connect_time = monotonic_now();;
|
||||
|
||||
/* Initialise server specific parts of the session */
|
||||
svr_ses.childpipe = childpipe;
|
||||
#ifdef USE_VFORK
|
||||
@@ -95,8 +105,6 @@ void svr_session(int sock, int childpipe) {
|
||||
chaninitialise(svr_chantypes);
|
||||
svr_chansessinitialise();
|
||||
|
||||
ses.connect_time = time(NULL);
|
||||
|
||||
/* for logging the remote address */
|
||||
get_socket_address(ses.sock_in, NULL, NULL, &host, &port, 0);
|
||||
len = strlen(host) + strlen(port) + 2;
|
||||
@@ -128,7 +136,7 @@ void svr_session(int sock, int childpipe) {
|
||||
|
||||
/* Run the main for loop. NULL is for the dispatcher - only the client
|
||||
* code makes use of it */
|
||||
session_loop(NULL);
|
||||
session_loop(svr_sessionloop);
|
||||
|
||||
/* Not reached */
|
||||
|
||||
|
||||
24
svr-tcpfwd.c
24
svr-tcpfwd.c
@@ -34,14 +34,6 @@
|
||||
#include "runopts.h"
|
||||
#include "auth.h"
|
||||
|
||||
static void send_msg_request_failure();
|
||||
|
||||
static void send_msg_request_failure() {
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
|
||||
encrypt_packet();
|
||||
}
|
||||
|
||||
#ifndef ENABLE_SVR_REMOTETCPFWD
|
||||
|
||||
/* This is better than SSH_MSG_UNIMPLEMENTED */
|
||||
@@ -53,7 +45,6 @@ void recv_msg_global_request_remotetcp() {
|
||||
/* */
|
||||
#endif /* !ENABLE_SVR_REMOTETCPFWD */
|
||||
|
||||
static void send_msg_request_success();
|
||||
static int svr_cancelremotetcp();
|
||||
static int svr_remotetcpreq();
|
||||
static int newtcpdirect(struct Channel * channel);
|
||||
@@ -62,7 +53,7 @@ static int newtcpdirect(struct Channel * channel);
|
||||
static const struct ChanType svr_chan_tcpremote = {
|
||||
1, /* sepfds */
|
||||
"forwarded-tcpip",
|
||||
NULL,
|
||||
tcp_prio_inithandler,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
@@ -115,15 +106,6 @@ out:
|
||||
TRACE(("leave recv_msg_global_request"))
|
||||
}
|
||||
|
||||
|
||||
static void send_msg_request_success() {
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
|
||||
encrypt_packet();
|
||||
|
||||
}
|
||||
|
||||
static int matchtcp(void* typedata1, void* typedata2) {
|
||||
|
||||
const struct TCPListener *info1 = (struct TCPListener*)typedata1;
|
||||
@@ -258,6 +240,8 @@ static int newtcpdirect(struct Channel * channel) {
|
||||
int len;
|
||||
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
||||
|
||||
TRACE(("newtcpdirect channel %d", channel->index))
|
||||
|
||||
if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {
|
||||
TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
|
||||
goto out;
|
||||
@@ -299,6 +283,8 @@ static int newtcpdirect(struct Channel * channel) {
|
||||
* progress succeeds */
|
||||
channel->writefd = sock;
|
||||
channel->initconn = 1;
|
||||
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
|
||||
err = SSH_OPEN_IN_PROGRESS;
|
||||
|
||||
|
||||
@@ -182,10 +182,15 @@ void x11cleanup(struct ChanSess *chansess) {
|
||||
}
|
||||
}
|
||||
|
||||
static int x11_inithandler(struct Channel *channel) {
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ChanType chan_x11 = {
|
||||
0, /* sepfds */
|
||||
"x11",
|
||||
NULL, /* inithandler */
|
||||
x11_inithandler, /* inithandler */
|
||||
NULL, /* checkclose */
|
||||
NULL, /* reqhandler */
|
||||
NULL /* closehandler */
|
||||
|
||||
@@ -251,4 +251,10 @@
|
||||
#define USE_VFORK
|
||||
#endif /* don't HAVE_FORK */
|
||||
|
||||
#if MAX_UNAUTH_CLIENTS > MAX_CHANNELS
|
||||
#define DROPBEAR_LISTEN_BACKLOG MAX_UNAUTH_CLIENTS
|
||||
#else
|
||||
#define DROPBEAR_LISTEN_BACKLOG MAX_CHANNELS
|
||||
#endif
|
||||
|
||||
/* no include guard for this file */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "buffer.h"
|
||||
#include "packet.h"
|
||||
#include "listener.h"
|
||||
#include "listener.h"
|
||||
#include "runopts.h"
|
||||
|
||||
#ifdef DROPBEAR_TCP_ACCEPT
|
||||
@@ -44,6 +45,13 @@ static void cleanup_tcp(struct Listener *listener) {
|
||||
m_free(tcpinfo);
|
||||
}
|
||||
|
||||
int tcp_prio_inithandler(struct Channel* channel)
|
||||
{
|
||||
TRACE(("tcp_prio_inithandler channel %d", channel->index))
|
||||
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tcp_acceptor(struct Listener *listener, int sock) {
|
||||
|
||||
int fd;
|
||||
|
||||
Reference in New Issue
Block a user