version 1.189, 2008/05/08 12:02:23 |
version 1.190, 2008/05/08 13:06:10 |
|
|
char **env; |
char **env; |
}; |
}; |
|
|
|
struct channel_reply_ctx { |
|
const char *request_type; |
|
int id, do_close; |
|
}; |
|
|
/*XXX*/ |
/*XXX*/ |
extern Kex *xxx_kex; |
extern Kex *xxx_kex; |
|
|
|
|
} |
} |
|
|
static void |
static void |
client_subsystem_reply(int type, u_int32_t seq, void *ctxt) |
client_status_confirm(int type, Channel *c, void *ctx) |
{ |
{ |
int id; |
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
Channel *c; |
char errmsg[256]; |
|
int tochan; |
|
|
id = packet_get_int(); |
/* XXX supress on mux _client_ quietmode */ |
packet_check_eom(); |
tochan = options.log_level >= SYSLOG_LEVEL_ERROR && |
|
c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; |
|
|
if ((c = channel_lookup(id)) == NULL) { |
if (type == SSH2_MSG_CHANNEL_SUCCESS) { |
error("%s: no channel for id %d", __func__, id); |
debug2("%s request accepted on channel %d", |
return; |
cr->request_type, c->self); |
|
} else if (type == SSH2_MSG_CHANNEL_FAILURE) { |
|
if (tochan) { |
|
snprintf(errmsg, sizeof(errmsg), |
|
"%s request failed\r\n", cr->request_type); |
|
} else { |
|
snprintf(errmsg, sizeof(errmsg), |
|
"%s request failed on channel %d", |
|
cr->request_type, c->self); |
|
} |
|
/* If error occurred on primary session channel, then exit */ |
|
if (cr->do_close && c->self == session_ident) |
|
fatal("%s", errmsg); |
|
/* If error occurred on mux client, append to their stderr */ |
|
if (tochan) |
|
buffer_append(&c->extended, errmsg, strlen(errmsg)); |
|
else |
|
error("%s", errmsg); |
|
if (cr->do_close) { |
|
chan_read_failed(c); |
|
chan_write_failed(c); |
|
} |
} |
} |
|
xfree(cr); |
|
} |
|
|
if (type == SSH2_MSG_CHANNEL_SUCCESS) |
static void |
debug2("Request suceeded on channel %d", id); |
client_abandon_status_confirm(Channel *c, void *ctx) |
else if (type == SSH2_MSG_CHANNEL_FAILURE) { |
{ |
error("Request failed on channel %d", id); |
xfree(ctx); |
channel_free(c); |
|
} |
|
} |
} |
|
|
static void |
static void |
|
client_expect_confirm(int id, const char *request, int do_close) |
|
{ |
|
struct channel_reply_ctx *cr = xmalloc(sizeof(*cr)); |
|
|
|
cr->request_type = request; |
|
cr->do_close = do_close; |
|
|
|
channel_register_status_confirm(id, client_status_confirm, |
|
client_abandon_status_confirm, cr); |
|
} |
|
|
|
static void |
client_extra_session2_setup(int id, void *arg) |
client_extra_session2_setup(int id, void *arg) |
{ |
{ |
struct confirm_ctx *cctx = arg; |
struct confirm_ctx *cctx = arg; |
|
|
} |
} |
|
|
client_session2_setup(id, cctx->want_tty, cctx->want_subsys, |
client_session2_setup(id, cctx->want_tty, cctx->want_subsys, |
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env, |
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); |
client_subsystem_reply); |
|
|
|
c->open_confirm_ctx = NULL; |
c->open_confirm_ctx = NULL; |
buffer_free(&cctx->cmd); |
buffer_free(&cctx->cmd); |
|
|
static int |
static int |
simple_escape_filter(Channel *c, char *buf, int len) |
simple_escape_filter(Channel *c, char *buf, int len) |
{ |
{ |
/* XXX we assume c->extended is writeable */ |
if (c->extended_usage != CHAN_EXTENDED_WRITE) |
|
return 0; |
|
|
return process_escapes(&c->input, &c->output, &c->extended, buf, len); |
return process_escapes(&c->input, &c->output, &c->extended, buf, len); |
} |
} |
|
|
|
|
|
|
void |
void |
client_session2_setup(int id, int want_tty, int want_subsystem, |
client_session2_setup(int id, int want_tty, int want_subsystem, |
const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env, |
const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) |
dispatch_fn *subsys_repl) |
|
{ |
{ |
int len; |
int len; |
Channel *c = NULL; |
Channel *c = NULL; |
|
|
if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) |
if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) |
memset(&ws, 0, sizeof(ws)); |
memset(&ws, 0, sizeof(ws)); |
|
|
channel_request_start(id, "pty-req", 0); |
channel_request_start(id, "pty-req", 1); |
|
client_expect_confirm(id, "PTY allocation", 0); |
packet_put_cstring(term != NULL ? term : ""); |
packet_put_cstring(term != NULL ? term : ""); |
packet_put_int((u_int)ws.ws_col); |
packet_put_int((u_int)ws.ws_col); |
packet_put_int((u_int)ws.ws_row); |
packet_put_int((u_int)ws.ws_row); |
|
|
if (len > 900) |
if (len > 900) |
len = 900; |
len = 900; |
if (want_subsystem) { |
if (want_subsystem) { |
debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd)); |
debug("Sending subsystem: %.*s", |
channel_request_start(id, "subsystem", subsys_repl != NULL); |
len, (u_char*)buffer_ptr(cmd)); |
if (subsys_repl != NULL) { |
channel_request_start(id, "subsystem", 1); |
/* register callback for reply */ |
client_expect_confirm(id, "subsystem", 1); |
/* XXX we assume that client_loop has already been called */ |
|
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl); |
|
dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl); |
|
} |
|
} else { |
} else { |
debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd)); |
debug("Sending command: %.*s", |
channel_request_start(id, "exec", 0); |
len, (u_char*)buffer_ptr(cmd)); |
|
channel_request_start(id, "exec", 1); |
|
client_expect_confirm(id, "exec", 1); |
} |
} |
packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
packet_send(); |
packet_send(); |
} else { |
} else { |
channel_request_start(id, "shell", 0); |
channel_request_start(id, "shell", 1); |
|
client_expect_confirm(id, "shell", 1); |
packet_send(); |
packet_send(); |
} |
} |
} |
} |