diff options
author | Damien Miller <djm@cvs.openbsd.org> | 2004-05-21 11:33:12 +0000 |
---|---|---|
committer | Damien Miller <djm@cvs.openbsd.org> | 2004-05-21 11:33:12 +0000 |
commit | 8106e52f84202c6eb8b41895a9a614f03da0d26c (patch) | |
tree | b48fc2c674f6965dd09b616b1620f9b54fac8026 | |
parent | 9d70dbf252fd142c7ad3b1fc28f9d3b4906ee0e4 (diff) |
bz #756: add support for the cancel-tcpip-forward request for the server and
the client (through the ~C commandline). reported by z3p AT twistedmatrix.com;
ok markus@
-rw-r--r-- | usr.bin/ssh/channels.c | 67 | ||||
-rw-r--r-- | usr.bin/ssh/channels.h | 4 | ||||
-rw-r--r-- | usr.bin/ssh/clientloop.c | 84 | ||||
-rw-r--r-- | usr.bin/ssh/serverloop.c | 13 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.1 | 13 |
5 files changed, 147 insertions, 34 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c index 450444dbcb8..3ef20026f31 100644 --- a/usr.bin/ssh/channels.c +++ b/usr.bin/ssh/channels.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.201 2004/05/11 19:01:43 deraadt Exp $"); +RCSID("$OpenBSD: channels.c,v 1.202 2004/05/21 11:33:11 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -2218,6 +2218,26 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por return success; } +int +channel_cancel_rport_listener(const char *host, u_short port) +{ + int i, found = 0; + + for(i = 0; i < channels_alloc; i++) { + Channel *c = channels[i]; + + if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && + strncmp(c->path, host, sizeof(c->path)) == 0 && + c->listening_port == port) { + debug2("%s: close clannel %d", __func__, i); + channel_free(c); + found = 1; + } + } + + return (found); +} + /* protocol local port fwd, used by ssh (and sshd in v1) */ int channel_setup_local_fwd_listener(u_short listen_port, @@ -2295,6 +2315,42 @@ channel_request_remote_forwarding(u_short listen_port, } /* + * Request cancellation of remote forwarding of connection host:port from + * local side. + */ + +void +channel_request_rforward_cancel(u_short port) +{ + int i; + const char *address_to_bind = "0.0.0.0"; + + if (!compat20) + return; + + for (i = 0; i < num_permitted_opens; i++) { + if (permitted_opens[i].host_to_connect != NULL && + permitted_opens[i].listen_port == port) + break; + } + if (i >= num_permitted_opens) { + debug("%s: requested forward not found", __func__); + return; + } + packet_start(SSH2_MSG_GLOBAL_REQUEST); + packet_put_cstring("cancel-tcpip-forward"); + packet_put_char(0); + packet_put_cstring(address_to_bind); + packet_put_int(port); + packet_send(); + + permitted_opens[i].listen_port = 0; + permitted_opens[i].port_to_connect = 0; + free(permitted_opens[i].host_to_connect); + permitted_opens[i].host_to_connect = NULL; +} + +/* * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates * listening for the port, and sends back a success reply (or disconnect * message if there was an error). This never returns if there was an error. @@ -2361,7 +2417,8 @@ channel_clear_permitted_opens(void) int i; for (i = 0; i < num_permitted_opens; i++) - xfree(permitted_opens[i].host_to_connect); + if (permitted_opens[i].host_to_connect != NULL) + xfree(permitted_opens[i].host_to_connect); num_permitted_opens = 0; } @@ -2429,7 +2486,8 @@ channel_connect_by_listen_address(u_short listen_port) int i; for (i = 0; i < num_permitted_opens; i++) - if (permitted_opens[i].listen_port == listen_port) + if (permitted_opens[i].host_to_connect != NULL && + permitted_opens[i].listen_port == listen_port) return connect_to( permitted_opens[i].host_to_connect, permitted_opens[i].port_to_connect); @@ -2447,7 +2505,8 @@ channel_connect_to(const char *host, u_short port) permit = all_opens_permitted; if (!permit) { for (i = 0; i < num_permitted_opens; i++) - if (permitted_opens[i].port_to_connect == port && + if (permitted_opens[i].host_to_connect != NULL && + permitted_opens[i].port_to_connect == port && strcmp(permitted_opens[i].host_to_connect, host) == 0) permit = 1; diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h index 37395fe09fc..90ac3de5c1a 100644 --- a/usr.bin/ssh/channels.h +++ b/usr.bin/ssh/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.71 2003/09/23 20:41:11 markus Exp $ */ +/* $OpenBSD: channels.h,v 1.72 2004/05/21 11:33:11 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -199,8 +199,10 @@ void channel_input_port_forward_request(int, int); int channel_connect_to(const char *, u_short); int channel_connect_by_listen_address(u_short); void channel_request_remote_forwarding(u_short, const char *, u_short); +void channel_request_rforward_cancel(u_short port); int channel_setup_local_fwd_listener(u_short, const char *, u_short, int); int channel_setup_remote_fwd_listener(const char *, u_short, int); +int channel_cancel_rport_listener(const char *, u_short); /* x11 forwarding */ diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index 9cbc1b0ce47..ce627e8b824 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.120 2004/05/20 10:58:05 dtucker Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.121 2004/05/21 11:33:11 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -506,6 +506,7 @@ process_cmdline(void) char *s, *cmd; u_short fwd_port, fwd_host_port; char buf[1024], sfwd_port[6], sfwd_host_port[6]; + int delete = 0; int local = 0; leave_raw_mode(); @@ -515,44 +516,77 @@ process_cmdline(void) goto out; while (*s && isspace(*s)) s++; + if (*s == '-') + s++; /* Skip cmdline '-', if any */ if (*s == '\0') goto out; - if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) { + + if (*s == '?') { + logit("Commands:"); + logit(" -Lport:host:hostport Request local forward"); + logit(" -Rport:host:hostport Request remote forward"); + logit(" -KRhostport Cancel remote forward"); + goto out; + } + + if (*s == 'K') { + delete = 1; + s++; + } + if (*s != 'L' && *s != 'R') { logit("Invalid command."); goto out; } - if (s[1] == 'L') + if (*s == 'L') local = 1; - if (!local && !compat20) { + if (local && delete) { + logit("Not supported."); + goto out; + } + if ((!local || delete) && !compat20) { logit("Not supported for SSH protocol version 1."); goto out; } - s += 2; + + s++; while (*s && isspace(*s)) s++; - if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", - sfwd_port, buf, sfwd_host_port) != 3 && - sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", - sfwd_port, buf, sfwd_host_port) != 3) { - logit("Bad forwarding specification."); - goto out; - } - if ((fwd_port = a2port(sfwd_port)) == 0 || - (fwd_host_port = a2port(sfwd_host_port)) == 0) { - logit("Bad forwarding port(s)."); - goto out; - } - if (local) { - if (channel_setup_local_fwd_listener(fwd_port, buf, - fwd_host_port, options.gateway_ports) < 0) { - logit("Port forwarding failed."); + if (delete) { + if (sscanf(s, "%5[0-9]", sfwd_host_port) != 1) { + logit("Bad forwarding specification."); + goto out; + } + if ((fwd_host_port = a2port(sfwd_host_port)) == 0) { + logit("Bad forwarding port(s)."); + goto out; + } + channel_request_rforward_cancel(fwd_host_port); + } else { + if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", + sfwd_port, buf, sfwd_host_port) != 3 && + sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", + sfwd_port, buf, sfwd_host_port) != 3) { + logit("Bad forwarding specification."); goto out; } - } else - channel_request_remote_forwarding(fwd_port, buf, - fwd_host_port); - logit("Forwarding port."); + if ((fwd_port = a2port(sfwd_port)) == 0 || + (fwd_host_port = a2port(sfwd_host_port)) == 0) { + logit("Bad forwarding port(s)."); + goto out; + } + if (local) { + if (channel_setup_local_fwd_listener(fwd_port, buf, + fwd_host_port, options.gateway_ports) < 0) { + logit("Port forwarding failed."); + goto out; + } + } else + channel_request_remote_forwarding(fwd_port, buf, + fwd_host_port); + logit("Forwarding port."); + } + out: signal(SIGINT, handler); enter_raw_mode(); diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index e2f093ff5f2..a9c8dcbf456 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.115 2004/01/19 21:25:15 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.116 2004/05/21 11:33:11 djm Exp $"); #include "xmalloc.h" #include "packet.h" @@ -986,6 +986,17 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) listen_address, listen_port, options.gateway_ports); } xfree(listen_address); + } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { + char *cancel_address; + u_short cancel_port; + + cancel_address = packet_get_string(NULL); + cancel_port = (u_short)packet_get_int(); + debug("%s: cancel-tcpip-forward addr %s port %d", __func__, + cancel_address, cancel_port); + + success = channel_cancel_rport_listener(cancel_address, + cancel_port); } if (want_reply) { packet_start(success ? diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1 index b7b126440cc..7da143b198d 100644 --- a/usr.bin/ssh/ssh.1 +++ b/usr.bin/ssh/ssh.1 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.185 2004/05/02 11:57:52 dtucker Exp $ +.\" $OpenBSD: ssh.1,v 1.186 2004/05/21 11:33:11 djm Exp $ .Dd September 25, 1999 .Dt SSH 1 .Os @@ -302,11 +302,18 @@ Display a list of escape characters. Send a BREAK to the remote system (only useful for SSH protocol version 2 and if the peer supports it). .It Cm ~C -Open command line (only useful for adding port forwardings using the +Open command line. +Currently this allows the addition of port forwardings using the .Fl L and .Fl R -options). +options (see below). +It also allows the cancellation of existing remote port-forwardings +using +.Fl KR Ar hostport . +Basic help is available, using the +.Fl ? +option. .It Cm ~R Request rekeying of the connection (only useful for SSH protocol version 2 and if the peer supports it). |