Mercurial > dropbear
changeset 970:0bb16232e7c4
Make keepalive handling more robust, this should now match what OpenSSH does
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 19 Aug 2014 23:08:56 +0800 |
parents | 939944f0fca9 |
children | 763979a9c1f1 eb5cb4f45cd6 3fbb9a72fb75 |
files | LICENSE auth.h channel.h chansession.h cli-agentfwd.c cli-chansession.c cli-session.c common-channel.c common-session.c session.h svr-chansession.c svr-main.c svr-session.c sysoptions.h |
diffstat | 14 files changed, 88 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/LICENSE Wed Aug 13 22:07:43 2014 +0800 +++ b/LICENSE Tue Aug 19 23:08:56 2014 +0800 @@ -8,7 +8,7 @@ Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the same license: -Copyright (c) 2002-2013 Matt Johnston +Copyright (c) 2002-2014 Matt Johnston Portions copyright (c) 2004 Mihnea Stoenescu All rights reserved.
--- a/auth.h Wed Aug 13 22:07:43 2014 +0800 +++ b/auth.h Tue Aug 19 23:08:56 2014 +0800 @@ -106,7 +106,7 @@ valid */ unsigned int failcount; /* Number of (failed) authentication attempts.*/ unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for - client and server (though has differing [obvious] + client and server (though has differing meanings). */ unsigned perm_warn : 1; /* Server only, set if bad permissions on ~/.ssh/authorized_keys have already been
--- a/channel.h Wed Aug 13 22:07:43 2014 +0800 +++ b/channel.h Tue Aug 19 23:08:56 2014 +0800 @@ -105,6 +105,9 @@ void setchannelfds(fd_set *readfd, fd_set *writefd); void channelio(fd_set *readfd, fd_set *writefd); struct Channel* getchannel(); +/* Returns an arbitrary channel that is in a ready state - not +being initialised and no EOF in either direction. NULL if none. */ +struct Channel* get_any_ready_channel(); void recv_msg_channel_open(); void recv_msg_channel_request(); @@ -128,8 +131,10 @@ void recv_msg_channel_open_confirmation(); void recv_msg_channel_open_failure(); #endif +void start_send_channel_request(struct Channel *channel, unsigned char *type); void send_msg_request_success(); void send_msg_request_failure(); + #endif /* _CHANNEL_H_ */
--- a/chansession.h Wed Aug 13 22:07:43 2014 +0800 +++ b/chansession.h Tue Aug 19 23:08:56 2014 +0800 @@ -89,7 +89,6 @@ #ifdef ENABLE_CLI_NETCAT void cli_send_netcat_request(); #endif -void cli_start_send_channel_request(struct Channel *channel, unsigned char *type); void svr_chansessinitialise(); extern const struct ChanType svrchansess;
--- a/cli-agentfwd.c Wed Aug 13 22:07:43 2014 +0800 +++ b/cli-agentfwd.c Tue Aug 19 23:08:56 2014 +0800 @@ -234,7 +234,7 @@ return; } - cli_start_send_channel_request(channel, "[email protected]"); + start_send_channel_request(channel, "[email protected]"); /* Don't want replies */ buf_putbyte(ses.writepayload, 0); encrypt_packet();
--- a/cli-chansession.c Wed Aug 13 22:07:43 2014 +0800 +++ b/cli-chansession.c Tue Aug 19 23:08:56 2014 +0800 @@ -92,17 +92,6 @@ } } -void cli_start_send_channel_request(struct Channel *channel, - unsigned char *type) { - - CHECKCLEARTOWRITE(); - buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST); - buf_putint(ses.writepayload, channel->remotechan); - - buf_putstring(ses.writepayload, type, strlen(type)); - -} - /* Taken from OpenSSH's sshtty.c: * RCSID("OpenBSD: sshtty.c,v 1.5 2003/09/19 17:43:35 markus Exp "); */ static void cli_tty_setup() { @@ -287,7 +276,7 @@ TRACE(("enter send_chansess_pty_req")) - cli_start_send_channel_request(channel, "pty-req"); + start_send_channel_request(channel, "pty-req"); /* Don't want replies */ buf_putbyte(ses.writepayload, 0); @@ -330,7 +319,7 @@ reqtype = "shell"; } - cli_start_send_channel_request(channel, reqtype); + start_send_channel_request(channel, reqtype); /* XXX TODO */ buf_putbyte(ses.writepayload, 0); /* Don't want replies */
--- a/cli-session.c Wed Aug 13 22:07:43 2014 +0800 +++ b/cli-session.c Tue Aug 19 23:08:56 2014 +0800 @@ -70,11 +70,15 @@ {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}, + {SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response}, + {SSH_MSG_CHANNEL_FAILURE, ignore_recv_response}, #ifdef ENABLE_CLI_REMOTETCPFWD {SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */ {SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */ #else - {SSH_MSG_REQUEST_FAILURE, ignore_recv_msg_request_failure}, /* for keepalive */ + /* For keepalive */ + {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response}, + {SSH_MSG_REQUEST_FAILURE, ignore_recv_response}, #endif {0, 0} /* End */ };
--- a/common-channel.c Wed Aug 13 22:07:43 2014 +0800 +++ b/common-channel.c Tue Aug 19 23:08:56 2014 +0800 @@ -627,7 +627,12 @@ && !channel->close_handler_done) { channel->type->reqhandler(channel); } else { - send_msg_channel_failure(channel); + int wantreply; + buf_eatstring(ses.payload); + wantreply = buf_getbool(ses.payload); + if (wantreply) { + send_msg_channel_failure(channel); + } } TRACE(("leave recv_msg_channel_request")) @@ -1134,3 +1139,30 @@ buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE); encrypt_packet(); } + +struct Channel* get_any_ready_channel() { + if (ses.chancount == 0) { + return NULL; + } + size_t i; + for (i = 0; i < ses.chansize; i++) { + struct Channel *chan = ses.channels[i]; + if (chan + && !(chan->sent_eof || chan->recv_eof) + && !(chan->await_open || chan->initconn)) { + return chan; + } + } + return NULL; +} + +void start_send_channel_request(struct Channel *channel, + unsigned char *type) { + + CHECKCLEARTOWRITE(); + buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST); + buf_putint(ses.writepayload, channel->remotechan); + + buf_putstring(ses.writepayload, type, strlen(type)); + +}
--- a/common-session.c Wed Aug 13 22:07:43 2014 +0800 +++ b/common-session.c Tue Aug 19 23:08:56 2014 +0800 @@ -394,19 +394,30 @@ return pos+1; } -void ignore_recv_msg_request_failure() { +void ignore_recv_response() { // Do nothing - TRACE(("Ignored msg_request_failure")) + TRACE(("Ignored msg_request_response")) } static void send_msg_keepalive() { CHECKCLEARTOWRITE(); 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, "[email protected]", 0); + + struct Channel *chan = get_any_ready_channel(); + + if (chan) { + /* Channel requests are preferable, more implementations + handle them than SSH_MSG_GLOBAL_REQUEST */ + TRACE(("keepalive channel request %d", chan->index)) + start_send_channel_request(chan, DROPBEAR_KEEPALIVE_STRING); + } else { + TRACE(("keepalive global request")) + /* Some peers will reply with SSH_MSG_REQUEST_FAILURE, + some will reply with SSH_MSG_UNIMPLEMENTED, some will exit. */ + buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); + buf_putstring(ses.writepayload, DROPBEAR_KEEPALIVE_STRING, + strlen(DROPBEAR_KEEPALIVE_STRING)); + } buf_putbyte(ses.writepayload, 1); /* want_reply */ encrypt_packet(); @@ -435,7 +446,10 @@ send_msg_kexinit(); } - if (opts.keepalive_secs > 0) { + if (opts.keepalive_secs > 0 && ses.authstate.authdone) { + /* Avoid sending keepalives prior to auth - those are + not valid pre-auth packet types */ + /* Send keepalives if we've been idle */ if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) { send_msg_keepalive();
--- a/session.h Wed Aug 13 22:07:43 2014 +0800 +++ b/session.h Tue Aug 19 23:08:56 2014 +0800 @@ -47,7 +47,7 @@ void session_cleanup(); void send_session_identification(); void send_msg_ignore(); -void ignore_recv_msg_request_failure(); +void ignore_recv_response(); void update_channel_prio();
--- a/svr-chansession.c Wed Aug 13 22:07:43 2014 +0800 +++ b/svr-chansession.c Tue Aug 19 23:08:56 2014 +0800 @@ -53,6 +53,7 @@ static void closechansess(struct Channel *channel); static int newchansess(struct Channel *channel); static void chansessionrequest(struct Channel *channel); +static int sesscheckclose(struct Channel *channel); static void send_exitsignalstatus(struct Channel *channel); static void send_msg_chansess_exitstatus(struct Channel * channel, @@ -61,6 +62,14 @@ struct ChanSess * chansess); static void get_termmodes(struct ChanSess *chansess); +const struct ChanType svrchansess = { + 0, /* sepfds */ + "session", /* name */ + newchansess, /* inithandler */ + sesscheckclose, /* checkclosehandler */ + chansessionrequest, /* reqhandler */ + closechansess, /* closehandler */ +}; /* required to clear environment */ extern char** environ; @@ -968,16 +977,6 @@ dropbear_exit("Child failed"); } -const struct ChanType svrchansess = { - 0, /* sepfds */ - "session", /* name */ - newchansess, /* inithandler */ - sesscheckclose, /* checkclosehandler */ - chansessionrequest, /* reqhandler */ - closechansess, /* closehandler */ -}; - - /* Set up the general chansession environment, in particular child-exit * handling */ void svr_chansessinitialise() {
--- a/svr-main.c Wed Aug 13 22:07:43 2014 +0800 +++ b/svr-main.c Tue Aug 19 23:08:56 2014 +0800 @@ -409,7 +409,7 @@ size_t sockpos = 0; int nsock; - TRACE(("listensockets: %d to try\n", svr_opts.portcount)) + TRACE(("listensockets: %d to try", svr_opts.portcount)) for (i = 0; i < svr_opts.portcount; i++) {
--- a/svr-session.c Wed Aug 13 22:07:43 2014 +0800 +++ b/svr-session.c Tue Aug 19 23:08:56 2014 +0800 @@ -58,7 +58,10 @@ {SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open}, {SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof}, {SSH_MSG_CHANNEL_CLOSE, recv_msg_channel_close}, - {SSH_MSG_REQUEST_FAILURE, ignore_recv_msg_request_failure}, /* for keepalive */ + {SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response}, + {SSH_MSG_CHANNEL_FAILURE, ignore_recv_response}, + {SSH_MSG_REQUEST_FAILURE, ignore_recv_response}, /* for keepalive */ + {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response}, /* client */ #ifdef USING_LISTENERS {SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation}, {SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
--- a/sysoptions.h Wed Aug 13 22:07:43 2014 +0800 +++ b/sysoptions.h Tue Aug 19 23:08:56 2014 +0800 @@ -257,4 +257,7 @@ #define DROPBEAR_LISTEN_BACKLOG MAX_CHANNELS #endif +/* Use this string since some implementations might special-case it */ +#define DROPBEAR_KEEPALIVE_STRING "[email protected]" + /* no include guard for this file */