From 6893f00e42619311e5f12faf4eb12b35b271c2f2 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 18 May 2018 13:46:36 +0100 Subject: [PATCH] Fix constant rekeying. Another piece of fallout from this morning's patch series, which I didn't notice until I left a session running for more than an hour: once do_ssh2_transport is told to begin a rekey, it has no way of knowing _not_ to immediately do another one, and another, and so on. Added a value RK_NONE to the rekey class enumeration, and set rekey_class to that immediately after a key exchange completes. Then a new one won't start until some code actually sets rekey_class to a nonzero value again. --- ssh.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ssh.c b/ssh.c index b40a17c8..74947f13 100644 --- a/ssh.c +++ b/ssh.c @@ -853,8 +853,9 @@ struct queued_handler { * discriminate between classes of reason that the code needs to treat * differently. * - * RK_INITIAL is a dummy value indicating that we haven't even done - * the _first_ key exchange yet. RK_NORMAL is the usual case. + * RK_NONE == 0 is the value indicating that no rekey is currently + * needed at all. RK_INITIAL indicates that we haven't even done the + * _first_ key exchange yet. RK_NORMAL is the usual case. * RK_GSS_UPDATE indicates that we're rekeying because we've just got * new GSSAPI credentials (hence there's no point in doing a * preliminary check for new GSS creds, because we already know the @@ -868,7 +869,13 @@ struct queued_handler { * decides whether it needs a rekey at all. In the other cases, * rekey_reason is set up at the same time as rekey_class. */ -enum RekeyClass { RK_INITIAL, RK_NORMAL, RK_POST_USERAUTH, RK_GSS_UPDATE }; +enum RekeyClass { + RK_NONE = 0, + RK_INITIAL, + RK_NORMAL, + RK_POST_USERAUTH, + RK_GSS_UPDATE +}; struct ssh_tag { const struct plug_function_table *fn; @@ -8443,7 +8450,8 @@ static void do_ssh2_transport(void *vctx) * other is if we find ssh->rekey_reason is non-NULL, i.e. we've * decided to initiate a rekey ourselves for some reason. */ - while (!pq_peek(&ssh->pq_ssh2_transport) && !ssh->rekey_reason) { + ssh->rekey_class = RK_NONE; + while (!pq_peek(&ssh->pq_ssh2_transport) && !ssh->rekey_class) { wait_for_rekey: if (!ssh->current_user_input_fn) { /*