Hi folks,

I hacked in OpenSSH style "Server Alive" and "Client Alive" messages into dropbear.

In OpenSSH, the ServerAliveInterval and ServerAliveCountMax options cause the client to send "global requests" to the server with the name "[email protected]" with the flag "want reply" set to 1.

When an SSH server sees the message they fail to recognize it and issue a "failure" response to the client. It appears the OpenSSH people purposely used a request name nobody else would use to guarantee that the server does nothing except send back an error.

If the client does not receive ServerAliveCountMax consecutive responses to its requests, it disconnects. The default value of ServerAliveCountMax is 3. The interval at which the client sends requests is controlled by ServerAliveInterval. But its default value is 0 which disables the feature.

So it's a heart beat. It lets the client know to disconnect if the server disappears off the network.

"Client alive" works the same way. There's a ClientAliveCountMax and ClientAliveInterval. And in this case the client responds to the [email protected] requests.

In dropbear, however, the "global requests" only get serviced when ENABLE_SVR_REMOTETCPFWD is defined in because the only global requests supported are for tcp forwarding. And the client doesn't service any global requests. So an OpenSSH client can use server alives against a Dropbear server if remote TCP forwarding is compiled in. But an OpenSSH server sending client alives would very quickly disconnect a Dropbear client.

I patched dropbear and dbclient to always respond to global requests, but only handle the "tcpip-forward" and "cancel-tcpip-forward" messages when it's enabled. And like OpenSSH it sends failure for the "p...@dropbear" requests for consistency with any other SSH server that doesn't know what these requests are.

To turn on server/client alives, you pass the "-A" option to dbclient/dropbear. That sets the interval. But to change the number of responses that can be missed, you have to do that via the options.h file. I ran out of letters in the alphabet to choose from.

I tried to avoid reorganizing the code. Which means the changes aren't as clean as they should be. And it's not well tested so beware.

Ahilan
diff -cr dropbear-0.52/cli-runopts.c dropbear-0.52-serveralives/cli-runopts.c
*** dropbear-0.52/cli-runopts.c	2008-11-11 06:09:02.000000000 -0800
--- dropbear-0.52-serveralives/cli-runopts.c	2010-01-07 15:32:16.000000000 -0800
***************
*** 75,80 ****
--- 75,81 ----
  #endif
  					"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
  					"-K <keepalive>  (0 is never, default %d)\n"
+ 					"-A <serveralive>  (0 is never, default %d)\n"
  					"-I <idle_timeout>  (0 is never, default %d)\n"
  #ifdef ENABLE_CLI_NETCAT
  					"-B <endhost:endport> Netcat-alike forwarding\n"
***************
*** 86,92 ****
  					"-v    verbose (compiled with DEBUG_TRACE)\n"
  #endif
  					,DROPBEAR_VERSION, cli_opts.progname,
! 					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
  					
  }
  
--- 87,94 ----
  					"-v    verbose (compiled with DEBUG_TRACE)\n"
  #endif
  					,DROPBEAR_VERSION, cli_opts.progname,
! 					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_SERVERALIVE,
! 					DEFAULT_IDLE_TIMEOUT);
  					
  }
  
***************
*** 112,117 ****
--- 114,120 ----
  	char* recv_window_arg = NULL;
  	char* keepalive_arg = NULL;
  	char* idle_timeout_arg = NULL;
+ 	char* serveralive_arg = NULL;
  
  	/* see printhelp() for options */
  	cli_opts.progname = argv[0];
***************
*** 142,147 ****
--- 145,152 ----
  	opts.ipv6 = 1;
  	*/
  	opts.recv_window = DEFAULT_RECV_WINDOW;
+         opts.checkalive_secs = DEFAULT_CLIENTALIVE;
+         opts.checkalive_count_max = DEFAULT_CLIENTALIVE_COUNT_MAX;
  
  	fill_own_user();
  
***************
*** 263,268 ****
--- 268,276 ----
  				case 'K':
  					next = &keepalive_arg;
  					break;
+ 				case 'A':
+ 					next = &serveralive_arg;
+ 					break;
  				case 'I':
  					next = &idle_timeout_arg;
  					break;
***************
*** 380,385 ****
--- 388,399 ----
  		}
  	}
  
+ 	if (serveralive_arg) {
+ 		if (m_str_to_uint(serveralive_arg, &opts.checkalive_secs) == DROPBEAR_FAILURE) {
+ 			dropbear_exit("Bad clientalive '%s'", serveralive_arg);
+ 		}
+ 	}
+ 
  #ifdef ENABLE_CLI_NETCAT
  	if (cli_opts.cmd && cli_opts.netcat_host) {
  		dropbear_log(LOG_INFO, "Ignoring command '%s' in netcat mode", cli_opts.cmd);
diff -cr dropbear-0.52/cli-session.c dropbear-0.52-serveralives/cli-session.c
*** dropbear-0.52/cli-session.c	2008-11-11 06:09:02.000000000 -0800
--- dropbear-0.52-serveralives/cli-session.c	2010-01-06 19:30:05.000000000 -0800
***************
*** 1,3 ****
--- 1,4 ----
+ 
  /*
   * Dropbear SSH
   * 
***************
*** 37,45 ****
--- 38,50 ----
  #include "chansession.h"
  
  static void cli_remoteclosed();
+ static void cli_checkalive();
  static void cli_sessionloop();
  static void cli_session_init();
  static void cli_finished();
+ static void cli_recv_msg_global_request();
+ static void cli_recv_msg_request_success();
+ static void cli_recv_msg_request_failure();
  
  struct clientsession cli_ses; /* GLOBAL */
  
***************
*** 64,73 ****
  	{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
  	{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
  	{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
! #ifdef  ENABLE_CLI_REMOTETCPFWD
  	{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
  	{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
- #endif
  	{0, 0} /* End */
  };
  
--- 69,77 ----
  	{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
  	{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
  	{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
! 	{SSH_MSG_GLOBAL_REQUEST, cli_recv_msg_global_request}, /* client */
  	{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
  	{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
  	{0, 0} /* End */
  };
  
***************
*** 143,149 ****
   * service, userauth and channel requests */
  static void cli_sessionloop() {
  
! 	TRACE(("enter cli_sessionloop"))
  
  	if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
  		cli_ses.kex_state = KEXINIT_RCVD;
--- 147,153 ----
   * service, userauth and channel requests */
  static void cli_sessionloop() {
  
! 	TRACE(("enter cli_sessionloop"));
  
  	if (ses.lastpacket == SSH_MSG_KEXINIT && cli_ses.kex_state == KEX_NOTHING) {
  		cli_ses.kex_state = KEXINIT_RCVD;
***************
*** 297,302 ****
--- 301,354 ----
  	dropbear_exit("remote closed the connection");
  }
  
+ static void send_msg_request_failure() {
+ 
+ 	CHECKCLEARTOWRITE();
+ 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
+ 	encrypt_packet();
+ 
+ }
+ 
+ static void cli_recv_msg_global_request() {
+ 
+ 	unsigned char* reqname = NULL;
+ 	unsigned int namelen;
+ 	unsigned int wantreply = 0;
+ 	int ret = DROPBEAR_FAILURE;
+ 
+ 	TRACE(("enter recv_msg_global_request"))
+ 
+ 	reqname = buf_getstring(ses.payload, &namelen);
+ 	wantreply = buf_getbool(ses.payload);
+ 
+ 	if (namelen > MAX_NAME_LEN) {
+ 		TRACE(("name len is wrong: %d", namelen))
+ 	}
+ 
+ 	if (wantreply) {
+ 		send_msg_request_failure();
+ 	}
+ 
+ 	m_free(reqname);
+ 
+ 	TRACE(("leave recv_msg_global_request"))
+ }
+ 
+ static void cli_recv_msg_request_success() {
+ 	ses.checkalivetimeouts = 0;
+ #ifdef ENABLE_CLI_REMOTETCPFWD
+ 	cli_recv_msg_fwd_request_success();
+ #endif
+ }
+ 
+ static void cli_recv_msg_request_failure() {
+ 	ses.checkalivetimeouts = 0;
+ #ifdef ENABLE_CLI_REMOTETCPFWD
+ 	cli_recv_msg_fwd_request_failure();
+ #endif
+ }
+ 
+ 
  /* Operates in-place turning dirty (untrusted potentially containing control
   * characters) text into clean text. 
   * Note: this is safe only with ascii - other charsets could have problems. */
diff -cr dropbear-0.52/cli-tcpfwd.c dropbear-0.52-serveralives/cli-tcpfwd.c
*** dropbear-0.52/cli-tcpfwd.c	2008-11-11 06:09:02.000000000 -0800
--- dropbear-0.52-serveralives/cli-tcpfwd.c	2009-12-10 17:01:02.000000000 -0800
***************
*** 147,153 ****
   * Since there isn't any identifier in these messages, we have to rely on them
   * being in the same order as we sent the requests. This is the ordering
   * of the cli_opts.remotefwds list */
! void cli_recv_msg_request_success() {
  
  	/* Nothing in the packet. We just mark off that we have received the reply,
  	 * so that we can report failure for later ones. */
--- 147,153 ----
   * Since there isn't any identifier in these messages, we have to rely on them
   * being in the same order as we sent the requests. This is the ordering
   * of the cli_opts.remotefwds list */
! void cli_recv_msg_fwd_request_success() {
  
  	/* Nothing in the packet. We just mark off that we have received the reply,
  	 * so that we can report failure for later ones. */
***************
*** 164,170 ****
  	}
  }
  
! void cli_recv_msg_request_failure() {
  	struct TCPFwdList * iter = NULL;
  
  	iter = cli_opts.remotefwds;
--- 164,170 ----
  	}
  }
  
! void cli_recv_msg_fwd_request_failure() {
  	struct TCPFwdList * iter = NULL;
  
  	iter = cli_opts.remotefwds;
diff -cr dropbear-0.52/common-session.c dropbear-0.52-serveralives/common-session.c
*** dropbear-0.52/common-session.c	2008-11-11 06:09:02.000000000 -0800
--- dropbear-0.52-serveralives/common-session.c	2009-12-11 16:37:01.000000000 -0800
***************
*** 37,42 ****
--- 37,43 ----
  #include "runopts.h"
  
  static void checktimeouts();
+ static void checkalive();
  static long select_timeout();
  static int ident_readln(int fd, char* buf, int count);
  
***************
*** 64,69 ****
--- 65,71 ----
  
  	ses.connect_time = 0;
  	ses.last_trx_packet_time = 0;
+ 	ses.last_recv_packet_time = 0;
  	ses.last_packet_time = 0;
  	
  	if (pipe(ses.signal_pipe) < 0) {
***************
*** 124,129 ****
--- 126,133 ----
  
  	ses.allowprivport = 0;
  
+ 	ses.checkalivetimeouts = 0;
+ 
  	TRACE(("leave session_init"))
  }
  
***************
*** 174,179 ****
--- 178,187 ----
  			FD_ZERO(&writefd);
  			FD_ZERO(&readfd);
  		}
+ 
+ 		if (val == 0) {
+ 			checkalive();
+ 		}
  		
  		/* We'll just empty out the pipe if required. We don't do
  		any thing with the data, since the pipe's purpose is purely to
***************
*** 375,380 ****
--- 383,396 ----
  	encrypt_packet();
  }
  
+ void send_check_alive() {
+ 	CHECKCLEARTOWRITE();
+ 	buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
+ 	buf_putstring(ses.writepayload, "p...@dropbear", strlen("p...@dropbear"));
+ 	buf_putbyte(ses.writepayload, 1); /* want_reply */
+ 	encrypt_packet();
+ }
+ 
  /* Check all timeouts which are required. Currently these are the time for
   * user authentication, and the automatic rekeying. */
  static void checktimeouts() {
***************
*** 410,415 ****
--- 426,453 ----
  	}
  }
  
+ /* When I tried to put this into checktimeouts (causing it to run even
+  * if select returned > 0) it broke dbclient. It would erroneously
+  * think the other side didn't respond in time and exit early.
+  */
+ static void checkalive() {
+ 
+ 	time_t now;
+ 
+ 	now = time(NULL);
+ 
+ 	if (opts.checkalive_secs > 0 && opts.checkalive_count_max > 0
+ 			&& ses.last_recv_packet_time > 0
+ 			&& now - ses.last_recv_packet_time >= opts.checkalive_secs) {
+ 		if (++ses.checkalivetimeouts > opts.checkalive_count_max) {
+ 			dropbear_exit("Timeout contacting %s",
+ 				      (IS_DROPBEAR_CLIENT) ? "server" : "client");
+ 		}
+ 		/* send a server/client alive request */
+ 		send_check_alive();
+ 	}
+ }
+ 
  static long select_timeout() {
  	/* determine the minimum timeout that might be required, so
  	as to avoid waking when unneccessary */
***************
*** 420,427 ****
  		ret = MIN(AUTH_TIMEOUT, ret);
  	if (opts.keepalive_secs > 0)
  		ret = MIN(opts.keepalive_secs, ret);
!     if (opts.idle_timeout_secs > 0)
!         ret = MIN(opts.idle_timeout_secs, ret);
  	return ret;
  }
  
--- 458,467 ----
  		ret = MIN(AUTH_TIMEOUT, ret);
  	if (opts.keepalive_secs > 0)
  		ret = MIN(opts.keepalive_secs, ret);
!         if (opts.idle_timeout_secs > 0)
! 		ret = MIN(opts.idle_timeout_secs, ret);
! 	if (opts.checkalive_secs > 0)
! 		ret = MIN(opts.checkalive_secs, ret);
  	return ret;
  }
  
Only in dropbear-0.52-serveralives: config.log
Only in dropbear-0.52-serveralives: config.status
Only in dropbear-0.52-serveralives/libtomcrypt: Makefile
Only in dropbear-0.52-serveralives/libtomcrypt/src/misc: mpi
Only in dropbear-0.52-serveralives/libtomcrypt/src/pk: dh
Only in dropbear-0.52-serveralives/libtomcrypt/src: prng
Only in dropbear-0.52-serveralives/libtommath: Makefile
diff -cr dropbear-0.52/options.h dropbear-0.52-serveralives/options.h
*** dropbear-0.52/options.h	2008-11-11 06:13:50.000000000 -0800
--- dropbear-0.52-serveralives/options.h	2009-12-10 17:01:02.000000000 -0800
***************
*** 262,267 ****
--- 262,285 ----
  be overridden at runtime with -I. 0 disables idle timeouts */
  #define DEFAULT_IDLE_TIMEOUT 0
  
+ /* Server only: ensure that the client is alive every CLIENTALIVE seconds.
+ This can be overriden at runtime with -A. O disables checkalives */
+ #define DEFAULT_CLIENTALIVE 0
+ 
+ /* Server only: Maximum number of client alive requests that be be sent
+ without receiving a responses from the server. Once this threshold is reached,
+ the session will be disconnected. */
+ #define DEFAULT_CLIENTALIVE_COUNT_MAX 3
+ 
+ /* Client only: ensure that the server is alive every SERVERALIVE seconds.
+ This can be overriden at runtime with -A. O disables checkalives */
+ #define DEFAULT_SERVERALIVE 0
+ 
+ /* Server only: Maximum number of server alive requests that be be sent
+ without receiving a responses from the server. Once this threshold is reached,
+ the session will be disconnected. */
+ #define DEFAULT_SERVERALIVE_COUNT_MAX 3
+ 
  /* The default path. This will often get replaced by the shell */
  #define DEFAULT_PATH "/usr/bin:/bin"
  
diff -cr dropbear-0.52/process-packet.c dropbear-0.52-serveralives/process-packet.c
*** dropbear-0.52/process-packet.c	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/process-packet.c	2009-12-10 17:01:02.000000000 -0800
***************
*** 70,76 ****
  			dropbear_close("Disconnect received");
  	}
  
!     ses.last_packet_time = time(NULL);
  
  	/* This applies for KEX, where the spec says the next packet MUST be
  	 * NEWKEYS */
--- 70,77 ----
  			dropbear_close("Disconnect received");
  	}
  
! 	ses.last_recv_packet_time = time(NULL);
! 	ses.last_packet_time = time(NULL);
  
  	/* This applies for KEX, where the spec says the next packet MUST be
  	 * NEWKEYS */
diff -cr dropbear-0.52/runopts.h dropbear-0.52-serveralives/runopts.h
*** dropbear-0.52/runopts.h	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/runopts.h	2009-12-10 17:01:02.000000000 -0800
***************
*** 39,45 ****
  	unsigned int recv_window;
  	unsigned int keepalive_secs;
  	unsigned int idle_timeout_secs;
! 
  } runopts;
  
  extern runopts opts;
--- 39,46 ----
  	unsigned int recv_window;
  	unsigned int keepalive_secs;
  	unsigned int idle_timeout_secs;
! 	unsigned int checkalive_secs;
! 	unsigned int checkalive_count_max;
  } runopts;
  
  extern runopts opts;
diff -cr dropbear-0.52/session.h dropbear-0.52-serveralives/session.h
*** dropbear-0.52/session.h	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/session.h	2009-12-10 17:01:02.000000000 -0800
***************
*** 46,51 ****
--- 46,52 ----
  void common_session_cleanup();
  void session_identification();
  void send_msg_ignore();
+ void send_check_alive();
  
  const char* get_user_shell();
  void fill_passwd(const char* username);
***************
*** 154,159 ****
--- 155,164 ----
  	time_t last_trx_packet_time; /* time of the last packet transmission, for
  							keepalive purposes */
  
+ 	time_t last_recv_packet_time; /* time of the last packet
+ 					 receive, for server alive
+ 					 purposes */
+ 
  	time_t last_packet_time; /* time of the last packet transmission or receive, for
  								idle timeout purposes */
  
***************
*** 202,207 ****
--- 207,214 ----
  	 * really belong here, but nowhere else fits nicely */
  	int allowprivport;
  
+ 	int checkalivetimeouts;
+ 
  };
  
  struct serversession {
diff -cr dropbear-0.52/svr-runopts.c dropbear-0.52-serveralives/svr-runopts.c
*** dropbear-0.52/svr-runopts.c	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/svr-runopts.c	2009-12-10 17:01:02.000000000 -0800
***************
*** 82,87 ****
--- 82,88 ----
  #endif
  					"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
  					"-K <keepalive>  (0 is never, default %d)\n"
+ 					"-A <clientalive>  (0 is never, default %d)\n"
  					"-I <idle_timeout>  (0 is never, default %d)\n"
  #ifdef DEBUG_TRACE
  					"-v		verbose (compiled with DEBUG_TRACE)\n"
***************
*** 94,100 ****
  					RSA_PRIV_FILENAME,
  #endif
  					DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
! 					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_IDLE_TIMEOUT);
  }
  
  void svr_getopts(int argc, char ** argv) {
--- 95,102 ----
  					RSA_PRIV_FILENAME,
  #endif
  					DROPBEAR_MAX_PORTS, DROPBEAR_DEFPORT, DROPBEAR_PIDFILE,
! 					DEFAULT_RECV_WINDOW, DEFAULT_KEEPALIVE, DEFAULT_CLIENTALIVE,
! 					DEFAULT_IDLE_TIMEOUT);
  }
  
  void svr_getopts(int argc, char ** argv) {
***************
*** 105,110 ****
--- 107,113 ----
  	char* recv_window_arg = NULL;
  	char* keepalive_arg = NULL;
  	char* idle_timeout_arg = NULL;
+ 	char* clientalive_arg = NULL;
  
  	/* see printhelp() for options */
  	svr_opts.rsakeyfile = NULL;
***************
*** 138,144 ****
  	opts.recv_window = DEFAULT_RECV_WINDOW;
  	opts.keepalive_secs = DEFAULT_KEEPALIVE;
  	opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
! 	
  #ifdef ENABLE_SVR_REMOTETCPFWD
  	opts.listen_fwd_all = 0;
  #endif
--- 141,149 ----
  	opts.recv_window = DEFAULT_RECV_WINDOW;
  	opts.keepalive_secs = DEFAULT_KEEPALIVE;
  	opts.idle_timeout_secs = DEFAULT_IDLE_TIMEOUT;
! 	opts.checkalive_secs = DEFAULT_SERVERALIVE;
! 	opts.checkalive_count_max = DEFAULT_SERVERALIVE_COUNT_MAX;
! 
  #ifdef ENABLE_SVR_REMOTETCPFWD
  	opts.listen_fwd_all = 0;
  #endif
***************
*** 221,226 ****
--- 226,234 ----
  				case 'K':
  					next = &keepalive_arg;
  					break;
+ 				case 'A':
+ 					next = &clientalive_arg;
+ 					break;
  				case 'I':
  					next = &idle_timeout_arg;
  					break;
***************
*** 306,311 ****
--- 314,326 ----
  			dropbear_exit("Bad idle_timeout '%s'", idle_timeout_arg);
  		}
  	}
+ 
+ 	if (clientalive_arg) {
+ 		if (m_str_to_uint(clientalive_arg, &opts.checkalive_secs) == DROPBEAR_FAILURE) {
+ 			dropbear_exit("Bad clientalive '%s'", clientalive_arg);
+ 		}
+ 	}
+ 
  }
  
  static void addportandaddress(char* spec) {
diff -cr dropbear-0.52/svr-session.c dropbear-0.52-serveralives/svr-session.c
*** dropbear-0.52/svr-session.c	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/svr-session.c	2009-12-11 16:40:42.000000000 -0800
***************
*** 41,46 ****
--- 41,50 ----
  #include "runopts.h"
  
  static void svr_remoteclosed();
+ static void send_msg_request_success();
+ static void send_msg_request_failure();
+ static void svr_recv_msg_global_request();
+ static void svr_recv_msg_keep_alive();
  
  struct serversession svr_ses; /* GLOBAL */
  
***************
*** 52,60 ****
  	{SSH_MSG_KEXINIT, recv_msg_kexinit},
  	{SSH_MSG_KEXDH_INIT, recv_msg_kexdh_init}, /* server */
  	{SSH_MSG_NEWKEYS, recv_msg_newkeys},
! #ifdef ENABLE_SVR_REMOTETCPFWD
! 	{SSH_MSG_GLOBAL_REQUEST, recv_msg_global_request_remotetcp},
! #endif
  	{SSH_MSG_CHANNEL_REQUEST, recv_msg_channel_request},
  	{SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
  	{SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
--- 56,65 ----
  	{SSH_MSG_KEXINIT, recv_msg_kexinit},
  	{SSH_MSG_KEXDH_INIT, recv_msg_kexdh_init}, /* server */
  	{SSH_MSG_NEWKEYS, recv_msg_newkeys},
! 	{SSH_MSG_GLOBAL_REQUEST, svr_recv_msg_global_request},
! 	/* client alive */
! 	{SSH_MSG_REQUEST_SUCCESS, svr_recv_msg_keep_alive},
! 	{SSH_MSG_REQUEST_FAILURE, svr_recv_msg_keep_alive},
  	{SSH_MSG_CHANNEL_REQUEST, recv_msg_channel_request},
  	{SSH_MSG_CHANNEL_OPEN, recv_msg_channel_open},
  	{SSH_MSG_CHANNEL_EOF, recv_msg_channel_eof},
***************
*** 203,205 ****
--- 208,269 ----
  
  }
  
+ static void send_msg_request_success() {
+ 
+ 	CHECKCLEARTOWRITE();
+ 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
+ 	encrypt_packet();
+ 
+ }
+ 
+ static void send_msg_request_failure() {
+ 
+ 	CHECKCLEARTOWRITE();
+ 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
+ 	encrypt_packet();
+ 
+ }
+ 
+ static void svr_recv_msg_global_request() {
+ 
+ 	unsigned char* reqname = NULL;
+ 	unsigned int namelen;
+ 	unsigned int wantreply = 0;
+ 	int ret = DROPBEAR_FAILURE;
+ 
+ 	TRACE(("enter recv_msg_global_request"))
+ 
+ 	reqname = buf_getstring(ses.payload, &namelen);
+ 	wantreply = buf_getbool(ses.payload);
+ 
+ 	if (namelen > MAX_NAME_LEN) {
+ 		TRACE(("name len is wrong: %d", namelen))
+ 		goto out;
+ 	}
+ 
+ 	if ((strcmp("tcpip-forward", reqname) == 0) ||
+ 	    (strcmp("cancel-tcpip-forward", reqname) == 0)) {
+ #ifdef ENABLE_SVR_REMOTETCPFWD
+ 		ret = recv_msg_global_request_remotetcp(reqname);
+ #endif
+ 	} else {
+ 		TRACE(("reqname isn't tcpip-forward: '%s'", reqname))
+ 	}
+ 
+ out:
+ 	if (wantreply) {
+ 		if (ret == DROPBEAR_SUCCESS) {
+ 			send_msg_request_success();
+ 		} else {
+ 			send_msg_request_failure();
+ 		}
+ 	}
+ 
+ 	m_free(reqname);
+ 
+ 	TRACE(("leave recv_msg_global_request"))
+ }
+ 
+ static void svr_recv_msg_keep_alive() {
+ 	ses.checkalivetimeouts = 0;
+ }
diff -cr dropbear-0.52/svr-tcpfwd.c dropbear-0.52-serveralives/svr-tcpfwd.c
*** dropbear-0.52/svr-tcpfwd.c	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/svr-tcpfwd.c	2009-12-10 17:01:02.000000000 -0800
***************
*** 36,43 ****
  
  #ifdef ENABLE_SVR_REMOTETCPFWD
  
- static void send_msg_request_success();
- static void send_msg_request_failure();
  static int svr_cancelremotetcp();
  static int svr_remotetcpreq();
  static int newtcpdirect(struct Channel * channel);
--- 36,41 ----
***************
*** 64,74 ****
  /* At the moment this is completely used for tcp code (with the name reflecting
   * that). If new request types are added, this should be replaced with code
   * similar to the request-switching in chansession.c */
! void recv_msg_global_request_remotetcp() {
  
- 	unsigned char* reqname = NULL;
- 	unsigned int namelen;
- 	unsigned int wantreply = 0;
  	int ret = DROPBEAR_FAILURE;
  
  	TRACE(("enter recv_msg_global_request_remotetcp"))
--- 62,69 ----
  /* At the moment this is completely used for tcp code (with the name reflecting
   * that). If new request types are added, this should be replaced with code
   * similar to the request-switching in chansession.c */
! int recv_msg_global_request_remotetcp(unsigned char *reqname) {
  
  	int ret = DROPBEAR_FAILURE;
  
  	TRACE(("enter recv_msg_global_request_remotetcp"))
***************
*** 78,91 ****
  		goto out;
  	}
  
- 	reqname = buf_getstring(ses.payload, &namelen);
- 	wantreply = buf_getbool(ses.payload);
- 
- 	if (namelen > MAX_NAME_LEN) {
- 		TRACE(("name len is wrong: %d", namelen))
- 		goto out;
- 	}
- 
  	if (strcmp("tcpip-forward", reqname) == 0) {
  		ret = svr_remotetcpreq();
  	} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
--- 73,78 ----
***************
*** 95,129 ****
  	}
  
  out:
! 	if (wantreply) {
! 		if (ret == DROPBEAR_SUCCESS) {
! 			send_msg_request_success();
! 		} else {
! 			send_msg_request_failure();
! 		}
! 	}
! 
! 	m_free(reqname);
! 
! 	TRACE(("leave recv_msg_global_request"))
! }
! 
! 
! static void send_msg_request_success() {
! 
! 	CHECKCLEARTOWRITE();
! 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
! 	encrypt_packet();
! 
  }
  
- static void send_msg_request_failure() {
- 
- 	CHECKCLEARTOWRITE();
- 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
- 	encrypt_packet();
- 
- }
  
  static int matchtcp(void* typedata1, void* typedata2) {
  
--- 82,91 ----
  	}
  
  out:
! 	TRACE(("leave recv_msg_global_request_remotetcp"))
! 	return ret;
  }
  
  
  static int matchtcp(void* typedata1, void* typedata2) {
  
diff -cr dropbear-0.52/tcpfwd.h dropbear-0.52-serveralives/tcpfwd.h
*** dropbear-0.52/tcpfwd.h	2008-11-11 06:09:03.000000000 -0800
--- dropbear-0.52-serveralives/tcpfwd.h	2009-12-10 17:01:02.000000000 -0800
***************
*** 56,62 ****
  };
  
  /* Server */
! void recv_msg_global_request_remotetcp();
  
  extern const struct ChanType svr_chan_tcpdirect;
  
--- 56,62 ----
  };
  
  /* Server */
! int recv_msg_global_request_remotetcp(unsigned char *reqname);
  
  extern const struct ChanType svr_chan_tcpdirect;
  
***************
*** 64,71 ****
  void setup_localtcp();
  void setup_remotetcp();
  extern const struct ChanType cli_chan_tcpremote;
! void cli_recv_msg_request_success();
! void cli_recv_msg_request_failure();
  
  /* Common */
  int listen_tcpfwd(struct TCPListener* tcpinfo);
--- 64,71 ----
  void setup_localtcp();
  void setup_remotetcp();
  extern const struct ChanType cli_chan_tcpremote;
! void cli_recv_msg_fwd_request_success();
! void cli_recv_msg_fwd_request_failure();
  
  /* Common */
  int listen_tcpfwd(struct TCPListener* tcpinfo);

Reply via email to