Protocol 2 remote forwarding patch (again)

Jarno Huuskonen jhuuskon at messi.uku.fi
Wed Sep 20 05:20:29 EST 2000


Hi,

I'm sending you the little bit of code that I've made to get remote 
portforwarding working (protocol 2). Unfortunately at the moment I have no 
time to make any improvements to it.

I'll try to explain the changes I've made so hopefully it'll be easier for
someone to finish this.

ssh2 CLIENT changes:

ssh.c:
  - added init_remote_fwd(void)
  - call init_remote_fwd from ssh_session2
  - changed channel_request_local_forwarding calls (added one extra parameter)
    (see below)

channels.c:
  - changed channel_request_remote_forwarding:
    - if compat20 send SSH2_MSG_GLOBAL_REQUEST/tcpip-forward (doesn't want
      a reply from the server because correctly handling all possible cases
      might be tricky (rekey msgs))
    - protocol1 handle SSH_MSG_FAILURE, because commercial server sends it
      if portforwarding is not allowed
  - added client_forwarded_tcpip_request. It's called when the server sends
    SSH2_MSG_GLOBAL_REQUEST/forwarded-tcpip (some1 connects to the remote 
    socket). This just tries to validate the request and creates a new channel.

channels.h:
- client_forwarded_tcpip_request prototype

clientloop.c:
- modified client_input_channel_open to handle forwarded-tcpip message
  (just calls client_forwarded_tcpip_request)


ssh2 SERVER changes:
auth2.c:
- modified input_userauth_request: if the user is authenticated as root
  then user_authenticated_as_root flag is set to true. 

channels.c:
- user_authenticated_as_root flag. Server checks this when remote forwarding
  is requested to see if a reserved port can be forwarded.
- channel_post_port_listener: If the channel type is SSH2_CHANNEL_PORT_LISTENER
  then sends forwarded-tcpip message (instead of direct-tcpip).
- Added pre/post handlers for the new SSH2_CHANNEL_PORT_LISTENER channel type
- channel_server_global_request: This function handles tcpip-forward/cancel-
  tcpip-forward messages. (NOTE: handling cancel-tcpip-forward message is 
  untested). 
- channel_request_local_forwarding:
  added ssh2_remote_fwd parameter which is set to true when the server creates
  remote forward listener. (This is needed so channel_post_port_listener knows
  to send forwarded-tcpip msg).

channels.h:
- added the new SSH2_CHANNEL_PORT_LISTENER define
- channel_server_global_request prototype
- modified channel_request_local_forwarding prototype ssh2_remote_fwd param.

serverloop.c:
- added handling of SSH2_MSG_GLOBAL_REQUEST messages 
  (channel_server_global_request)



Stuff that needs more work:
- Test "cancel-tcpip-forward" handling.
- Make logging consistent
- Also somekind of access control for portforwarding might be nice 
  (Is this of any use when users have shell access ?)


Cheers,
- 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.2.0p1/auth2.c openssh-2.2.0p1-jh/auth2.c
--- openssh-2.2.0p1/auth2.c	Wed Aug 23 03:46:24 2000
+++ openssh-2.2.0p1-jh/auth2.c	Tue Sep 19 18:41:43 2000
@@ -65,6 +65,7 @@
 extern ServerOptions options;
 extern unsigned char *session_id2;
 extern int session_id2_len;
+extern int user_authenticated_as_root; /* Jarno: From channels.c */
 
 /* protocol */
 
@@ -239,6 +240,14 @@
 		packet_put_char(0);				/* XXX partial success, unused */
 		packet_send();
 		packet_write_wait();
+	}
+	
+	/* Jarno: Set the user_authenticated_as_root flag */
+	if ( authenticated && pw && pw->pw_uid == (uid_t)0 ) {
+		user_authenticated_as_root = 1;
+	}
+	else {
+		user_authenticated_as_root = 0;
 	}
 
 	xfree(service);
diff -u -r openssh-2.2.0p1/channels.c openssh-2.2.0p1-jh/channels.c
--- openssh-2.2.0p1/channels.c	Wed Aug 23 03:46:24 2000
+++ openssh-2.2.0p1-jh/channels.c	Tue Sep 19 18:41:43 2000
@@ -56,6 +56,10 @@
  */
 static Channel *channels = NULL;
 
+int user_authenticated_as_root;   /* Set to true if user is root. Checked
+																	 * if the user can forward privileged ports
+																	 */
+
 /*
  * Size of the channel array.  All slots of the array must always be
  * initialized (at least the type field); unused slots are marked with type
@@ -586,13 +590,20 @@
 		    "connect from %.200s port %d",
 		    c->listening_port, c->path, c->host_port,
 		    remote_hostname, remote_port);
-		newch = channel_new("direct-tcpip",
+		/* Jarno: If the channel is SSH2 port listener (server) then send
+		 * forwarded-tcpip message.
+		 */
+		newch = channel_new( (c->type == SSH2_CHANNEL_PORT_LISTENER) ?
+												 "forwarded-tcpip" : "direct-tcpip",
 		    SSH_CHANNEL_OPENING, newsock, newsock, -1,
 		    c->local_window_max, c->local_maxpacket,
 		    0, xstrdup(buf));
 		if (compat20) {
 			packet_start(SSH2_MSG_CHANNEL_OPEN);
-			packet_put_cstring("direct-tcpip");
+			if (c->type == SSH2_CHANNEL_PORT_LISTENER)
+				packet_put_cstring("forwarded-tcpip");
+			else
+				packet_put_cstring("direct-tcpip");
 			packet_put_int(newch);
 			packet_put_int(c->local_window_max);
 			packet_put_int(c->local_maxpacket);
@@ -798,10 +809,12 @@
 	channel_pre[SSH_CHANNEL_OPEN] =			&channel_pre_open_20;
 	channel_pre[SSH_CHANNEL_X11_OPEN] =		&channel_pre_x11_open;
 	channel_pre[SSH_CHANNEL_PORT_LISTENER] =	&channel_pre_listener;
+	channel_pre[SSH2_CHANNEL_PORT_LISTENER] =	&channel_pre_listener;
 	channel_pre[SSH_CHANNEL_X11_LISTENER] =		&channel_pre_listener;
 
 	channel_post[SSH_CHANNEL_OPEN] =		&channel_post_open_2;
 	channel_post[SSH_CHANNEL_PORT_LISTENER] =	&channel_post_port_listener;
+	channel_post[SSH2_CHANNEL_PORT_LISTENER] =	&channel_post_port_listener;
 	channel_post[SSH_CHANNEL_X11_LISTENER] =	&channel_post_x11_listener;
 }
 
@@ -1287,6 +1300,97 @@
 	c->remote_window += adjust;
 }
 
+/* Jarno Huuskonen: This is called when server receives 
+ * SSH2_MSG_GLOBAL_REQUEST. Handles both "tcpip-forward" and
+ * "cancel-tcpip-forward" requests.
+ */
+void 
+channel_server_global_request(int type, int plen)
+{
+	char *rtype;
+	char want_reply;
+	int success = 0;
+
+	rtype = packet_get_string(NULL);
+	want_reply = packet_get_char();
+	
+	if ( strcmp(rtype, "tcpip-forward") == 0 ) {
+		char *address_to_bind;
+		int port_to_bind;
+
+		address_to_bind = packet_get_string(NULL);
+		port_to_bind = packet_get_int();
+
+		/* Check if the client is allowed to forward (this port) */
+		if ( port_to_bind < IPPORT_RESERVED && !user_authenticated_as_root ) {
+			log("User tries to forward privileged port %d", port_to_bind);
+			packet_send_debug("Requested forwarding of port %d but user is not root.", port_to_bind);
+			success = 0;
+		}
+		else {
+			/* Start listening on the port */
+			channel_request_local_forwarding( port_to_bind, address_to_bind,
+																				port_to_bind, 1, 
+																				1 /* ssh2_remote_fwd*/);
+			/* NOT REACHED if error (disconnects). 
+			 * Note: if error xfree not called
+			 * for address_to_bind
+			 */
+			success = 1;
+		}
+
+		xfree( address_to_bind );
+	}
+
+	/* TODO: This is untested !!! create some test code !!!*/
+	if ( strcmp(rtype, "cancel-tcpip-forward") == 0 ) {
+		char *address_to_bind;
+		int port_to_bind;
+		int chan;
+
+		address_to_bind = packet_get_string(NULL);
+		port_to_bind = packet_get_int();
+
+		/* Lookup the channel listening for this port:
+			 First see if the channel type is SSH2_CHANNEL_PORT_LISTENER and then 
+			 compare port/addr.
+			 TODO: Is it safe to use strcmp on address_to_bind ?
+		 */
+		for (chan = 0; chan < channels_alloc; chan++) {
+			if ( channels[chan].type == SSH2_CHANNEL_PORT_LISTENER ) {
+				if ( channels[chan].listening_port == port_to_bind &&
+						 (strcmp(address_to_bind, channels[chan].path) == 0) )
+					break;
+			}
+		}
+		
+		if ( chan < channels_alloc ) {
+			/* We have a winner --> close the channel*/
+			channel_free( channels[chan].self );
+			success = 1;
+		}
+		else {
+			debug("Invalid cancel-tcpip-forward request: Couldn't find channel.");
+		}
+		xfree( address_to_bind );
+	}
+
+	/* Client requested a reply */
+	if ( want_reply ) {
+		if ( success ) {
+			packet_start(SSH2_MSG_REQUEST_SUCCESS);
+		}
+		else {
+			packet_start(SSH2_MSG_REQUEST_FAILURE);
+		}
+		/* Now send the SUCCESS/FAILURE */
+		packet_send();
+		packet_write_wait();
+	}
+	xfree(rtype);
+}
+
+
 /*
  * Stops listening for channels, and removes any unix domain sockets that we
  * might have.
@@ -1304,6 +1408,7 @@
 			channel_free(i);
 			break;
 		case SSH_CHANNEL_PORT_LISTENER:
+		case SSH2_CHANNEL_PORT_LISTENER: /* Jarno */
 		case SSH_CHANNEL_X11_LISTENER:
 			close(channels[i].sock);
 			channel_free(i);
@@ -1347,6 +1452,7 @@
 		case SSH_CHANNEL_FREE:
 		case SSH_CHANNEL_X11_LISTENER:
 		case SSH_CHANNEL_PORT_LISTENER:
+		case SSH2_CHANNEL_PORT_LISTENER: /* Jarno */
 		case SSH_CHANNEL_CLOSED:
 		case SSH_CHANNEL_AUTH_SOCKET:
 			continue;
@@ -1392,6 +1498,7 @@
 		case SSH_CHANNEL_FREE:
 		case SSH_CHANNEL_X11_LISTENER:
 		case SSH_CHANNEL_PORT_LISTENER:
+		case SSH2_CHANNEL_PORT_LISTENER: /* Jarno */
 		case SSH_CHANNEL_CLOSED:
 		case SSH_CHANNEL_AUTH_SOCKET:
 			continue;
@@ -1424,10 +1531,9 @@
  * Initiate forwarding of connections to local port "port" through the secure
  * channel to host:port from remote side.
  */
-
 void
 channel_request_local_forwarding(u_short port, const char *host,
-				 u_short host_port, int gateway_ports)
+				 u_short host_port, int gateway_ports, int ssh2_remote_fwd)
 {
 	int success, ch, sock, on = 1;
 	struct addrinfo hints, *ai, *aitop;
@@ -1494,7 +1600,8 @@
 		}
 		/* Allocate a channel number for the socket. */
 		ch = channel_new(
-		    "port listener", SSH_CHANNEL_PORT_LISTENER,
+		    "port listener", 
+				ssh2_remote_fwd ? SSH2_CHANNEL_PORT_LISTENER : SSH_CHANNEL_PORT_LISTENER,
 		    sock, sock, -1,
 		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
 		    0, xstrdup("port listener"));
@@ -1518,38 +1625,149 @@
 				  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 */
+
+		/* Don't ask for a reply because: while waiting for a reply server can
+			 send rekey-msg and handling that correctly might be messy.
+			 Not requesting a reply is not the best solution: We have no way of  
+			 know if the server doesn't allow port forwarding.
+		*/
+		packet_put_char(0); /* Boolean 1 asks for reply */
 		packet_put_cstring(address_to_bind);
 		packet_put_int(listen_port);
-	} else {
+		packet_send();
+		packet_write_wait();
+		success = 1;   /* Assume that server accepts the request and put the
+											forward request to permitted_opens */
+ 
+		/*
+		type = packet_read(&payload_len);
+		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:
+				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 ) {
+		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:
+ * This gets called after ssh client has received 
+ * SSH2_MSG_GLOBAL_REQUEST type "forwarded-tcpip".
+ *
+ * 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 *listen_address;       /* Remote (server) address that is listening 
+																 for the connection */
+	int listen_port;
+	char* originator_address;   /* Address of the client connecting to 
+																 listen_address */
+	int originator_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 */
+	listen_address = packet_get_string(&connected_len);
+	listen_port = packet_get_int();
+	originator_address = packet_get_string(&client_len);
+	originator_port = packet_get_int();
+	packet_done();
+
+	/* Check if we have requested this remote forwarding 
+	 * Note: this is not fool proof, because we don't ask the server to
+	 * acknowledge our remote forward request.
+	 */
+	for (i = 0; i<num_permitted_opens; i++) {
+		if ( permitted_opens[i].listen_port == listen_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: Somekind of access control ??
+	 * Maybe tcp_wrappers/username/group based access control ??
+	 */
+
+	/* Open socket and allocate a channel for it */
+	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(originator_address));
+		c = channel_lookup( newch );
+	}
+	/* client_input_channel_open calls xfree(request_type) Don't call it here */
+	xfree(originator_address);
+	xfree(listen_address);
+	return c;
+}
+
 /*
  * This is called after receiving CHANNEL_FORWARDING_REQUEST.  This initates
  * listening for the port, and sends back a success reply (or disconnect
@@ -1577,7 +1795,10 @@
 	/*
 	 * Initiate forwarding,
 	 */
-	channel_request_local_forwarding(port, hostname, host_port, gateway_ports);
+	/* Jarno: The last parameter is used to signal if this is protocol 2 
+		 server listening for remote forward --> false */
+	channel_request_local_forwarding(port, hostname, host_port, 
+																	 gateway_ports, 0);
 
 	/* Free the argument string. */
 	xfree(hostname);
@@ -1633,12 +1854,12 @@
 	return sock;
 }
 
+
 /*
  * This is called after receiving PORT_OPEN message.  This attempts to
  * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION
  * or CHANNEL_OPEN_FAILURE.
  */
-
 void
 channel_input_port_open(int type, int plen)
 {
@@ -1649,7 +1870,7 @@
 
 	/* Get remote channel number. */
 	remote_channel = packet_get_int();
-
+ 
 	/* Get host name to connect to. */
 	host = packet_get_string(&host_len);
 
diff -u -r openssh-2.2.0p1/channels.h openssh-2.2.0p1-jh/channels.h
--- openssh-2.2.0p1/channels.h	Wed Aug 23 03:46:24 2000
+++ openssh-2.2.0p1-jh/channels.h	Tue Sep 19 21:12:37 2000
@@ -15,7 +15,13 @@
 #define SSH_CHANNEL_INPUT_DRAINING	8	/* sending remaining data to conn */
 #define SSH_CHANNEL_OUTPUT_DRAINING	9	/* sending remaining data to app */
 #define SSH_CHANNEL_LARVAL		10	/* larval session */
-#define SSH_CHANNEL_MAX_TYPE		11
+#define SSH2_CHANNEL_PORT_LISTENER	11	/* Jarno: protocol 2 remote port 
+																				 * listener. (needs different type 
+																				 * because with protocol 2 remote
+																				 * forward the server sends
+																				 * forwarded-tcpip (not direct-tcpip)
+																				 */
+#define SSH_CHANNEL_MAX_TYPE		12
 
 /*
  * Data structure for channel data.  This is iniailized in channel_allocate
@@ -99,8 +105,12 @@
 void	channel_input_open_failure(int type, int plen);
 void	channel_input_port_open(int type, int plen);
 void	channel_input_window_adjust(int type, int plen);
+
 void	channel_input_open(int type, int plen);
 
+/* Jarno Huuskonen: */
+void channel_server_global_request(int type, int plen);
+
 /* Sets specific protocol options. */
 void    channel_set_options(int hostname_in_open);
 
@@ -157,9 +167,12 @@
  * channel to host:port from remote side.  This never returns if there was an
  * error.
  */
+/* Jarno: Added ssh2_remote_fwd flag. Used when protocol2 server gets 
+ * tcpip-forward request
+ */
 void
 channel_request_local_forwarding(u_short port, const char *host,
-    u_short remote_port, int gateway_ports);
+    u_short remote_port, int gateway_ports, int ssh2_remote_fwd);
 
 /*
  * Initiate forwarding of connections to port "port" on remote host through
@@ -170,6 +183,12 @@
 void
 channel_request_remote_forwarding(u_short port, const char *host,
     u_short remote_port);
+
+/* Jarno Huuskonen: 
+ */
+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
diff -u -r openssh-2.2.0p1/clientloop.c openssh-2.2.0p1-jh/clientloop.c
--- openssh-2.2.0p1/clientloop.c	Wed Aug 23 03:46:24 2000
+++ openssh-2.2.0p1-jh/clientloop.c	Tue Sep 19 18:41:43 2000
@@ -993,6 +993,12 @@
 	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) {
 		int sock;
 		char *originator;
@@ -1035,7 +1041,8 @@
 		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: Perhaps a little better 
+																			explanation */
 		packet_put_cstring("");
 		packet_send();
 	}
diff -u -r openssh-2.2.0p1/serverloop.c openssh-2.2.0p1-jh/serverloop.c
--- openssh-2.2.0p1/serverloop.c	Tue Jul 11 10:31:38 2000
+++ openssh-2.2.0p1-jh/serverloop.c	Tue Sep 19 18:41:43 2000
@@ -723,10 +723,13 @@
 
 	/* XXX check permission */
 	if (no_port_forwarding_flag) {
+		packet_send_debug("Server configuration rejects port forwardings.");
+		debug("Port forwarding disabled in server configuration.");
 		xfree(target);
 		xfree(originator);
 		return -1;
 	}
+
 	sock = channel_connect_to(target, target_port);
 	xfree(target);
 	xfree(originator);
@@ -819,6 +822,7 @@
 	dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
 	dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
 	dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+	dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &channel_server_global_request);
 }
 void
 server_init_dispatch_13()
diff -u -r openssh-2.2.0p1/ssh.c openssh-2.2.0p1-jh/ssh.c
--- openssh-2.2.0p1/ssh.c	Tue Aug 29 03:33:51 2000
+++ openssh-2.2.0p1-jh/ssh.c	Tue Sep 19 18:41:43 2000
@@ -834,7 +834,7 @@
 		channel_request_local_forwarding(options.local_forwards[i].port,
 						 options.local_forwards[i].host,
 						 options.local_forwards[i].host_port,
-						 options.gateway_ports);
+						 options.gateway_ports, 0);
 	}
 
 	/* Initiate remote TCP/IP port forwardings. */
@@ -890,7 +890,25 @@
 		channel_request_local_forwarding(options.local_forwards[i].port,
 						 options.local_forwards[i].host,
 						 options.local_forwards[i].host_port,
-						 options.gateway_ports);
+						 options.gateway_ports, 0);
+	}
+}
+
+/* Jarno Huuskonen: ssh2 client calls this to initiate remote port forwarding
+ * requests.
+ */
+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);
 	}
 }
 
@@ -972,7 +990,8 @@
 
 	/* should be pre-session */
 	init_local_fwd();
-	
+	init_remote_fwd();
+
 	/* If requested, let ssh continue in the background. */
 	if (fork_after_authentication_flag)
 		if (daemon(1, 1) < 0)


More information about the openssh-unix-dev mailing list