
bert.wesarg at googlemail
May 3, 2012, 4:33 AM
Post #1 of 1
(117 views)
Permalink
|
|
[PATCH/RFC 2/6] merge local and remote forward lists
|
|
--- mux.c | 99 ++++++++++++++++++++-------------------------------------- readconf.c | 87 +++++++++++++++----------------------------------- readconf.h | 13 ++----- ssh.c | 74 ++++++++++++++++++++++++------------------- sshconnect.c | 8 ++-- 5 files changed, 110 insertions(+), 171 deletions(-) diff --git a/mux.c b/mux.c index e7b81d1..d57c1de 100644 --- a/mux.c +++ b/mux.c @@ -584,11 +584,15 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) return; } buffer_init(&out); - if (fctx->fid >= options.num_remote_forwards) { + if (fctx->fid >= options.num_forwards) { xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); goto fail; } - rfwd = &options.remote_forwards[fctx->fid]; + rfwd = &options.forwards[fctx->fid]; + if (rfwd->type != SSH_FWD_REMOTE) { + xasprintf(&failmsg, "non-remote forwarding id %d", fctx->fid); + goto fail; + } debug("%s: %s for: listen %d, connect %s:%d", __func__, type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); @@ -688,37 +692,23 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) } /* Skip forwards that have already been requested */ - switch (fwd.type) { - 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)) { - exists: - debug2("%s: found existing forwarding", - __func__); - buffer_put_int(r, MUX_S_OK); - buffer_put_int(r, rid); - goto out; - } - } - break; - case MUX_FWD_REMOTE: - for (i = 0; i < options.num_remote_forwards; i++) { - if (compare_forward(&fwd, - options.remote_forwards + i)) { - if (fwd.listen_port != 0) - goto exists; - debug2("%s: found allocated port", - __func__); - buffer_put_int(r, MUX_S_REMOTE_PORT); - buffer_put_int(r, rid); - buffer_put_int(r, - options.remote_forwards[i].allocated_port); - goto out; - } + for (i = 0; i < options.num_forwards; i++) { + if (!compare_forward(&fwd, &options.forwards[i])) + continue; + if (fwd.type == MUX_FWD_REMOTE && fwd.listen_port == 0) { + debug2("%s: found allocated port", + __func__); + buffer_put_int(r, MUX_S_REMOTE_PORT); + buffer_put_int(r, rid); + buffer_put_int(r, + options.forwards[i].allocated_port); + } else { + debug2("%s: found existing forwarding", + __func__); + buffer_put_int(r, MUX_S_OK); + buffer_put_int(r, rid); } - break; + goto out; } if (options.control_master == SSHCTL_MASTER_ASK || @@ -743,7 +733,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) buffer_put_cstring(r, "Port forwarding failed"); goto out; } - add_local_forward(&options, &fwd); + add_forward(&options, &fwd); freefwd = 0; } else { struct mux_channel_confirm_ctx *fctx; @@ -752,11 +742,11 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) fwd.listen_port, fwd.connect_host, fwd.connect_port); if (fwd.handle < 0) goto fail; - add_remote_forward(&options, &fwd); + add_forward(&options, &fwd); fctx = xcalloc(1, sizeof(*fctx)); fctx->cid = c->self; fctx->rid = rid; - fctx->fid = options.num_remote_forwards - 1; + fctx->fid = options.num_forwards - 1; client_register_global_confirm(mux_confirm_remote_forward, fctx); freefwd = 0; @@ -811,26 +801,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) /* make sure this has been requested */ found_fwd = NULL; - switch (fwd.type) { - 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; - } + for (i = 0; i < options.num_forwards; i++) { + if (compare_forward(&fwd, &options.forwards[i])) { + found_fwd = &options.forwards[i]; + break; } - break; } if (found_fwd == NULL) @@ -838,7 +813,7 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 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. + * between options.forwards and permitted_opens. * However, for dynamic allocated listen ports we need * to lookup the actual listen port. */ @@ -1674,19 +1649,13 @@ mux_client_forwards(int fd, int cancel_flag) { int i, ret = 0; - debug3("%s: %s forwardings: %d local, %d remote", __func__, - cancel_flag ? "cancel" : "request", - options.num_local_forwards, options.num_remote_forwards); + debug3("%s: %s %d forwardings", __func__, + cancel_flag ? "cancel" : "request", options.num_forwards); /* XXX ExitOnForwardingFailure */ - for (i = 0; i < options.num_local_forwards; i++) { - if (mux_client_forward(fd, cancel_flag, - options.local_forwards + i) != 0) - ret = -1; - } - for (i = 0; i < options.num_remote_forwards; i++) { + for (i = 0; i < options.num_forwards; i++) { if (mux_client_forward(fd, cancel_flag, - options.remote_forwards + i) != 0) + &options.forwards[i]) != 0) ret = -1; } return ret; diff --git a/readconf.c b/readconf.c index 29e12bd..d0687af 100644 --- a/readconf.c +++ b/readconf.c @@ -256,48 +256,30 @@ static struct { */ void -add_local_forward(Options *options, const Forward *newfwd) +add_forward(Options *options, const Forward *newfwd) { Forward *fwd; #ifndef NO_IPPORT_RESERVED_CONCEPT - extern uid_t original_real_uid; - if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) - fatal("Privileged ports can only be forwarded by root."); + if (newfwd->type != SSH_FWD_REMOTE) { + extern uid_t original_real_uid; + if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) + fatal("Privileged ports can only be forwarded by root."); + } #endif - options->local_forwards = xrealloc(options->local_forwards, - options->num_local_forwards + 1, - 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; - fwd->connect_port = newfwd->connect_port; -} - -/* - * Adds a remote TCP/IP port forward to options. Never returns if there is - * an error. - */ - -void -add_remote_forward(Options *options, const Forward *newfwd) -{ - Forward *fwd; - - options->remote_forwards = xrealloc(options->remote_forwards, - options->num_remote_forwards + 1, - sizeof(*options->remote_forwards)); - fwd = &options->remote_forwards[options->num_remote_forwards++]; + options->forwards = xrealloc(options->forwards, + options->num_forwards + 1, + sizeof(*options->forwards)); + fwd = &options->forwards[options->num_forwards++]; fwd->type = newfwd->type; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; - fwd->handle = newfwd->handle; - fwd->allocated_port = 0; + if (newfwd->type == SSH_FWD_REMOTE) { + fwd->handle = newfwd->handle; + fwd->allocated_port = 0; + } } static void @@ -305,26 +287,16 @@ clear_forwardings(Options *options) { int i; - for (i = 0; i < options->num_local_forwards; i++) { - if (options->local_forwards[i].listen_host != NULL) - xfree(options->local_forwards[i].listen_host); - xfree(options->local_forwards[i].connect_host); + for (i = 0; i < options->num_forwards; i++) { + if (options->forwards[i].listen_host != NULL) + xfree(options->forwards[i].listen_host); + xfree(options->forwards[i].connect_host); } - if (options->num_local_forwards > 0) { - xfree(options->local_forwards); - options->local_forwards = NULL; + if (options->num_forwards > 0) { + xfree(options->forwards); + options->forwards = NULL; } - options->num_local_forwards = 0; - for (i = 0; i < options->num_remote_forwards; i++) { - if (options->remote_forwards[i].listen_host != NULL) - xfree(options->remote_forwards[i].listen_host); - xfree(options->remote_forwards[i].connect_host); - } - if (options->num_remote_forwards > 0) { - xfree(options->remote_forwards); - options->remote_forwards = NULL; - } - options->num_remote_forwards = 0; + options->num_forwards = 0; options->tun_open = SSH_TUNMODE_NO; } @@ -792,13 +764,8 @@ parse_int: fatal("%.200s line %d: Bad forwarding specification.", filename, linenum); - if (*activep) { - if (opcode == oLocalForward || - opcode == oDynamicForward) - add_local_forward(options, &fwd); - else if (opcode == oRemoteForward) - add_remote_forward(options, &fwd); - } + if (*activep) + add_forward(options, &fwd); break; case oClearAllForwardings: @@ -1173,10 +1140,8 @@ initialize_options(Options * options) options->escape_char = -1; options->num_system_hostfiles = 0; options->num_user_hostfiles = 0; - options->local_forwards = NULL; - options->num_local_forwards = 0; - options->remote_forwards = NULL; - options->num_remote_forwards = 0; + options->forwards = NULL; + options->num_forwards = 0; options->clear_forwardings = -1; options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; diff --git a/readconf.h b/readconf.h index b15d916..c4ce149 100644 --- a/readconf.h +++ b/readconf.h @@ -104,13 +104,9 @@ typedef struct { char *identity_files[SSH_MAX_IDENTITY_FILES]; Key *identity_keys[SSH_MAX_IDENTITY_FILES]; - /* Local TCP/IP forward requests. */ - int num_local_forwards; - Forward *local_forwards; - - /* Remote TCP/IP forward requests. */ - int num_remote_forwards; - Forward *remote_forwards; + /* Local and remote TCP/IP forward requests. */ + int num_forwards; + Forward *forwards; int clear_forwardings; int enable_ssh_keysign; @@ -162,7 +158,6 @@ 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 *); +void add_forward(Options *, const Forward *); #endif /* READCONF_H */ diff --git a/ssh.c b/ssh.c index a63bfab..c29f522 100644 --- a/ssh.c +++ b/ssh.c @@ -184,7 +184,7 @@ Buffer command; int subsystem_flag = 0; /* # of replies received for global requests */ -static int remote_forward_confirms_received = 0; +static int remote_forward_confirms_pending = 0; /* mux.c */ extern int muxserver_sock; @@ -539,7 +539,7 @@ main(int ac, char **av) case 'L': if (parse_forward(&fwd, optarg, SSH_FWD_LOCAL)) - add_local_forward(&options, &fwd); + add_forward(&options, &fwd); else { fprintf(stderr, "Bad local forwarding specification '%s'\n", @@ -550,7 +550,7 @@ main(int ac, char **av) case 'R': if (parse_forward(&fwd, optarg, SSH_FWD_REMOTE)) { - add_remote_forward(&options, &fwd); + add_forward(&options, &fwd); } else { fprintf(stderr, "Bad remote forwarding specification " @@ -561,7 +561,7 @@ main(int ac, char **av) case 'D': if (parse_forward(&fwd, optarg, SSH_FWD_DYNAMIC)) { - add_local_forward(&options, &fwd); + add_forward(&options, &fwd); } else { fprintf(stderr, "Bad dynamic forwarding specification " @@ -1019,6 +1019,7 @@ static void ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) { Forward *rfwd = (Forward *)ctxt; + remote_forward_confirms_pending--; /* XXX verbose() on failure? */ debug("remote forward %s for: listen %d, connect %s:%d", @@ -1045,7 +1046,7 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) logit("Warning: remote port forwarding failed for " "listen port %d", rfwd->listen_port); } - if (++remote_forward_confirms_received == options.num_remote_forwards) { + if (remote_forward_confirms_pending == 0) { debug("All remote forwarding requests processed"); if (fork_after_authentication_flag) fork_postauth(); @@ -1085,54 +1086,63 @@ static void ssh_init_forwarding(void) { int success = 0; + int num_local_forwards = 0; int i; /* Initiate local TCP/IP port forwardings. */ - for (i = 0; i < options.num_local_forwards; i++) { + for (i = 0; i < options.num_forwards; i++) { + if (options.forwards[i].type == SSH_FWD_REMOTE) + continue; + num_local_forwards++; debug("Local connections to %.200s:%d forwarded to remote " "address %.200s:%d", - (options.local_forwards[i].listen_host == NULL) ? + (options.forwards[i].listen_host == NULL) ? (options.gateway_ports ? "*" : "LOCALHOST") : - options.local_forwards[i].listen_host, - options.local_forwards[i].listen_port, - options.local_forwards[i].connect_host, - options.local_forwards[i].connect_port); + options.forwards[i].listen_host, + options.forwards[i].listen_port, + options.forwards[i].connect_host, + options.forwards[i].connect_port); success += channel_setup_local_fwd_listener( - options.local_forwards[i].listen_host, - options.local_forwards[i].listen_port, - options.local_forwards[i].connect_host, - options.local_forwards[i].connect_port, + options.forwards[i].listen_host, + options.forwards[i].listen_port, + options.forwards[i].connect_host, + options.forwards[i].connect_port, options.gateway_ports); } - if (i > 0 && success != i && options.exit_on_forward_failure) + if (num_local_forwards > 0 && + success != num_local_forwards && + options.exit_on_forward_failure) fatal("Could not request local forwarding."); - if (i > 0 && success == 0) + if (num_local_forwards > 0 && success == 0) error("Could not request local forwarding."); /* Initiate remote TCP/IP port forwardings. */ - for (i = 0; i < options.num_remote_forwards; i++) { + for (i = 0; i < options.num_forwards; i++) { + if (options.forwards[i].type != SSH_FWD_REMOTE) + continue; debug("Remote connections from %.200s:%d forwarded to " "local address %.200s:%d", - (options.remote_forwards[i].listen_host == NULL) ? - "LOCALHOST" : options.remote_forwards[i].listen_host, - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port); - options.remote_forwards[i].handle = + (options.forwards[i].listen_host == NULL) ? + "LOCALHOST" : options.forwards[i].listen_host, + options.forwards[i].listen_port, + options.forwards[i].connect_host, + options.forwards[i].connect_port); + options.forwards[i].handle = channel_request_remote_forwarding( - options.remote_forwards[i].listen_host, - options.remote_forwards[i].listen_port, - options.remote_forwards[i].connect_host, - options.remote_forwards[i].connect_port); - if (options.remote_forwards[i].handle < 0) { + options.forwards[i].listen_host, + options.forwards[i].listen_port, + options.forwards[i].connect_host, + options.forwards[i].connect_port); + if (options.forwards[i].handle < 0) { if (options.exit_on_forward_failure) fatal("Could not request remote forwarding."); else logit("Warning: Could not request remote " "forwarding."); } else { + remote_forward_confirms_pending++; client_register_global_confirm(ssh_confirm_remote_forward, - &options.remote_forwards[i]); + &options.forwards[i]); } } @@ -1291,7 +1301,7 @@ ssh_session(void) */ if (fork_after_authentication_flag) { if (options.exit_on_forward_failure && - options.num_remote_forwards > 0) { + remote_forward_confirms_pending) { debug("deferring postauth fork until remote forward " "confirmation received"); } else @@ -1475,7 +1485,7 @@ ssh_session2(void) */ if (fork_after_authentication_flag) { if (options.exit_on_forward_failure && - options.num_remote_forwards > 0) { + remote_forward_confirms_pending) { debug("deferring postauth fork until remote forward " "confirmation received"); } else diff --git a/sshconnect.c b/sshconnect.c index 0ee7266..9e98346 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1014,12 +1014,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, options.forward_x11 = 0; cancelled_forwarding = 1; } - if (options.num_local_forwards > 0 || - options.num_remote_forwards > 0) { + if (options.num_forwards > 0) { error("Port forwarding is disabled to avoid " "man-in-the-middle attacks."); - options.num_local_forwards = - options.num_remote_forwards = 0; + options.num_forwards = 0; + xfree(options.forwards); + options.forwards = NULL; cancelled_forwarding = 1; } if (options.tun_open != SSH_TUNMODE_NO) { -- 1.7.9.rc0.542.g07ca1 _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev [at] mindrot https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
|