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");
-
- 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");
-
- /* 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));
+ /*
+ * 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", "repeat",
+ "Options controlling key re-exchange");
+
+ 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.
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)
* 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);
{
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);
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 */
}