version 1.302, 2017/08/30 03:59:08 |
version 1.303, 2017/09/12 06:32:07 |
|
|
}; |
}; |
|
|
/* Global request success/failure callbacks */ |
/* Global request success/failure callbacks */ |
|
/* XXX move to struct ssh? */ |
struct global_confirm { |
struct global_confirm { |
TAILQ_ENTRY(global_confirm) entry; |
TAILQ_ENTRY(global_confirm) entry; |
global_confirm_cb *cb; |
global_confirm_cb *cb; |
|
|
* control master process, or if there is no ControlPersist timeout. |
* control master process, or if there is no ControlPersist timeout. |
*/ |
*/ |
static void |
static void |
set_control_persist_exit_time(void) |
set_control_persist_exit_time(struct ssh *ssh) |
{ |
{ |
if (muxserver_sock == -1 || !options.control_persist |
if (muxserver_sock == -1 || !options.control_persist |
|| options.control_persist_timeout == 0) { |
|| options.control_persist_timeout == 0) { |
/* not using a ControlPersist timeout */ |
/* not using a ControlPersist timeout */ |
control_persist_exit_time = 0; |
control_persist_exit_time = 0; |
} else if (channel_still_open()) { |
} else if (channel_still_open(ssh)) { |
/* some client connections are still open */ |
/* some client connections are still open */ |
if (control_persist_exit_time > 0) |
if (control_persist_exit_time > 0) |
debug2("%s: cancel scheduled exit", __func__); |
debug2("%s: cancel scheduled exit", __func__); |
|
|
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
#define X11_TIMEOUT_SLACK 60 |
#define X11_TIMEOUT_SLACK 60 |
int |
int |
client_x11_get_proto(const char *display, const char *xauth_path, |
client_x11_get_proto(struct ssh *ssh, const char *display, |
u_int trusted, u_int timeout, char **_proto, char **_data) |
const char *xauth_path, u_int trusted, u_int timeout, |
|
char **_proto, char **_data) |
{ |
{ |
char cmd[1024], line[512], xdisplay[512]; |
char cmd[1024], line[512], xdisplay[512]; |
char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; |
char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; |
|
|
x11_refuse_time = UINT_MAX; |
x11_refuse_time = UINT_MAX; |
else |
else |
x11_refuse_time = now + timeout; |
x11_refuse_time = now + timeout; |
channel_set_x11_refuse_time(x11_refuse_time); |
channel_set_x11_refuse_time(ssh, |
|
x11_refuse_time); |
} |
} |
if (system(cmd) == 0) |
if (system(cmd) == 0) |
generated = 1; |
generated = 1; |
|
|
*/ |
*/ |
|
|
static void |
static void |
client_check_window_change(void) |
client_check_window_change(struct ssh *ssh) |
{ |
{ |
if (!received_window_change_signal) |
if (!received_window_change_signal) |
return; |
return; |
|
|
|
|
debug2("%s: changed", __func__); |
debug2("%s: changed", __func__); |
|
|
channel_send_window_changes(); |
channel_send_window_changes(ssh); |
} |
} |
|
|
static int |
static int |
|
|
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) |
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) |
return 0; |
return 0; |
if (gc->cb != NULL) |
if (gc->cb != NULL) |
gc->cb(type, seq, gc->ctx); |
gc->cb(ssh, type, seq, gc->ctx); |
if (--gc->ref_count <= 0) { |
if (--gc->ref_count <= 0) { |
TAILQ_REMOVE(&global_confirms, gc, entry); |
TAILQ_REMOVE(&global_confirms, gc, entry); |
explicit_bzero(gc, sizeof(*gc)); |
explicit_bzero(gc, sizeof(*gc)); |
|
|
* one of the file descriptors). |
* one of the file descriptors). |
*/ |
*/ |
static void |
static void |
client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, |
client_wait_until_can_do_something(struct ssh *ssh, |
|
fd_set **readsetp, fd_set **writesetp, |
int *maxfdp, u_int *nallocp, int rekeying) |
int *maxfdp, u_int *nallocp, int rekeying) |
{ |
{ |
struct timeval tv, *tvp; |
struct timeval tv, *tvp; |
|
|
nallocp, &minwait_secs); |
nallocp, &minwait_secs); |
|
|
/* channel_prepare_select could have closed the last channel */ |
/* channel_prepare_select could have closed the last channel */ |
if (session_closed && !channel_still_open() && |
if (session_closed && !channel_still_open(ssh) && |
!packet_have_data_to_write()) { |
!packet_have_data_to_write()) { |
/* clear mask since we did not call select() */ |
/* clear mask since we did not call select() */ |
memset(*readsetp, 0, *nallocp); |
memset(*readsetp, 0, *nallocp); |
|
|
} |
} |
if (options.rekey_interval > 0 && !rekeying) |
if (options.rekey_interval > 0 && !rekeying) |
timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); |
timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); |
set_control_persist_exit_time(); |
set_control_persist_exit_time(ssh); |
if (control_persist_exit_time > 0) { |
if (control_persist_exit_time > 0) { |
timeout_secs = MINIMUM(timeout_secs, |
timeout_secs = MINIMUM(timeout_secs, |
control_persist_exit_time - now); |
control_persist_exit_time - now); |
|
|
} |
} |
|
|
static void |
static void |
client_status_confirm(int type, Channel *c, void *ctx) |
client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) |
{ |
{ |
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
char errmsg[256]; |
char errmsg[256]; |
|
|
* their stderr. |
* their stderr. |
*/ |
*/ |
if (tochan) { |
if (tochan) { |
buffer_append(&c->extended, errmsg, |
buffer_append(c->extended, errmsg, strlen(errmsg)); |
strlen(errmsg)); |
|
} else |
} else |
error("%s", errmsg); |
error("%s", errmsg); |
if (cr->action == CONFIRM_TTY) { |
if (cr->action == CONFIRM_TTY) { |
|
|
if (c->self == session_ident) |
if (c->self == session_ident) |
leave_raw_mode(0); |
leave_raw_mode(0); |
else |
else |
mux_tty_alloc_failed(c); |
mux_tty_alloc_failed(ssh, c); |
} else if (cr->action == CONFIRM_CLOSE) { |
} else if (cr->action == CONFIRM_CLOSE) { |
chan_read_failed(c); |
chan_read_failed(ssh, c); |
chan_write_failed(c); |
chan_write_failed(ssh, c); |
} |
} |
} |
} |
free(cr); |
free(cr); |
} |
} |
|
|
static void |
static void |
client_abandon_status_confirm(Channel *c, void *ctx) |
client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) |
{ |
{ |
free(ctx); |
free(ctx); |
} |
} |
|
|
void |
void |
client_expect_confirm(int id, const char *request, |
client_expect_confirm(struct ssh *ssh, int id, const char *request, |
enum confirm_action action) |
enum confirm_action action) |
{ |
{ |
struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); |
struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); |
|
|
cr->request_type = request; |
cr->request_type = request; |
cr->action = action; |
cr->action = action; |
|
|
channel_register_status_confirm(id, client_status_confirm, |
channel_register_status_confirm(ssh, id, client_status_confirm, |
client_abandon_status_confirm, cr); |
client_abandon_status_confirm, cr); |
} |
} |
|
|
|
|
} |
} |
|
|
static void |
static void |
process_cmdline(void) |
process_cmdline(struct ssh *ssh) |
{ |
{ |
void (*handler)(int); |
void (*handler)(int); |
char *s, *cmd; |
char *s, *cmd; |
|
|
goto out; |
goto out; |
} |
} |
if (remote) |
if (remote) |
ok = channel_request_rforward_cancel(&fwd) == 0; |
ok = channel_request_rforward_cancel(ssh, &fwd) == 0; |
else if (dynamic) |
else if (dynamic) |
ok = channel_cancel_lport_listener(&fwd, |
ok = channel_cancel_lport_listener(ssh, &fwd, |
0, &options.fwd_opts) > 0; |
0, &options.fwd_opts) > 0; |
else |
else |
ok = channel_cancel_lport_listener(&fwd, |
ok = channel_cancel_lport_listener(ssh, &fwd, |
CHANNEL_CANCEL_PORT_STATIC, |
CHANNEL_CANCEL_PORT_STATIC, |
&options.fwd_opts) > 0; |
&options.fwd_opts) > 0; |
if (!ok) { |
if (!ok) { |
|
|
goto out; |
goto out; |
} |
} |
if (local || dynamic) { |
if (local || dynamic) { |
if (!channel_setup_local_fwd_listener(&fwd, |
if (!channel_setup_local_fwd_listener(ssh, &fwd, |
&options.fwd_opts)) { |
&options.fwd_opts)) { |
logit("Port forwarding failed."); |
logit("Port forwarding failed."); |
goto out; |
goto out; |
} |
} |
} else { |
} else { |
if (channel_request_remote_forwarding(&fwd) < 0) { |
if (channel_request_remote_forwarding(ssh, &fwd) < 0) { |
logit("Port forwarding failed."); |
logit("Port forwarding failed."); |
goto out; |
goto out; |
} |
} |
|
|
* Process the characters one by one. |
* Process the characters one by one. |
*/ |
*/ |
static int |
static int |
process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, |
process_escapes(struct ssh *ssh, Channel *c, |
|
Buffer *bin, Buffer *bout, Buffer *berr, |
char *buf, int len) |
char *buf, int len) |
{ |
{ |
char string[1024]; |
char string[1024]; |
|
|
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
|
|
if (c && c->ctl_chan != -1) { |
if (c && c->ctl_chan != -1) { |
chan_read_failed(c); |
chan_read_failed(ssh, c); |
chan_write_failed(c); |
chan_write_failed(ssh, c); |
if (c->detach_user) |
if (c->detach_user) { |
c->detach_user(c->self, NULL); |
c->detach_user(ssh, |
|
c->self, NULL); |
|
} |
c->type = SSH_CHANNEL_ABANDONED; |
c->type = SSH_CHANNEL_ABANDONED; |
buffer_clear(&c->input); |
buffer_clear(c->input); |
chan_ibuf_empty(c); |
chan_ibuf_empty(ssh, c); |
return 0; |
return 0; |
} else |
} else |
quit_pending = 1; |
quit_pending = 1; |
|
|
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%cB\r\n", efc->escape_char); |
"%cB\r\n", efc->escape_char); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
channel_request_start(c->self, "break", 0); |
channel_request_start(ssh, c->self, "break", 0); |
packet_put_int(1000); |
packet_put_int(1000); |
packet_send(); |
packet_send(); |
continue; |
continue; |
|
|
options.request_tty == REQUEST_TTY_FORCE); |
options.request_tty == REQUEST_TTY_FORCE); |
|
|
/* Stop listening for new connections. */ |
/* Stop listening for new connections. */ |
channel_stop_listening(); |
channel_stop_listening(ssh); |
|
|
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c& [backgrounded]\n", efc->escape_char); |
"%c& [backgrounded]\n", efc->escape_char); |
|
|
snprintf(string, sizeof string, "%c#\r\n", |
snprintf(string, sizeof string, "%c#\r\n", |
efc->escape_char); |
efc->escape_char); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
s = channel_open_message(); |
s = channel_open_message(ssh); |
buffer_append(berr, s, strlen(s)); |
buffer_append(berr, s, strlen(s)); |
free(s); |
free(s); |
continue; |
continue; |
|
|
case 'C': |
case 'C': |
if (c && c->ctl_chan != -1) |
if (c && c->ctl_chan != -1) |
goto noescape; |
goto noescape; |
process_cmdline(); |
process_cmdline(ssh); |
continue; |
continue; |
|
|
default: |
default: |
|
|
|
|
/* Free the escape filter context on channel free */ |
/* Free the escape filter context on channel free */ |
void |
void |
client_filter_cleanup(int cid, void *ctx) |
client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) |
{ |
{ |
free(ctx); |
free(ctx); |
} |
} |
|
|
int |
int |
client_simple_escape_filter(Channel *c, char *buf, int len) |
client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) |
{ |
{ |
if (c->extended_usage != CHAN_EXTENDED_WRITE) |
if (c->extended_usage != CHAN_EXTENDED_WRITE) |
return 0; |
return 0; |
|
|
return process_escapes(c, &c->input, &c->output, &c->extended, |
return process_escapes(ssh, c, c->input, c->output, c->extended, |
buf, len); |
buf, len); |
} |
} |
|
|
static void |
static void |
client_channel_closed(int id, void *arg) |
client_channel_closed(struct ssh *ssh, int id, void *arg) |
{ |
{ |
channel_cancel_cleanup(id); |
channel_cancel_cleanup(ssh, id); |
session_closed = 1; |
session_closed = 1; |
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
} |
} |
|
|
* remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character |
* remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character |
* used as an escape character for terminating or suspending the session. |
* used as an escape character for terminating or suspending the session. |
*/ |
*/ |
|
|
int |
int |
client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) |
client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, |
|
int ssh2_chan_id) |
{ |
{ |
fd_set *readset = NULL, *writeset = NULL; |
fd_set *readset = NULL, *writeset = NULL; |
double start_time, total_time; |
double start_time, total_time; |
|
|
session_ident = ssh2_chan_id; |
session_ident = ssh2_chan_id; |
if (session_ident != -1) { |
if (session_ident != -1) { |
if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
channel_register_filter(session_ident, |
channel_register_filter(ssh, session_ident, |
client_simple_escape_filter, NULL, |
client_simple_escape_filter, NULL, |
client_filter_cleanup, |
client_filter_cleanup, |
client_new_escape_filter_ctx( |
client_new_escape_filter_ctx( |
escape_char_arg)); |
escape_char_arg)); |
} |
} |
channel_register_cleanup(session_ident, |
channel_register_cleanup(ssh, session_ident, |
client_channel_closed, 0); |
client_channel_closed, 0); |
} |
} |
|
|
|
|
/* Process buffered packets sent by the server. */ |
/* Process buffered packets sent by the server. */ |
client_process_buffered_input_packets(); |
client_process_buffered_input_packets(); |
|
|
if (session_closed && !channel_still_open()) |
if (session_closed && !channel_still_open(ssh)) |
break; |
break; |
|
|
if (ssh_packet_is_rekeying(active_state)) { |
if (ssh_packet_is_rekeying(ssh)) { |
debug("rekeying in progress"); |
debug("rekeying in progress"); |
} else if (need_rekeying) { |
} else if (need_rekeying) { |
/* manual rekey request */ |
/* manual rekey request */ |
debug("need rekeying"); |
debug("need rekeying"); |
if ((r = kex_start_rekex(active_state)) != 0) |
if ((r = kex_start_rekex(ssh)) != 0) |
fatal("%s: kex_start_rekex: %s", __func__, |
fatal("%s: kex_start_rekex: %s", __func__, |
ssh_err(r)); |
ssh_err(r)); |
need_rekeying = 0; |
need_rekeying = 0; |
|
|
* enqueue them for sending to the server. |
* enqueue them for sending to the server. |
*/ |
*/ |
if (packet_not_very_much_data_to_write()) |
if (packet_not_very_much_data_to_write()) |
channel_output_poll(); |
channel_output_poll(ssh); |
|
|
/* |
/* |
* Check if the window size has changed, and buffer a |
* Check if the window size has changed, and buffer a |
* message about it to the server if so. |
* message about it to the server if so. |
*/ |
*/ |
client_check_window_change(); |
client_check_window_change(ssh); |
|
|
if (quit_pending) |
if (quit_pending) |
break; |
break; |
|
|
* available on one of the descriptors). |
* available on one of the descriptors). |
*/ |
*/ |
max_fd2 = max_fd; |
max_fd2 = max_fd; |
client_wait_until_can_do_something(&readset, &writeset, |
client_wait_until_can_do_something(ssh, &readset, &writeset, |
&max_fd2, &nalloc, ssh_packet_is_rekeying(active_state)); |
&max_fd2, &nalloc, ssh_packet_is_rekeying(ssh)); |
|
|
if (quit_pending) |
if (quit_pending) |
break; |
break; |
|
|
/* Do channel operations unless rekeying in progress. */ |
/* Do channel operations unless rekeying in progress. */ |
if (!ssh_packet_is_rekeying(active_state)) |
if (!ssh_packet_is_rekeying(ssh)) |
channel_after_select(active_state, readset, writeset); |
channel_after_select(ssh, readset, writeset); |
|
|
/* Buffer input from the connection. */ |
/* Buffer input from the connection. */ |
client_process_net_input(readset); |
client_process_net_input(readset); |
|
|
packet_send(); |
packet_send(); |
packet_write_wait(); |
packet_write_wait(); |
|
|
channel_free_all(); |
channel_free_all(ssh); |
|
|
if (have_pty) |
if (have_pty) |
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
|
|
/*********/ |
/*********/ |
|
|
static Channel * |
static Channel * |
client_request_forwarded_tcpip(const char *request_type, int rchan, |
client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, |
u_int rwindow, u_int rmaxpack) |
int rchan, u_int rwindow, u_int rmaxpack) |
{ |
{ |
Channel *c = NULL; |
Channel *c = NULL; |
struct sshbuf *b = NULL; |
struct sshbuf *b = NULL; |
|
|
debug("%s: listen %s port %d, originator %s port %d", __func__, |
debug("%s: listen %s port %d, originator %s port %d", __func__, |
listen_address, listen_port, originator_address, originator_port); |
listen_address, listen_port, originator_address, originator_port); |
|
|
c = channel_connect_by_listen_address(listen_address, listen_port, |
c = channel_connect_by_listen_address(ssh, listen_address, listen_port, |
"forwarded-tcpip", originator_address); |
"forwarded-tcpip", originator_address); |
|
|
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
|
|
(r = sshbuf_put_u32(b, listen_port)) != 0 || |
(r = sshbuf_put_u32(b, listen_port)) != 0 || |
(r = sshbuf_put_cstring(b, originator_address)) != 0 || |
(r = sshbuf_put_cstring(b, originator_address)) != 0 || |
(r = sshbuf_put_u32(b, originator_port)) != 0 || |
(r = sshbuf_put_u32(b, originator_port)) != 0 || |
(r = sshbuf_put_stringb(&c->output, b)) != 0) { |
(r = sshbuf_put_stringb(c->output, b)) != 0) { |
error("%s: compose for muxclient %s", __func__, |
error("%s: compose for muxclient %s", __func__, |
ssh_err(r)); |
ssh_err(r)); |
goto out; |
goto out; |
|
|
} |
} |
|
|
static Channel * |
static Channel * |
client_request_forwarded_streamlocal(const char *request_type, int rchan) |
client_request_forwarded_streamlocal(struct ssh *ssh, |
|
const char *request_type, int rchan) |
{ |
{ |
Channel *c = NULL; |
Channel *c = NULL; |
char *listen_path; |
char *listen_path; |
|
|
|
|
debug("%s: %s", __func__, listen_path); |
debug("%s: %s", __func__, listen_path); |
|
|
c = channel_connect_by_listen_path(listen_path, |
c = channel_connect_by_listen_path(ssh, listen_path, |
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); |
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); |
free(listen_path); |
free(listen_path); |
return c; |
return c; |
} |
} |
|
|
static Channel * |
static Channel * |
client_request_x11(const char *request_type, int rchan) |
client_request_x11(struct ssh *ssh, const char *request_type, int rchan) |
{ |
{ |
Channel *c = NULL; |
Channel *c = NULL; |
char *originator; |
char *originator; |
|
|
debug("client_request_x11: request from %s %d", originator, |
debug("client_request_x11: request from %s %d", originator, |
originator_port); |
originator_port); |
free(originator); |
free(originator); |
sock = x11_connect_display(); |
sock = x11_connect_display(ssh); |
if (sock < 0) |
if (sock < 0) |
return NULL; |
return NULL; |
c = channel_new("x11", |
c = channel_new(ssh, "x11", |
SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
c->force_drain = 1; |
c->force_drain = 1; |
|
|
} |
} |
|
|
static Channel * |
static Channel * |
client_request_agent(const char *request_type, int rchan) |
client_request_agent(struct ssh *ssh, const char *request_type, int rchan) |
{ |
{ |
Channel *c = NULL; |
Channel *c = NULL; |
int r, sock; |
int r, sock; |
|
|
__func__, ssh_err(r)); |
__func__, ssh_err(r)); |
return NULL; |
return NULL; |
} |
} |
c = channel_new("authentication agent connection", |
c = channel_new(ssh, "authentication agent connection", |
SSH_CHANNEL_OPEN, sock, sock, -1, |
SSH_CHANNEL_OPEN, sock, sock, -1, |
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, |
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, |
"authentication agent connection", 1); |
"authentication agent connection", 1); |
|
|
} |
} |
|
|
int |
int |
client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) |
client_request_tun_fwd(struct ssh *ssh, int tun_mode, |
|
int local_tun, int remote_tun) |
{ |
{ |
Channel *c; |
Channel *c; |
int fd; |
int fd; |
|
|
return -1; |
return -1; |
} |
} |
|
|
c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
c->datagram = 1; |
c->datagram = 1; |
|
|
|
|
ctype, rchan, rwindow, rmaxpack); |
ctype, rchan, rwindow, rmaxpack); |
|
|
if (strcmp(ctype, "forwarded-tcpip") == 0) { |
if (strcmp(ctype, "forwarded-tcpip") == 0) { |
c = client_request_forwarded_tcpip(ctype, rchan, rwindow, |
c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, |
rmaxpack); |
rmaxpack); |
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { |
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { |
c = client_request_forwarded_streamlocal(ctype, rchan); |
c = client_request_forwarded_streamlocal(ssh, ctype, rchan); |
} else if (strcmp(ctype, "x11") == 0) { |
} else if (strcmp(ctype, "x11") == 0) { |
c = client_request_x11(ctype, rchan); |
c = client_request_x11(ssh, ctype, rchan); |
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
c = client_request_agent(ctype, rchan); |
c = client_request_agent(ssh, ctype, rchan); |
} |
} |
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
debug3("proxied to downstream: %s", ctype); |
debug3("proxied to downstream: %s", ctype); |
|
|
char *rtype; |
char *rtype; |
|
|
id = packet_get_int(); |
id = packet_get_int(); |
c = channel_lookup(id); |
c = channel_lookup(ssh, id); |
if (channel_proxy_upstream(c, type, seq, ssh)) |
if (channel_proxy_upstream(c, type, seq, ssh)) |
return 0; |
return 0; |
rtype = packet_get_string(NULL); |
rtype = packet_get_string(NULL); |
|
|
"unknown channel", id); |
"unknown channel", id); |
} else if (strcmp(rtype, "eow@openssh.com") == 0) { |
} else if (strcmp(rtype, "eow@openssh.com") == 0) { |
packet_check_eom(); |
packet_check_eom(); |
chan_rcvd_eow(c); |
chan_rcvd_eow(ssh, c); |
} else if (strcmp(rtype, "exit-status") == 0) { |
} else if (strcmp(rtype, "exit-status") == 0) { |
exitval = packet_get_int(); |
exitval = packet_get_int(); |
if (c->ctl_chan != -1) { |
if (c->ctl_chan != -1) { |
mux_exit_message(c, exitval); |
mux_exit_message(ssh, c, exitval); |
success = 1; |
success = 1; |
} else if (id == session_ident) { |
} else if (id == session_ident) { |
/* Record exit value of local session */ |
/* Record exit value of local session */ |
|
|
} |
} |
|
|
static void |
static void |
client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) |
client_global_hostkeys_private_confirm(struct ssh *ssh, int type, |
|
u_int32_t seq, void *_ctx) |
{ |
{ |
struct ssh *ssh = active_state; /* XXX */ |
|
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
size_t i, ndone; |
size_t i, ndone; |
struct sshbuf *signdata; |
struct sshbuf *signdata; |
|
|
} |
} |
|
|
void |
void |
client_session2_setup(int id, int want_tty, int want_subsystem, |
client_session2_setup(struct ssh *ssh, 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) |
{ |
{ |
int len; |
int len; |
|
|
|
|
debug2("%s: id %d", __func__, id); |
debug2("%s: id %d", __func__, id); |
|
|
if ((c = channel_lookup(id)) == NULL) |
if ((c = channel_lookup(ssh, id)) == NULL) |
fatal("client_session2_setup: channel %d: unknown channel", id); |
fatal("%s: channel %d: unknown channel", __func__, id); |
|
|
packet_set_interactive(want_tty, |
packet_set_interactive(want_tty, |
options.ip_qos_interactive, options.ip_qos_bulk); |
options.ip_qos_interactive, options.ip_qos_bulk); |
|
|
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", 1); |
channel_request_start(ssh, id, "pty-req", 1); |
client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); |
client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); |
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); |
|
|
} |
} |
|
|
debug("Sending env %s = %s", name, val); |
debug("Sending env %s = %s", name, val); |
channel_request_start(id, "env", 0); |
channel_request_start(ssh, id, "env", 0); |
packet_put_cstring(name); |
packet_put_cstring(name); |
packet_put_cstring(val); |
packet_put_cstring(val); |
packet_send(); |
packet_send(); |
|
|
if (want_subsystem) { |
if (want_subsystem) { |
debug("Sending subsystem: %.*s", |
debug("Sending subsystem: %.*s", |
len, (u_char*)buffer_ptr(cmd)); |
len, (u_char*)buffer_ptr(cmd)); |
channel_request_start(id, "subsystem", 1); |
channel_request_start(ssh, id, "subsystem", 1); |
client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); |
client_expect_confirm(ssh, id, "subsystem", |
|
CONFIRM_CLOSE); |
} else { |
} else { |
debug("Sending command: %.*s", |
debug("Sending command: %.*s", |
len, (u_char*)buffer_ptr(cmd)); |
len, (u_char*)buffer_ptr(cmd)); |
channel_request_start(id, "exec", 1); |
channel_request_start(ssh, id, "exec", 1); |
client_expect_confirm(id, "exec", CONFIRM_CLOSE); |
client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); |
} |
} |
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", 1); |
channel_request_start(ssh, id, "shell", 1); |
client_expect_confirm(id, "shell", CONFIRM_CLOSE); |
client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); |
packet_send(); |
packet_send(); |
} |
} |
} |
} |