version 1.277, 2018/07/16 03:09:13 |
version 1.278, 2018/12/27 03:25:25 |
|
|
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
#include <limits.h> |
#include <limits.h> |
|
#include <poll.h> |
#include <signal.h> |
#include <signal.h> |
#include <time.h> |
#include <time.h> |
|
|
|
|
|
|
if ((ssh = calloc(1, sizeof(*ssh))) == NULL || |
if ((ssh = calloc(1, sizeof(*ssh))) == NULL || |
(state = calloc(1, sizeof(*state))) == NULL || |
(state = calloc(1, sizeof(*state))) == NULL || |
|
(ssh->kex = kex_new()) == NULL || |
(state->input = sshbuf_new()) == NULL || |
(state->input = sshbuf_new()) == NULL || |
(state->output = sshbuf_new()) == NULL || |
(state->output = sshbuf_new()) == NULL || |
(state->outgoing_packet = sshbuf_new()) == NULL || |
(state->outgoing_packet = sshbuf_new()) == NULL || |
|
|
ssh->state = state; |
ssh->state = state; |
return ssh; |
return ssh; |
fail: |
fail: |
|
if (ssh) { |
|
kex_free(ssh->kex); |
|
free(ssh); |
|
} |
if (state) { |
if (state) { |
sshbuf_free(state->input); |
sshbuf_free(state->input); |
sshbuf_free(state->output); |
sshbuf_free(state->output); |
|
|
sshbuf_free(state->outgoing_packet); |
sshbuf_free(state->outgoing_packet); |
free(state); |
free(state); |
} |
} |
free(ssh); |
|
return NULL; |
return NULL; |
} |
} |
|
|
|
|
int |
int |
ssh_packet_is_rekeying(struct ssh *ssh) |
ssh_packet_is_rekeying(struct ssh *ssh) |
{ |
{ |
return ssh->state->rekeying || |
return ssh->state->rekeying || ssh->kex->done == 0; |
(ssh->kex != NULL && ssh->kex->done == 0); |
|
} |
} |
|
|
/* |
/* |
|
|
return 0; |
return 0; |
|
|
/* Haven't keyed yet or KEX in progress. */ |
/* Haven't keyed yet or KEX in progress. */ |
if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) |
if (ssh_packet_is_rekeying(ssh)) |
return 0; |
return 0; |
|
|
/* Peer can't rekey */ |
/* Peer can't rekey */ |
|
|
ssh_packet_set_server(struct ssh *ssh) |
ssh_packet_set_server(struct ssh *ssh) |
{ |
{ |
ssh->state->server_side = 1; |
ssh->state->server_side = 1; |
|
ssh->kex->server = 1; /* XXX unify? */ |
} |
} |
|
|
void |
void |
|
|
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 || |
(r = sshbuf_put_stringb(m, kex->my)) != 0 || |
(r = sshbuf_put_stringb(m, kex->my)) != 0 || |
(r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_put_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_put_u32(m, kex->flags)) != 0 || |
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 || |
(r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || |
(r = sshbuf_put_stringb(m, kex->server_version)) != 0 || |
(r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) |
(r = sshbuf_put_u32(m, kex->flags)) != 0) |
return r; |
return r; |
return 0; |
return 0; |
} |
} |
|
|
struct kex *kex; |
struct kex *kex; |
int r; |
int r; |
|
|
if ((kex = calloc(1, sizeof(struct kex))) == NULL || |
if ((kex = kex_new()) == NULL) |
(kex->my = sshbuf_new()) == NULL || |
return SSH_ERR_ALLOC_FAIL; |
(kex->peer = sshbuf_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
|
goto out; |
|
} |
|
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || |
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 || |
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || |
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || |
|
|
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || |
(r = sshbuf_get_stringb(m, kex->my)) != 0 || |
(r = sshbuf_get_stringb(m, kex->my)) != 0 || |
(r = sshbuf_get_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_get_stringb(m, kex->peer)) != 0 || |
(r = sshbuf_get_u32(m, &kex->flags)) != 0 || |
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 || |
(r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || |
(r = sshbuf_get_stringb(m, kex->server_version)) != 0 || |
(r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) |
(r = sshbuf_get_u32(m, &kex->flags)) != 0) |
goto out; |
goto out; |
kex->server = 1; |
kex->server = 1; |
kex->done = 1; |
kex->done = 1; |
r = 0; |
r = 0; |
out: |
out: |
if (r != 0 || kexp == NULL) { |
if (r != 0 || kexp == NULL) { |
if (kex != NULL) { |
kex_free(kex); |
sshbuf_free(kex->my); |
|
sshbuf_free(kex->peer); |
|
free(kex); |
|
} |
|
if (kexp != NULL) |
if (kexp != NULL) |
*kexp = NULL; |
*kexp = NULL; |
} else { |
} else { |
|
kex_free(*kexp); |
*kexp = kex; |
*kexp = kex; |
} |
} |
return r; |
return r; |