Experimental -R support patch for openssh client

Jarno Huuskonen jhuuskon at messi.uku.fi
Wed Aug 16 02:55:11 EST 2000


Hi !

Here's an experimental patch for openssh-2.1.1p4 to add support
(to openssh client) for -R (protocol 2).

So if you have access to a commercial ssh2 server (that allows port
forwardings) could you test this patch.
(Note the openssh server doesn't have support for -R with protocol 2 so
testing with openssh server won't do much good).

To test remember to use -o "Protocol 2".

This is my first go at implementing -R support so expect a few glitches.

Thanks,
-Jarno


-- 
Jarno Huuskonen - System Administrator   |  Jarno.Huuskonen at uku.fi
University of Kuopio - Computer Center   |  Work:   +358 17 162822
PO BOX 1627, 70211 Kuopio, Finland       |  Mobile: +358 40 5388169
-------------- next part --------------
diff -u -r openssh-2.1.1p4/channels.c openssh-2.1.1p4-jhchanges/channels.c
--- openssh-2.1.1p4/channels.c	Mon Jun 26 03:22:53 2000
+++ openssh-2.1.1p4-jhchanges/channels.c	Tue Aug 15 19:10:49 2000
@@ -1506,38 +1509,139 @@
 				  u_short port_to_connect)
 {
 	int payload_len;
+	int type;
+	int success = 0;
+
 	/* Record locally that connection to this host/port is permitted. */
 	if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
 		fatal("channel_request_remote_forwarding: too many forwards");
 
-	permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
-	permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
-	permitted_opens[num_permitted_opens].listen_port = listen_port;
-	num_permitted_opens++;
-
 	/* Send the forward request to the remote side. */
 	if (compat20) {
 		const char *address_to_bind = "0.0.0.0";
 		packet_start(SSH2_MSG_GLOBAL_REQUEST);
 		packet_put_cstring("tcpip-forward");
-		packet_put_char(0);			/* boolean: want reply */
+		/* Ask for reply so we know to expect 'forwarded-tcpip' messages */
+		packet_put_char(1); /* Boolean 1 asks for reply */
 		packet_put_cstring(address_to_bind);
 		packet_put_int(listen_port);
-	} else {
+		packet_send();
+		packet_write_wait();
+
+		type = packet_read(&payload_len); /* Expect reply from server */
+		switch (type) {
+		case SSH2_MSG_REQUEST_SUCCESS:
+			success = 1;
+			break;
+		case SSH2_MSG_REQUEST_FAILURE:
+			log("Warning: Server doesn't do port forwarding.");
+			break;
+		default:
+			/* Unknown packet */
+			packet_disconnect("Protocol error for port forward request: received packet type %d.", type);
+		}
+
+	} 
+	else {
+		/* Protocol 1 */
 		packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
 		packet_put_int(listen_port);
 		packet_put_cstring(host_to_connect);
 		packet_put_int(port_to_connect);
 		packet_send();
 		packet_write_wait();
-		/*
-		 * Wait for response from the remote side.  It will send a disconnect
-		 * message on failure, and we will never see it here.
+
+		/* Jarno: Server can send SSH_SMSG_FAILURE if it won't do port 
+		 *	 forwardings. Read the server reply.
 		 */
-		packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
+		type = packet_read(&payload_len); /* Expect reply from server */
+		switch (type) {
+		case SSH_SMSG_SUCCESS:
+			success = 1;
+			break;
+		case SSH_SMSG_FAILURE:
+			log("Warning: Server doesn't do port forwarding.");
+			break;
+		default:
+			/* Unknown packet */
+			packet_disconnect("Protocol error for port forward request: received packet type %d.", type);
+		}
+	}
+
+	if ( success ) {
+		debug("Server acknowledged our remote port forward request");
+		permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
+		permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
+		permitted_opens[num_permitted_opens].listen_port = listen_port;
+		num_permitted_opens++;
 	}
 }
 
+/* Jarno Huuskonen:
+ *	 ssh2
+ * This called after client has received SSH2_MSG_GLOBAL_REQUEST/
+ * "forwarded-tcpip".
+ * Checks if creating the channel is ok. And connects to required host.
+ * returns new channel if OK or NULL for failure.
+ */
+Channel*
+client_forwarded_tcpip_request(const char *request_type, int rchan,
+															 int rwindow, int rmaxpack)
+{
+	Channel* c = NULL;
+	int sock;
+	char *connected_address; /* Remote address that is listening for the
+															connection */
+	int connected_port;      /* Remote port connected */
+
+	char* client_address;    /* Client that connected to connected_address */
+	int client_port;         /* Client port */
+
+	unsigned int client_len, connected_len;
+
+	int newch;
+	int i;
+
+	debug("ssh2 server tries to open forwarded-tcpip channel.");
+
+	/* Get rest of the packet */
+	connected_address = packet_get_string(&connected_len);
+	connected_port = packet_get_int();
+	client_address = packet_get_string(&client_len);
+	client_port = packet_get_int();
+	packet_done();
+
+	/* Check if we have requested this remote forwarding */
+	for (i = 0; i<num_permitted_opens; i++) {
+		if ( permitted_opens[i].listen_port == connected_port ) {
+			break;
+		}
+	}
+
+	/* We haven't requested the connection to be forwarded ! */
+	if ( i >= num_permitted_opens ) {
+		log("Received request to open remote forwarded channel (%d) but the request was denied", rchan);
+		return NULL;
+	}
+
+	/* TODO: call somekind of forward allowed function to check if connection
+	 * is allowed.
+	 */
+	/* int allowed = allow_forwarded_tcpip( .... ); */
+
+	/* Open socket */
+	sock = channel_connect_to(permitted_opens[i].host_to_connect, 
+														permitted_opens[i].port_to_connect);
+
+	if ( sock >= 0 ) {
+		newch = channel_new("forwarded-tcpip", SSH_CHANNEL_OPEN,
+												sock, sock, -1, 4*1024, 32*1024, 0, 
+												xstrdup(client_address));
+		c = channel_lookup( newch );
+	}
+	return c;
+}
+
 /*
  * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates
  * listening for the port, and sends back a success reply (or disconnect
diff -u -r openssh-2.1.1p4/channels.h openssh-2.1.1p4-jhchanges/channels.h
--- openssh-2.1.1p4/channels.h	Thu Jun 22 14:32:31 2000
+++ openssh-2.1.1p4-jhchanges/channels.h	Tue Aug 15 19:03:17 2000
@@ -163,6 +163,12 @@
 channel_request_remote_forwarding(u_short port, const char *host,
     u_short remote_port);
 
+/* Jarno: Copy comment from source
+ */
+Channel *
+client_forwarded_tcpip_request(const char *request_type, int rchan,
+															 int rwindow, int rmaxpack);
+
 /*
  * Permits opening to any host/port in SSH_MSG_PORT_OPEN.  This is usually
  * called by the server, because the user could connect to any port anyway,
diff -u -r openssh-2.1.1p4/clientloop.c openssh-2.1.1p4-jhchanges/clientloop.c
--- openssh-2.1.1p4/clientloop.c	Sat Jul 15 07:14:17 2000
+++ openssh-2.1.1p4-jhchanges/clientloop.c	Tue Aug 15 19:16:15 2000
@@ -974,6 +974,16 @@
 	debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
 	    ctype, rchan, rwindow, rmaxpack);
 
+	/* Jarno: Check if ssh2 server tries to open remote forward channel */
+	if (strcmp(ctype, "forwarded-tcpip") == 0) {
+		c = client_forwarded_tcpip_request( ctype, rchan, rwindow, rmaxpack );
+	}
+
+	/*	if (strcmp(ctype, "x11") == 0) {
+		c = client_forwarded_x11_request( ctype, rchan, rwindow, rmaxpack );
+	}
+	*/
+
 	if (strcmp(ctype, "x11") == 0) {
 		int sock;
 		char *originator;
@@ -1015,7 +1025,7 @@
 		packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
 		packet_put_int(rchan);
 		packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
-		packet_put_cstring("bla bla");
+		packet_put_cstring("bla bla"); /* TODO: Shouldn't we send a reason ?*/
 		packet_put_cstring("");
 		packet_send();
 	}
diff -u -r openssh-2.1.1p4/ssh.c openssh-2.1.1p4-jhchanges/ssh.c
--- openssh-2.1.1p4/ssh.c	Sat Jul 15 07:14:17 2000
+++ openssh-2.1.1p4-jhchanges/ssh.c	Mon Aug 14 20:04:53 2000
@@ -891,6 +891,22 @@
 	}
 }
 
+/* Jarno: ssh2_session calls this */
+void
+init_remote_fwd(void)
+{
+	int i;
+	for (i = 0; i < options.num_remote_forwards; i++) {
+		debug("Connections to remote port %d forwarded to local address %.200s:%d",
+		      options.remote_forwards[i].port,
+		      options.remote_forwards[i].host,
+		      options.remote_forwards[i].host_port);
+		channel_request_remote_forwarding(options.remote_forwards[i].port,
+						  options.remote_forwards[i].host,
+						  options.remote_forwards[i].host_port);
+	}
+}
+
 extern void client_set_session_ident(int id);
 
 void
@@ -963,7 +979,9 @@
 
 	/* should be pre-session */
 	init_local_fwd();
-	
+	/* Jarno */
+	init_remote_fwd();
+
 	window = 32*1024;
 	if (tty_flag) {
 		packetmax = window/8;


More information about the openssh-unix-dev mailing list