Fix the SSH2 key re-exchange bug. Session id != exchange hash,

because the session id is the exchange hash from the _first_ key
exchange, so in subsequent key exchanges they're different.

[originally from svn r901]
This commit is contained in:
Simon Tatham 2001-01-26 18:50:13 +00:00
Родитель 62a76699ad
Коммит 65b47c59c6
1 изменённых файлов: 24 добавлений и 11 удалений

35
ssh.c
Просмотреть файл

@ -2096,14 +2096,14 @@ static int in_commasep_string(char *needle, char *haystack, int haylen) {
/* /*
* SSH2 key creation method. * SSH2 key creation method.
*/ */
static void ssh2_mkkey(Bignum K, char *H, char chr, char *keyspace) { static void ssh2_mkkey(Bignum K, char *H, char *sessid, char chr, char *keyspace) {
SHA_State s; SHA_State s;
/* First 20 bytes. */ /* First 20 bytes. */
SHA_Init(&s); SHA_Init(&s);
sha_mpint(&s, K); sha_mpint(&s, K);
SHA_Bytes(&s, H, 20); SHA_Bytes(&s, H, 20);
SHA_Bytes(&s, &chr, 1); SHA_Bytes(&s, &chr, 1);
SHA_Bytes(&s, H, 20); SHA_Bytes(&s, sessid, 20);
SHA_Final(&s, keyspace); SHA_Final(&s, keyspace);
/* Next 20 bytes. */ /* Next 20 bytes. */
SHA_Init(&s); SHA_Init(&s);
@ -2133,6 +2133,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
static int hostkeylen, siglen; static int hostkeylen, siglen;
static void *hkey; /* actual host key */ static void *hkey; /* actual host key */
static unsigned char exchange_hash[20]; static unsigned char exchange_hash[20];
static unsigned char first_exchange_hash[20];
static unsigned char keyspace[40]; static unsigned char keyspace[40];
static const struct ssh_cipher *preferred_cipher; static const struct ssh_cipher *preferred_cipher;
static const struct ssh_compress *preferred_comp; static const struct ssh_compress *preferred_comp;
@ -2389,8 +2390,10 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
fingerprint = hostkey->fingerprint(hkey); fingerprint = hostkey->fingerprint(hkey);
verify_ssh_host_key(savedhost, savedport, hostkey->keytype, verify_ssh_host_key(savedhost, savedport, hostkey->keytype,
keystr, fingerprint); keystr, fingerprint);
logevent("Host key fingerprint is:"); if (first_kex) { /* don't bother logging this in rekeys */
logevent(fingerprint); logevent("Host key fingerprint is:");
logevent(fingerprint);
}
sfree(fingerprint); sfree(fingerprint);
sfree(keystr); sfree(keystr);
hostkey->freekey(hkey); hostkey->freekey(hkey);
@ -2413,14 +2416,23 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
cscomp->compress_init(); cscomp->compress_init();
sccomp->decompress_init(); sccomp->decompress_init();
/* /*
* Set IVs after keys. * Set IVs after keys. Here we use the exchange hash from the
* _first_ key exchange.
*/ */
ssh2_mkkey(K, exchange_hash, 'C', keyspace); cscipher->setcskey(keyspace); if (first_kex)
ssh2_mkkey(K, exchange_hash, 'D', keyspace); sccipher->setsckey(keyspace); memcpy(first_exchange_hash, exchange_hash, sizeof(exchange_hash));
ssh2_mkkey(K, exchange_hash, 'A', keyspace); cscipher->setcsiv(keyspace); ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'C', keyspace);
ssh2_mkkey(K, exchange_hash, 'B', keyspace); sccipher->setsciv(keyspace); cscipher->setcskey(keyspace);
ssh2_mkkey(K, exchange_hash, 'E', keyspace); csmac->setcskey(keyspace); ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'D', keyspace);
ssh2_mkkey(K, exchange_hash, 'F', keyspace); scmac->setsckey(keyspace); sccipher->setsckey(keyspace);
ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'A', keyspace);
cscipher->setcsiv(keyspace);
ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'B', keyspace);
sccipher->setsciv(keyspace);
ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'E', keyspace);
csmac->setcskey(keyspace);
ssh2_mkkey(K, exchange_hash, first_exchange_hash, 'F', keyspace);
scmac->setsckey(keyspace);
/* /*
* If this is the first key exchange phase, we must pass the * If this is the first key exchange phase, we must pass the
@ -2444,6 +2456,7 @@ static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
do { do {
crReturn(1); crReturn(1);
} while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT)); } while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT));
logevent("Server initiated key re-exchange");
goto begin_key_exchange; goto begin_key_exchange;
crFinish(1); crFinish(1);