546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
|
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
|
+
+
|
int v1_compressing;
int v1_remote_protoflags;
int v1_local_protoflags;
int agentfwd_enabled;
int X11_fwd_enabled;
int remote_bugs;
const struct ssh_cipher *cipher;
void *v1_cipher_ctx;
const struct ssh2_cipher *cscipher, *sccipher;
void *cs_cipher_ctx, *sc_cipher_ctx;
const struct ssh_mac *csmac, *scmac;
const struct ssh_compress *cscomp, *sccomp;
const struct ssh_kex *kex;
const struct ssh_signkey *hostkey;
unsigned char v2_session_id[20];
char *savedhost;
|
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
|
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
|
-
+
|
if (ssh->cipher && detect_attack(ssh->pktin.data, st->biglen, NULL)) {
bombout(("Network attack (CRC compensation) detected!"));
crReturn(0);
}
if (ssh->cipher)
ssh->cipher->decrypt(ssh->pktin.data, st->biglen);
ssh->cipher->decrypt(ssh->v1_cipher_ctx, ssh->pktin.data, st->biglen);
st->realcrc = crc32(ssh->pktin.data, st->biglen - 4);
st->gotcrc = GET_32BIT(ssh->pktin.data + st->biglen - 4);
if (st->gotcrc != st->realcrc) {
bombout(("Incorrect CRC received on packet"));
crReturn(0);
}
|
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
|
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
|
-
+
+
|
while ((*datalen) == 0)
crReturn(st->cipherblk - st->i);
ssh->pktin.data[st->i] = *(*data)++;
(*datalen)--;
}
if (ssh->sccipher)
ssh->sccipher->decrypt(ssh->pktin.data, st->cipherblk);
ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
ssh->pktin.data, st->cipherblk);
/*
* Now get the length and padding figures.
*/
st->len = GET_32BIT(ssh->pktin.data);
st->pad = ssh->pktin.data[4];
|
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
|
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
|
-
+
+
|
while ((*datalen) == 0)
crReturn(st->packetlen + st->maclen - st->i);
ssh->pktin.data[st->i] = *(*data)++;
(*datalen)--;
}
/* Decrypt everything _except_ the MAC. */
if (ssh->sccipher)
ssh->sccipher->decrypt(ssh->pktin.data + st->cipherblk,
ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
ssh->pktin.data + st->cipherblk,
st->packetlen - st->cipherblk);
/*
* Check the MAC.
*/
if (ssh->scmac
&& !ssh->scmac->verify(ssh->pktin.data, st->len + 4,
|
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
|
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
|
-
+
|
for (i = 0; i < pad; i++)
ssh->pktout.data[i + 4] = random_byte();
crc = crc32(ssh->pktout.data + 4, biglen - 4);
PUT_32BIT(ssh->pktout.data + biglen, crc);
PUT_32BIT(ssh->pktout.data, len);
if (ssh->cipher)
ssh->cipher->encrypt(ssh->pktout.data + 4, biglen);
ssh->cipher->encrypt(ssh->v1_cipher_ctx, ssh->pktout.data + 4, biglen);
return biglen + 4;
}
static void s_wrpkt(Ssh ssh)
{
int len, backlog;
|
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
|
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
|
+
-
+
|
PUT_32BIT(ssh->pktout.data, ssh->pktout.length + padding - 4);
if (ssh->csmac)
ssh->csmac->generate(ssh->pktout.data, ssh->pktout.length + padding,
ssh->v2_outgoing_sequence);
ssh->v2_outgoing_sequence++; /* whether or not we MACed */
if (ssh->cscipher)
ssh->cscipher->encrypt(ssh->cs_cipher_ctx,
ssh->cscipher->encrypt(ssh->pktout.data, ssh->pktout.length + padding);
ssh->pktout.data, ssh->pktout.length + padding);
/* Ready-to-send packet starts at ssh->pktout.data. We return length. */
return ssh->pktout.length + padding + maclen;
}
/*
* Construct and send an SSH2 packet immediately.
|
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
|
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
|
+
-
+
+
+
+
+
+
|
logevent("Trying to enable encryption...");
sfree(s->rsabuf);
ssh->cipher = (s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
s->cipher_type == SSH_CIPHER_DES ? &ssh_des :
&ssh_3des);
ssh->v1_cipher_ctx = ssh->cipher->make_context();
ssh->cipher->sesskey(ssh->session_key);
ssh->cipher->sesskey(ssh->v1_cipher_ctx, ssh->session_key);
{
char buf[256];
sprintf(buf, "Initialised %.200s encryption", ssh->cipher->text_name);
logevent(buf);
}
crWaitUntil(ispkt);
if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
bombout(("Encryption not successfully enabled"));
crReturn(0);
}
|
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
|
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
|
+
+
+
+
+
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
|
bombout(("expected new-keys packet from server"));
crReturn(0);
}
/*
* Create and initialise session keys.
*/
if (ssh->cs_cipher_ctx)
ssh->cscipher->free_context(ssh->cs_cipher_ctx);
ssh->cscipher = s->cscipher_tobe;
ssh->cs_cipher_ctx = ssh->cscipher->make_context();
if (ssh->sc_cipher_ctx)
ssh->sccipher->free_context(ssh->sc_cipher_ctx);
ssh->sccipher = s->sccipher_tobe;
ssh->sc_cipher_ctx = ssh->sccipher->make_context();
ssh->csmac = s->csmac_tobe;
ssh->scmac = s->scmac_tobe;
ssh->cscomp = s->cscomp_tobe;
ssh->sccomp = s->sccomp_tobe;
ssh->cscomp->compress_init();
ssh->sccomp->decompress_init();
/*
* Set IVs after keys. Here we use the exchange hash from the
* _first_ key exchange.
*/
{
unsigned char keyspace[40];
if (s->first_kex)
memcpy(ssh->v2_session_id, s->exchange_hash,
sizeof(s->exchange_hash));
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'C',keyspace);
ssh->cscipher->setcskey(keyspace);
ssh->cscipher->setkey(ssh->cs_cipher_ctx, keyspace);
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'D',keyspace);
ssh->sccipher->setsckey(keyspace);
ssh->sccipher->setkey(ssh->sc_cipher_ctx, keyspace);
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'A',keyspace);
ssh->cscipher->setcsiv(keyspace);
ssh->cscipher->setiv(ssh->cs_cipher_ctx, keyspace);
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'B',keyspace);
ssh->sccipher->setsciv(keyspace);
ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'E',keyspace);
ssh->csmac->setcskey(keyspace);
ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'F',keyspace);
ssh->scmac->setsckey(keyspace);
}
{
char buf[256];
sprintf(buf, "Initialised %.200s client->server encryption",
ssh->cscipher->text_name);
logevent(buf);
sprintf(buf, "Initialised %.200s server->client encryption",
ssh->sccipher->text_name);
logevent(buf);
}
/*
* If this is the first key exchange phase, we must pass the
* SSH2_MSG_NEWKEYS packet to the next layer, not because it
* wants to see it but because it will need time to initialise
* itself before it sees an actual packet. In subsequent key
* exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because
|