зеркало из https://github.com/github/putty.git
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:
Родитель
62a76699ad
Коммит
65b47c59c6
35
ssh.c
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче