Explicitly check for and start time-based rekeying in the client
authordjm <djm@openbsd.org>
Fri, 16 Jul 2021 09:00:23 +0000 (09:00 +0000)
committerdjm <djm@openbsd.org>
Fri, 16 Jul 2021 09:00:23 +0000 (09:00 +0000)
and server mainloops.

Previously the rekey timeout could expire but rekeying would not start
until a packet was sent or received. This could cause us to spin in
select() on the rekey timeout if the connection was quiet.

ok markus@

usr.bin/ssh/clientloop.c
usr.bin/ssh/packet.c
usr.bin/ssh/packet.h
usr.bin/ssh/serverloop.c

index 83efcef..b84c986 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.366 2021/07/13 23:48:36 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.367 2021/07/16 09:00:23 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1350,6 +1350,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
                if (quit_pending)
                        break;
 
+               /* A timeout may have triggered rekeying */
+               if ((r = ssh_packet_check_rekey(ssh)) != 0)
+                       fatal_fr(r, "cannot start rekeying");
+
                /*
                 * Send as much buffered packet data as possible to the
                 * sender.
index 3156eed..2401861 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.300 2021/04/03 06:18:40 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.301 2021/07/16 09:00:23 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -982,6 +982,15 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
            (state->p_read.blocks > state->max_blocks_in));
 }
 
+int
+ssh_packet_check_rekey(struct ssh *ssh)
+{
+       if (!ssh_packet_need_rekeying(ssh, 0))
+               return 0;
+       debug3_f("rekex triggered");
+       return kex_start_rekex(ssh);
+}
+
 /*
  * Delayed compression for SSH2 is enabled after authentication:
  * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
@@ -1674,12 +1683,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
        /* reset for next packet */
        state->packlen = 0;
 
-       /* do we need to rekey? */
-       if (ssh_packet_need_rekeying(ssh, 0)) {
-               debug3_f("rekex triggered");
-               if ((r = kex_start_rekex(ssh)) != 0)
-                       return r;
-       }
+       if ((r = ssh_packet_check_rekey(ssh)) != 0)
+               return r;
  out:
        return r;
 }
index 2fc6c5b..ac03c27 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.92 2020/03/06 18:11:10 markus Exp $ */
+/* $OpenBSD: packet.h,v 1.93 2021/07/16 09:00:23 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -99,6 +99,7 @@ void   ssh_packet_clear_keys(struct ssh *);
 void    ssh_clear_newkeys(struct ssh *, int);
 
 int     ssh_packet_is_rekeying(struct ssh *);
+int     ssh_packet_check_rekey(struct ssh *);
 void     ssh_packet_set_protocol_flags(struct ssh *, u_int);
 u_int   ssh_packet_get_protocol_flags(struct ssh *);
 void    ssh_packet_set_tos(struct ssh *, int);
index dd13b79..ab2af54 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.227 2021/06/25 03:38:17 dtucker Exp $ */
+/* $OpenBSD: serverloop.c,v 1.228 2021/07/16 09:00:23 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -329,7 +329,7 @@ void
 server_loop2(struct ssh *ssh, Authctxt *authctxt)
 {
        fd_set *readset = NULL, *writeset = NULL;
-       int max_fd;
+       int r, max_fd;
        u_int nalloc = 0, connection_in, connection_out;
        u_int64_t rekey_timeout_ms = 0;
        sigset_t bsigset, osigset;
@@ -391,6 +391,9 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt)
                        channel_after_select(ssh, readset, writeset);
                if (process_input(ssh, readset, connection_in) < 0)
                        break;
+               /* A timeout may have triggered rekeying */
+               if ((r = ssh_packet_check_rekey(ssh)) != 0)
+                       fatal_fr(r, "cannot start rekeying");
                process_output(ssh, writeset, connection_out);
        }
        collect_children(ssh);