Hi !
Here's a patch to add remote port forwarding support (protocol 2) for
openssh. I have tried to test that it works like it should but a more
thorough testing is needed. This patch adds both client/server support.
The patch should be applied to openssh-2.1.1p4 source tree.
Also included is a PortForwarding sshd_config option, new ./configure
option --disable-forwarding that should make it possible to disable
port forwarding in server altogether and some earlier patch to make
ssh client fork with -f (when using protocol 2).
Please test the patch and give me feedback.
-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/auth2.c openssh-2.1.1p4-jhchanges/auth2.c
--- openssh-2.1.1p4/auth2.c Tue Jul 11 10:31:38 2000
+++ openssh-2.1.1p4-jhchanges/auth2.c Tue Aug 22 19:43:09 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.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 Wed Aug 23 09:27:47 2000
@@ -59,6 +59,12 @@
*/
static int channels_alloc = 0;
+/* Jarno: Needed to check if port_forwarding is allowed */
+int allow_port_forwarding;
+int user_authenticated_as_root; /* This could be uid so we could log who
+ * tried to forward ports.
+ */
+
/*
* Maximum file descriptor value used in any of the channels. This is
* updated in channel_allocate.
@@ -581,13 +587,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);
@@ -786,10 +799,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;
}
@@ -1275,6 +1290,122 @@
c->remote_window += adjust;
}
+/* Jarno Huuskonen: Checks if the server allows port forwarding.
+ * Logs all failed attempts.
+ * Return 1 if the forwarding is allowed or 0 for failure.
+ */
+int allow_remote_forwarding(const char *address_to_listen, int port)
+{
+#ifdef DISABLE_FORWARDING
+ return 0;
+#endif /* DISABLE_FORWARDING */
+
+ /* Only root can forward privileged ports */
+ if ( port < IPPORT_RESERVED && !user_authenticated_as_root ) {
+ debug("Non-root user tries to forward privileged port %d", port);
+ /* Commercial ssh2 doesn't disconnect so same behaviour here */
+ packet_send_debug("Requested forwarding of port %d but user is not
root.",
+ port);
+ return 0;
+ }
+
+ /* Is forwarding disabled in configuration */
+ if ( allow_port_forwarding ) {
+ return 1;
+ }
+ /* TODO: Better logging of refused forwards:
+ * log("Refused port forward request from %.100s port %d.");
+ */
+ return 0;
+}
+
+/* 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();
+ debug("server received: %.100s request (reply=%d)",rtype,
+ (int)want_reply);
+
+ 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 ( allow_remote_forwarding(address_to_bind, port_to_bind) ) {
+ /* Start listening on the port */
+ channel_request_local_forwarding( port_to_bind, address_to_bind,
+ port_to_bind, 1, 1 );
+ /* NOT REACHED if error (disconnects).
+ * Note: if error xfree not called
+ * for address_to_bind
+ */
+ success = 1;
+ }
+ else {
+ success = 0;
+ packet_send_debug("Server has disabled port forwarding.");
+ }
+
+ 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 ?
+ */
+ 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;
+ }
+ 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.
@@ -1292,6 +1423,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);
@@ -1335,6 +1467,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;
@@ -1380,6 +1513,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;
@@ -1412,10 +1546,14 @@
* Initiate forwarding of connections to local port "port" through
the secure
* channel to host:port from remote side.
*/
-
+/* Jarno: If ssh2_remote_fwd is true then protocol 2 server called this
+ * and we need to use channel type SSH2_CHANNEL_PORT_LISTENER (when someone
+ * connects to the listening socket we know to send "forwarded-tcpip"
message
+ * instead of "direct-tcpip").
+ */
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;
@@ -1482,7 +1620,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"));
@@ -1506,38 +1645,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
@@ -1565,7 +1815,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);
@@ -1621,22 +1874,49 @@
return sock;
}
+/* Jarno: This is only a wrapper for channel_input_port_open that
+ * server calls after receiving PORT_OPEN. The only purpose for this is to
+ * make it possible to refuse forwarding requests (in server).
+ */
+void server_channel_input_port_open(int type, int plen)
+{
+ int remote_channel = packet_get_int();
+
+#ifndef DISABLE_FORWARDING
+ if (!allow_port_forwarding) {
+#endif
+ debug("Refused port forward request.");
+ packet_send_debug("Server configuration rejects port
forwardings.");
+ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+ packet_put_int(remote_channel);
+ packet_send();
+ return;
+#ifndef DISABLE_FORWARDING
+ }
+#endif
+ channel_input_port_open(type, plen, remote_channel);
+}
+
+/* Jarno: This is only a client wrapper for channel_input_port_open */
+void client_channel_input_port_open(int type, int plen)
+{
+ int remote_channel = packet_get_int();
+ channel_input_port_open(type, plen, remote_channel);
+}
+
+
/*
* 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)
+channel_input_port_open(int type, int plen, int remote_channel)
{
u_short host_port;
char *host, *originator_string;
- int remote_channel, sock = -1, newch, i, denied;
+ int sock = -1, newch, i, denied;
unsigned int host_len, originator_len;
-
- /* 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.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 22 21:36:16 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
@@ -89,10 +95,27 @@
void channel_input_oclose(int type, int plen);
void channel_input_open_confirmation(int type, int plen);
void channel_input_open_failure(int type, int plen);
-void channel_input_port_open(int type, int plen);
+/* Jarno: This is only a wrapper for channel_input_port_open that the
+ * server calls after receiving PORT_OPEN. The only purpose of this is to
+ * make it possible to refuse forwarding requests.
+ */
+void server_channel_input_port_open(int type, int plen);
+/* Jarno: This is only a client wrapper for channel_input_port_open */
+void client_channel_input_port_open(int type, int plen);
+void channel_input_port_open(int type, int plen, int remote_channel);
void channel_input_window_adjust(int type, int plen);
+
+/* Jarno Huuskonen: Checks if the server allows port forwarding.
+ * Logs all failed attempts.
+ * Return 1 if the forwarding is allowed or 0 for failure.
+ */
+int allow_remote_forwarding(const char *address_to_listen, int port);
+
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);
@@ -149,9 +172,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
@@ -162,6 +188,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.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 22 21:37:57 2000
@@ -974,6 +974,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;
@@ -1015,7 +1021,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();
}
@@ -1045,7 +1052,7 @@
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
&channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+ dispatch_set(SSH_MSG_PORT_OPEN, &client_channel_input_port_open); /* Jarno
*/
dispatch_set(SSH_SMSG_AGENT_OPEN, &auth_input_open_request);
dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
diff -u -r openssh-2.1.1p4/configure.in openssh-2.1.1p4-jhchanges/configure.in
--- openssh-2.1.1p4/configure.in Sat Jul 15 07:59:14 2000
+++ openssh-2.1.1p4-jhchanges/configure.in Fri Aug 18 20:02:20 2000
@@ -1094,6 +1094,12 @@
AC_DEFINE_UNQUOTED(PIDDIR, "$piddir")
AC_SUBST(piddir)
+# Disable server port forwarding
+AC_ARG_ENABLE(forwarding,
+ [ --disable-forwarding disable port forwarding in server [no]],
+ [ AC_DEFINE(DISABLE_FORWARDING) ]
+)
+
dnl allow user to disable some login recording features
AC_ARG_ENABLE(lastlog,
[ --disable-lastlog disable use of lastlog even if detected [no]],
@@ -1370,7 +1376,6 @@
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Use IPv4 by default hack: $IPV4_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
-
echo ""
echo "Compiler flags: ${CFLAGS}"
diff -u -r openssh-2.1.1p4/config.h.in openssh-2.1.1p4-jhchanges/config.h.in
--- openssh-2.1.1p4/config.h.in Sun Jul 16 06:26:46 2000
+++ openssh-2.1.1p4-jhchanges/config.h.in Fri Aug 18 19:58:58 2000
@@ -73,6 +73,9 @@
#undef HAVE_TIME_IN_UTMP
#undef HAVE_TIME_IN_UTMPX
+/* Define if you want to disable port forwarding in server */
+#undef DISABLE_FORWARDING
+
/* Define if you don't want to use your system's login() call */
#undef DISABLE_LOGIN
diff -u -r openssh-2.1.1p4/servconf.c openssh-2.1.1p4-jhchanges/servconf.c
--- openssh-2.1.1p4/servconf.c Sat Jul 15 07:14:17 2000
+++ openssh-2.1.1p4-jhchanges/servconf.c Mon Aug 21 20:48:09 2000
@@ -19,6 +19,9 @@
#include "xmalloc.h"
#include "compat.h"
+/* Jarno: import */
+extern int allow_port_forwarding;
+
/* add listen address */
void add_listen_addr(ServerOptions *options, char *addr);
@@ -45,6 +48,7 @@
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->xauth_location = NULL;
+ allow_port_forwarding = -1;
options->strict_modes = -1;
options->keepalives = -1;
options->log_facility = (SyslogFacility) - 1;
@@ -116,6 +120,8 @@
if (options->xauth_location == NULL)
options->xauth_location = XAUTH_PATH;
#endif /* XAUTH_PATH */
+ if (allow_port_forwarding == -1)
+ allow_port_forwarding = 1; /* Allow forwarding */
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->keepalives == -1)
@@ -180,9 +186,9 @@
sSkeyAuthentication,
#endif
sPasswordAuthentication, sListenAddress,
- sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
- sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
- sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
+ sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
+ sPortForwarding, sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives,
+ sCheckMail, sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
} ServerOpCodes;
@@ -227,6 +233,7 @@
{ "x11forwarding", sX11Forwarding },
{ "x11displayoffset", sX11DisplayOffset },
{ "xauthlocation", sXAuthLocation },
+ { "portforwarding", sPortForwarding },
{ "strictmodes", sStrictModes },
{ "permitemptypasswords", sEmptyPasswd },
{ "uselogin", sUseLogin },
@@ -518,7 +525,11 @@
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
-
+
+ case sPortForwarding:
+ intptr = &allow_port_forwarding;
+ goto parse_flag;
+
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
diff -u -r openssh-2.1.1p4/serverloop.c openssh-2.1.1p4-jhchanges/serverloop.c
--- openssh-2.1.1p4/serverloop.c Tue Jul 11 10:31:38 2000
+++ openssh-2.1.1p4-jhchanges/serverloop.c Tue Aug 22 21:26:20 2000
@@ -44,6 +44,9 @@
static unsigned int buffer_high;/* "Soft" max buffer size. */
static int max_fd; /* Max file descriptor number for select(). */
+/* Jarno: import */
+extern int allow_port_forwarding;
+
/*
* This SIGCHLD kludge is used to detect when the child exits. The server
* will exit after that, as soon as forwarded connections have terminated.
@@ -722,11 +725,19 @@
originator, originator_port, target, target_port);
/* XXX check permission */
- if (no_port_forwarding_flag) {
+ /* Jarno: TODO: call function to check forwarding+better logging */
+#ifndef DISABLE_FORWARDING
+ if (no_port_forwarding_flag || !allow_port_forwarding) {
+#endif /* DISABLE_FORWARDING */
+ packet_send_debug("Server configuration rejects port
forwardings.");
+ debug("Port forwarding disabled in server configuration.");
xfree(target);
xfree(originator);
return -1;
+#ifndef DISABLE_FORWARDING
}
+#endif /* DISABLE_FORWARDING */
+
sock = channel_connect_to(target, target_port);
xfree(target);
xfree(originator);
@@ -819,6 +830,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()
@@ -833,7 +845,7 @@
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
&channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
+ dispatch_set(SSH_MSG_PORT_OPEN, &server_channel_input_port_open); /* Jarno
*/
}
void
server_init_dispatch_15()
diff -u -r openssh-2.1.1p4/session.c openssh-2.1.1p4-jhchanges/session.c
--- openssh-2.1.1p4/session.c Wed Jul 12 02:45:27 2000
+++ openssh-2.1.1p4-jhchanges/session.c Wed Aug 23 10:25:53 2000
@@ -82,6 +82,9 @@
/* import */
extern ServerOptions options;
+/* Jarno */
+extern int allow_port_forwarding;
+
#ifdef HAVE___PROGNAME
extern char *__progname;
#else /* HAVE___PROGNAME */
@@ -324,6 +327,19 @@
debug("Port forwarding not permitted for this authentication.");
break;
}
+
+ /* JARNO: Todo: Better logging */
+#ifndef DISABLE_FORWARDING
+ if ( !allow_port_forwarding ) {
+#endif /* DISABLE_FORWARDING */
+ debug("Port forwarding disabled in server configuration.");
+ packet_send_debug("Server has disabled port forwarding.");
+ success = 0;
+ break;
+#ifndef DISABLE_FORWARDING
+ }
+#endif /* DISABLE_FORWARDING */
+
debug("Received TCP/IP port forwarding request.");
channel_input_port_forward_request(pw->pw_uid == 0,
options.gateway_ports);
success = 1;
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 21 18:37:31 2000
@@ -460,10 +460,6 @@
}
}
- /* Cannot fork to background if no command. */
- if (fork_after_authentication_flag && buffer_len(&command) == 0)
- fatal("Cannot fork into background without a command to execute.");
-
/* Allocate a tty by default if no command specified. */
if (buffer_len(&command) == 0)
tty_flag = 1;
@@ -511,6 +507,29 @@
/* reinit */
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
+ /* -N option only makes sense with protocol 2. It doesn't make sense
+ without port forwarding ??????
+ */
+ if ( options.num_local_forwards == 0 && options.num_remote_forwards ==
0 &&
+ no_shell_flag ) {
+ fprintf(stderr, "-N makes sense only with port forwardings\n");
+ usage();
+ /* NOT REACHED */
+ }
+ if ((options.protocol & SSH_PROTO_2) && no_shell_flag &&
+ buffer_len(&command) > 0) {
+ fprintf(stderr,"-N option works only with protocol version 2 and w/out a
command\n");
+ usage();
+ /* NOT REACHED */
+ }
+
+ /* Cannot fork to background if no command.
+ Command not needed for protocol 2 & -N
+ */
+ if ((options.protocol & SSH_PROTO_1) && !(options.protocol &
SSH_PROTO_2) &&
+ fork_after_authentication_flag && buffer_len(&command) == 0)
+ fatal("Cannot fork into background without a command to
execute.");
+
/* check if RSA support exists */
if ((options.protocol & SSH_PROTO_1) &&
rsa_alive() == 0) {
@@ -831,7 +850,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. */
@@ -887,7 +906,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);
}
}
@@ -963,7 +1000,9 @@
/* should be pre-session */
init_local_fwd();
-
+ /* Jarno */
+ init_remote_fwd();
+
window = 32*1024;
if (tty_flag) {
packetmax = window/8;
@@ -979,6 +1018,12 @@
channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init,
(void *)0);
+
+ /* Jarno: User wants us to fork */
+ if (fork_after_authentication_flag) {
+ if (daemon(1, 1) < 0)
+ fatal("daemon() failed: %.200s", strerror(errno));
+ }
return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
}
diff -u -r openssh-2.1.1p4/sshd.8 openssh-2.1.1p4-jhchanges/sshd.8
--- openssh-2.1.1p4/sshd.8 Tue Jul 11 10:31:39 2000
+++ openssh-2.1.1p4-jhchanges/sshd.8 Sun Aug 13 13:47:46 2000
@@ -485,6 +485,10 @@
listens on.
The default is 22.
Multiple options of this type are permitted.
+.It Cm PortForwarding
+Specifies whether TCP/IP port forwarding is permitted.
+The default is
+.Dq yes .
.It Cm PrintMotd
Specifies whether
.Nm