version 1.17, 2010/05/14 23:29:23 |
version 1.18, 2010/05/16 12:55:51 |
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "log.h" |
#include "log.h" |
#include "ssh.h" |
#include "ssh.h" |
|
#include "ssh2.h" |
#include "pathnames.h" |
#include "pathnames.h" |
#include "misc.h" |
#include "misc.h" |
#include "match.h" |
#include "match.h" |
|
|
u_int rid; |
u_int rid; |
}; |
}; |
|
|
|
/* Context for global channel callback */ |
|
struct mux_channel_confirm_ctx { |
|
u_int cid; /* channel id */ |
|
u_int rid; /* request id */ |
|
int fid; /* forward id */ |
|
}; |
|
|
/* fd to control socket */ |
/* fd to control socket */ |
int muxserver_sock = -1; |
int muxserver_sock = -1; |
|
|
|
|
#define MUX_S_EXIT_MESSAGE 0x80000004 |
#define MUX_S_EXIT_MESSAGE 0x80000004 |
#define MUX_S_ALIVE 0x80000005 |
#define MUX_S_ALIVE 0x80000005 |
#define MUX_S_SESSION_OPENED 0x80000006 |
#define MUX_S_SESSION_OPENED 0x80000006 |
|
#define MUX_S_REMOTE_PORT 0x80000007 |
|
|
/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ |
/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ |
#define MUX_FWD_LOCAL 1 |
#define MUX_FWD_LOCAL 1 |
|
|
return 1; |
return 1; |
} |
} |
|
|
|
static void |
|
mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) |
|
{ |
|
struct mux_channel_confirm_ctx *fctx = ctxt; |
|
char *failmsg = NULL; |
|
Forward *rfwd; |
|
Channel *c; |
|
Buffer out; |
|
|
|
if ((c = channel_by_id(fctx->cid)) == NULL) { |
|
/* no channel for reply */ |
|
error("%s: unknown channel", __func__); |
|
return; |
|
} |
|
buffer_init(&out); |
|
if (fctx->fid >= options.num_remote_forwards) { |
|
xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); |
|
goto fail; |
|
} |
|
rfwd = &options.remote_forwards[fctx->fid]; |
|
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); |
|
if (type == SSH2_MSG_REQUEST_SUCCESS) { |
|
if (rfwd->listen_port == 0) { |
|
rfwd->allocated_port = packet_get_int(); |
|
logit("Allocated port %u for mux remote forward" |
|
" to %s:%d", rfwd->allocated_port, |
|
rfwd->connect_host, rfwd->connect_port); |
|
buffer_put_int(&out, MUX_S_REMOTE_PORT); |
|
buffer_put_int(&out, fctx->rid); |
|
buffer_put_int(&out, rfwd->allocated_port); |
|
} else { |
|
buffer_put_int(&out, MUX_S_OK); |
|
buffer_put_int(&out, fctx->rid); |
|
} |
|
goto out; |
|
} else { |
|
xasprintf(&failmsg, "remote port forwarding failed for " |
|
"listen port %d", rfwd->listen_port); |
|
} |
|
fail: |
|
error("%s: %s", __func__, failmsg); |
|
buffer_put_int(&out, MUX_S_FAILURE); |
|
buffer_put_int(&out, fctx->rid); |
|
buffer_put_cstring(&out, failmsg); |
|
xfree(failmsg); |
|
out: |
|
buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out)); |
|
buffer_free(&out); |
|
if (c->mux_pause <= 0) |
|
fatal("%s: mux_pause %d", __func__, c->mux_pause); |
|
c->mux_pause = 0; /* start processing messages again */ |
|
} |
|
|
static int |
static int |
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) |
{ |
{ |
|
|
ftype != MUX_FWD_DYNAMIC) { |
ftype != MUX_FWD_DYNAMIC) { |
logit("%s: invalid forwarding type %u", __func__, ftype); |
logit("%s: invalid forwarding type %u", __func__, ftype); |
invalid: |
invalid: |
xfree(fwd.listen_host); |
if (fwd.listen_host) |
xfree(fwd.connect_host); |
xfree(fwd.listen_host); |
|
if (fwd.connect_host) |
|
xfree(fwd.connect_host); |
buffer_put_int(r, MUX_S_FAILURE); |
buffer_put_int(r, MUX_S_FAILURE); |
buffer_put_int(r, rid); |
buffer_put_int(r, rid); |
buffer_put_cstring(r, "Invalid forwarding request"); |
buffer_put_cstring(r, "Invalid forwarding request"); |
return 0; |
return 0; |
} |
} |
/* XXX support rport0 forwarding with reply of port assigned */ |
if (fwd.listen_port >= 65536) { |
if (fwd.listen_port == 0 || fwd.listen_port >= 65536) { |
|
logit("%s: invalid listen port %u", __func__, |
logit("%s: invalid listen port %u", __func__, |
fwd.listen_port); |
fwd.listen_port); |
goto invalid; |
goto invalid; |
|
|
case MUX_FWD_REMOTE: |
case MUX_FWD_REMOTE: |
for (i = 0; i < options.num_remote_forwards; i++) { |
for (i = 0; i < options.num_remote_forwards; i++) { |
if (compare_forward(&fwd, |
if (compare_forward(&fwd, |
options.remote_forwards + i)) |
options.remote_forwards + i)) { |
goto exists; |
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; |
|
} |
} |
} |
break; |
break; |
} |
} |
|
|
add_local_forward(&options, &fwd); |
add_local_forward(&options, &fwd); |
freefwd = 0; |
freefwd = 0; |
} else { |
} else { |
/* XXX wait for remote to confirm */ |
struct mux_channel_confirm_ctx *fctx; |
|
|
if (options.num_remote_forwards + 1 >= |
if (options.num_remote_forwards + 1 >= |
SSH_MAX_FORWARDS_PER_DIRECTION || |
SSH_MAX_FORWARDS_PER_DIRECTION || |
channel_request_remote_forwarding(fwd.listen_host, |
channel_request_remote_forwarding(fwd.listen_host, |
fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) |
fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) |
goto fail; |
goto fail; |
add_remote_forward(&options, &fwd); |
add_remote_forward(&options, &fwd); |
|
fctx = xcalloc(1, sizeof(*fctx)); |
|
fctx->cid = c->self; |
|
fctx->rid = rid; |
|
fctx->fid = options.num_remote_forwards-1; |
|
client_register_global_confirm(mux_confirm_remote_forward, |
|
fctx); |
freefwd = 0; |
freefwd = 0; |
|
c->mux_pause = 1; /* wait for mux_confirm_remote_forward */ |
|
/* delayed reply in mux_confirm_remote_forward */ |
|
goto out; |
} |
} |
buffer_put_int(r, MUX_S_OK); |
buffer_put_int(r, MUX_S_OK); |
buffer_put_int(r, rid); |
buffer_put_int(r, rid); |
|
|
switch (type) { |
switch (type) { |
case MUX_S_OK: |
case MUX_S_OK: |
break; |
break; |
|
case MUX_S_REMOTE_PORT: |
|
fwd->allocated_port = buffer_get_int(&m); |
|
logit("Allocated port %u for remote forward to %s:%d", |
|
fwd->allocated_port, |
|
fwd->connect_host ? fwd->connect_host : "", |
|
fwd->connect_port); |
|
if (muxclient_command == SSHMUX_COMMAND_FORWARD) |
|
fprintf(stdout, "%u\n", fwd->allocated_port); |
|
break; |
case MUX_S_PERMISSION_DENIED: |
case MUX_S_PERMISSION_DENIED: |
e = buffer_get_string(&m, NULL); |
e = buffer_get_string(&m, NULL); |
buffer_free(&m); |
buffer_free(&m); |
|
|
case SSHMUX_COMMAND_TERMINATE: |
case SSHMUX_COMMAND_TERMINATE: |
mux_client_request_terminate(sock); |
mux_client_request_terminate(sock); |
fprintf(stderr, "Exit request sent.\r\n"); |
fprintf(stderr, "Exit request sent.\r\n"); |
|
exit(0); |
|
case SSHMUX_COMMAND_FORWARD: |
|
if (mux_client_request_forwards(sock) != 0) |
|
fatal("%s: master forward request failed", __func__); |
exit(0); |
exit(0); |
case SSHMUX_COMMAND_OPEN: |
case SSHMUX_COMMAND_OPEN: |
if (mux_client_request_forwards(sock) != 0) { |
if (mux_client_request_forwards(sock) != 0) { |