Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-updates-src > by-pkgid > 765b0ce55b9baa6c70749f0319c589c7 > files > 5

openssh-6.6p1-5.3.mga5.src.rpm

diff -Naurp openssh-5.3p1/clientloop.c openssh-5.3p1.oden/clientloop.c
--- openssh-5.3p1/clientloop.c	2009-08-28 03:21:07.000000000 +0200
+++ openssh-5.3p1.oden/clientloop.c	2009-10-07 17:39:17.000000000 +0200
@@ -155,6 +155,7 @@ static Buffer stderr_buffer;	/* Buffer f
 static u_int buffer_high;/* Soft max buffer size. */
 static int connection_in;	/* Connection to server (input). */
 static int connection_out;	/* Connection to server (output). */
+static time_t idle_time_last; /* Last time of packet transmission. */
 static int need_rekeying;	/* Set to non-zero if rekeying is requested. */
 static int session_closed = 0;	/* In SSH2: login session closed. */
 
@@ -568,16 +569,19 @@ client_wait_until_can_do_something(fd_se
 	 * event pending.
 	 */
 
-	if (options.server_alive_interval == 0 || !compat20)
-		tvp = NULL;
-	else {
+	if (options.server_alive_interval != 0 && compat20){
 		tv.tv_sec = options.server_alive_interval;
-		tv.tv_usec = 0;
+ 		tv.tv_usec = 0;
+ 		tvp = &tv;
+ 	}
+	else{
+		tv.tv_sec = 0;
+		tv.tv_usec = 500 * 1000;	/* time slot is 0.5sec */
 		tvp = &tv;
 	}
-	ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
-	if (ret < 0) {
-		char buf[100];
+  	ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+  	if (ret < 0) {
+  		char buf[100];
 
 		/*
 		 * We have to clear the select masks, because we return.
@@ -593,8 +597,43 @@ client_wait_until_can_do_something(fd_se
 		snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
 		buffer_append(&stderr_buffer, buf, strlen(buf));
 		quit_pending = 1;
-	} else if (ret == 0)
-		server_alive_check();
+	} else if (ret == 0){
+		if (options.server_alive_interval != 0 && compat20){
+			server_alive_check();
+		}
+	}
+
+	/* If the output channel has been silent for more than a specified
+	 * time, send a keepalive packet (heartbeat) to the server.
+	 * Keepalive packet is useful for keeping the connection over
+	 * IP masquerade / NAT boxes, firewalls, etc.
+	 * Some servers equipped with a watchdog timer require keepalive
+	 * packets (heartbeats) to detect link down.
+	 *
+	 * Note: Although the interval between keepalive packets is not
+	 * very precise, it's okay.
+	 *
+	 * Note: Some old servers may crash when they receive SSH_MSG_IGNORE.
+	 * Those who want to connect to such a server should turn this
+	 * function off by the option setting (e.g. Heartbeat 0).
+	 */
+	if (options.heartbeat_interval > 0) {
+		if (FD_ISSET(connection_out,*writesetp)) {
+			/* Update the time of last data transmission. */
+			idle_time_last = time(NULL);
+		}
+		if (time(NULL) - idle_time_last >= (int)options.heartbeat_interval){
+			if (compat20) {
+				packet_start(SSH2_MSG_IGNORE);
+			}
+			else {
+				packet_start(SSH_MSG_IGNORE);
+			}
+			packet_put_string("", 0);
+			packet_send();
+			/* fputs("*",stderr); */
+		}
+	}
 }
 
 static void
@@ -1312,6 +1351,7 @@ client_loop(int have_pty, int escape_cha
 	debug("Entering interactive session.");
 
 	start_time = get_current_time();
+	idle_time_last = time(NULL);
 
 	/* Initialize variables. */
 	escape_pending1 = 0;
diff -Naurp openssh-5.3p1/readconf.c openssh-5.3p1.oden/readconf.c
--- openssh-5.3p1/readconf.c	2009-07-05 23:12:27.000000000 +0200
+++ openssh-5.3p1.oden/readconf.c	2009-10-07 17:39:17.000000000 +0200
@@ -118,7 +118,7 @@ typedef enum {
 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
-	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
+	oCompressionLevel, oTCPKeepAlive, oHeartbeat, oNumberOfPasswordPrompts,
 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
@@ -199,6 +199,7 @@ static struct {
 	{ "compressionlevel", oCompressionLevel },
 	{ "tcpkeepalive", oTCPKeepAlive },
 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
+	{ "heartbeat", oHeartbeat },
 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
 	{ "loglevel", oLogLevel },
 	{ "dynamicforward", oDynamicForward },
@@ -502,6 +503,10 @@ parse_yesnoask:
 		intptr = &options->no_host_authentication_for_localhost;
 		goto parse_flag;
 
+	case oHeartbeat:
+		intptr = &options->heartbeat_interval;
+		goto parse_int;
+
 	case oNumberOfPasswordPrompts:
 		intptr = &options->number_of_password_prompts;
 		goto parse_int;
@@ -1024,6 +1029,7 @@ initialize_options(Options * options)
 	options->strict_host_key_checking = -1;
 	options->compression = -1;
 	options->tcp_keep_alive = -1;
+	options->heartbeat_interval = -1;
 	options->compression_level = -1;
 	options->port = -1;
 	options->address_family = -1;
@@ -1125,6 +1131,8 @@ fill_default_options(Options * options)
 		options->compression = 0;
 	if (options->tcp_keep_alive == -1)
 		options->tcp_keep_alive = 1;
+	if (options->heartbeat_interval == -1)
+		options->heartbeat_interval = 0;	/* 0 means "no heartbeat" */
 	if (options->compression_level == -1)
 		options->compression_level = 6;
 	if (options->port == -1)
diff -Naurp openssh-5.3p1/readconf.h openssh-5.3p1.oden/readconf.h
--- openssh-5.3p1/readconf.h	2009-07-05 23:12:27.000000000 +0200
+++ openssh-5.3p1.oden/readconf.h	2009-10-07 17:39:17.000000000 +0200
@@ -57,6 +57,9 @@ typedef struct {
 	int     compression_level;	/* Compression level 1 (fast) to 9
 					 * (best). */
 	int     tcp_keep_alive;	/* Set SO_KEEPALIVE. */
+	int     heartbeat_interval;	/* Number of seconds between keepalive
+					 * packets (heartbeats) over encrypted
+					 * channel. (in secs.) */
 	LogLevel log_level;	/* Level for logging. */
 
 	int     port;		/* Port to connect. */
diff -Naurp openssh-5.3p1/servconf.c openssh-5.3p1.oden/servconf.c
--- openssh-5.3p1/servconf.c	2009-06-21 12:26:17.000000000 +0200
+++ openssh-5.3p1.oden/servconf.c	2009-10-07 17:39:17.000000000 +0200
@@ -80,6 +80,8 @@ initialize_server_options(ServerOptions 
 	options->xauth_location = NULL;
 	options->strict_modes = -1;
 	options->tcp_keep_alive = -1;
+	options->watchdog_timeout = -1;
+	options->watchdog_timeout1 = -1;
 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
 	options->log_level = SYSLOG_LEVEL_NOT_SET;
 	options->rhosts_rsa_authentication = -1;
@@ -186,6 +188,10 @@ fill_default_server_options(ServerOption
 		options->strict_modes = 1;
 	if (options->tcp_keep_alive == -1)
 		options->tcp_keep_alive = 1;
+	if (options->watchdog_timeout == -1)
+		options->watchdog_timeout = 0;  /* 0 means "no timeout" */
+	if (options->watchdog_timeout1 == -1)
+		options->watchdog_timeout1 = 0;  /* 0 means "no timeout" */
 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
 		options->log_facility = SYSLOG_FACILITY_AUTH;
 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
@@ -293,7 +299,7 @@ typedef enum {
 	sListenAddress, sAddressFamily,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
-	sStrictModes, sEmptyPasswd, sTCPKeepAlive,
+	sStrictModes, sEmptyPasswd, sTCPKeepAlive, sWatchdogTimeout, sWatchdogTimeout1,
 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
@@ -395,6 +401,8 @@ static struct {
 	{ "compression", sCompression, SSHCFG_GLOBAL },
 	{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
 	{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },	/* obsolete alias */
+	{ "watchdogtimeout", sWatchdogTimeout, SSHCFG_GLOBAL },
+	{ "watchdogtimeout1", sWatchdogTimeout1, SSHCFG_GLOBAL },
 	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
 	{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
 	{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
@@ -943,6 +951,14 @@ process_server_config_line(ServerOptions
 		intptr = &options->tcp_keep_alive;
 		goto parse_flag;
 
+	case sWatchdogTimeout:
+		intptr = &options->watchdog_timeout;
+		goto parse_int;
+
+	case sWatchdogTimeout1:
+		intptr = &options->watchdog_timeout1;
+		goto parse_int;
+
 	case sEmptyPasswd:
 		intptr = &options->permit_empty_passwd;
 		goto parse_flag;
diff -Naurp openssh-5.3p1/servconf.h openssh-5.3p1.oden/servconf.h
--- openssh-5.3p1/servconf.h	2009-01-28 06:31:23.000000000 +0100
+++ openssh-5.3p1.oden/servconf.h	2009-10-07 17:39:17.000000000 +0200
@@ -67,6 +67,10 @@ typedef struct {
 	char   *xauth_location;	/* Location of xauth program */
 	int     strict_modes;	/* If true, require string home dir modes. */
 	int     tcp_keep_alive;	/* If true, set SO_KEEPALIVE. */
+	int     watchdog_timeout, watchdog_timeout1;
+				/* Timeout of the watchdog timer which
+				   checks the input activities over
+				   encrypted channel. (in secs.) */
 	char   *ciphers;	/* Supported SSH2 ciphers. */
 	char   *macs;		/* Supported SSH2 macs. */
 	int	protocol;	/* Supported protocol versions. */
diff -Naurp openssh-5.3p1/serverloop.c openssh-5.3p1.oden/serverloop.c
--- openssh-5.3p1/serverloop.c	2009-09-09 03:07:28.000000000 +0200
+++ openssh-5.3p1.oden/serverloop.c	2009-10-07 17:40:09.000000000 +0200
@@ -107,6 +107,8 @@ static int connection_out;	/* Connection
 static int connection_closed = 0;	/* Connection to client closed. */
 static u_int buffer_high;	/* "Soft" max buffer size. */
 static int no_more_sessions = 0; /* Disallow further sessions. */
+static time_t idle_time_last; /* Last time of packet receipt. */
+static int child_forced_to_terminate; /* The child will be killed by sshd. */
 
 /*
  * This SIGCHLD kludge is used to detect when the child exits.  The server
@@ -281,6 +283,7 @@ wait_until_can_do_something(fd_set **rea
 {
 	struct timeval tv, *tvp;
 	int ret;
+	int watchdog_timeout = 0;
 	int client_alive_scheduled = 0;
 	int program_alive_scheduled = 0;
 
@@ -350,6 +353,19 @@ wait_until_can_do_something(fd_set **rea
 		if (max_time_milliseconds == 0 || client_alive_scheduled)
 			max_time_milliseconds = 100;
 
+	/* When the watchdog is needed, set the maximum length
+	 * of timeout to 0.25sec.
+	 */
+	watchdog_timeout = options.watchdog_timeout;
+	if (!compat20 && options.watchdog_timeout1 > 0){
+		watchdog_timeout = options.watchdog_timeout1;
+	}
+	if (watchdog_timeout > 0) {
+		if (max_time_milliseconds == 0 || max_time_milliseconds > 250) {
+			max_time_milliseconds = 250;
+		}
+	}
+
 	if (max_time_milliseconds == 0)
 		tvp = NULL;
 	else {
@@ -377,6 +393,23 @@ wait_until_can_do_something(fd_set **rea
 		}
 	}
 
+ 	/*
+ 	 * Watchdog timer:
+ 	 * If the input channel has been silent for more than the specified
+ 	 * time, try to kill the child process(es) to protect server resources.
+ 	 */
+ 	if (watchdog_timeout > 0) {
+ 		if (FD_ISSET(connection_in,*readsetp)) {
+ 			/* Update the time of last data receipt. */
+ 			idle_time_last = time(NULL);
+ 			/* fputs("*",stderr); */
+ 		}
+ 		if (!child_terminated && \
+ 		    (time(NULL) - idle_time_last) > watchdog_timeout) {
+ 			child_forced_to_terminate = 1;
+ 		}
+ 	}
+
 	notify_done(*readsetp);
 }
 
@@ -560,7 +593,9 @@ server_loop(pid_t pid, int fdin_arg, int
 	u_int max_time_milliseconds;
 	u_int previous_stdout_buffer_bytes;
 	u_int stdout_buffer_bytes;
-	int type;
+	int type, i;
+
+	child_forced_to_terminate = 0;
 
 	debug("Entering interactive session.");
 
@@ -627,6 +662,8 @@ server_loop(pid_t pid, int fdin_arg, int
 
 	server_init_dispatch();
 
+	idle_time_last = time(NULL);
+
 	/* Main loop of the server for the interactive session mode. */
 	for (;;) {
 
@@ -707,6 +744,9 @@ server_loop(pid_t pid, int fdin_arg, int
 			cleanup_exit(255);
 		}
 
+		/* Break, if watchdog timeout occured. */
+		if (child_forced_to_terminate)  break;
+
 		/* Process any channel events. */
 		channel_after_select(readset, writeset);
 
@@ -716,6 +756,24 @@ server_loop(pid_t pid, int fdin_arg, int
 		/* Process output to the client and to program stdin. */
 		process_output(writeset);
 	}
+
+	/*
+	 * If the child should be terminated due to
+	 * watchdog timeout, send kill signal to the child.
+	 */
+	if (child_forced_to_terminate) {
+		/* We won't have pid=0. However, for safety... */
+		if ( pid != 0 ){
+			kill(pid, SIGHUP);
+			for (i=0 ; i<5 ; i++){
+				sleep(1);
+				if (child_terminated)  break;
+			}
+			if (i>=5)  kill(pid, SIGKILL);
+ 			logit("Warning: Command has been killed due to watchdog timeout.");
+		}
+	}
+
 	if (readset)
 		xfree(readset);
 	if (writeset)
@@ -724,7 +782,9 @@ server_loop(pid_t pid, int fdin_arg, int
 	/* Cleanup and termination code. */
 
 	/* Wait until all output has been sent to the client. */
-	drain_output();
+	if (!child_forced_to_terminate) {
+		drain_output();
+	}
 
 	debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
 	    stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
@@ -752,6 +812,12 @@ server_loop(pid_t pid, int fdin_arg, int
 	/* We no longer want our SIGCHLD handler to be called. */
 	mysignal(SIGCHLD, SIG_DFL);
 
+ 	/* If the child has been terminated, free the session and exit here. */
+ 	if (child_forced_to_terminate) {
+ 		session_destroy_all(NULL);
+ 		return;
+ 	}
+ 
 	while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0)
 		if (errno != EINTR)
 			packet_disconnect("wait: %.100s", strerror(errno));
@@ -825,6 +891,7 @@ server_loop2(Authctxt *authctxt)
 
 	mysignal(SIGCHLD, sigchld_handler);
 	child_terminated = 0;
+	child_forced_to_terminate = 0;
 	connection_in = packet_get_connection_in();
 	connection_out = packet_get_connection_out();
 
@@ -841,6 +908,8 @@ server_loop2(Authctxt *authctxt)
 
 	server_init_dispatch();
 
+	idle_time_last = time(NULL);
+
 	for (;;) {
 		process_buffered_input_packets();
 
@@ -857,6 +926,12 @@ server_loop2(Authctxt *authctxt)
 			cleanup_exit(255);
 		}
 
+		/* Terminate child processes, if watchdog timeout occured. */
+		if (child_forced_to_terminate){
+			packet_disconnect("Command has been killed due to watchdog timeout.");
+			logit("Warning: Command has been killed due to watchdog timeout.");
+		}
+
 		collect_children();
 		if (!rekeying) {
 			channel_after_select(readset, writeset);
diff -Naurp openssh-5.3p1/ssh.1 openssh-5.3p1.oden/ssh.1
--- openssh-5.3p1/ssh.1	2009-06-21 09:48:52.000000000 +0200
+++ openssh-5.3p1.oden/ssh.1	2009-10-07 17:39:17.000000000 +0200
@@ -453,6 +453,7 @@ For full details of the options listed b
 .It GSSAPIAuthentication
 .It GSSAPIDelegateCredentials
 .It HashKnownHosts
+.It Heartbeat
 .It Host
 .It HostbasedAuthentication
 .It HostKeyAlgorithms
diff -Naurp openssh-5.3p1/ssh_config.5 openssh-5.3p1.oden/ssh_config.5
--- openssh-5.3p1/ssh_config.5	2009-02-23 00:53:58.000000000 +0100
+++ openssh-5.3p1.oden/ssh_config.5	2009-10-07 17:39:17.000000000 +0200
@@ -500,6 +500,23 @@ Note that existing names and addresses i
 will not be converted automatically,
 but may be manually hashed using
 .Xr ssh-keygen 1 .
+.It Cm Heartbeat
+Specifies the interval between heartbeats, in seconds.  If the output
+channel has been silent for more than the specified time, a null message
+(SSH_MSG_IGNORE) is sent to the server.
+.Cm Heartbeat
+is useful for keeping alive connections over IP masquerade / NAT boxes,
+firewalls, etc., that implement connection timeouts, and in combination
+with the
+.Cm WatchdogTimeout
+option to
+.Xr sshd 8 .
+Heartbeat does not work if
+.Cm ServerAliveInterval
+is enabled at the same time.
+The default is
+.Dq 0 ,
+which disables the hearbeat.
 .It Cm HostbasedAuthentication
 Specifies whether to try rhosts based authentication with public key
 authentication.
diff -Naurp openssh-5.3p1/sshd_config.5 openssh-5.3p1.oden/sshd_config.5
--- openssh-5.3p1/sshd_config.5	2009-08-28 02:27:08.000000000 +0200
+++ openssh-5.3p1.oden/sshd_config.5	2009-10-07 17:39:17.000000000 +0200
@@ -939,6 +939,30 @@ The goal of privilege separation is to p
 escalation by containing any corruption within the unprivileged processes.
 The default is
 .Dq yes .
+.It Cm WatchdogTimeout
+Specifies the watchdog timeout interval, in seconds.
+If a session input channel has been silent for more than the specified interval,
+.Cm sshd
+terminates the session by killing the child process(es).  Only input
+packets from the client reset the watchdog timer; this makes it possible
+to terminate a session even if the serever continues sending some data
+to the client.
+When used in combination with
+.Cm ClientAliveInterval
+and/or the
+.Cm Heartbeat
+option of
+.Xr ssh 1
+this feature will detect and terminate hung sessions over unreliable
+networks, without interfering with normal usage.
+The default is
+.Dq 0 ,
+which disables the watchdog.
+.It Cm WatchdogTimeout1
+Specifies the watchdog timeout interval, in seconds, for SSH1 protocol
+only.  See the 
+.Cm WatchdogTimeout
+option.
 .It Cm X11DisplayOffset
 Specifies the first display number available for
 .Xr sshd 8 Ns 's