version 1.293, 2017/04/30 23:18:44 |
version 1.294, 2017/04/30 23:21:54 |
|
|
|
|
/* Common data for the client loop code. */ |
/* Common data for the client loop code. */ |
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ |
static int escape_char1; /* Escape character. (proto1 only) */ |
|
static int escape_pending1; /* Last character was an escape (proto1 only) */ |
|
static int last_was_cr; /* Last character was a newline. */ |
static int last_was_cr; /* Last character was a newline. */ |
static int exit_status; /* Used to store the command exit status. */ |
static int exit_status; /* Used to store the command exit status. */ |
static int stdin_eof; /* EOF has been encountered on stderr. */ |
static Buffer stderr_buffer; /* Used for final exit message. */ |
static Buffer stdin_buffer; /* Buffer for stdin data. */ |
|
static Buffer stdout_buffer; /* Buffer for stdout data. */ |
|
static Buffer stderr_buffer; /* Buffer for stderr data. */ |
|
static u_int buffer_high; /* Soft max buffer size. */ |
|
static int connection_in; /* Connection to server (input). */ |
static int connection_in; /* Connection to server (input). */ |
static int connection_out; /* Connection to server (output). */ |
static int connection_out; /* Connection to server (output). */ |
static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
static int need_rekeying; /* Set to non-zero if rekeying is requested. */ |
|
|
memset(*readsetp, 0, *nallocp); |
memset(*readsetp, 0, *nallocp); |
memset(*writesetp, 0, *nallocp); |
memset(*writesetp, 0, *nallocp); |
return; |
return; |
} else { |
|
FD_SET(connection_in, *readsetp); |
|
} |
} |
|
|
|
FD_SET(connection_in, *readsetp); |
|
|
/* Select server connection if have data to write to the server. */ |
/* Select server connection if have data to write to the server. */ |
if (packet_have_data_to_write()) |
if (packet_have_data_to_write()) |
FD_SET(connection_out, *writesetp); |
FD_SET(connection_out, *writesetp); |
|
|
u_int i; |
u_int i; |
u_char ch; |
u_char ch; |
char *s; |
char *s; |
int *escape_pendingp, escape_char; |
struct escape_filter_ctx *efc = c->filter_ctx == NULL ? |
struct escape_filter_ctx *efc; |
NULL : (struct escape_filter_ctx *)c->filter_ctx; |
|
|
if (c == NULL) { |
if (c->filter_ctx == NULL) |
escape_pendingp = &escape_pending1; |
return 0; |
escape_char = escape_char1; |
|
} else { |
|
if (c->filter_ctx == NULL) |
|
return 0; |
|
efc = (struct escape_filter_ctx *)c->filter_ctx; |
|
escape_pendingp = &efc->escape_pending; |
|
escape_char = efc->escape_char; |
|
} |
|
|
|
if (len <= 0) |
if (len <= 0) |
return (0); |
return (0); |
|
|
/* Get one character at a time. */ |
/* Get one character at a time. */ |
ch = buf[i]; |
ch = buf[i]; |
|
|
if (*escape_pendingp) { |
if (efc->escape_pending) { |
/* We have previously seen an escape character. */ |
/* We have previously seen an escape character. */ |
/* Clear the flag now. */ |
/* Clear the flag now. */ |
*escape_pendingp = 0; |
efc->escape_pending = 0; |
|
|
/* Process the escaped character. */ |
/* Process the escaped character. */ |
switch (ch) { |
switch (ch) { |
case '.': |
case '.': |
/* Terminate the connection. */ |
/* Terminate the connection. */ |
snprintf(string, sizeof string, "%c.\r\n", |
snprintf(string, sizeof string, "%c.\r\n", |
escape_char); |
efc->escape_char); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
|
|
if (c && c->ctl_chan != -1) { |
if (c && c->ctl_chan != -1) { |
|
|
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c%s escape not available to " |
"%c%s escape not available to " |
"multiplexed sessions\r\n", |
"multiplexed sessions\r\n", |
escape_char, b); |
efc->escape_char, b); |
buffer_append(berr, string, |
buffer_append(berr, string, |
strlen(string)); |
strlen(string)); |
continue; |
continue; |
} |
} |
/* Suspend the program. Inform the user */ |
/* Suspend the program. Inform the user */ |
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c^Z [suspend ssh]\r\n", escape_char); |
"%c^Z [suspend ssh]\r\n", efc->escape_char); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
|
|
/* Restore terminal modes and suspend. */ |
/* Restore terminal modes and suspend. */ |
|
|
|
|
case 'B': |
case 'B': |
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%cB\r\n", 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(c->self, "break", 0); |
packet_put_int(1000); |
packet_put_int(1000); |
|
|
if (!log_is_on_stderr()) { |
if (!log_is_on_stderr()) { |
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c%c [Logging to syslog]\r\n", |
"%c%c [Logging to syslog]\r\n", |
escape_char, ch); |
efc->escape_char, ch); |
buffer_append(berr, string, |
buffer_append(berr, string, |
strlen(string)); |
strlen(string)); |
continue; |
continue; |
|
|
SYSLOG_LEVEL_DEBUG3) |
SYSLOG_LEVEL_DEBUG3) |
log_change_level(++options.log_level); |
log_change_level(++options.log_level); |
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c%c [LogLevel %s]\r\n", escape_char, ch, |
"%c%c [LogLevel %s]\r\n", |
|
efc->escape_char, ch, |
log_level_name(options.log_level)); |
log_level_name(options.log_level)); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
continue; |
continue; |
|
|
channel_stop_listening(); |
channel_stop_listening(); |
|
|
snprintf(string, sizeof string, |
snprintf(string, sizeof string, |
"%c& [backgrounded]\n", escape_char); |
"%c& [backgrounded]\n", efc->escape_char); |
buffer_append(berr, string, strlen(string)); |
buffer_append(berr, string, strlen(string)); |
|
|
/* Fork into background. */ |
/* Fork into background. */ |
|
|
/* fake EOF on stdin */ |
/* fake EOF on stdin */ |
return -1; |
return -1; |
case '?': |
case '?': |
print_escape_help(berr, escape_char, |
print_escape_help(berr, efc->escape_char, |
(c && c->ctl_chan != -1), |
(c && c->ctl_chan != -1), |
log_is_on_stderr()); |
log_is_on_stderr()); |
continue; |
continue; |
|
|
case '#': |
case '#': |
snprintf(string, sizeof string, "%c#\r\n", |
snprintf(string, sizeof string, "%c#\r\n", |
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(); |
buffer_append(berr, s, strlen(s)); |
buffer_append(berr, s, strlen(s)); |
|
|
continue; |
continue; |
|
|
default: |
default: |
if (ch != escape_char) { |
if (ch != efc->escape_char) { |
buffer_put_char(bin, escape_char); |
buffer_put_char(bin, efc->escape_char); |
bytes++; |
bytes++; |
} |
} |
/* Escaped characters fall through here */ |
/* Escaped characters fall through here */ |
|
|
* The previous character was not an escape char. |
* The previous character was not an escape char. |
* Check if this is an escape. |
* Check if this is an escape. |
*/ |
*/ |
if (last_was_cr && ch == escape_char) { |
if (last_was_cr && ch == efc->escape_char) { |
/* |
/* |
* It is. Set the flag and continue to |
* It is. Set the flag and continue to |
* next character. |
* next character. |
*/ |
*/ |
*escape_pendingp = 1; |
efc->escape_pending = 1; |
continue; |
continue; |
} |
} |
} |
} |
|
|
start_time = get_current_time(); |
start_time = get_current_time(); |
|
|
/* Initialize variables. */ |
/* Initialize variables. */ |
escape_pending1 = 0; |
|
last_was_cr = 1; |
last_was_cr = 1; |
exit_status = -1; |
exit_status = -1; |
stdin_eof = 0; |
|
buffer_high = 64 * 1024; |
|
connection_in = packet_get_connection_in(); |
connection_in = packet_get_connection_in(); |
connection_out = packet_get_connection_out(); |
connection_out = packet_get_connection_out(); |
max_fd = MAXIMUM(connection_in, connection_out); |
max_fd = MAXIMUM(connection_in, connection_out); |
|
|
quit_pending = 0; |
quit_pending = 0; |
escape_char1 = escape_char_arg; |
|
|
|
/* Initialize buffers. */ |
/* Initialize buffers. */ |
buffer_init(&stdin_buffer); |
|
buffer_init(&stdout_buffer); |
|
buffer_init(&stderr_buffer); |
buffer_init(&stderr_buffer); |
|
|
client_init_dispatch(); |
client_init_dispatch(); |
|
|
buffer_append(&stderr_buffer, buf, strlen(buf)); |
buffer_append(&stderr_buffer, buf, strlen(buf)); |
} |
} |
|
|
/* Output any buffered data for stdout. */ |
|
if (buffer_len(&stdout_buffer) > 0) { |
|
len = atomicio(vwrite, fileno(stdout), |
|
buffer_ptr(&stdout_buffer), buffer_len(&stdout_buffer)); |
|
if (len < 0 || (u_int)len != buffer_len(&stdout_buffer)) |
|
error("Write failed flushing stdout buffer."); |
|
else |
|
buffer_consume(&stdout_buffer, len); |
|
} |
|
|
|
/* Output any buffered data for stderr. */ |
/* Output any buffered data for stderr. */ |
if (buffer_len(&stderr_buffer) > 0) { |
if (buffer_len(&stderr_buffer) > 0) { |
len = atomicio(vwrite, fileno(stderr), |
len = atomicio(vwrite, fileno(stderr), |
|
|
|
|
/* Clear and free any buffers. */ |
/* Clear and free any buffers. */ |
explicit_bzero(buf, sizeof(buf)); |
explicit_bzero(buf, sizeof(buf)); |
buffer_free(&stdin_buffer); |
|
buffer_free(&stdout_buffer); |
|
buffer_free(&stderr_buffer); |
buffer_free(&stderr_buffer); |
|
|
/* Report bytes transferred, and transfer rates. */ |
/* Report bytes transferred, and transfer rates. */ |
|
|
*/ |
*/ |
struct sshkey **keys; |
struct sshkey **keys; |
int *keys_seen; |
int *keys_seen; |
size_t nkeys; |
size_t nkeys, nnew; |
|
|
size_t nnew; |
|
|
|
/* |
/* |
* Keys that are in known_hosts, but were not present in the update |
* Keys that are in known_hosts, but were not present in the update |