3 # User Matt Johnston <matt@ucc.asn.au>
4 # Date 1408460936 -28800
5 # Node ID 0bb16232e7c4162daa43e8618521cf453847ac16
6 # Parent 939944f0fca9b2dcdf8470bb24efcc37a3843e8b
7 Make keepalive handling more robust, this should now match what OpenSSH does
9 diff -r 939944f0fca9 -r 0bb16232e7c4 LICENSE
10 --- a/LICENSE Wed Aug 13 22:07:43 2014 +0800
11 +++ b/LICENSE Tue Aug 19 23:08:56 2014 +0800
13 Portions of the client-mode work are (c) 2004 Mihnea Stoenescu, under the
16 -Copyright (c) 2002-2013 Matt Johnston
17 +Copyright (c) 2002-2014 Matt Johnston
18 Portions copyright (c) 2004 Mihnea Stoenescu
21 diff -r 939944f0fca9 -r 0bb16232e7c4 auth.h
22 --- a/auth.h Wed Aug 13 22:07:43 2014 +0800
23 +++ b/auth.h Tue Aug 19 23:08:56 2014 +0800
26 unsigned int failcount; /* Number of (failed) authentication attempts.*/
27 unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for
28 - client and server (though has differing [obvious]
29 + client and server (though has differing
31 unsigned perm_warn : 1; /* Server only, set if bad permissions on
32 ~/.ssh/authorized_keys have already been
33 diff -r 939944f0fca9 -r 0bb16232e7c4 channel.h
34 --- a/channel.h Wed Aug 13 22:07:43 2014 +0800
35 +++ b/channel.h Tue Aug 19 23:08:56 2014 +0800
37 void setchannelfds(fd_set *readfd, fd_set *writefd);
38 void channelio(fd_set *readfd, fd_set *writefd);
39 struct Channel* getchannel();
40 +/* Returns an arbitrary channel that is in a ready state - not
41 +being initialised and no EOF in either direction. NULL if none. */
42 +struct Channel* get_any_ready_channel();
44 void recv_msg_channel_open();
45 void recv_msg_channel_request();
47 void recv_msg_channel_open_confirmation();
48 void recv_msg_channel_open_failure();
50 +void start_send_channel_request(struct Channel *channel, unsigned char *type);
52 void send_msg_request_success();
53 void send_msg_request_failure();
56 #endif /* _CHANNEL_H_ */
57 diff -r 939944f0fca9 -r 0bb16232e7c4 chansession.h
58 --- a/chansession.h Wed Aug 13 22:07:43 2014 +0800
59 +++ b/chansession.h Tue Aug 19 23:08:56 2014 +0800
61 #ifdef ENABLE_CLI_NETCAT
62 void cli_send_netcat_request();
64 -void cli_start_send_channel_request(struct Channel *channel, unsigned char *type);
66 void svr_chansessinitialise();
67 extern const struct ChanType svrchansess;
68 diff -r 939944f0fca9 -r 0bb16232e7c4 cli-agentfwd.c
69 --- a/cli-agentfwd.c Wed Aug 13 22:07:43 2014 +0800
70 +++ b/cli-agentfwd.c Tue Aug 19 23:08:56 2014 +0800
75 - cli_start_send_channel_request(channel, "auth-agent-req@openssh.com");
76 + start_send_channel_request(channel, "auth-agent-req@openssh.com");
77 /* Don't want replies */
78 buf_putbyte(ses.writepayload, 0);
80 diff -r 939944f0fca9 -r 0bb16232e7c4 cli-chansession.c
81 --- a/cli-chansession.c Wed Aug 13 22:07:43 2014 +0800
82 +++ b/cli-chansession.c Tue Aug 19 23:08:56 2014 +0800
87 -void cli_start_send_channel_request(struct Channel *channel,
88 - unsigned char *type) {
90 - CHECKCLEARTOWRITE();
91 - buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
92 - buf_putint(ses.writepayload, channel->remotechan);
94 - buf_putstring(ses.writepayload, type, strlen(type));
98 /* Taken from OpenSSH's sshtty.c:
99 * RCSID("OpenBSD: sshtty.c,v 1.5 2003/09/19 17:43:35 markus Exp "); */
100 static void cli_tty_setup() {
103 TRACE(("enter send_chansess_pty_req"))
105 - cli_start_send_channel_request(channel, "pty-req");
106 + start_send_channel_request(channel, "pty-req");
108 /* Don't want replies */
109 buf_putbyte(ses.writepayload, 0);
114 - cli_start_send_channel_request(channel, reqtype);
115 + start_send_channel_request(channel, reqtype);
118 buf_putbyte(ses.writepayload, 0); /* Don't want replies */
119 diff -r 939944f0fca9 -r 0bb16232e7c4 cli-session.c
120 --- a/cli-session.c Wed Aug 13 22:07:43 2014 +0800
121 +++ b/cli-session.c Tue Aug 19 23:08:56 2014 +0800
123 {SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
124 {SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
125 {SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_cli},
126 + {SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
127 + {SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
128 #ifdef ENABLE_CLI_REMOTETCPFWD
129 {SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
130 {SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
132 - {SSH_MSG_REQUEST_FAILURE, ignore_recv_msg_request_failure}, /* for keepalive */
133 + /* For keepalive */
134 + {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response},
135 + {SSH_MSG_REQUEST_FAILURE, ignore_recv_response},
139 diff -r 939944f0fca9 -r 0bb16232e7c4 common-channel.c
140 --- a/common-channel.c Wed Aug 13 22:07:43 2014 +0800
141 +++ b/common-channel.c Tue Aug 19 23:08:56 2014 +0800
143 && !channel->close_handler_done) {
144 channel->type->reqhandler(channel);
146 - send_msg_channel_failure(channel);
148 + buf_eatstring(ses.payload);
149 + wantreply = buf_getbool(ses.payload);
151 + send_msg_channel_failure(channel);
155 TRACE(("leave recv_msg_channel_request"))
156 @@ -1134,3 +1139,30 @@
157 buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
161 +struct Channel* get_any_ready_channel() {
162 + if (ses.chancount == 0) {
166 + for (i = 0; i < ses.chansize; i++) {
167 + struct Channel *chan = ses.channels[i];
169 + && !(chan->sent_eof || chan->recv_eof)
170 + && !(chan->await_open || chan->initconn)) {
177 +void start_send_channel_request(struct Channel *channel,
178 + unsigned char *type) {
180 + CHECKCLEARTOWRITE();
181 + buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
182 + buf_putint(ses.writepayload, channel->remotechan);
184 + buf_putstring(ses.writepayload, type, strlen(type));
187 diff -r 939944f0fca9 -r 0bb16232e7c4 common-session.c
188 --- a/common-session.c Wed Aug 13 22:07:43 2014 +0800
189 +++ b/common-session.c Tue Aug 19 23:08:56 2014 +0800
190 @@ -394,19 +394,30 @@
194 -void ignore_recv_msg_request_failure() {
195 +void ignore_recv_response() {
197 - TRACE(("Ignored msg_request_failure"))
198 + TRACE(("Ignored msg_request_response"))
201 static void send_msg_keepalive() {
203 time_t old_time_idle = ses.last_packet_time_idle;
204 - /* Try to force a response from the other end. Some peers will
205 - reply with SSH_MSG_REQUEST_FAILURE, some will reply with SSH_MSG_UNIMPLEMENTED */
206 - buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
207 - /* A short string */
208 - buf_putstring(ses.writepayload, "k@dropbear.nl", 0);
210 + struct Channel *chan = get_any_ready_channel();
213 + /* Channel requests are preferable, more implementations
214 + handle them than SSH_MSG_GLOBAL_REQUEST */
215 + TRACE(("keepalive channel request %d", chan->index))
216 + start_send_channel_request(chan, DROPBEAR_KEEPALIVE_STRING);
218 + TRACE(("keepalive global request"))
219 + /* Some peers will reply with SSH_MSG_REQUEST_FAILURE,
220 + some will reply with SSH_MSG_UNIMPLEMENTED, some will exit. */
221 + buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
222 + buf_putstring(ses.writepayload, DROPBEAR_KEEPALIVE_STRING,
223 + strlen(DROPBEAR_KEEPALIVE_STRING));
225 buf_putbyte(ses.writepayload, 1); /* want_reply */
232 - if (opts.keepalive_secs > 0) {
233 + if (opts.keepalive_secs > 0 && ses.authstate.authdone) {
234 + /* Avoid sending keepalives prior to auth - those are
235 + not valid pre-auth packet types */
237 /* Send keepalives if we've been idle */
238 if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) {
239 send_msg_keepalive();
240 diff -r 939944f0fca9 -r 0bb16232e7c4 session.h
241 --- a/session.h Wed Aug 13 22:07:43 2014 +0800
242 +++ b/session.h Tue Aug 19 23:08:56 2014 +0800
244 void session_cleanup();
245 void send_session_identification();
246 void send_msg_ignore();
247 -void ignore_recv_msg_request_failure();
248 +void ignore_recv_response();
250 void update_channel_prio();
252 diff -r 939944f0fca9 -r 0bb16232e7c4 svr-chansession.c
253 --- a/svr-chansession.c Wed Aug 13 22:07:43 2014 +0800
254 +++ b/svr-chansession.c Tue Aug 19 23:08:56 2014 +0800
256 static void closechansess(struct Channel *channel);
257 static int newchansess(struct Channel *channel);
258 static void chansessionrequest(struct Channel *channel);
259 +static int sesscheckclose(struct Channel *channel);
261 static void send_exitsignalstatus(struct Channel *channel);
262 static void send_msg_chansess_exitstatus(struct Channel * channel,
264 struct ChanSess * chansess);
265 static void get_termmodes(struct ChanSess *chansess);
267 +const struct ChanType svrchansess = {
269 + "session", /* name */
270 + newchansess, /* inithandler */
271 + sesscheckclose, /* checkclosehandler */
272 + chansessionrequest, /* reqhandler */
273 + closechansess, /* closehandler */
276 /* required to clear environment */
277 extern char** environ;
279 dropbear_exit("Child failed");
282 -const struct ChanType svrchansess = {
284 - "session", /* name */
285 - newchansess, /* inithandler */
286 - sesscheckclose, /* checkclosehandler */
287 - chansessionrequest, /* reqhandler */
288 - closechansess, /* closehandler */
292 /* Set up the general chansession environment, in particular child-exit
294 void svr_chansessinitialise() {
295 diff -r 939944f0fca9 -r 0bb16232e7c4 svr-main.c
296 --- a/svr-main.c Wed Aug 13 22:07:43 2014 +0800
297 +++ b/svr-main.c Tue Aug 19 23:08:56 2014 +0800
302 - TRACE(("listensockets: %d to try\n", svr_opts.portcount))
303 + TRACE(("listensockets: %d to try", svr_opts.portcount))
305 for (i = 0; i < svr_opts.portcount; i++) {
307 diff -r 939944f0fca9 -r 0bb16232e7c4 svr-session.c
308 --- a/svr-session.c Wed Aug 13 22:07:43 2014 +0800
309 +++ b/svr-session.c Tue Aug 19 23:08:56 2014 +0800
311 {SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
312 {SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
313 {SSH_MSG_CHANNEL_CLOSE, recv_msg_channel_close},
314 - {SSH_MSG_REQUEST_FAILURE, ignore_recv_msg_request_failure}, /* for keepalive */
315 + {SSH_MSG_CHANNEL_SUCCESS, ignore_recv_response},
316 + {SSH_MSG_CHANNEL_FAILURE, ignore_recv_response},
317 + {SSH_MSG_REQUEST_FAILURE, ignore_recv_response}, /* for keepalive */
318 + {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response}, /* client */
319 #ifdef USING_LISTENERS
320 {SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation},
321 {SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
322 diff -r 939944f0fca9 -r 0bb16232e7c4 sysoptions.h
323 --- a/sysoptions.h Wed Aug 13 22:07:43 2014 +0800
324 +++ b/sysoptions.h Tue Aug 19 23:08:56 2014 +0800
326 #define DROPBEAR_LISTEN_BACKLOG MAX_CHANNELS
329 +/* Use this string since some implementations might special-case it */
330 +#define DROPBEAR_KEEPALIVE_STRING "keepalive@openssh.com"
332 /* no include guard for this file */