version 1.1, 2008/05/09 14:18:44 |
version 1.2, 2008/06/12 03:40:52 |
|
|
|
|
/* ssh session multiplexing support */ |
/* ssh session multiplexing support */ |
|
|
|
/* |
|
* TODO: |
|
* 1. partial reads in muxserver_accept_control (maybe make channels |
|
* from accepted connections) |
|
* 2. Better signalling from master to slave, especially passing of |
|
* error messages |
|
* 3. Better fall-back from mux slave error to new connection. |
|
* 3. Add/delete forwardings via slave |
|
* 4. ExitOnForwardingFailure (after #3 obviously) |
|
* 5. Maybe extension mechanisms for multi-X11/multi-agent forwarding |
|
* 6. Document the mux mini-protocol somewhere. |
|
* 6. Support ~^Z in mux slaves. |
|
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
int subsystem_flag; |
int subsystem_flag; |
extern Buffer command; |
extern Buffer command; |
|
|
|
/* Context for session open confirmation callback */ |
|
struct mux_session_confirm_ctx { |
|
int want_tty; |
|
int want_subsys; |
|
int want_x_fwd; |
|
int want_agent_fwd; |
|
Buffer cmd; |
|
char *term; |
|
struct termios tio; |
|
char **env; |
|
}; |
|
|
/* fd to control socket */ |
/* fd to control socket */ |
int muxserver_sock = -1; |
int muxserver_sock = -1; |
|
|
|
|
|
|
/* Callback on open confirmation in mux master for a mux client session. */ |
/* Callback on open confirmation in mux master for a mux client session. */ |
static void |
static void |
client_extra_session2_setup(int id, void *arg) |
mux_session_confirm(int id, void *arg) |
{ |
{ |
struct mux_session_confirm_ctx *cctx = arg; |
struct mux_session_confirm_ctx *cctx = arg; |
const char *display; |
const char *display; |
|
|
struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
struct mux_session_confirm_ctx *cctx; |
struct mux_session_confirm_ctx *cctx; |
char *cmd; |
char *cmd; |
u_int i, j, len, env_len, mux_command, flags; |
u_int i, j, len, env_len, mux_command, flags, escape_char; |
uid_t euid; |
uid_t euid; |
gid_t egid; |
gid_t egid; |
int start_close = 0; |
int start_close = 0; |
|
|
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; |
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; |
cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0; |
cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0; |
cctx->term = buffer_get_string(&m, &len); |
cctx->term = buffer_get_string(&m, &len); |
|
escape_char = buffer_get_int(&m); |
|
|
cmd = buffer_get_string(&m, &len); |
cmd = buffer_get_string(&m, &len); |
buffer_init(&cctx->cmd); |
buffer_init(&cctx->cmd); |
|
|
new_fd[0], new_fd[1], new_fd[2], window, packetmax, |
new_fd[0], new_fd[1], new_fd[2], window, packetmax, |
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); |
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); |
|
|
/* XXX */ |
|
c->ctl_fd = client_fd; |
c->ctl_fd = client_fd; |
|
if (cctx->want_tty && escape_char != 0xffffffff) { |
|
channel_register_filter(c->self, |
|
client_simple_escape_filter, NULL, |
|
client_new_escape_filter_ctx((int)escape_char)); |
|
} |
|
|
debug3("%s: channel_new: %d", __func__, c->self); |
debug3("%s: channel_new: %d", __func__, c->self); |
|
|
channel_send_open(c->self); |
channel_send_open(c->self); |
channel_register_open_confirm(c->self, |
channel_register_open_confirm(c->self, mux_session_confirm, cctx); |
client_extra_session2_setup, cctx); |
|
return 0; |
return 0; |
} |
} |
|
|
|
|
fprintf(stderr, "Exit request sent.\r\n"); |
fprintf(stderr, "Exit request sent.\r\n"); |
exit(0); |
exit(0); |
case SSHMUX_COMMAND_OPEN: |
case SSHMUX_COMMAND_OPEN: |
/* continue below */ |
buffer_put_cstring(&m, term ? term : ""); |
break; |
if (options.escape_char == SSH_ESCAPECHAR_NONE) |
default: |
buffer_put_int(&m, 0xffffffff); |
fatal("silly muxclient_command %d", muxclient_command); |
else |
} |
buffer_put_int(&m, options.escape_char); |
|
buffer_append(&command, "\0", 1); |
|
buffer_put_cstring(&m, buffer_ptr(&command)); |
|
|
/* SSHMUX_COMMAND_OPEN */ |
if (options.num_send_env == 0 || environ == NULL) { |
buffer_put_cstring(&m, term ? term : ""); |
buffer_put_int(&m, 0); |
buffer_append(&command, "\0", 1); |
} else { |
buffer_put_cstring(&m, buffer_ptr(&command)); |
/* Pass environment */ |
|
num_env = 0; |
if (options.num_send_env == 0 || environ == NULL) { |
for (i = 0; environ[i] != NULL; i++) { |
buffer_put_int(&m, 0); |
if (env_permitted(environ[i])) |
} else { |
num_env++; /* Count */ |
/* Pass environment */ |
|
num_env = 0; |
|
for (i = 0; environ[i] != NULL; i++) |
|
if (env_permitted(environ[i])) |
|
num_env++; /* Count */ |
|
|
|
buffer_put_int(&m, num_env); |
|
|
|
for (i = 0; environ[i] != NULL && num_env >= 0; i++) |
|
if (env_permitted(environ[i])) { |
|
num_env--; |
|
buffer_put_cstring(&m, environ[i]); |
|
} |
} |
|
buffer_put_int(&m, num_env); |
|
for (i = 0; environ[i] != NULL && num_env >= 0; i++) { |
|
if (env_permitted(environ[i])) { |
|
num_env--; |
|
buffer_put_cstring(&m, environ[i]); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
fatal("unrecognised muxclient_command %d", muxclient_command); |
} |
} |
|
|
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) |
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) |