Petr Šabata 81d24c
diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c
Petr Šabata 81d24c
--- openssh-7.4p1/channels.c.x11max	2016-12-23 15:46:32.071506625 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/channels.c	2016-12-23 15:46:32.139506636 +0100
Petr Šabata 81d24c
@@ -152,8 +152,8 @@ static int all_opens_permitted = 0;
Petr Šabata 81d24c
 #define FWD_PERMIT_ANY_HOST	"*"
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 /* -- X11 forwarding */
Petr Šabata 81d24c
-/* Maximum number of fake X11 displays to try. */
Petr Šabata 81d24c
-#define MAX_DISPLAYS  1000
Petr Šabata 81d24c
+/* Minimum port number for X11 forwarding */
Petr Šabata 81d24c
+#define X11_PORT_MIN 6000
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 /* Per-channel callback for pre/post select() actions */
Petr Šabata 81d24c
 typedef void chan_fn(struct ssh *, Channel *c,
Petr Šabata 81d24c
@@ -4228,7 +4228,7 @@ channel_send_window_changes(void)
Petr Šabata 81d24c
  */
Petr Šabata 81d24c
 int
Petr Šabata 81d24c
 x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
Petr Šabata 81d24c
-    int x11_use_localhost, int single_connection,
Petr Šabata 81d24c
+    int x11_use_localhost, int x11_max_displays, int single_connection,
Petr Šabata 81d24c
     u_int *display_numberp, int **chanids)
Petr Šabata 81d24c
 {
Petr Šabata 81d24c
 	Channel *nc = NULL;
Petr Šabata 81d24c
@@ -4240,10 +4241,15 @@ x11_create_display_inet(int x11_display_
Petr Šabata 81d24c
 	if (chanids == NULL)
Petr Šabata 81d24c
 		return -1;
Petr Šabata 81d24c
 
Petr Šabata 81d24c
+	/* Try to bind ports starting at 6000+X11DisplayOffset */
Petr Šabata 81d24c
+	x11_max_displays = x11_max_displays + x11_display_offset;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
 	for (display_number = x11_display_offset;
Petr Šabata 81d24c
-	    display_number < MAX_DISPLAYS;
Petr Šabata 81d24c
+	    display_number < x11_max_displays;
Petr Šabata 81d24c
 	    display_number++) {
Petr Šabata 81d24c
-		port = 6000 + display_number;
Petr Šabata 81d24c
+		port = X11_PORT_MIN + display_number;
Petr Šabata 81d24c
+		if (port < X11_PORT_MIN) /* overflow */
Petr Šabata 81d24c
+			break;
Petr Šabata 81d24c
 		memset(&hints, 0, sizeof(hints));
Petr Šabata 81d24c
 		hints.ai_family = ssh->chanctxt->IPv4or6;
Petr Šabata 81d24c
 		hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
Petr Šabata 81d24c
@@ -4295,7 +4301,7 @@ x11_create_display_inet(int x11_display_
Petr Šabata 81d24c
 		if (num_socks > 0)
Petr Šabata 81d24c
 			break;
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
-	if (display_number >= MAX_DISPLAYS) {
Petr Šabata 81d24c
+	if (display_number >= x11_max_displays || port < X11_PORT_MIN ) {
Petr Šabata 81d24c
 		error("Failed to allocate internet-domain X11 display socket.");
Petr Šabata 81d24c
 		return -1;
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
@@ -4441,7 +4447,7 @@ x11_connect_display(void)
Petr Šabata 81d24c
 	memset(&hints, 0, sizeof(hints));
Petr Šabata 81d24c
 	hints.ai_family = ssh->chanctxt->IPv4or6;
Petr Šabata 81d24c
 	hints.ai_socktype = SOCK_STREAM;
Petr Šabata 81d24c
-	snprintf(strport, sizeof strport, "%u", 6000 + display_number);
Petr Šabata 81d24c
+	snprintf(strport, sizeof strport, "%u", X11_PORT_MIN + display_number);
Petr Šabata 81d24c
 	if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
Petr Šabata 81d24c
 		error("%.100s: unknown host. (%s)", buf,
Petr Šabata 81d24c
 		ssh_gai_strerror(gaierr));
Petr Šabata 81d24c
@@ -4457,7 +4463,7 @@ x11_connect_display(void)
Petr Šabata 81d24c
 		/* Connect it to the display. */
Petr Šabata 81d24c
 		if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
Petr Šabata 81d24c
 			debug2("connect %.100s port %u: %.100s", buf,
Petr Šabata 81d24c
-			    6000 + display_number, strerror(errno));
Petr Šabata 81d24c
+			    X11_PORT_MIN + display_number, strerror(errno));
Petr Šabata 81d24c
 			close(sock);
Petr Šabata 81d24c
 			continue;
Petr Šabata 81d24c
 		}
Petr Šabata 81d24c
@@ -4466,8 +4472,8 @@ x11_connect_display(void)
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
 	freeaddrinfo(aitop);
Petr Šabata 81d24c
 	if (!ai) {
Petr Šabata 81d24c
-		error("connect %.100s port %u: %.100s", buf,
Petr Šabata 81d24c
-		    6000 + display_number, strerror(errno));
Petr Šabata 81d24c
+		error("connect %.100s port %u: %.100s", buf,
Petr Šabata 81d24c
+		    X11_PORT_MIN + display_number, strerror(errno));
Petr Šabata 81d24c
 		return -1;
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
 	set_nodelay(sock);
Petr Šabata 81d24c
diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h
Petr Šabata 81d24c
--- openssh-7.4p1/channels.h.x11max	2016-12-19 05:59:41.000000000 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/channels.h	2016-12-23 15:46:32.139506636 +0100
Petr Šabata 81d24c
@@ -293,7 +293,7 @@ int	 permitopen_port(const char *);
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 void	 channel_set_x11_refuse_time(struct ssh *, u_int);
Petr Šabata 81d24c
 int	 x11_connect_display(struct ssh *);
Petr Šabata 81d24c
-int	 x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
Petr Šabata 81d24c
+int	 x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **);
Petr Šabata 81d24c
 void	 x11_request_forwarding_with_spoofing(struct ssh *, int,
Petr Šabata 81d24c
 	    const char *, const char *, const char *, int);
Petr Šabata 81d24c
 
Petr Šabata 81d24c
diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c
Petr Šabata 81d24c
--- openssh-7.4p1/servconf.c.x11max	2016-12-23 15:46:32.133506635 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/servconf.c	2016-12-23 15:47:27.320519121 +0100
Petr Šabata 81d24c
@@ -95,6 +95,7 @@ initialize_server_options(ServerOptions
Petr Šabata 81d24c
 	options->print_lastlog = -1;
Petr Šabata 81d24c
 	options->x11_forwarding = -1;
Petr Šabata 81d24c
 	options->x11_display_offset = -1;
Petr Šabata 81d24c
+	options->x11_max_displays = -1;
Petr Šabata 81d24c
 	options->x11_use_localhost = -1;
Petr Šabata 81d24c
 	options->permit_tty = -1;
Petr Šabata 81d24c
 	options->permit_user_rc = -1;
Petr Šabata 81d24c
@@ -243,6 +244,8 @@ fill_default_server_options(ServerOption
Petr Šabata 81d24c
 		options->x11_forwarding = 0;
Petr Šabata 81d24c
 	if (options->x11_display_offset == -1)
Petr Šabata 81d24c
 		options->x11_display_offset = 10;
Petr Šabata 81d24c
+	if (options->x11_max_displays == -1)
Petr Šabata 81d24c
+		options->x11_max_displays = DEFAULT_MAX_DISPLAYS;
Petr Šabata 81d24c
 	if (options->x11_use_localhost == -1)
Petr Šabata 81d24c
 		options->x11_use_localhost = 1;
Petr Šabata 81d24c
 	if (options->xauth_location == NULL)
Petr Šabata 81d24c
@@ -419,7 +422,7 @@ typedef enum {
Petr Šabata 81d24c
 	sPasswordAuthentication, sKbdInteractiveAuthentication,
Petr Šabata 81d24c
 	sListenAddress, sAddressFamily,
Petr Šabata 81d24c
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
Petr Šabata 81d24c
-	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
Petr Šabata 81d24c
+	sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost,
Petr Šabata 81d24c
 	sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
Petr Šabata 81d24c
 	sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
Petr Šabata 81d24c
 	sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
Petr Šabata 81d24c
@@ -540,6 +543,7 @@ static struct {
Petr Šabata 81d24c
 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
Petr Šabata 81d24c
 	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
Petr Šabata 81d24c
 	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
Petr Šabata 81d24c
+	{ "x11maxdisplays", sX11MaxDisplays, SSHCFG_ALL },
Petr Šabata 81d24c
 	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
Petr Šabata 81d24c
 	{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
Petr Šabata 81d24c
 	{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
Petr Šabata 81d24c
@@ -1316,6 +1320,10 @@ process_server_config_line(ServerOptions
Petr Šabata 81d24c
 			*intptr = value;
Petr Šabata 81d24c
 		break;
Petr Šabata 81d24c
 
Petr Šabata 81d24c
+	case sX11MaxDisplays:
Petr Šabata 81d24c
+		intptr = &options->x11_max_displays;
Petr Šabata 81d24c
+		goto parse_int;
Petr Šabata 81d24c
+
Petr Šabata 81d24c
 	case sX11UseLocalhost:
Petr Šabata 81d24c
 		intptr = &options->x11_use_localhost;
Petr Šabata 81d24c
 		goto parse_flag;
Petr Šabata 81d24c
@@ -2063,6 +2071,7 @@ copy_set_server_options(ServerOptions *d
Petr Šabata 81d24c
 	M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
Petr Šabata 81d24c
 	M_CP_INTOPT(x11_display_offset);
Petr Šabata 81d24c
 	M_CP_INTOPT(x11_forwarding);
Petr Šabata 81d24c
+	M_CP_INTOPT(x11_max_displays);
Petr Šabata 81d24c
 	M_CP_INTOPT(x11_use_localhost);
Petr Šabata 81d24c
 	M_CP_INTOPT(permit_tty);
Petr Šabata 81d24c
 	M_CP_INTOPT(permit_user_rc);
Petr Šabata 81d24c
@@ -2315,6 +2324,7 @@ dump_config(ServerOptions *o)
Petr Šabata 81d24c
 #endif
Petr Šabata 81d24c
 	dump_cfg_int(sLoginGraceTime, o->login_grace_time);
Petr Šabata 81d24c
 	dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
Petr Šabata 81d24c
+	dump_cfg_int(sX11MaxDisplays, o->x11_max_displays);
Petr Šabata 81d24c
 	dump_cfg_int(sMaxAuthTries, o->max_authtries);
Petr Šabata 81d24c
 	dump_cfg_int(sMaxSessions, o->max_sessions);
Petr Šabata 81d24c
 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
Petr Šabata 81d24c
diff -up openssh-7.4p1/servconf.h.x11max openssh-7.4p1/servconf.h
Petr Šabata 81d24c
--- openssh-7.4p1/servconf.h.x11max	2016-12-23 15:46:32.133506635 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/servconf.h	2016-12-23 15:46:32.140506636 +0100
Petr Šabata 81d24c
@@ -55,6 +55,7 @@
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 #define DEFAULT_AUTH_FAIL_MAX	6	/* Default for MaxAuthTries */
Petr Šabata 81d24c
 #define DEFAULT_SESSIONS_MAX	10	/* Default for MaxSessions */
Petr Šabata 81d24c
+#define DEFAULT_MAX_DISPLAYS	1000 /* Maximum number of fake X11 displays to try. */
Petr Šabata 81d24c
 
Petr Šabata 81d24c
 /* Magic name for internal sftp-server */
Petr Šabata 81d24c
 #define INTERNAL_SFTP_NAME	"internal-sftp"
Petr Šabata 81d24c
@@ -85,6 +86,7 @@ typedef struct {
Petr Šabata 81d24c
 	int     x11_forwarding;	/* If true, permit inet (spoofing) X11 fwd. */
Petr Šabata 81d24c
 	int     x11_display_offset;	/* What DISPLAY number to start
Petr Šabata 81d24c
 					 * searching at */
Petr Šabata 81d24c
+	int 	x11_max_displays; /* Number of displays to search */
Petr Šabata 81d24c
 	int     x11_use_localhost;	/* If true, use localhost for fake X11 server. */
Petr Šabata 81d24c
 	char   *xauth_location;	/* Location of xauth program */
Petr Šabata 81d24c
 	int	permit_tty;	/* If false, deny pty allocation */
Petr Šabata 81d24c
diff -up openssh-7.4p1/session.c.x11max openssh-7.4p1/session.c
Petr Šabata 81d24c
--- openssh-7.4p1/session.c.x11max	2016-12-23 15:46:32.136506636 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/session.c	2016-12-23 15:46:32.141506636 +0100
Petr Šabata 81d24c
@@ -2518,8 +2518,9 @@ session_setup_x11fwd(Session *s)
Petr Šabata 81d24c
 		return 0;
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
	if (x11_create_display_inet(ssh, options.x11_display_offset,
Petr Šabata 81d24c
-	    options.x11_use_localhost, s->single_connection,
Petr Šabata 81d24c
-	    &s->display_number, &s->x11_chanids) == -1) {
Petr Šabata 81d24c
+	    options.x11_use_localhost, options.x11_max_displays,
Petr Šabata 81d24c
+	    s->single_connection, &s->display_number,
Petr Šabata 81d24c
+	    &s->x11_chanids) == -1) {
Petr Šabata 81d24c
 		debug("x11_create_display_inet failed.");
Petr Šabata 81d24c
 		return 0;
Petr Šabata 81d24c
 	}
Petr Šabata 81d24c
diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5
Petr Šabata 81d24c
--- openssh-7.4p1/sshd_config.5.x11max	2016-12-23 15:46:32.134506635 +0100
Petr Šabata 81d24c
+++ openssh-7.4p1/sshd_config.5	2016-12-23 15:46:32.141506636 +0100
Petr Šabata 81d24c
@@ -1133,6 +1133,7 @@ Available keywords are
Petr Šabata 81d24c
 .Cm StreamLocalBindUnlink ,
Petr Šabata 81d24c
 .Cm TrustedUserCAKeys ,
Petr Šabata 81d24c
 .Cm X11DisplayOffset ,
Petr Šabata 81d24c
+.Cm X11MaxDisplays ,
Petr Šabata 81d24c
 .Cm X11Forwarding
Petr Šabata 81d24c
 and
Petr Šabata 81d24c
 .Cm X11UseLocalhost .
Petr Šabata 81d24c
@@ -1566,6 +1567,12 @@ Specifies the first display number avail
Petr Šabata 81d24c
 X11 forwarding.
Petr Šabata 81d24c
 This prevents sshd from interfering with real X11 servers.
Petr Šabata 81d24c
 The default is 10.
Petr Šabata 81d24c
+.It Cm X11MaxDisplays
Petr Šabata 81d24c
+Specifies the maximum number of displays available for
Petr Šabata 81d24c
+.Xr sshd 8 Ns 's
Petr Šabata 81d24c
+X11 forwarding.
Petr Šabata 81d24c
+This prevents sshd from exhausting local ports.
Petr Šabata 81d24c
+The default is 1000.
Petr Šabata 81d24c
 .It Cm X11Forwarding
Petr Šabata 81d24c
 Specifies whether X11 forwarding is permitted.
Petr Šabata 81d24c
 The argument must be