version 1.6, 2000/05/08 17:42:25 |
version 1.7, 2000/05/25 20:45:20 |
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "buffer.h" |
#include "buffer.h" |
#include "bufaux.h" |
#include "bufaux.h" |
|
#include "packet.h" |
#include "cipher.h" |
#include "cipher.h" |
#include "compat.h" |
#include "compat.h" |
|
|
|
|
|
|
#include "kex.h" |
#include "kex.h" |
|
|
|
#define KEX_COOKIE_LEN 16 |
|
|
Buffer * |
Buffer * |
kex_init(char *myproposal[PROPOSAL_MAX]) |
kex_init(char *myproposal[PROPOSAL_MAX]) |
{ |
{ |
char c = 0; |
int first_kex_packet_follows = 0; |
unsigned char cookie[16]; |
unsigned char cookie[KEX_COOKIE_LEN]; |
u_int32_t rand = 0; |
u_int32_t rand = 0; |
int i; |
int i; |
Buffer *ki = xmalloc(sizeof(*ki)); |
Buffer *ki = xmalloc(sizeof(*ki)); |
for (i = 0; i < 16; i++) { |
for (i = 0; i < KEX_COOKIE_LEN; i++) { |
if (i % 4 == 0) |
if (i % 4 == 0) |
rand = arc4random(); |
rand = arc4random(); |
cookie[i] = rand & 0xff; |
cookie[i] = rand & 0xff; |
|
|
buffer_append(ki, (char *)cookie, sizeof cookie); |
buffer_append(ki, (char *)cookie, sizeof cookie); |
for (i = 0; i < PROPOSAL_MAX; i++) |
for (i = 0; i < PROPOSAL_MAX; i++) |
buffer_put_cstring(ki, myproposal[i]); |
buffer_put_cstring(ki, myproposal[i]); |
buffer_append(ki, &c, 1); /* boolean first_kex_packet_follows */ |
buffer_put_char(ki, first_kex_packet_follows); |
buffer_put_int(ki, 0); /* uint32 0 (reserved for future extension) */ |
buffer_put_int(ki, 0); /* uint32 reserved */ |
return ki; |
return ki; |
} |
} |
|
|
|
/* send kexinit, parse and save reply */ |
|
void |
|
kex_exchange_kexinit( |
|
Buffer *my_kexinit, Buffer *peer_kexint, |
|
char *peer_proposal[PROPOSAL_MAX]) |
|
{ |
|
int i; |
|
char *ptr; |
|
int plen; |
|
|
|
debug("send KEXINIT"); |
|
packet_start(SSH2_MSG_KEXINIT); |
|
packet_put_raw(buffer_ptr(my_kexinit), buffer_len(my_kexinit)); |
|
packet_send(); |
|
packet_write_wait(); |
|
debug("done"); |
|
|
|
/* |
|
* read and save raw KEXINIT payload in buffer. this is used during |
|
* computation of the session_id and the session keys. |
|
*/ |
|
debug("wait KEXINIT"); |
|
packet_read_expect(&plen, SSH2_MSG_KEXINIT); |
|
ptr = packet_get_raw(&plen); |
|
buffer_append(peer_kexint, ptr, plen); |
|
|
|
/* parse packet and save algorithm proposal */ |
|
/* skip cookie */ |
|
for (i = 0; i < KEX_COOKIE_LEN; i++) |
|
packet_get_char(); |
|
/* extract kex init proposal strings */ |
|
for (i = 0; i < PROPOSAL_MAX; i++) { |
|
peer_proposal[i] = packet_get_string(NULL); |
|
debug("got kexinit: %s", peer_proposal[i]); |
|
} |
|
/* first kex follow / reserved */ |
|
i = packet_get_char(); |
|
debug("first kex follow: %d ", i); |
|
i = packet_get_int(); |
|
debug("reserved: %d ", i); |
|
packet_done(); |
|
debug("done"); |
|
} |
|
|
/* diffie-hellman-group1-sha1 */ |
/* diffie-hellman-group1-sha1 */ |
|
|
int |
int |
|
|
} |
} |
|
|
void |
void |
bignum_print(BIGNUM *b) |
|
{ |
|
BN_print_fp(stderr,b); |
|
} |
|
|
|
void |
|
dump_digest(unsigned char *digest, int len) |
dump_digest(unsigned char *digest, int len) |
{ |
{ |
int i; |
int i; |
|
|
get_match(char *client, char *server) |
get_match(char *client, char *server) |
{ |
{ |
char *sproposals[MAX_PROP]; |
char *sproposals[MAX_PROP]; |
char *p; |
char *c, *s, *p, *ret; |
int i, j, nproposals; |
int i, j, nproposals; |
|
|
for ((p = strtok(server, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { |
c = xstrdup(client); |
|
s = xstrdup(server); |
|
|
|
for ((p = strtok(s, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { |
if (i < MAX_PROP) |
if (i < MAX_PROP) |
sproposals[i] = p; |
sproposals[i] = p; |
else |
else |
|
|
} |
} |
nproposals = i; |
nproposals = i; |
|
|
for ((p = strtok(client, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { |
for ((p = strtok(c, SEP)), i=0; p; (p = strtok(NULL, SEP)), i++) { |
for (j = 0; j < nproposals; j++) |
for (j = 0; j < nproposals; j++) { |
if (strcmp(p, sproposals[j]) == 0) |
if (strcmp(p, sproposals[j]) == 0) { |
return xstrdup(p); |
ret = xstrdup(p); |
|
xfree(c); |
|
xfree(s); |
|
return ret; |
|
} |
|
} |
} |
} |
|
xfree(c); |
|
xfree(s); |
return NULL; |
return NULL; |
} |
} |
void |
void |
|
|
Kex * |
Kex * |
kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server) |
kex_choose_conf(char *cprop[PROPOSAL_MAX], char *sprop[PROPOSAL_MAX], int server) |
{ |
{ |
int i; |
|
int mode; |
int mode; |
int ctos; /* direction: if true client-to-server */ |
int ctos; /* direction: if true client-to-server */ |
int need; |
int need; |
|
|
choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); |
choose_kex(k, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); |
choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], |
choose_hostkeyalg(k, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], |
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); |
for (i = 0; i < PROPOSAL_MAX; i++) { |
|
xfree(cprop[i]); |
|
xfree(sprop[i]); |
|
} |
|
need = 0; |
need = 0; |
for (mode = 0; mode < MODE_MAX; mode++) { |
for (mode = 0; mode < MODE_MAX; mode++) { |
if (need < k->enc[mode].key_len) |
if (need < k->enc[mode].key_len) |
|
|
if (need < k->mac[mode].key_len) |
if (need < k->mac[mode].key_len) |
need = k->mac[mode].key_len; |
need = k->mac[mode].key_len; |
} |
} |
/* need runden? */ |
/* XXX need runden? */ |
#define WE_NEED 32 |
|
k->we_need = WE_NEED; |
|
k->we_need = need; |
k->we_need = need; |
return k; |
return k; |
} |
} |