Forwarding race resulting in lost data in openssh-2.9p2

Tobias Ringstrom tori at unhappy.mine.nu
Tue Jul 3 03:28:10 EST 2001


When a TCP connection is established through a tunnel (e.g. using
-L 2000:www.openssh.org:80), all data sent by the local TCP client is
silently dropped until the sshd has opened the connection to the remote
(www.openssh.org).  This is very visible when forwarding to a remote host
that is far away (i.e. has high ping time) from the sshd.

I have attached a sample program that shows the problem.  To reproduce the
problem, run the following:
[server] sshd
[client window 1] slogin -L 2000:www.openssh.org:80 server
[client window 2] gcc get.c -o get
[client window 2] ./get 5      (no problem, takes time)
[client window 2] ./get        (hangs forever)

After the attached patch, which may or may not be correct, the problem
goes away.  Even if the patch is not correct, it clearly illustrates what
the problem is, namely that sshd silently drops data when in the
CONNECTING state (and other states too, possibly).

(I'm not on the list, so please CC any replies to me.)

/Tobias
-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	struct sockaddr_in remoteAddr;
	int sock, delay = 0, n;
	char buf[1024];

	if (argc > 1)
		delay = atoi(argv[1]);

	memset(&remoteAddr, 0, sizeof(&remoteAddr));
	remoteAddr.sin_family = AF_INET;
	remoteAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	remoteAddr.sin_port = htons(8000);

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == -1)
		abort();
	if (connect(sock, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr)) == -1)
		abort();

	if (delay)
		sleep(delay);

	write(sock, "GET /\n\n", 7);

	while ((n = read(sock, buf, sizeof(buf))) > 0)
		write(1, buf, n);
	
	close(sock);

	return 0;
}
-------------- next part --------------
--- channels.c.orig	Wed Jun 13 21:18:05 2001
+++ channels.c	Mon Jul  2 19:00:09 2001
@@ -1302,7 +1302,8 @@
 
 	/* Ignore any data for non-open channels (might happen on close) */
 	if (c->type != SSH_CHANNEL_OPEN &&
-	    c->type != SSH_CHANNEL_X11_OPEN)
+	    c->type != SSH_CHANNEL_X11_OPEN &&
+		c->type != SSH_CHANNEL_CONNECTING)
 		return;
 
 	/* same for protocol 1.5 if output end is no longer open */


More information about the openssh-unix-dev mailing list