version 1.221, 2015/12/11 04:21:12 |
version 1.222, 2016/01/14 16:17:40 |
|
|
#include "channels.h" |
#include "channels.h" |
#include "ssh.h" |
#include "ssh.h" |
#include "packet.h" |
#include "packet.h" |
#include "roaming.h" |
|
#include "ssherr.h" |
#include "ssherr.h" |
#include "sshbuf.h" |
#include "sshbuf.h" |
|
|
|
|
ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) |
{ |
{ |
struct session_state *state = ssh->state; |
struct session_state *state = ssh->state; |
int len, r, ms_remain, cont; |
int len, r, ms_remain; |
fd_set *setp; |
fd_set *setp; |
char buf[8192]; |
char buf[8192]; |
struct timeval timeout, start, *timeoutp = NULL; |
struct timeval timeout, start, *timeoutp = NULL; |
|
|
if (r == 0) |
if (r == 0) |
return SSH_ERR_CONN_TIMEOUT; |
return SSH_ERR_CONN_TIMEOUT; |
/* Read data from the socket. */ |
/* Read data from the socket. */ |
do { |
len = read(state->connection_in, buf, sizeof(buf)); |
cont = 0; |
|
len = roaming_read(state->connection_in, buf, |
|
sizeof(buf), &cont); |
|
} while (len == 0 && cont); |
|
if (len == 0) { |
if (len == 0) { |
r = SSH_ERR_CONN_CLOSED; |
r = SSH_ERR_CONN_CLOSED; |
goto out; |
goto out; |
|
|
{ |
{ |
struct session_state *state = ssh->state; |
struct session_state *state = ssh->state; |
int len = sshbuf_len(state->output); |
int len = sshbuf_len(state->output); |
int cont, r; |
int r; |
|
|
if (len > 0) { |
if (len > 0) { |
cont = 0; |
len = write(state->connection_out, |
len = roaming_write(state->connection_out, |
sshbuf_ptr(state->output), len); |
sshbuf_ptr(state->output), len, &cont); |
|
if (len == -1) { |
if (len == -1) { |
if (errno == EINTR || errno == EAGAIN) |
if (errno == EINTR || errno == EAGAIN) |
return 0; |
return 0; |
return SSH_ERR_SYSTEM_ERROR; |
return SSH_ERR_SYSTEM_ERROR; |
} |
} |
if (len == 0 && !cont) |
if (len == 0) |
return SSH_ERR_CONN_CLOSED; |
return SSH_ERR_CONN_CLOSED; |
if ((r = sshbuf_consume(state->output, len)) != 0) |
if ((r = sshbuf_consume(state->output, len)) != 0) |
return r; |
return r; |
|
|
return (void *)ssh->state->output; |
return (void *)ssh->state->output; |
} |
} |
|
|
/* XXX TODO update roaming to new API (does not work anyway) */ |
|
/* |
|
* Save the state for the real connection, and use a separate state when |
|
* resuming a suspended connection. |
|
*/ |
|
void |
|
ssh_packet_backup_state(struct ssh *ssh, |
|
struct ssh *backup_state) |
|
{ |
|
struct ssh *tmp; |
|
|
|
close(ssh->state->connection_in); |
|
ssh->state->connection_in = -1; |
|
close(ssh->state->connection_out); |
|
ssh->state->connection_out = -1; |
|
if (backup_state) |
|
tmp = backup_state; |
|
else |
|
tmp = ssh_alloc_session_state(); |
|
backup_state = ssh; |
|
ssh = tmp; |
|
} |
|
|
|
/* XXX FIXME FIXME FIXME */ |
|
/* |
|
* Swap in the old state when resuming a connecion. |
|
*/ |
|
void |
|
ssh_packet_restore_state(struct ssh *ssh, |
|
struct ssh *backup_state) |
|
{ |
|
struct ssh *tmp; |
|
u_int len; |
|
int r; |
|
|
|
tmp = backup_state; |
|
backup_state = ssh; |
|
ssh = tmp; |
|
ssh->state->connection_in = backup_state->state->connection_in; |
|
backup_state->state->connection_in = -1; |
|
ssh->state->connection_out = backup_state->state->connection_out; |
|
backup_state->state->connection_out = -1; |
|
len = sshbuf_len(backup_state->state->input); |
|
if (len > 0) { |
|
if ((r = sshbuf_putb(ssh->state->input, |
|
backup_state->state->input)) != 0) |
|
fatal("%s: %s", __func__, ssh_err(r)); |
|
sshbuf_reset(backup_state->state->input); |
|
add_recv_bytes(len); |
|
} |
|
} |
|
|
|
/* Reset after_authentication and reset compression in post-auth privsep */ |
/* Reset after_authentication and reset compression in post-auth privsep */ |
static int |
static int |
ssh_packet_set_postauth(struct ssh *ssh) |
ssh_packet_set_postauth(struct ssh *ssh) |
|
|
(r = sshbuf_put_stringb(m, state->output)) != 0) |
(r = sshbuf_put_stringb(m, state->output)) != 0) |
return r; |
return r; |
|
|
if (compat20) { |
|
if ((r = sshbuf_put_u64(m, get_sent_bytes())) != 0 || |
|
(r = sshbuf_put_u64(m, get_recv_bytes())) != 0) |
|
return r; |
|
} |
|
return 0; |
return 0; |
} |
} |
|
|
|
|
size_t ssh1keylen, rlen, slen, ilen, olen; |
size_t ssh1keylen, rlen, slen, ilen, olen; |
int r; |
int r; |
u_int ssh1cipher = 0; |
u_int ssh1cipher = 0; |
u_int64_t sent_bytes = 0, recv_bytes = 0; |
|
|
|
if (!compat20) { |
if (!compat20) { |
if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || |
if ((r = sshbuf_get_u32(m, &state->remote_protocol_flags)) != 0 || |
|
|
(r = sshbuf_put(state->output, output, olen)) != 0) |
(r = sshbuf_put(state->output, output, olen)) != 0) |
return r; |
return r; |
|
|
if (compat20) { |
|
if ((r = sshbuf_get_u64(m, &sent_bytes)) != 0 || |
|
(r = sshbuf_get_u64(m, &recv_bytes)) != 0) |
|
return r; |
|
roam_set_bytes(sent_bytes, recv_bytes); |
|
} |
|
if (sshbuf_len(m)) |
if (sshbuf_len(m)) |
return SSH_ERR_INVALID_FORMAT; |
return SSH_ERR_INVALID_FORMAT; |
debug3("%s: done", __func__); |
debug3("%s: done", __func__); |