Support reconfiguration of key exchange in mid-session. The fiddly

bit is working out when to reschedule the next rekey for when the
timeout or data limit changes; sometimes it will be _right now_
because we're already over the new limit.

Still to do: the Kex panel should not appear in mid-session if we
are using SSHv1.

[originally from svn r5031]
This commit is contained in:
Simon Tatham 2004-12-28 14:10:32 +00:00
Родитель 81df0d4253
Коммит d77102a8d5
2 изменённых файлов: 61 добавлений и 29 удалений

Просмотреть файл

@ -1576,37 +1576,39 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
HELPCTX(ssh_ciphers),
dlg_stdcheckbox_handler,
I(offsetof(Config,ssh2_des_cbc)));
}
/*
* The Connection/SSH/Kex panel.
*/
ctrl_settitle(b, "Connection/SSH/Kex",
"Options controlling SSH key exchange");
/*
* The Connection/SSH/Kex panel. (Owing to repeat key
* exchange, this is all meaningful in mid-session.)
*/
ctrl_settitle(b, "Connection/SSH/Kex",
"Options controlling SSH key exchange");
s = ctrl_getset(b, "Connection/SSH/Kex", "main",
"Key exchange algorithm options");
c = ctrl_draglist(s, "Algorithm selection policy", 's',
HELPCTX(ssh_kexlist),
kexlist_handler, P(NULL));
c->listbox.height = 5;
s = ctrl_getset(b, "Connection/SSH/Kex", "main",
"Key exchange algorithm options");
c = ctrl_draglist(s, "Algorithm selection policy", 's',
HELPCTX(ssh_kexlist),
kexlist_handler, P(NULL));
c->listbox.height = 5;
s = ctrl_getset(b, "Connection/SSH/Kex", "repeat",
"Options controlling key re-exchange");
s = ctrl_getset(b, "Connection/SSH/Kex", "repeat",
"Options controlling key re-exchange");
/* FIXME: these could usefully be configured mid-session in SSH-2.
* (So could cipher/compression/kex, now we have rekey.) */
ctrl_editbox(s, "Max minutes before rekey (0 for no limit)", 't', 20,
HELPCTX(ssh_kex_repeat),
dlg_stdeditbox_handler,
I(offsetof(Config,ssh_rekey_time)),
I(-1));
ctrl_editbox(s, "Max data before rekey (0 for no limit)", 'd', 20,
HELPCTX(ssh_kex_repeat),
dlg_stdeditbox_handler,
I(offsetof(Config,ssh_rekey_data)),
I(16));
ctrl_text(s, "(Use 1M for 1 megabyte, 1G for 1 gigabyte etc)",
HELPCTX(ssh_kex_repeat));
ctrl_editbox(s, "Max minutes before rekey (0 for no limit)", 't', 20,
HELPCTX(ssh_kex_repeat),
dlg_stdeditbox_handler,
I(offsetof(Config,ssh_rekey_time)),
I(-1));
ctrl_editbox(s, "Max data before rekey (0 for no limit)", 'd', 20,
HELPCTX(ssh_kex_repeat),
dlg_stdeditbox_handler,
I(offsetof(Config,ssh_rekey_data)),
I(16));
ctrl_text(s, "(Use 1M for 1 megabyte, 1G for 1 gigabyte etc)",
HELPCTX(ssh_kex_repeat));
if (!midsession) {
/*
* The Connection/SSH/Auth panel.

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

@ -746,7 +746,7 @@ struct ssh_tag {
unsigned long incoming_data_size, outgoing_data_size, deferred_data_size;
unsigned long max_data_size;
int kex_in_progress;
long next_rekey;
long next_rekey, last_rekey;
};
#define logevent(s) logevent(ssh->frontend, s)
@ -5211,6 +5211,7 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen,
* 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);
@ -7213,7 +7214,7 @@ static void ssh2_timer(void *ctx, long now)
{
Ssh ssh = (Ssh)ctx;
if (!ssh->kex_in_progress &&
if (!ssh->kex_in_progress && ssh->cfg.ssh_rekey_time != 0 &&
now - ssh->next_rekey >= 0) {
do_ssh2_transport(ssh, "Initiating key re-exchange (timeout)",
-1, NULL);
@ -7459,8 +7460,37 @@ static void ssh_free(void *handle)
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) {
long new_next = ssh->last_rekey + cfg->ssh_rekey_time*60*TICKSPERSEC;
long now = GETTICKCOUNT();
if (new_next - now < 0) {
rekeying = "Initiating key re-exchange (timeout shortened)";
} else {
ssh->next_rekey = schedule_timer(new_next - now, ssh2_timer, ssh);
}
}
old_max_data_size = ssh->max_data_size;
ssh->max_data_size = parse_blocksize(cfg->ssh_rekey_data);
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 */
}