And the patch actually attached here.
On Mon, Apr 01, 2013 at 11:01:42PM +0800, Matt Johnston wrote:
> Hi,
>
> The attached attached patch against 2013.56 should fix it, or
> https://secure.ucc.asn.au/hg/dropbear/rev/70811267715c
>
> Dropbear wasn't running cleanup handlers when it exited due
> to the TCP connection being closed.
>
> Matt
>
> On Thu, Mar 28, 2013 at 07:24:55PM +0800, Matt Johnston wrote:
> > I think that -K on the server should be enough. On the
> > server can you run "tcpdump -i eth0 -w cap1.cap port 22",
> > get a ssh session going, pull out the cable, wait 10
> > minutes, then send me the capture?
> >
> > Could you also check that the Dropbear process for the
> > connection is still running after the connection should have
> > been finished. It's possible that the process is exiting but
> > the session cleanup code isn't working correctly. The whole
> > debug log might give me an idea what's going on.
> >
> > Cheers,
> > Matt
> >
> > On Thu, Mar 28, 2013 at 09:56:02AM +0100, Mattias Walström wrote:
> > > Thanks for your responses, all your suggestions imply that you should do
> > > something
> > > in the client (set keepalive on client end), but shouldn't the server
> > > itself be able to
> > > decide if a client is dead (can't OpenSSH do this?).
> > >
> > > If I do the -K 15 -I 20 on the server end only, this will close the
> > > connection when
> > > the OpenSSH client has not sent any characters in 20s. I expected the
> > > keepalive to be
> > > two way, that the server got responses on these packages as well, is that
> > > not the case?
> > >
> > > Regards
> > > Mattias
> >
> > > >>On Wed, Mar 27, 2013 at 11:24 AM, Mattias Walström <
> > > >>[email protected]> wrote:
> > > >>
> > > >>>Hi!
> > > >>>I am running dropbear 2013.56, connecting to the server with a PC but
> > > >>>not performing a clean close (I pulled my ethernet cable), this caused
> > > >>>dropbear to never drop its connection.
> > > >>>
> > > >>>Looking at the utmp entries, I could see that the connection never got
> > > >>>dropped,
> > > >>>the utmp entries was kept forever, and running with debug indicates
> > > >>>that
> > > >>>also.
> > > >>> Tried to use -K to send keepalive, but it just keeps sending
> > > >>> keepalives
> > > >>>to the peer,
> > > >>>even it is no longer there, and not possible to reach. Shouldn't
> > > >>>the connection be dropped if the keepalive does not reach its
> > > >>>destination?
> > > >>>
> > > >>>I know there is the -I option, but that does not really do what I want,
> > > >>>I want the connection to be tear down when the peer is unreachable, not
> > > >>>when the user has been idle for a while.
> > > >>>
> > > >>>Regards
> > > >>> Mattias
> > > >>>
> > >
diff -r 1b8b2b9d6e94 cli-main.c
--- a/cli-main.c Thu Mar 21 23:29:04 2013 +0800
+++ b/cli-main.c Mon Apr 01 22:59:26 2013 +0800
@@ -98,8 +98,7 @@
}
/* Do the cleanup first, since then the terminal will be reset */
- cli_session_cleanup();
- common_session_cleanup();
+ session_cleanup();
_dropbear_log(LOG_INFO, fmtbuf, param);
diff -r 1b8b2b9d6e94 cli-session.c
--- a/cli-session.c Thu Mar 21 23:29:04 2013 +0800
+++ b/cli-session.c Mon Apr 01 22:59:26 2013 +0800
@@ -41,6 +41,7 @@
static void cli_sessionloop();
static void cli_session_init();
static void cli_finished();
+static void cli_session_cleanup(void);
struct clientsession cli_ses; /* GLOBAL */
@@ -142,6 +143,7 @@
/* For printing "remote host closed" for the user */
ses.remoteclosed = cli_remoteclosed;
+ ses.extra_session_cleanup = cli_session_cleanup;
ses.buf_match_algo = cli_buf_match_algo;
/* packet handlers */
@@ -278,7 +280,7 @@
}
-void cli_session_cleanup() {
+static void cli_session_cleanup(void) {
if (!sessinitdone) {
return;
@@ -296,8 +298,7 @@
static void cli_finished() {
- cli_session_cleanup();
- common_session_cleanup();
+ session_cleanup();
fprintf(stderr, "Connection to %s@%s:%s closed.\n", cli_opts.username,
cli_opts.remotehost, cli_opts.remoteport);
exit(cli_ses.retval);
diff -r 1b8b2b9d6e94 common-session.c
--- a/common-session.c Thu Mar 21 23:29:04 2013 +0800
+++ b/common-session.c Mon Apr 01 22:59:26 2013 +0800
@@ -225,7 +225,7 @@
}
/* clean up a session on exit */
-void common_session_cleanup() {
+void session_cleanup() {
TRACE(("enter session_cleanup"))
@@ -234,6 +234,10 @@
TRACE(("leave session_cleanup: !sessinitdone"))
return;
}
+
+ if (ses.extra_session_cleanup) {
+ ses.extra_session_cleanup();
+ }
m_free(ses.session_id);
m_burn(ses.keys, sizeof(struct key_context));
diff -r 1b8b2b9d6e94 session.h
--- a/session.h Thu Mar 21 23:29:04 2013 +0800
+++ b/session.h Mon Apr 01 22:59:26 2013 +0800
@@ -44,7 +44,7 @@
void common_session_init(int sock_in, int sock_out);
void session_loop(void(*loophandler)());
-void common_session_cleanup();
+void session_cleanup();
void session_identification();
void send_msg_ignore();
@@ -58,7 +58,6 @@
/* Client */
void cli_session(int sock_in, int sock_out);
-void cli_session_cleanup();
void cleantext(unsigned char* dirtytext);
/* crypto parameters that are stored individually for transmit and receive */
@@ -178,6 +177,7 @@
void(*remoteclosed)(); /* A callback to handle closure of the
remote connection */
+ void(*extra_session_cleanup)(); /* client or server specific cleanup */
struct AuthState authstate; /* Common amongst client and server, since most
struct elements are common */
diff -r 1b8b2b9d6e94 svr-session.c
--- a/svr-session.c Thu Mar 21 23:29:04 2013 +0800
+++ b/svr-session.c Mon Apr 01 22:59:26 2013 +0800
@@ -72,6 +72,13 @@
NULL /* Null termination is mandatory. */
};
+static void
+svr_session_cleanup(void)
+{
+ /* free potential public key options */
+ svr_pubkey_options_cleanup();
+}
+
void svr_session(int sock, int childpipe) {
char *host, *port;
size_t len;
@@ -103,6 +110,7 @@
/* set up messages etc */
ses.remoteclosed = svr_remoteclosed;
+ ses.extra_session_cleanup = svr_session_cleanup;
/* packet handlers */
ses.packettypes = svr_packettypes;
@@ -160,11 +168,8 @@
if (svr_ses.server_pid == getpid())
#endif
{
- /* free potential public key options */
- svr_pubkey_options_cleanup();
-
/* must be after we've done with username etc */
- common_session_cleanup();
+ session_cleanup();
}
exit(exitcode);