[PATCH/RFC 2/6] merge local and remote forward lists
Bert Wesarg
bert.wesarg at googlemail.com
Thu May 3 21:33:48 EST 2012
---
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
More information about the openssh-unix-dev
mailing list