- djm@cvs.openbsd.org 2008/05/08 12:21:16
     [monitor.c monitor_wrap.c session.h servconf.c servconf.h session.c]
     [sshd_config sshd_config.5]
     Make the maximum number of sessions run-time controllable via
     a sshd_config MaxSessions knob. This is useful for disabling
     login/shell/subsystem access while leaving port-forwarding working
     (MaxSessions 0), disabling connection multiplexing (MaxSessions 1) or
     simply increasing the number of allows multiplexed sessions.
     Because some bozos are sure to configure MaxSessions in excess of the
     number of available file descriptors in sshd (which, at peak, might be
     as many as 9*MaxSessions), audit sshd to ensure that it doesn't leak fds
     on error paths, and make it fail gracefully on out-of-fd conditions -
     sending channel errors instead of than exiting with fatal().
     bz#1090; MaxSessions config bits and manpage from junyer AT gmail.com
     ok markus@
diff --git a/servconf.c b/servconf.c
index b8a968a..94dff1f 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.179 2008/05/08 12:02:23 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.180 2008/05/08 12:21:16 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -114,6 +114,7 @@
 	options->max_startups_rate = -1;
 	options->max_startups = -1;
 	options->max_authtries = -1;
+	options->max_sessions = -1;
 	options->banner = NULL;
 	options->use_dns = -1;
 	options->client_alive_interval = -1;
@@ -237,6 +238,8 @@
 		options->max_startups_begin = options->max_startups;
 	if (options->max_authtries == -1)
 		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
+	if (options->max_sessions == -1)
+		options->max_sessions = DEFAULT_SESSIONS_MAX;
 	if (options->use_dns == -1)
 		options->use_dns = 1;
 	if (options->client_alive_interval == -1)
@@ -291,7 +294,7 @@
 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
-	sMaxStartups, sMaxAuthTries,
+	sMaxStartups, sMaxAuthTries, sMaxSessions,
 	sBanner, sUseDNS, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
@@ -395,6 +398,7 @@
 	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
 	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
+	{ "maxsessions", sMaxSessions, SSHCFG_ALL },
 	{ "banner", sBanner, SSHCFG_ALL },
 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
@@ -695,7 +699,7 @@
 
 	case sServerKeyBits:
 		intptr = &options->server_key_bits;
-parse_int:
+ parse_int:
 		arg = strdelim(&cp);
 		if (!arg || *arg == '\0')
 			fatal("%s line %d: missing integer value.",
@@ -707,7 +711,7 @@
 
 	case sLoginGraceTime:
 		intptr = &options->login_grace_time;
-parse_time:
+ parse_time:
 		arg = strdelim(&cp);
 		if (!arg || *arg == '\0')
 			fatal("%s line %d: missing time value.",
@@ -776,7 +780,7 @@
 			fatal("%s line %d: too many host keys specified (max %d).",
 			    filename, linenum, MAX_HOSTKEYS);
 		charptr = &options->host_key_files[*intptr];
-parse_filename:
+ parse_filename:
 		arg = strdelim(&cp);
 		if (!arg || *arg == '\0')
 			fatal("%s line %d: missing file name.",
@@ -819,7 +823,7 @@
 
 	case sIgnoreRhosts:
 		intptr = &options->ignore_rhosts;
-parse_flag:
+ parse_flag:
 		arg = strdelim(&cp);
 		if (!arg || *arg == '\0')
 			fatal("%s line %d: missing yes/no argument.",
@@ -1155,6 +1159,10 @@
 		intptr = &options->max_authtries;
 		goto parse_int;
 
+	case sMaxSessions:
+		intptr = &options->max_sessions;
+		goto parse_int;
+
 	case sBanner:
 		charptr = &options->banner;
 		goto parse_filename;
@@ -1382,6 +1390,7 @@
 	M_CP_INTOPT(x11_display_offset);
 	M_CP_INTOPT(x11_forwarding);
 	M_CP_INTOPT(x11_use_localhost);
+	M_CP_INTOPT(max_sessions);
 
 	M_CP_STROPT(banner);
 	if (preauth)