- markus@cvs.openbsd.org 2001/10/07 17:49:40
     [channels.c channels.h]
     avoid possible FD_ISSET overflow for channels established
     during channnel_after_select() (used for dynamic channels).
diff --git a/channels.c b/channels.c
index 758ea50..1ec6074 100644
--- a/channels.c
+++ b/channels.c
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.136 2001/10/04 15:05:40 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.137 2001/10/07 17:49:40 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -241,6 +241,7 @@
 	}
 	/* Initialize and return new channel. */
 	c = channels[found] = xmalloc(sizeof(Channel));
+	memset(c, 0, sizeof(Channel));
 	buffer_init(&c->input);
 	buffer_init(&c->output);
 	buffer_init(&c->extended);
@@ -974,7 +975,7 @@
 	int have, ret;
 
 	have = buffer_len(&c->input);
-
+	c->delayed = 0;
 	debug2("channel %d: pre_dynamic: have %d", c->self, have);
 	/* buffer_dump(&c->input); */
 	/* check if the fixed size part of the packet is in buffer. */
@@ -1133,11 +1134,18 @@
 		    "to %.100s port %d requested.",
 		    c->listening_port, c->path, c->host_port);
 
-		rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
-		    "forwarded-tcpip" : "direct-tcpip";
-		nextstate = (c->host_port == 0 &&
-		    c->type != SSH_CHANNEL_RPORT_LISTENER) ?
-		    SSH_CHANNEL_DYNAMIC : SSH_CHANNEL_OPENING;
+		if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
+			nextstate = SSH_CHANNEL_OPENING;
+			rtype = "forwarded-tcpip";
+		} else {
+			if (c->host_port == 0) {
+				nextstate = SSH_CHANNEL_DYNAMIC;
+				rtype = "direct-tcpip";
+			} else {
+				nextstate = SSH_CHANNEL_OPENING;
+				rtype = "direct-tcpip";
+			}
+		}
 
 		addrlen = sizeof(addr);
 		newsock = accept(c->sock, &addr, &addrlen);
@@ -1158,8 +1166,16 @@
 		nc->host_port = c->host_port;
 		strlcpy(nc->path, c->path, sizeof(nc->path));
 
-		if (nextstate != SSH_CHANNEL_DYNAMIC)
+		if (nextstate == SSH_CHANNEL_DYNAMIC) {
+			/*
+			 * do not call the channel_post handler until
+			 * this flag has been reset by a pre-handler.
+			 * otherwise the FD_ISSET calls might overflow
+			 */
+			nc->delayed = 1;
+		} else {
 			port_open_helper(nc, rtype);
+		}
 	}
 }
 
@@ -1409,6 +1425,8 @@
 static void
 channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset)
 {
+	if (c->delayed)
+		return;
 	channel_handle_rfd(c, readset, writeset);
 	channel_handle_wfd(c, readset, writeset);
 }
@@ -1416,6 +1434,8 @@
 static void
 channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset)
 {
+	if (c->delayed)
+		return;
 	channel_handle_rfd(c, readset, writeset);
 	channel_handle_wfd(c, readset, writeset);
 	channel_handle_efd(c, readset, writeset);