Bert Wesarg
2012-May-03 11:33 UTC
[PATCH/RFC 0/6] New mux client request to list open tcp forwardings.
These patches implement a new mux client request to list the currently opened TCP forwardings. It also removes some todos regarding keeping the list of forwardings in the options up-to-date. Bert Wesarg (6): attach the forwarding type to struct Forward merge local and remote forward lists generate unique ids for forwardings to be used for identification remove closed forwardings from options maintain lists of forwards when changed from a mux client command line [mux.c] new request to list open forwardings PROTOCOL.mux | 36 ++++++++++- clientloop.c | 40 +++++++++--- mux.c | 200 ++++++++++++++++++++++++++++------------------------------ readconf.c | 128 +++++++++++++++++++------------------ readconf.h | 23 ++++--- ssh.c | 103 +++++++++++++++++++----------- sshconnect.c | 8 +- 7 files changed, 308 insertions(+), 230 deletions(-) -- 1.7.9.rc0.542.g07ca1
Bert Wesarg
2012-May-03 11:33 UTC
[PATCH/RFC 1/6] attach the forwarding type to struct Forward
--- clientloop.c | 21 +++++++++--------- mux.c | 65 ++++++++++++++++++++++++++++----------------------------- readconf.c | 19 ++++++++++------ readconf.h | 8 ++++++- ssh.c | 8 +++--- 5 files changed, 66 insertions(+), 55 deletions(-) diff --git a/clientloop.c b/clientloop.c index 58357cf..6c62bb7 100644 --- a/clientloop.c +++ b/clientloop.c @@ -863,7 +863,8 @@ process_cmdline(void) { void (*handler)(int); char *s, *cmd, *cancel_host; - int delete = 0, local = 0, remote = 0, dynamic = 0; + int delete = 0, i; + u_int fwdtype; int cancel_port, ok; Forward fwd; @@ -914,11 +915,11 @@ process_cmdline(void) s++; } if (*s == 'L') - local = 1; + fwdtype = SSH_FWD_LOCAL; else if (*s == 'R') - remote = 1; + fwdtype = SSH_FWD_REMOTE; else if (*s == 'D') - dynamic = 1; + fwdtype = SSH_FWD_DYNAMIC; else { logit("Invalid command."); goto out; @@ -947,14 +948,14 @@ process_cmdline(void) logit("Bad forwarding close port"); goto out; } - if (remote) + if (fwdtype == SSH_FWD_REMOTE) ok = channel_request_rforward_cancel(cancel_host, cancel_port) == 0; - else if (dynamic) - ok = channel_cancel_lport_listener(cancel_host, + else if (fwdtype == SSH_FWD_DYNAMIC) + ok = channel_cancel_lport_listener(cancel_host, cancel_port, 0, options.gateway_ports) > 0; else - ok = channel_cancel_lport_listener(cancel_host, + ok = channel_cancel_lport_listener(cancel_host, cancel_port, CHANNEL_CANCEL_PORT_STATIC, options.gateway_ports) > 0; if (!ok) { @@ -963,11 +964,11 @@ process_cmdline(void) } logit("Canceled forwarding."); } else { - if (!parse_forward(&fwd, s, dynamic, remote)) { + if (!parse_forward(&fwd, s, fwdtype)) { logit("Bad forwarding specification."); goto out; } - if (local || dynamic) { + if (fwdtype == SSH_FWD_LOCAL || fwdtype == SSH_FWD_DYNAMIC) { if (channel_setup_local_fwd_listener(fwd.listen_host, fwd.listen_port, fwd.connect_host, fwd.connect_port, options.gateway_ports) < 0) { diff --git a/mux.c b/mux.c index d90605e..e7b81d1 100644 --- a/mux.c +++ b/mux.c @@ -156,9 +156,9 @@ struct mux_master_state { #define MUX_S_TTY_ALLOC_FAIL 0x80000008 /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ -#define MUX_FWD_LOCAL 1 -#define MUX_FWD_REMOTE 2 -#define MUX_FWD_DYNAMIC 3 +#define MUX_FWD_LOCAL SSH_FWD_LOCAL +#define MUX_FWD_REMOTE SSH_FWD_REMOTE +#define MUX_FWD_DYNAMIC SSH_FWD_DYNAMIC static void mux_session_confirm(int, int, void *); @@ -511,11 +511,11 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) } static char * -format_forward(u_int ftype, Forward *fwd) +format_forward(Forward *fwd) { char *ret; - switch (ftype) { + switch (fwd->type) { case MUX_FWD_LOCAL: xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", (fwd->listen_host == NULL) ? @@ -537,7 +537,7 @@ format_forward(u_int ftype, Forward *fwd) fwd->connect_host, fwd->connect_port); break; default: - fatal("%s: unknown forward type %u", __func__, ftype); + fatal("%s: unknown forward type %u", __func__, fwd->type); } return ret; } @@ -555,6 +555,8 @@ compare_host(const char *a, const char *b) static int compare_forward(Forward *a, Forward *b) { + if (a->type != b->type) + return 0; if (!compare_host(a->listen_host, b->listen_host)) return 0; if (a->listen_port != b->listen_port) @@ -631,11 +633,10 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) { Forward fwd; char *fwd_desc = NULL; - u_int ftype; int i, ret = 0, freefwd = 1; fwd.listen_host = fwd.connect_host = NULL; - if (buffer_get_int_ret(&ftype, m) != 0 || + if (buffer_get_int_ret(&fwd.type, m) != 0 || (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&fwd.listen_port, m) != 0 || (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || @@ -655,11 +656,11 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } debug2("%s: channel %d: request %s", __func__, c->self, - (fwd_desc = format_forward(ftype, &fwd))); + (fwd_desc = format_forward(&fwd))); - if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE && - ftype != MUX_FWD_DYNAMIC) { - logit("%s: invalid forwarding type %u", __func__, ftype); + if (fwd.type != MUX_FWD_LOCAL && fwd.type != MUX_FWD_REMOTE && + fwd.type != MUX_FWD_DYNAMIC) { + logit("%s: invalid forwarding type %u", __func__, fwd.type); invalid: if (fwd.listen_host) xfree(fwd.listen_host); @@ -675,19 +676,19 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) fwd.listen_port); goto invalid; } - if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && - ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { + if (fwd.connect_port >= 65536 || (fwd.type != MUX_FWD_DYNAMIC && + fwd.type != MUX_FWD_REMOTE && fwd.connect_port == 0)) { logit("%s: invalid connect port %u", __func__, fwd.connect_port); goto invalid; } - if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { + if (fwd.type != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { logit("%s: missing connect host", __func__); goto invalid; } /* Skip forwards that have already been requested */ - switch (ftype) { + switch (fwd.type) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { @@ -731,7 +732,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } } - if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { + if (fwd.type == MUX_FWD_LOCAL || fwd.type == MUX_FWD_DYNAMIC) { if (channel_setup_local_fwd_listener(fwd.listen_host, fwd.listen_port, fwd.connect_host, fwd.connect_port, options.gateway_ports) < 0) { @@ -783,11 +784,10 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) Forward fwd, *found_fwd; char *fwd_desc = NULL; const char *error_reason = NULL; - u_int ftype; int i, listen_port, ret = 0; fwd.listen_host = fwd.connect_host = NULL; - if (buffer_get_int_ret(&ftype, m) != 0 || + if (buffer_get_int_ret(&fwd.type, m) != 0 || (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&fwd.listen_port, m) != 0 || (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || @@ -807,11 +807,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } debug2("%s: channel %d: request cancel %s", __func__, c->self, - (fwd_desc = format_forward(ftype, &fwd))); + (fwd_desc = format_forward(&fwd))); /* make sure this has been requested */ found_fwd = NULL; - switch (ftype) { + switch (fwd.type) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { @@ -835,22 +835,22 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) if (found_fwd == NULL) error_reason = "port not forwarded"; - else if (ftype == MUX_FWD_REMOTE) { + else if (found_fwd->type == MUX_FWD_REMOTE) { /* * This shouldn't fail unless we confused the host/port * between options.remote_forwards and permitted_opens. * However, for dynamic allocated listen ports we need * to lookup the actual listen port. */ - listen_port = (fwd.listen_port == 0) ? - found_fwd->allocated_port : fwd.listen_port; - if (channel_request_rforward_cancel(fwd.listen_host, + listen_port = (found_fwd->listen_port == 0) ? + found_fwd->allocated_port : found_fwd->listen_port; + if (channel_request_rforward_cancel(found_fwd->listen_host, 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, + if (channel_cancel_lport_listener(found_fwd->listen_host, + found_fwd->listen_port, found_fwd->connect_port, options.gateway_ports) == -1) error_reason = "port not found"; } @@ -859,6 +859,7 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) buffer_put_int(r, MUX_S_OK); buffer_put_int(r, rid); + found_fwd->type = 0; if (found_fwd->listen_host != NULL) xfree(found_fwd->listen_host); if (found_fwd->connect_host != NULL) @@ -1597,13 +1598,13 @@ mux_client_request_terminate(int fd) } static int -mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) +mux_client_forward(int fd, int cancel_flag, Forward *fwd) { Buffer m; char *e, *fwd_desc; u_int type, rid; - fwd_desc = format_forward(ftype, fwd); + fwd_desc = format_forward(fwd); debug("Requesting %s %s", cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); xfree(fwd_desc); @@ -1611,7 +1612,7 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) buffer_init(&m); 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_int(&m, fwd->type); buffer_put_cstring(&m, fwd->listen_host == NULL ? "" : fwd->listen_host); buffer_put_int(&m, fwd->listen_port); @@ -1680,13 +1681,11 @@ mux_client_forwards(int fd, int cancel_flag) /* XXX ExitOnForwardingFailure */ for (i = 0; i < options.num_local_forwards; i++) { 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) ret = -1; } for (i = 0; i < options.num_remote_forwards; i++) { - if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE, + if (mux_client_forward(fd, cancel_flag, options.remote_forwards + i) != 0) ret = -1; } diff --git a/readconf.c b/readconf.c index 097bb05..29e12bd 100644 --- a/readconf.c +++ b/readconf.c @@ -269,6 +269,7 @@ add_local_forward(Options *options, const Forward *newfwd) sizeof(*options->local_forwards)); fwd = &options->local_forwards[options->num_local_forwards++]; + fwd->type = newfwd->type; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->connect_host = newfwd->connect_host; @@ -290,6 +291,7 @@ add_remote_forward(Options *options, const Forward *newfwd) sizeof(*options->remote_forwards)); fwd = &options->remote_forwards[options->num_remote_forwards++]; + fwd->type = newfwd->type; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->connect_host = newfwd->connect_host; @@ -784,8 +786,9 @@ parse_int: } if (parse_forward(&fwd, fwdarg, - opcode == oDynamicForward ? 1 : 0, - opcode == oRemoteForward ? 1 : 0) == 0) + opcode == oDynamicForward ? SSH_FWD_DYNAMIC : + opcode == oRemoteForward ? SSH_FWD_REMOTE : + SSH_FWD_LOCAL) == 0) fatal("%.200s line %d: Bad forwarding specification.", filename, linenum); @@ -1378,19 +1381,20 @@ fill_default_options(Options * options) /* * parse_forward * parses a string containing a port forwarding specification of the form: - * dynamicfwd == 0 + * fwdtype != SSH_FWD_DYNAMIC * [listenhost:]listenport:connecthost:connectport - * dynamicfwd == 1 + * fwdtype == SSH_FWD_DYNAMIC * [listenhost:]listenport * returns number of arguments parsed or zero on error */ int -parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) +parse_forward(Forward *fwd, const char *fwdspec, u_int fwdtype) { int i; char *p, *cp, *fwdarg[4]; memset(fwd, '\0', sizeof(*fwd)); + fwd->type = fwdtype; cp = p = xstrdup(fwdspec); @@ -1438,7 +1442,7 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) xfree(p); - if (dynamicfwd) { + if (fwd->type == SSH_FWD_DYNAMIC) { if (!(i == 1 || i == 2)) goto fail_free; } else { @@ -1448,7 +1452,8 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) goto fail_free; } - if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) + if (fwd->listen_port < 0 || + (fwd->type != SSH_FWD_REMOTE && fwd->listen_port == 0)) goto fail_free; if (fwd->connect_host != NULL && diff --git a/readconf.h b/readconf.h index be30ee0..b15d916 100644 --- a/readconf.h +++ b/readconf.h @@ -18,7 +18,13 @@ /* Data structure for representing a forwarding request. */ +/* This is also part of the MUX protocol */ +#define SSH_FWD_LOCAL 1 +#define SSH_FWD_REMOTE 2 +#define SSH_FWD_DYNAMIC 3 + typedef struct { + u_int type; /* Type of forwarding [1, 2, 3] */ char *listen_host; /* Host (address) to listen on. */ int listen_port; /* Port to forward. */ char *connect_host; /* Host to connect. */ @@ -151,11 +157,11 @@ typedef struct { void initialize_options(Options *); void fill_default_options(Options *); int read_config_file(const char *, const char *, Options *, int); -int parse_forward(Forward *, const char *, int, int); int process_config_line(Options *, const char *, char *, const char *, int, int *); +int parse_forward(Forward *, const char *, u_int); void add_local_forward(Options *, const Forward *); void add_remote_forward(Options *, const Forward *); diff --git a/ssh.c b/ssh.c index 68e1315..a63bfab 100644 --- a/ssh.c +++ b/ssh.c @@ -456,7 +456,7 @@ main(int ac, char **av) fatal("stdio forward already specified"); if (muxclient_command != 0) fatal("Cannot specify stdio forward with -O"); - if (parse_forward(&fwd, optarg, 1, 0)) { + if (parse_forward(&fwd, optarg, SSH_FWD_DYNAMIC)) { stdio_forward_host = fwd.listen_host; stdio_forward_port = fwd.listen_port; xfree(fwd.connect_host); @@ -538,7 +538,7 @@ main(int ac, char **av) break; case 'L': - if (parse_forward(&fwd, optarg, 0, 0)) + if (parse_forward(&fwd, optarg, SSH_FWD_LOCAL)) add_local_forward(&options, &fwd); else { fprintf(stderr, @@ -549,7 +549,7 @@ main(int ac, char **av) break; case 'R': - if (parse_forward(&fwd, optarg, 0, 1)) { + if (parse_forward(&fwd, optarg, SSH_FWD_REMOTE)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, @@ -560,7 +560,7 @@ main(int ac, char **av) break; case 'D': - if (parse_forward(&fwd, optarg, 1, 0)) { + if (parse_forward(&fwd, optarg, SSH_FWD_DYNAMIC)) { add_local_forward(&options, &fwd); } else { fprintf(stderr, -- 1.7.9.rc0.542.g07ca1
--- mux.c | 8 +------- readconf.c | 32 ++++++++++++++++++++++++++++++++ readconf.h | 1 + 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/mux.c b/mux.c index 337ef54..c59bb97 100644 --- a/mux.c +++ b/mux.c @@ -835,13 +835,7 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) buffer_put_int(r, MUX_S_OK); buffer_put_int(r, rid); - found_fwd->type = 0; - 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; + remove_forward(&options, found_fwd); } else { buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, rid); diff --git a/readconf.c b/readconf.c index a89b07a..371570d 100644 --- a/readconf.c +++ b/readconf.c @@ -286,6 +286,38 @@ add_forward(Options *options, const Forward *newfwd) return fwd->id; } +/* + * Remove a TCP/IP port forward from the options. + */ + +void +remove_forward(Options *options, Forward *remfwd) +{ + if (remfwd < options->forwards || + options->forwards + options->num_forwards <= remfwd) + fatal("Invalid forwarding to remove."); + + if (remfwd->listen_host != NULL) + xfree(remfwd->listen_host); + if (remfwd->connect_host != NULL) + xfree(remfwd->connect_host); + remfwd->listen_host = remfwd->connect_host = NULL; + remfwd->listen_port = remfwd->connect_port = 0; + + options->num_forwards--; + while (remfwd < options->forwards + options->num_forwards) { + *remfwd = *(remfwd + 1); + remfwd++; + } + if (options->num_forwards > 0) + options->forwards = xrealloc(options->forwards, + options->num_forwards, sizeof(*remfwd)); + else { + xfree(options->forwards); + options->forwards = NULL; + } +} + static void clear_forwardings(Options *options) { diff --git a/readconf.h b/readconf.h index d44946b..6877888 100644 --- a/readconf.h +++ b/readconf.h @@ -160,5 +160,6 @@ process_config_line(Options *, const char *, char *, const char *, int, int *); int parse_forward(Forward *, const char *, u_int); u_int add_forward(Options *, const Forward *); +void remove_forward(Options *, Forward *); #endif /* READCONF_H */ -- 1.7.9.rc0.542.g07ca1
Bert Wesarg
2012-May-03 11:33 UTC
[PATCH/RFC 5/6] maintain lists of forwards when changed from a mux client command line
--- clientloop.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-) diff --git a/clientloop.c b/clientloop.c index 6c62bb7..018df0d 100644 --- a/clientloop.c +++ b/clientloop.c @@ -933,7 +933,6 @@ process_cmdline(void) while (isspace(*++s)) ; - /* XXX update list of forwards in options */ if (delete) { cancel_port = 0; cancel_host = hpdelim(&s); /* may be NULL */ @@ -962,6 +961,23 @@ process_cmdline(void) logit("Unkown port forwarding."); goto out; } + for (i = 0; i < options.num_forwards; i++) { + Forward *efwd = options.forwards + i; + int listen_port = (efwd->listen_port == 0) ? + efwd->allocated_port : efwd->listen_port; + if (fwdtype != efwd->type) + continue; + if (cancel_port != listen_port) + continue; + if ((efwd->listen_host == NULL && cancel_host != NULL) || + (efwd->listen_host != NULL && cancel_host == NULL)) + continue; + if (cancel_host == NULL || + strcmp(efwd->listen_host, cancel_host) == 0) { + remove_forward(&options, efwd); + break; + } + } logit("Canceled forwarding."); } else { if (!parse_forward(&fwd, s, fwdtype)) { @@ -983,6 +999,7 @@ process_cmdline(void) goto out; } } + add_forward(&options, &fwd); logit("Forwarding port."); } -- 1.7.9.rc0.542.g07ca1
Bert Wesarg
2012-May-03 11:33 UTC
[PATCH/RFC 6/6] [mux.c] new request to list open forwardings
--- PROTOCOL.mux | 36 +++++++++++++++++++++++++++++++++--- mux.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/PROTOCOL.mux b/PROTOCOL.mux index 49cbe5b..26b5f8d 100644 --- a/PROTOCOL.mux +++ b/PROTOCOL.mux @@ -171,13 +171,41 @@ and remove its listener socket. A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. -9. Status messages +9. Request a list of open forwardings from the mux listener + +A client may request the master to send the list of open port forwardings. + + uint32 MUX_C_LIST_FWDS + uint32 request id + +The server will reply with a MUX_S_RESULT and the following payload: + + uint32 MUX_S_RESULT + uint32 client request id + [ uint32 forwarding id + uint32 forwarding type + string listen host + uint32 listen port + string connect host + uint32 connect port + uint32 allocated port [if appropriate] ]... + +The allocated port entry is only there for remote forwardings with a listen port +equal zero. + +10. Status messages The MUX_S_OK message is empty: uint32 MUX_S_OK uint32 client request id +The MUX_S_RESULT message has a payload depending on the client request: + + uint32 MUX_S_RESULT + uint32 client request id + [payload] + The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: uint32 MUX_S_PERMISSION_DENIED @@ -188,7 +216,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: uint32 client request id string reason -10. Protocol numbers +11. Protocol numbers #define MUX_MSG_HELLO 0x00000001 #define MUX_C_NEW_SESSION 0x10000002 @@ -198,6 +226,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 +#define MUX_C_LIST_FWDS 0x1000000a #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 @@ -206,13 +235,14 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 +#define MUX_S_RESULT 0x80000009 #define MUX_FWD_LOCAL 1 #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 XXX TODO -XXX extended status (e.g. report open channels / forwards) +XXX extended status (e.g. report open channels) XXX lock (maybe) XXX watch in/out traffic (pre/post crypto) XXX inject packet (what about replies) diff --git a/mux.c b/mux.c index c59bb97..d975007 100644 --- a/mux.c +++ b/mux.c @@ -146,6 +146,7 @@ struct mux_master_state { #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 +#define MUX_C_LIST_FWDS 0x1000000a #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 @@ -154,6 +155,7 @@ struct mux_master_state { #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 +#define MUX_S_RESULT 0x80000009 /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ #define MUX_FWD_LOCAL SSH_FWD_LOCAL @@ -170,6 +172,7 @@ static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); +static int process_mux_list_fwds(u_int, Channel *, Buffer *, Buffer *); static const struct { u_int type; @@ -183,6 +186,7 @@ static const struct { { MUX_C_CLOSE_FWD, process_mux_close_fwd }, { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, { MUX_C_STOP_LISTENING, process_mux_stop_listening }, + { MUX_C_LIST_FWDS, process_mux_list_fwds }, { 0, NULL } }; @@ -982,6 +986,33 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) return 0; } +static int +process_mux_list_fwds(u_int rid, Channel *c, Buffer *m, Buffer *r) +{ + int i; + + debug("%s: channel %d: list forwardings", __func__, c->self); + + /* prepare reply */ + buffer_put_int(r, MUX_S_RESULT); + buffer_put_int(r, rid); + + for (i = 0; i < options.num_forwards; i++) { + Forward *fwd = &options.forwards[i]; + buffer_put_int(r, fwd->id); + buffer_put_int(r, fwd->type); + buffer_put_cstring(r, fwd->listen_host ? fwd->listen_host : ""); + buffer_put_int(r, fwd->listen_port); + buffer_put_cstring(r, fwd->connect_host ? fwd->connect_host : ""); + buffer_put_int(r, fwd->connect_port); + if (fwd->type == MUX_FWD_REMOTE && fwd->listen_port == 0) { + buffer_put_int(r, fwd->allocated_port); + } + } + + return 0; +} + /* Channel callbacks fired on read/write from mux slave fd */ static int mux_master_read_cb(Channel *c) -- 1.7.9.rc0.542.g07ca1
Alex Bligh
2012-May-03 12:35 UTC
[PATCH/RFC 0/6] New mux client request to list open tcp forwardings.
--On 3 May 2012 13:33:46 +0200 Bert Wesarg <bert.wesarg at googlemail.com> wrote:> These patches implement a new mux client request to list the currently > opened TCP forwardings. It also removes some todos regarding keeping the > list of forwardings in the options up-to-date.Interesting. I have a related application where a process on the /server/ wants to know the list of port forwardings. In essence I have a large number of clients all connecting using public key, and all forwarding one of their local ports with -R, and dynamically allocating a listen port on the server side. The server needs to establish (without being able to trust the client) which port an ssh session with a given public key is listening on. Currently I do this by a combination of forcing a command on the server side, and some nasty hackery with lsof type things. It would be useful if there were something that could be queried on the server to definitively establish which forwarded port was what, particularly as my method does not work with more than one forwarded port (hence fails with autossh). -- Alex Bligh
Reasonably Related Threads
- FWD: enable forwarding to remote named sockets in ssh
- [Bug 1379] New: memory leak in process_cmdline()
- [Bug 413] Port forwarding: [localhost:]localport:remotehost:remoteport
- Bug CVE-2005-2797
- [Bug 1012] Trouble creating remote port forwarding to ssh.com 2.4.0 server.