From 90b5691183f12d348d2651e026e8438ad278c2be Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Mon, 1 Apr 2013 22:26:55 +0800
Subject: [PATCH] Run the cleanup handler also when we close due to TCP
 connection being closed

---
 cli-main.c       |  3 +--
 cli-session.c    |  7 ++++---
 common-session.c |  6 +++++-
 session.h        |  4 ++--
 svr-session.c    | 13 +++++++++----
 5 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/cli-main.c b/cli-main.c
index 5f729693..1a8b02e0 100644
--- a/cli-main.c
+++ b/cli-main.c
@@ -98,8 +98,7 @@ static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
 	}
 
 	/* 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 --git a/cli-session.c b/cli-session.c
index 3adec731..0c6635ae 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -42,6 +42,7 @@ static void cli_sessionloop();
 static void cli_session_init();
 static void cli_finished();
 static void recv_msg_service_accept(void);
+static void cli_session_cleanup(void);
 
 struct clientsession cli_ses; /* GLOBAL */
 
@@ -143,6 +144,7 @@ static void cli_session_init() {
 
 	/* 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 */
@@ -290,7 +292,7 @@ static void cli_sessionloop() {
 
 }
 
-void cli_session_cleanup() {
+static void cli_session_cleanup(void) {
 
 	if (!sessinitdone) {
 		return;
@@ -308,8 +310,7 @@ void cli_session_cleanup() {
 
 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 --git a/common-session.c b/common-session.c
index ec5c9ed5..b5147966 100644
--- a/common-session.c
+++ b/common-session.c
@@ -234,7 +234,7 @@ void session_loop(void(*loophandler)()) {
 }
 
 /* clean up a session on exit */
-void common_session_cleanup() {
+void session_cleanup() {
 	
 	TRACE(("enter session_cleanup"))
 	
@@ -243,6 +243,10 @@ void common_session_cleanup() {
 		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 --git a/session.h b/session.h
index 39104a3f..dd486f02 100644
--- a/session.h
+++ b/session.h
@@ -44,7 +44,7 @@ extern int exitflag;
 
 void common_session_init(int sock_in, int sock_out);
 void session_loop(void(*loophandler)());
-void common_session_cleanup();
+void session_cleanup();
 void send_session_identification();
 void send_msg_ignore();
 
@@ -58,7 +58,6 @@ void svr_dropbear_log(int priority, const char* format, va_list param);
 
 /* 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 */
@@ -181,6 +180,7 @@ struct sshsession {
 	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 --git a/svr-session.c b/svr-session.c
index 7234f4ab..c235c8a4 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -72,6 +72,13 @@ static const struct ChanType *svr_chantypes[] = {
 	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 @@ void svr_session(int sock, int childpipe) {
 
 	/* 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 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
 	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);
-- 
GitLab