# HG changeset patch # User Matt Johnston # Date 1408462606 -28800 # Node ID 763979a9c1f18997304f3e6c11d98d8852c9b829 # Parent 67ff2be856ff0b9f7570466aa08a3f26f68f4c47# Parent 0bb16232e7c4162daa43e8618521cf453847ac16 merge diff -r 67ff2be856ff -r 763979a9c1f1 .hgsigs --- a/.hgsigs Fri Aug 08 21:26:07 2014 +0800 +++ b/.hgsigs Tue Aug 19 23:36:46 2014 +0800 @@ -11,3 +11,4 @@ 3d1d7d151c0ce3a79da62e86463f5632fa2b144a 0 iEYEABECAAYFAlKd5AEACgkQjPn4sExkf7wzWgCfdvPEEIdlMPqcbOQMJ7b+eAyy164An2ip1lPh1eS5g26/gSfruvWBVym4 277429102f1337bd10c89107d3e01de509cc1a7e 0 iEYEABECAAYFAlMEvF4ACgkQjPn4sExkf7xeVQCgtbxJ4G3hsFwUOM0K1WGr1J2vsbEAoMM8dEyr1mdrbgO1tzNLfD1nxbyn 96584b934d04ebab443f603e78d38fe692d36313 0 iEYEABECAAYFAlPVFrQACgkQjPn4sExkf7xr6ACglRiLE21vRrS1rJ809o2yMADIKtwAn1f5SyZUngSde8eE55JxCMwtMC5m +caac692b366c153cea0e9cd59aa2d79a7d843d4e 0 iEYEABECAAYFAlPk1mcACgkQjPn4sExkf7wLpgCeOqMYqpkf4lYUuyrn9VYThNpc7PkAn3JOSNgIqkKUcmSy6FstrI8jwJzq diff -r 67ff2be856ff -r 763979a9c1f1 .hgtags --- a/.hgtags Fri Aug 08 21:26:07 2014 +0800 +++ b/.hgtags Tue Aug 19 23:36:46 2014 +0800 @@ -44,3 +44,4 @@ 3d1d7d151c0ce3a79da62e86463f5632fa2b144a DROPBEAR_2013.62 2351b2da8e0d08dcc6e64fcc328b53b9630bda68 DROPBEAR_2014.63 0d2d39957c029adb7f4327d37fe6b4900f0736d9 DROPBEAR_2014.64 +e9579816f20ea85affc6135e87f8477992808948 DROPBEAR_2014.65 diff -r 67ff2be856ff -r 763979a9c1f1 CHANGES --- a/CHANGES Fri Aug 08 21:26:07 2014 +0800 +++ b/CHANGES Tue Aug 19 23:36:46 2014 +0800 @@ -1,3 +1,20 @@ +2014.65 - Friday 8 August 2014 + +- Fix 2014.64 regression, server session hang on exit with scp (and probably + others), thanks to NiLuJe for tracking it down + +- Fix 2014.64 regression, clock_gettime() error handling which broke on older + Linux kernels, reported by NiLuJe + +- Fix 2014.64 regression, writev() could occassionally fail with EAGAIN which + wasn't caught + +- Avoid error message when trying to set QoS on proxycommand or multihop pipes + +- Use /usr/bin/xauth, thanks to Mike Frysinger + +- Don't exit the client if the local user entry can't be found, thanks to iquaba + 2014.64 - Sunday 27 July 2014 - Fix compiling with ECDSA and DSS disabled diff -r 67ff2be856ff -r 763979a9c1f1 LICENSE --- a/LICENSE Fri Aug 08 21:26:07 2014 +0800 +++ b/LICENSE Tue Aug 19 23:36:46 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. diff -r 67ff2be856ff -r 763979a9c1f1 auth.h --- a/auth.h Fri Aug 08 21:26:07 2014 +0800 +++ b/auth.h Tue Aug 19 23:36:46 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 diff -r 67ff2be856ff -r 763979a9c1f1 channel.h --- a/channel.h Fri Aug 08 21:26:07 2014 +0800 +++ b/channel.h Tue Aug 19 23:36:46 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_ */ diff -r 67ff2be856ff -r 763979a9c1f1 chansession.h --- a/chansession.h Fri Aug 08 21:26:07 2014 +0800 +++ b/chansession.h Tue Aug 19 23:36:46 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; diff -r 67ff2be856ff -r 763979a9c1f1 cli-agentfwd.c --- a/cli-agentfwd.c Fri Aug 08 21:26:07 2014 +0800 +++ b/cli-agentfwd.c Tue Aug 19 23:36:46 2014 +0800 @@ -234,7 +234,7 @@ return; } - cli_start_send_channel_request(channel, "auth-agent-req@openssh.com"); + start_send_channel_request(channel, "auth-agent-req@openssh.com"); /* Don't want replies */ buf_putbyte(ses.writepayload, 0); encrypt_packet(); diff -r 67ff2be856ff -r 763979a9c1f1 cli-chansession.c --- a/cli-chansession.c Fri Aug 08 21:26:07 2014 +0800 +++ b/cli-chansession.c Tue Aug 19 23:36:46 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 */ diff -r 67ff2be856ff -r 763979a9c1f1 cli-session.c --- a/cli-session.c Fri Aug 08 21:26:07 2014 +0800 +++ b/cli-session.c Tue Aug 19 23:36:46 2014 +0800 @@ -70,9 +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 + /* For keepalive */ + {SSH_MSG_REQUEST_SUCCESS, ignore_recv_response}, + {SSH_MSG_REQUEST_FAILURE, ignore_recv_response}, #endif {0, 0} /* End */ }; diff -r 67ff2be856ff -r 763979a9c1f1 common-channel.c --- a/common-channel.c Fri Aug 08 21:26:07 2014 +0800 +++ b/common-channel.c Tue Aug 19 23:36:46 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)); + +} diff -r 67ff2be856ff -r 763979a9c1f1 common-session.c --- a/common-session.c Fri Aug 08 21:26:07 2014 +0800 +++ b/common-session.c Tue Aug 19 23:36:46 2014 +0800 @@ -394,14 +394,30 @@ return pos+1; } +void ignore_recv_response() { + // Do nothing + 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, "k@dropbear.nl", 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(); @@ -430,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(); diff -r 67ff2be856ff -r 763979a9c1f1 debian/changelog --- a/debian/changelog Fri Aug 08 21:26:07 2014 +0800 +++ b/debian/changelog Tue Aug 19 23:36:46 2014 +0800 @@ -1,3 +1,9 @@ +dropbear (2014.65-0.1) unstable; urgency=low + + * New upstream release. + + -- Matt Johnston Fri, 8 Aug 2014 22:54:00 +0800 + dropbear (2014.64-0.1) unstable; urgency=low * New upstream release. diff -r 67ff2be856ff -r 763979a9c1f1 loginrec.h --- a/loginrec.h Fri Aug 08 21:26:07 2014 +0800 +++ b/loginrec.h Tue Aug 19 23:36:46 2014 +0800 @@ -79,10 +79,10 @@ # if defined(HAVE_UTMP_H) && defined(UTMP_FILE) && !defined(DISABLE_UTMP) # define USE_UTMP # endif -# if defined(HAVE_WTMPX_H) && defined(WTMPX_FILE) && !defined(DISABLE_WTMPX) +# if defined(WTMPX_FILE) && !defined(DISABLE_WTMPX) # define USE_WTMPX # endif -# if defined(HAVE_WTMP_H) && defined(WTMP_FILE) && !defined(DISABLE_WTMP) +# if defined(WTMP_FILE) && !defined(DISABLE_WTMP) # define USE_WTMP # endif diff -r 67ff2be856ff -r 763979a9c1f1 session.h --- a/session.h Fri Aug 08 21:26:07 2014 +0800 +++ b/session.h Tue Aug 19 23:36:46 2014 +0800 @@ -47,6 +47,7 @@ void session_cleanup(); void send_session_identification(); void send_msg_ignore(); +void ignore_recv_response(); void update_channel_prio(); diff -r 67ff2be856ff -r 763979a9c1f1 svr-chansession.c --- a/svr-chansession.c Fri Aug 08 21:26:07 2014 +0800 +++ b/svr-chansession.c Tue Aug 19 23:36:46 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() { diff -r 67ff2be856ff -r 763979a9c1f1 svr-main.c --- a/svr-main.c Fri Aug 08 21:26:07 2014 +0800 +++ b/svr-main.c Tue Aug 19 23:36:46 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++) { diff -r 67ff2be856ff -r 763979a9c1f1 svr-session.c --- a/svr-session.c Fri Aug 08 21:26:07 2014 +0800 +++ b/svr-session.c Tue Aug 19 23:36:46 2014 +0800 @@ -58,6 +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_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}, diff -r 67ff2be856ff -r 763979a9c1f1 sysoptions.h --- a/sysoptions.h Fri Aug 08 21:26:07 2014 +0800 +++ b/sysoptions.h Tue Aug 19 23:36:46 2014 +0800 @@ -4,7 +4,7 @@ *******************************************************************/ #ifndef DROPBEAR_VERSION -#define DROPBEAR_VERSION "2014.64" +#define DROPBEAR_VERSION "2014.65" #endif #define LOCAL_IDENT "SSH-2.0-dropbear_" DROPBEAR_VERSION @@ -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 "keepalive@openssh.com" + /* no include guard for this file */