summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/mux.c')
-rw-r--r--crypto/openssh/mux.c133
1 files changed, 104 insertions, 29 deletions
diff --git a/crypto/openssh/mux.c b/crypto/openssh/mux.c
index add0e26..5e0e65f 100644
--- a/crypto/openssh/mux.c
+++ b/crypto/openssh/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.36 2012/07/06 01:37:21 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -316,6 +316,8 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
cctx->term = NULL;
cctx->rid = rid;
cmd = reserved = NULL;
+ cctx->env = NULL;
+ env_len = 0;
if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
@@ -329,22 +331,23 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
xfree(cmd);
if (reserved != NULL)
xfree(reserved);
+ for (j = 0; j < env_len; j++)
+ xfree(cctx->env[j]);
+ if (env_len > 0)
+ xfree(cctx->env);
if (cctx->term != NULL)
xfree(cctx->term);
+ xfree(cctx);
error("%s: malformed message", __func__);
return -1;
}
xfree(reserved);
reserved = NULL;
- cctx->env = NULL;
- env_len = 0;
while (buffer_len(m) > 0) {
#define MUX_MAX_ENV_VARS 4096
- if ((cp = buffer_get_string_ret(m, &len)) == NULL) {
- xfree(cmd);
+ if ((cp = buffer_get_string_ret(m, &len)) == NULL)
goto malf;
- }
if (!env_permitted(cp)) {
xfree(cp);
continue;
@@ -415,6 +418,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
xfree(cctx->env);
}
buffer_free(&cctx->cmd);
+ xfree(cctx);
return 0;
}
@@ -601,12 +605,16 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
buffer_put_int(&out, MUX_S_REMOTE_PORT);
buffer_put_int(&out, fctx->rid);
buffer_put_int(&out, rfwd->allocated_port);
+ channel_update_permitted_opens(rfwd->handle,
+ rfwd->allocated_port);
} else {
buffer_put_int(&out, MUX_S_OK);
buffer_put_int(&out, fctx->rid);
}
goto out;
} else {
+ if (rfwd->listen_port == 0)
+ channel_update_permitted_opens(rfwd->handle, -1);
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
}
@@ -745,8 +753,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} else {
struct mux_channel_confirm_ctx *fctx;
- if (channel_request_remote_forwarding(fwd.listen_host,
- fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
+ fwd.handle = channel_request_remote_forwarding(fwd.listen_host,
+ fwd.listen_port, fwd.connect_host, fwd.connect_port);
+ if (fwd.handle < 0)
goto fail;
add_remote_forward(&options, &fwd);
fctx = xcalloc(1, sizeof(*fctx));
@@ -777,10 +786,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, listen_port, ret = 0;
fwd.listen_host = fwd.connect_host = NULL;
if (buffer_get_int_ret(&ftype, m) != 0 ||
@@ -802,14 +812,70 @@ 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.
+ * 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) == -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);
@@ -1135,6 +1201,7 @@ muxserver_listen(void)
close(muxserver_sock);
muxserver_sock = -1;
}
+ xfree(orig_control_path);
xfree(options.control_path);
options.control_path = NULL;
options.control_master = SSHCTL_MASTER_NO;
@@ -1156,7 +1223,6 @@ muxserver_listen(void)
}
error("ControlSocket %s already exists, disabling multiplexing",
orig_control_path);
- xfree(orig_control_path);
unlink(options.control_path);
goto disable_mux_master;
}
@@ -1537,18 +1603,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 +1644,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 +1675,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 +2084,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 +2101,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);
}
OpenPOWER on IntegriCloud