Idletimeout patch

Jani Jaakkola jjaakkol at cs.Helsinki.FI
Thu Aug 16 22:04:19 EST 2001


While I was updating our ssh-servers, I rewrote my old patch that adds
idletimeout (just like in old ssh1) parameter to openssh. Since reapplying
the patch for all new versions of openssh is not fun at all, I would like
to have it included in the official openssh, if you consider the patch
worthy.

Unlike ClientAlive, idletimeout works for both protocol versions. It also
works together with ClientAlive (however, the code which prevents
clientalive-messages from resetting idletimeout is not foolproof.
Foolproof patch would require to add different idletimeout support to
different packets, which would be too complex).

It adds two time() syscalls to select loop, but only if idletimeout is
used in the configuration file.

Attached patch (also available from
http://www.cs.helsinki.fi/u/jjaakkol/idletimeout.patch
) is against openssh-2.9p2. If you will include it in the
official openssh, I would be very happy to also document it.

- Jani

-------------- next part --------------
diff -ru openssh-2.9p2.orig/CREDITS openssh-2.9p2/CREDITS
--- openssh-2.9p2.orig/CREDITS	Mon Apr 16 03:41:46 2001
+++ openssh-2.9p2/CREDITS	Wed Aug 15 22:00:02 2001
@@ -42,6 +42,7 @@
 IWAMURO Motonori <iwa at mmp.fujitsu.co.jp> - bugfixes
 Jani Hakala <jahakala at cc.jyu.fi> - Patches
 Jarno Huuskonen <jhuuskon at hytti.uku.fi> - Bugfixes
+Jani Jaakkola <jjaakkol at cs.helsinki.fi> - IdleTimeOut
 Jim Knoble <jmknoble at jmknoble.cx> - Many patches
 Jonchen (email unknown) - the original author of PAM support of SSH
 Juergen Keil <jk at tools.de> - scp bugfixing
diff -ru openssh-2.9p2.orig/servconf.c openssh-2.9p2/servconf.c
--- openssh-2.9p2.orig/servconf.c	Wed Apr 25 15:44:15 2001
+++ openssh-2.9p2/servconf.c	Wed Aug 15 22:10:23 2001
@@ -102,6 +102,7 @@
 	options->client_alive_interval = -1;
 	options->client_alive_count_max = -1;
 	options->pam_authentication_via_kbd_int = -1;
+	options->idletimeout = -1;
 }
 
 void
@@ -210,6 +211,8 @@
 		options->client_alive_count_max = 3;
 	if (options->pam_authentication_via_kbd_int == -1)
 		options->pam_authentication_via_kbd_int = 0;
+	if (options->idletimeout == -1)
+		options->idletimeout=0;
 }
 
 /* Keyword tokens. */
@@ -235,7 +238,8 @@
 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
 	sBanner, sReverseMappingCheck, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 
-	sClientAliveCountMax, sPAMAuthenticationViaKbdInt
+	sClientAliveCountMax, sPAMAuthenticationViaKbdInt,
+	sIdleTimeout
 } ServerOpCodes;
 
 /* Textual representation of the tokens. */
@@ -302,6 +306,7 @@
 	{ "clientaliveinterval", sClientAliveInterval },
 	{ "clientalivecountmax", sClientAliveCountMax },
 	{ "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt },
+	{ "idletimeout", sIdleTimeout },
 	{ NULL, 0 }
 };
 
@@ -801,7 +806,28 @@
 		case sPAMAuthenticationViaKbdInt:
 			intptr = &options->pam_authentication_via_kbd_int;
 			goto parse_flag;
-
+               case sIdleTimeout:
+			arg = strdelim(&cp);
+			if (!arg || *arg == '\0')
+				fatal("%s line %d: Missing IdleTimeout argument",
+					filename,linenum);
+			options->idletimeout=atoi(arg);
+			switch(arg[strlen(arg)-1]) {
+				case 'w': options->idletimeout*=7;
+				case 'd': options->idletimeout*=24;
+				case 'h': options->idletimeout*=60;
+				case 'm': options->idletimeout*=60;
+				case 's': 
+				case '0': case '1': case '2': case '3': 
+				case '4': case '5': case '6': case '7': 
+				case '8': case '9':
+	                               break;
+				default:
+					fatal("%s line %d: Invalid IdleTimeout argument",
+						filename,linenum);
+			}
+			break;
+	
 		default:
 			fatal("%s line %d: Missing handler for opcode %s (%d)",
 			    filename, linenum, arg, opcode);
diff -ru openssh-2.9p2.orig/servconf.h openssh-2.9p2/servconf.h
--- openssh-2.9p2.orig/servconf.h	Wed Apr 25 15:44:16 2001
+++ openssh-2.9p2/servconf.h	Wed Aug 15 22:09:33 2001
@@ -125,6 +125,10 @@
 					 * diconnect the session 
 					 */
 	int	pam_authentication_via_kbd_int;
+	int	idletimeout;		/*
+					 * If nonzero, the number of second
+					 * after which idle connections
+					 * will be terminated */
 }       ServerOptions;
 /*
  * Initializes the server options to special values that indicate that they
diff -ru openssh-2.9p2.orig/serverloop.c openssh-2.9p2/serverloop.c
--- openssh-2.9p2.orig/serverloop.c	Sat Apr 14 02:28:03 2001
+++ openssh-2.9p2/serverloop.c	Thu Aug 16 14:12:14 2001
@@ -79,7 +79,8 @@
 static int connection_out;	/* Connection to client (output). */
 static int connection_closed = 0;	/* Connection to client closed. */
 static u_int buffer_high;	/* "Soft" max buffer size. */
-
+static time_t idletime_last=0; /* The last time something happened
+				* for idletimeout. */
 /*
  * This SIGCHLD kludge is used to detect when the child exits.  The server
  * will exit after that, as soon as forwarded connections have terminated.
@@ -193,7 +194,9 @@
 	struct timeval tv, *tvp;
 	int ret;
 	int client_alive_scheduled = 0;
-
+	/* Secs until idletimeout, zero if no idletimeout */
+	int max_time_seconds=0; 
+	
 	/*
 	 * if using client_alive, set the max timeout accordingly, 
 	 * and indicate that this particular timeout was for client
@@ -208,6 +211,24 @@
 	} else 
 	        client_alive_scheduled = 0;
 
+
+	if (options.idletimeout>0) {
+		if (idletime_last==0) {
+			/* Initialize idletime_last */		
+			time(&idletime_last);  
+		}
+		/* Schedule idletimeout if no other timeouts are scheduled.
+		 * Idletimeouts are the longest and it is not a big deal,
+		 * if they are missed by few seconds. */
+		if (max_time_milliseconds == 0) {
+			time_t diff=time(NULL)-idletime_last;
+			if (diff>=options.idletimeout)
+				max_time_seconds=1;
+			else 
+				max_time_seconds=options.idletimeout-diff;
+		}
+	}
+	
 	/* When select fails we restart from here. */
 retry_select:
 
@@ -258,10 +279,17 @@
 	if (child_terminated && packet_not_very_much_data_to_write())
 		if (max_time_milliseconds == 0 || client_alive_scheduled)
 			max_time_milliseconds = 100;
-
-	if (max_time_milliseconds == 0)
-		tvp = NULL;
-	else {
+	
+	if (max_time_milliseconds == 0) {
+		/* Use max_time_seconds only if max_time_milliseconds is
+		 * not set */
+		if (max_time_seconds>0) {
+			tv.tv_sec=max_time_seconds;
+			tv.tv_usec=0;
+			tvp=&tv;
+		} else
+			tvp = NULL;
+	} else {
 		tv.tv_sec = max_time_milliseconds / 1000;
 		tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
 		tvp = &tv;
@@ -301,7 +329,22 @@
 				packet_disconnect(
 					"No open channels after timeout!");
 		}
-	} 
+	}
+
+	if (options.idletimeout>0) {
+		/* Reset idletimeout if something happened.
+		 * NOTE: events events happening while there is 
+		 * active client_alive_timeouts are ignored. This way
+		 * client_alive messages won't reset idletimeout counter.*/
+		if (ret>0 && client_alive_timeouts==0) {
+			time(&idletime_last);
+		}
+		/* Check if idletimeout has happened */
+		if (ret==0 && time(NULL)-idletime_last>options.idletimeout) {
+			packet_disconnect("Idletimeout.");
+			options.idletimeout=0;
+		}
+	}
 }
 
 /*


More information about the openssh-unix-dev mailing list