- markus@cvs.openbsd.org 2002/03/25 21:13:51
     [channels.c channels.h compat.c compat.h nchan.c]
     don't send stderr data after EOF, accept this from older known (broken)
     sshd servers only, fixes http://bugzilla.mindrot.org/show_bug.cgi?id=179
diff --git a/channels.c b/channels.c
index 2b1f33f..9581762 100644
--- a/channels.c
+++ b/channels.c
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.172 2002/03/25 21:13:51 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -706,7 +706,11 @@
 		if (buffer_len(&c->output) > 0) {
 			FD_SET(c->wfd, writeset);
 		} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
-			chan_obuf_empty(c);
+			if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
+                               debug2("channel %d: obuf_empty delayed efd %d/(%d)",
+                                   c->self, c->efd, buffer_len(&c->extended));
+			else
+				chan_obuf_empty(c);
 		}
 	}
 	/** XXX check close conditions, too */
@@ -714,7 +718,8 @@
 		if (c->extended_usage == CHAN_EXTENDED_WRITE &&
 		    buffer_len(&c->extended) > 0)
 			FD_SET(c->efd, writeset);
-		else if (c->extended_usage == CHAN_EXTENDED_READ &&
+		else if (!(c->flags & CHAN_EOF_SENT) &&
+		    c->extended_usage == CHAN_EXTENDED_READ &&
 		    buffer_len(&c->extended) < c->remote_window)
 			FD_SET(c->efd, readset);
 	}
@@ -1632,12 +1637,18 @@
 				fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
 			/*
 			 * input-buffer is empty and read-socket shutdown:
-			 * tell peer, that we will not send more data: send IEOF
+			 * tell peer, that we will not send more data: send IEOF.
+			 * hack for extended data: delay EOF if EFD still in use.
 			 */
-			chan_ibuf_empty(c);
+			if (CHANNEL_EFD_INPUT_ACTIVE(c))
+                               debug2("channel %d: ibuf_empty delayed efd %d/(%d)",
+                                   c->self, c->efd, buffer_len(&c->extended));
+			else
+				chan_ibuf_empty(c);
 		}
 		/* Send extended data, i.e. stderr */
 		if (compat20 &&
+		    !(c->flags & CHAN_EOF_SENT) &&
 		    c->remote_window > 0 &&
 		    (len = buffer_len(&c->extended)) > 0 &&
 		    c->extended_usage == CHAN_EXTENDED_READ) {
@@ -1726,6 +1737,13 @@
 		log("channel %d: ext data for non open", id);
 		return;
 	}
+	if (c->flags & CHAN_EOF_RCVD) {
+		if (datafellows & SSH_BUG_EXTEOF)
+			debug("channel %d: accepting ext data after eof", id);
+		else
+			packet_disconnect("Received extended_data after EOF "
+			    "on channel %d.", id);
+	}
 	tcode = packet_get_int();
 	if (c->efd == -1 ||
 	    c->extended_usage != CHAN_EXTENDED_WRITE ||