diff options
author | djm <djm> | 2011-09-22 11:38:52 +0000 |
---|---|---|
committer | djm <djm> | 2011-09-22 11:38:52 +0000 |
commit | cd36da700568ad7fbecfc23c3c4c179f98efe9f5 (patch) | |
tree | fa6c26c652c15b7c53415c0e214b7e10a244672f /mux.c | |
parent | 5a699b8fb53ea7bfae13001d0b11e62689e2f25c (diff) | |
download | openssh-cd36da700568ad7fbecfc23c3c4c179f98efe9f5.tar.gz |
- djm@cvs.openbsd.org 2011/09/09 22:46:44
[channels.c channels.h clientloop.h mux.c ssh.c]
support for cancelling local and remote port forwards via the multiplex
socket. Use ssh -O cancel -L xx:xx:xx -R yy:yy:yy user@host" to request
the cancellation of the specified forwardings; ok markus@
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 104 |
1 files changed, 83 insertions, 21 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.30 2011/09/09 22:46:44 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> * @@ -777,10 +777,11 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) static int process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) { - Forward fwd; + Forward fwd, *found_fwd; char *fwd_desc = NULL; + const char *error_reason = NULL; u_int ftype; - int ret = 0; + int i, ret = 0; fwd.listen_host = fwd.connect_host = NULL; if (buffer_get_int_ret(&ftype, m) != 0 || @@ -802,14 +803,66 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) fwd.connect_host = NULL; } - debug2("%s: channel %d: request %s", __func__, c->self, + debug2("%s: channel %d: request cancel %s", __func__, c->self, (fwd_desc = format_forward(ftype, &fwd))); - /* XXX implement this */ - buffer_put_int(r, MUX_S_FAILURE); - buffer_put_int(r, rid); - buffer_put_cstring(r, "unimplemented"); + /* make sure this has been requested */ + found_fwd = NULL; + switch (ftype) { + case MUX_FWD_LOCAL: + case MUX_FWD_DYNAMIC: + for (i = 0; i < options.num_local_forwards; i++) { + if (compare_forward(&fwd, + options.local_forwards + i)) { + found_fwd = options.local_forwards + i; + break; + } + } + break; + case MUX_FWD_REMOTE: + for (i = 0; i < options.num_remote_forwards; i++) { + if (compare_forward(&fwd, + options.remote_forwards + i)) { + found_fwd = options.remote_forwards + i; + break; + } + } + break; + } + if (found_fwd == NULL) + error_reason = "port not forwarded"; + else if (ftype == MUX_FWD_REMOTE) { + /* + * This shouldn't fail unless we confused the host/port + * between options.remote_forwards and permitted_opens. + */ + if (channel_request_rforward_cancel(fwd.listen_host, + fwd.listen_port) == -1) + error_reason = "port not in permitted opens"; + } else { /* local and dynamic forwards */ + /* Ditto */ + if (channel_cancel_lport_listener(fwd.listen_host, + fwd.listen_port, fwd.connect_port, + options.gateway_ports) == -1) + error_reason = "port not found"; + } + + if (error_reason == NULL) { + buffer_put_int(r, MUX_S_OK); + buffer_put_int(r, rid); + + if (found_fwd->listen_host != NULL) + xfree(found_fwd->listen_host); + if (found_fwd->connect_host != NULL) + xfree(found_fwd->connect_host); + found_fwd->listen_host = found_fwd->connect_host = NULL; + found_fwd->listen_port = found_fwd->connect_port = 0; + } else { + buffer_put_int(r, MUX_S_FAILURE); + buffer_put_int(r, rid); + buffer_put_cstring(r, error_reason); + } out: if (fwd_desc != NULL) xfree(fwd_desc); @@ -1537,18 +1590,19 @@ mux_client_request_terminate(int fd) } static int -mux_client_request_forward(int fd, u_int ftype, Forward *fwd) +mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) { Buffer m; char *e, *fwd_desc; u_int type, rid; fwd_desc = format_forward(ftype, fwd); - debug("Requesting %s", fwd_desc); + debug("Requesting %s %s", + cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); xfree(fwd_desc); buffer_init(&m); - buffer_put_int(&m, MUX_C_OPEN_FWD); + buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); buffer_put_int(&m, muxclient_request_id); buffer_put_int(&m, ftype); buffer_put_cstring(&m, @@ -1577,6 +1631,8 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) case MUX_S_OK: break; case MUX_S_REMOTE_PORT: + if (cancel_flag) + fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__); fwd->allocated_port = buffer_get_int(&m); logit("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, @@ -1606,27 +1662,28 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) } static int -mux_client_request_forwards(int fd) +mux_client_forwards(int fd, int cancel_flag) { - int i; + int i, ret = 0; - debug3("%s: requesting forwardings: %d local, %d remote", __func__, + debug3("%s: %s forwardings: %d local, %d remote", __func__, + cancel_flag ? "cancel" : "request", options.num_local_forwards, options.num_remote_forwards); /* XXX ExitOnForwardingFailure */ for (i = 0; i < options.num_local_forwards; i++) { - if (mux_client_request_forward(fd, + if (mux_client_forward(fd, cancel_flag, options.local_forwards[i].connect_port == 0 ? MUX_FWD_DYNAMIC : MUX_FWD_LOCAL, options.local_forwards + i) != 0) - return -1; + ret = -1; } for (i = 0; i < options.num_remote_forwards; i++) { - if (mux_client_request_forward(fd, MUX_FWD_REMOTE, + if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE, options.remote_forwards + i) != 0) - return -1; + ret = -1; } - return 0; + return ret; } static int @@ -2014,11 +2071,11 @@ muxclient(const char *path) fprintf(stderr, "Exit request sent.\r\n"); exit(0); case SSHMUX_COMMAND_FORWARD: - if (mux_client_request_forwards(sock) != 0) + if (mux_client_forwards(sock, 0) != 0) fatal("%s: master forward request failed", __func__); exit(0); case SSHMUX_COMMAND_OPEN: - if (mux_client_request_forwards(sock) != 0) { + if (mux_client_forwards(sock, 0) != 0) { error("%s: master forward request failed", __func__); return; } @@ -2031,6 +2088,11 @@ muxclient(const char *path) mux_client_request_stop_listening(sock); fprintf(stderr, "Stop listening request sent.\r\n"); exit(0); + case SSHMUX_COMMAND_CANCEL_FWD: + if (mux_client_forwards(sock, 1) != 0) + error("%s: master cancel forward request failed", + __func__); + exit(0); default: fatal("unrecognised muxclient_command %d", muxclient_command); } |