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;