| ︙ | | | ︙ | |
746
747
748
749
750
751
752
753
754
755
756
757
758
759
|
* Track incoming and outgoing data sizes and time, for
* size-based rekeys.
*/
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
long next_rekey, last_rekey;
};
#define logevent(s) logevent(ssh->frontend, s)
/* logevent, only printf-formatted. */
static void logeventf(Ssh ssh, const char *fmt, ...)
{
|
>
|
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
|
* Track incoming and outgoing data sizes and time, for
* size-based rekeys.
*/
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
long next_rekey, last_rekey;
char *deferred_rekey_reason; /* points to STATIC string; don't free */
};
#define logevent(s) logevent(ssh->frontend, s)
/* logevent, only printf-formatted. */
static void logeventf(Ssh ssh, const char *fmt, ...)
{
|
| ︙ | | | ︙ | |
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
|
void *hkey; /* actual host key */
unsigned char exchange_hash[20];
int n_preferred_kex;
const struct ssh_kex *preferred_kex[KEX_MAX];
int n_preferred_ciphers;
const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
const struct ssh_compress *preferred_comp;
int first_kex;
struct Packet *pktout;
};
crState(do_ssh2_transport_state);
crBegin(ssh->do_ssh2_transport_crstate);
s->cscipher_tobe = s->sccipher_tobe = NULL;
s->csmac_tobe = s->scmac_tobe = NULL;
s->cscomp_tobe = s->sccomp_tobe = NULL;
s->first_kex = 1;
{
int i;
/*
* Set up the preferred key exchange. (NULL => warn below here)
*/
s->n_preferred_kex = 0;
for (i = 0; i < KEX_MAX; i++) {
switch (ssh->cfg.ssh_kexlist[i]) {
case KEX_DHGEX:
|
|
>
|
>
>
>
>
>
>
>
>
>
|
|
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
|
void *hkey; /* actual host key */
unsigned char exchange_hash[20];
int n_preferred_kex;
const struct ssh_kex *preferred_kex[KEX_MAX];
int n_preferred_ciphers;
const struct ssh2_ciphers *preferred_ciphers[CIPHER_MAX];
const struct ssh_compress *preferred_comp;
int got_session_id, activated_authconn;
struct Packet *pktout;
};
crState(do_ssh2_transport_state);
crBegin(ssh->do_ssh2_transport_crstate);
s->cscipher_tobe = s->sccipher_tobe = NULL;
s->csmac_tobe = s->scmac_tobe = NULL;
s->cscomp_tobe = s->sccomp_tobe = NULL;
s->got_session_id = s->activated_authconn = FALSE;
/*
* Be prepared to work around the buggy MAC problem.
*/
if (ssh->remote_bugs & BUG_SSH2_HMAC)
s->maclist = buggymacs, s->nmacs = lenof(buggymacs);
else
s->maclist = macs, s->nmacs = lenof(macs);
begin_key_exchange:
{
int i, j, commalist_started;
/*
* Set up the preferred key exchange. (NULL => warn below here)
*/
s->n_preferred_kex = 0;
for (i = 0; i < KEX_MAX; i++) {
switch (ssh->cfg.ssh_kexlist[i]) {
case KEX_DHGEX:
|
| ︙ | | | ︙ | |
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
|
* the list. */
if (i < KEX_MAX - 1) {
s->preferred_kex[s->n_preferred_kex++] = NULL;
}
break;
}
}
}
{
int i;
/*
* Set up the preferred ciphers. (NULL => warn below here)
*/
s->n_preferred_ciphers = 0;
for (i = 0; i < CIPHER_MAX; i++) {
switch (ssh->cfg.ssh_cipherlist[i]) {
case CIPHER_BLOWFISH:
|
|
<
<
<
|
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
|
* the list. */
if (i < KEX_MAX - 1) {
s->preferred_kex[s->n_preferred_kex++] = NULL;
}
break;
}
}
/*
* Set up the preferred ciphers. (NULL => warn below here)
*/
s->n_preferred_ciphers = 0;
for (i = 0; i < CIPHER_MAX; i++) {
switch (ssh->cfg.ssh_cipherlist[i]) {
case CIPHER_BLOWFISH:
|
| ︙ | | | ︙ | |
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
|
* the list. */
if (i < CIPHER_MAX - 1) {
s->preferred_ciphers[s->n_preferred_ciphers++] = NULL;
}
break;
}
}
}
/*
* Set up preferred compression.
*/
if (ssh->cfg.compression)
s->preferred_comp = &ssh_zlib;
else
s->preferred_comp = &ssh_comp_none;
/*
* Be prepared to work around the buggy MAC problem.
*/
if (ssh->remote_bugs & BUG_SSH2_HMAC)
s->maclist = buggymacs, s->nmacs = lenof(buggymacs);
else
s->maclist = macs, s->nmacs = lenof(macs);
begin_key_exchange:
{
int i, j, commalist_started;
/*
* Enable queueing of outgoing auth- or connection-layer
* packets while we are in the middle of a key exchange.
*/
ssh->queueing = TRUE;
|
|
<
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
|
* the list. */
if (i < CIPHER_MAX - 1) {
s->preferred_ciphers[s->n_preferred_ciphers++] = NULL;
}
break;
}
}
/*
* Set up preferred compression.
*/
if (ssh->cfg.compression)
s->preferred_comp = &ssh_zlib;
else
s->preferred_comp = &ssh_comp_none;
/*
* Enable queueing of outgoing auth- or connection-layer
* packets while we are in the middle of a key exchange.
*/
ssh->queueing = TRUE;
|
| ︙ | | | ︙ | |
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
|
* checked the signature of the exchange hash.)
*/
s->keystr = ssh->hostkey->fmtkey(s->hkey);
s->fingerprint = ssh->hostkey->fingerprint(s->hkey);
verify_ssh_host_key(ssh->frontend,
ssh->savedhost, ssh->savedport, ssh->hostkey->keytype,
s->keystr, s->fingerprint);
if (s->first_kex) { /* don't bother logging this in rekeys */
logevent("Host key fingerprint is:");
logevent(s->fingerprint);
}
sfree(s->fingerprint);
sfree(s->keystr);
ssh->hostkey->freekey(s->hkey);
/*
* The exchange hash from the very first key exchange is also
* the session id, used in session key construction and
* authentication.
*/
if (s->first_kex)
memcpy(ssh->v2_session_id, s->exchange_hash,
sizeof(s->exchange_hash));
/*
* Send SSH2_MSG_NEWKEYS.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_NEWKEYS);
ssh2_pkt_send_noqueue(ssh, s->pktout);
ssh->outgoing_data_size = 0; /* start counting from here */
|
|
|
>
>
|
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
|
* checked the signature of the exchange hash.)
*/
s->keystr = ssh->hostkey->fmtkey(s->hkey);
s->fingerprint = ssh->hostkey->fingerprint(s->hkey);
verify_ssh_host_key(ssh->frontend,
ssh->savedhost, ssh->savedport, ssh->hostkey->keytype,
s->keystr, s->fingerprint);
if (!s->got_session_id) { /* don't bother logging this in rekeys */
logevent("Host key fingerprint is:");
logevent(s->fingerprint);
}
sfree(s->fingerprint);
sfree(s->keystr);
ssh->hostkey->freekey(s->hkey);
/*
* The exchange hash from the very first key exchange is also
* the session id, used in session key construction and
* authentication.
*/
if (!s->got_session_id) {
memcpy(ssh->v2_session_id, s->exchange_hash,
sizeof(s->exchange_hash));
s->got_session_id = TRUE;
}
/*
* Send SSH2_MSG_NEWKEYS.
*/
s->pktout = ssh2_pkt_init(SSH2_MSG_NEWKEYS);
ssh2_pkt_send_noqueue(ssh, s->pktout);
ssh->outgoing_data_size = 0; /* start counting from here */
|
| ︙ | | | ︙ | |
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
|
freebn(s->K);
if (ssh->kex == &ssh_diffiehellman_gex) {
freebn(s->g);
freebn(s->p);
}
/*
* Key exchange is over. Schedule a timer for our next rekey.
*/
ssh->kex_in_progress = FALSE;
ssh->last_rekey = GETTICKCOUNT();
if (ssh->cfg.ssh_rekey_time != 0)
ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
ssh2_timer, ssh);
/*
* 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
* it would only confuse the layer above.
*/
if (!s->first_kex) {
crReturn(1);
}
s->first_kex = 0;
/*
* Now we're encrypting. Begin returning 1 to the protocol main
* function so that other things can run on top of the
* transport. If we ever see a KEXINIT, we must go back to the
* start.
*
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
|
freebn(s->K);
if (ssh->kex == &ssh_diffiehellman_gex) {
freebn(s->g);
freebn(s->p);
}
/*
* Key exchange is over. Loop straight back round if we have a
* deferred rekey reason.
*/
if (ssh->deferred_rekey_reason) {
logevent(ssh->deferred_rekey_reason);
pktin = NULL;
ssh->deferred_rekey_reason = NULL;
goto begin_key_exchange;
}
/*
* Otherwise, schedule a timer for our next rekey.
*/
ssh->kex_in_progress = FALSE;
ssh->last_rekey = GETTICKCOUNT();
if (ssh->cfg.ssh_rekey_time != 0)
ssh->next_rekey = schedule_timer(ssh->cfg.ssh_rekey_time*60*TICKSPERSEC,
ssh2_timer, ssh);
/*
* 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
* it would only confuse the layer above.
*/
if (s->activated_authconn) {
crReturn(1);
}
s->activated_authconn = TRUE;
/*
* Now we're encrypting. Begin returning 1 to the protocol main
* function so that other things can run on top of the
* transport. If we ever see a KEXINIT, we must go back to the
* start.
*
|
| ︙ | | | ︙ | |
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
|
ssh->mainchan = NULL;
ssh->throttled_all = 0;
ssh->v1_stdout_throttling = 0;
ssh->queue = NULL;
ssh->queuelen = ssh->queuesize = 0;
ssh->queueing = FALSE;
ssh->qhead = ssh->qtail = NULL;
*backend_handle = ssh;
#ifdef MSCRYPTOAPI
if (crypto_startup() == 0)
return "Microsoft high encryption pack not installed!";
#endif
|
>
|
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
|
ssh->mainchan = NULL;
ssh->throttled_all = 0;
ssh->v1_stdout_throttling = 0;
ssh->queue = NULL;
ssh->queuelen = ssh->queuesize = 0;
ssh->queueing = FALSE;
ssh->qhead = ssh->qtail = NULL;
ssh->deferred_rekey_reason = NULL;
*backend_handle = ssh;
#ifdef MSCRYPTOAPI
if (crypto_startup() == 0)
return "Microsoft high encryption pack not installed!";
#endif
|
| ︙ | | | ︙ | |
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
|
/*
* Reconfigure the SSH backend.
*/
static void ssh_reconfig(void *handle, Config *cfg)
{
Ssh ssh = (Ssh) handle;
char *rekeying = NULL;
unsigned long old_max_data_size;
pinger_reconfig(ssh->pinger, &ssh->cfg, cfg);
ssh_setup_portfwd(ssh, cfg);
if (ssh->cfg.ssh_rekey_time != cfg->ssh_rekey_time &&
cfg->ssh_rekey_time != 0) {
|
|
|
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
|
/*
* Reconfigure the SSH backend.
*/
static void ssh_reconfig(void *handle, Config *cfg)
{
Ssh ssh = (Ssh) handle;
char *rekeying = NULL, rekey_mandatory = FALSE;
unsigned long old_max_data_size;
pinger_reconfig(ssh->pinger, &ssh->cfg, cfg);
ssh_setup_portfwd(ssh, cfg);
if (ssh->cfg.ssh_rekey_time != cfg->ssh_rekey_time &&
cfg->ssh_rekey_time != 0) {
|
| ︙ | | | ︙ | |
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
|
if (old_max_data_size != ssh->max_data_size &&
ssh->max_data_size != 0) {
if (ssh->outgoing_data_size > ssh->max_data_size ||
ssh->incoming_data_size > ssh->max_data_size)
rekeying = "Initiating key re-exchange (data limit lowered)";
}
if (rekeying && !ssh->kex_in_progress) {
do_ssh2_transport(ssh, rekeying, -1, NULL);
}
ssh->cfg = *cfg; /* STRUCTURE COPY */
}
/*
* Called to send data down the Telnet connection.
*/
static int ssh_send(void *handle, char *buf, int len)
{
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
|
if (old_max_data_size != ssh->max_data_size &&
ssh->max_data_size != 0) {
if (ssh->outgoing_data_size > ssh->max_data_size ||
ssh->incoming_data_size > ssh->max_data_size)
rekeying = "Initiating key re-exchange (data limit lowered)";
}
if (ssh->cfg.compression != cfg->compression) {
rekeying = "Initiating key re-exchange (compression setting changed)";
rekey_mandatory = TRUE;
}
if (ssh->cfg.ssh2_des_cbc != cfg->ssh2_des_cbc ||
memcmp(ssh->cfg.ssh_cipherlist, cfg->ssh_cipherlist,
sizeof(ssh->cfg.ssh_cipherlist))) {
rekeying = "Initiating key re-exchange (cipher settings changed)";
rekey_mandatory = TRUE;
}
ssh->cfg = *cfg; /* STRUCTURE COPY */
if (rekeying) {
if (!ssh->kex_in_progress) {
do_ssh2_transport(ssh, rekeying, -1, NULL);
} else if (rekey_mandatory) {
ssh->deferred_rekey_reason = rekeying;
}
}
}
/*
* Called to send data down the Telnet connection.
*/
static int ssh_send(void *handle, char *buf, int len)
{
|
| ︙ | | | ︙ | |