diff options
author | Darren Tucker <dtucker@cvs.openbsd.org> | 2013-05-16 02:00:35 +0000 |
---|---|---|
committer | Darren Tucker <dtucker@cvs.openbsd.org> | 2013-05-16 02:00:35 +0000 |
commit | 722d0265fc441f3b3c72fe882be8d4daf4b76180 (patch) | |
tree | 804ae16b71f4df528f2cb6e90fd2ff0e57519822 | |
parent | cfd6bfe7193d6d95e8ce3e2a98ca29537a900422 (diff) |
Add an optional second argument to RekeyLimit in the client to allow
rekeying based on elapsed time in addition to amount of traffic.
with djm@ jmc@, ok djm
-rw-r--r-- | usr.bin/ssh/clientloop.c | 23 | ||||
-rw-r--r-- | usr.bin/ssh/packet.c | 33 | ||||
-rw-r--r-- | usr.bin/ssh/packet.h | 5 | ||||
-rw-r--r-- | usr.bin/ssh/readconf.c | 80 | ||||
-rw-r--r-- | usr.bin/ssh/readconf.h | 3 | ||||
-rw-r--r-- | usr.bin/ssh/ssh_config | 3 | ||||
-rw-r--r-- | usr.bin/ssh/ssh_config.5 | 20 | ||||
-rw-r--r-- | usr.bin/ssh/sshconnect2.c | 7 |
8 files changed, 123 insertions, 51 deletions
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index 48da1e9b601..f26302226f9 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.248 2013/01/02 00:32:07 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.249 2013/05/16 02:00:34 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -575,7 +575,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, { struct timeval tv, *tvp; int timeout_secs; - time_t minwait_secs = 0; + time_t minwait_secs = 0, server_alive_time = 0, now = time(NULL); int ret; /* Add any selections by the channel mechanism. */ @@ -624,12 +624,16 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, */ timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ - if (options.server_alive_interval > 0 && compat20) + if (options.server_alive_interval > 0 && compat20) { timeout_secs = options.server_alive_interval; + server_alive_time = now + options.server_alive_interval; + } + if (options.rekey_interval > 0 && compat20 && !rekeying) + timeout_secs = MIN(timeout_secs, packet_get_rekey_timeout()); set_control_persist_exit_time(); if (control_persist_exit_time > 0) { timeout_secs = MIN(timeout_secs, - control_persist_exit_time - time(NULL)); + control_persist_exit_time - now); if (timeout_secs < 0) timeout_secs = 0; } @@ -661,8 +665,15 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); buffer_append(&stderr_buffer, buf, strlen(buf)); quit_pending = 1; - } else if (ret == 0) - server_alive_check(); + } else if (ret == 0) { + /* + * Timeout. Could have been either keepalive or rekeying. + * Keepalive we check here, rekeying is checked in clientloop. + */ + if (server_alive_time != 0 && server_alive_time <= time(NULL)) + server_alive_check(); + } + } static void diff --git a/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c index b8fb80ba5d2..4291bc8c1f9 100644 --- a/usr.bin/ssh/packet.c +++ b/usr.bin/ssh/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.183 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.184 2013/05/16 02:00:34 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -54,6 +54,7 @@ #include <string.h> #include <unistd.h> #include <signal.h> +#include <time.h> #include "xmalloc.h" #include "buffer.h" @@ -161,9 +162,14 @@ struct session_state { Newkeys *newkeys[MODE_MAX]; struct packet_state p_read, p_send; + /* Volume-based rekeying */ u_int64_t max_blocks_in, max_blocks_out; u_int32_t rekey_limit; + /* Time-based rekeying */ + time_t rekey_interval; /* how often in seconds */ + time_t rekey_time; /* time of last rekeying */ + /* Session key for protocol v1 */ u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; u_int ssh1_keylen; @@ -998,6 +1004,7 @@ packet_send2(void) /* after a NEWKEYS message we can send the complete queue */ if (type == SSH2_MSG_NEWKEYS) { active_state->rekeying = 0; + active_state->rekey_time = time(NULL); while ((p = TAILQ_FIRST(&active_state->outgoing))) { type = p->type; debug("dequeue packet: %u", type); @@ -1911,13 +1918,33 @@ packet_need_rekeying(void) (active_state->max_blocks_out && (active_state->p_send.blocks > active_state->max_blocks_out)) || (active_state->max_blocks_in && - (active_state->p_read.blocks > active_state->max_blocks_in)); + (active_state->p_read.blocks > active_state->max_blocks_in)) || + (active_state->rekey_interval != 0 && active_state->rekey_time + + active_state->rekey_interval <= time(NULL)); } void -packet_set_rekey_limit(u_int32_t bytes) +packet_set_rekey_limits(u_int32_t bytes, time_t seconds) { + debug3("rekey after %lld bytes, %d seconds", (long long)bytes, + (int)seconds); active_state->rekey_limit = bytes; + active_state->rekey_interval = seconds; + /* + * We set the time here so that in post-auth privsep slave we count + * from the completion of the authentication. + */ + active_state->rekey_time = time(NULL); +} + +time_t +packet_get_rekey_timeout(void) +{ + time_t seconds; + + seconds = active_state->rekey_time + active_state->rekey_interval - + time(NULL); + return (seconds < 0 ? 0 : seconds); } void diff --git a/usr.bin/ssh/packet.h b/usr.bin/ssh/packet.h index f2f009ef9ab..0941b5d54ab 100644 --- a/usr.bin/ssh/packet.h +++ b/usr.bin/ssh/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.57 2012/01/25 19:40:09 markus Exp $ */ +/* $OpenBSD: packet.h,v 1.58 2013/05/16 02:00:34 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -109,7 +109,8 @@ do { \ } while (0) int packet_need_rekeying(void); -void packet_set_rekey_limit(u_int32_t); +void packet_set_rekey_limits(u_int32_t, time_t); +time_t packet_get_rekey_timeout(void); void packet_backup_state(void); void packet_restore_state(void); diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c index 519e308e2a0..b7e85de6056 100644 --- a/usr.bin/ssh/readconf.c +++ b/usr.bin/ssh/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.197 2013/03/06 23:36:53 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.198 2013/05/16 02:00:34 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -558,39 +558,54 @@ parse_yesnoask: case oRekeyLimit: arg = strdelim(&s); if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); - if (arg[0] < '0' || arg[0] > '9') - fatal("%.200s line %d: Bad number.", filename, linenum); - orig = val64 = strtoll(arg, &endofnumber, 10); - if (arg == endofnumber) - fatal("%.200s line %d: Bad number.", filename, linenum); - switch (toupper(*endofnumber)) { - case '\0': - scale = 1; - break; - case 'K': - scale = 1<<10; - break; - case 'M': - scale = 1<<20; - break; - case 'G': - scale = 1<<30; - break; - default: - fatal("%.200s line %d: Invalid RekeyLimit suffix", - filename, linenum); + fatal("%.200s line %d: Missing argument.", filename, + linenum); + if (strcmp(arg, "default") == 0) { + val64 = 0; + } else { + if (arg[0] < '0' || arg[0] > '9') + fatal("%.200s line %d: Bad number.", filename, + linenum); + orig = val64 = strtoll(arg, &endofnumber, 10); + if (arg == endofnumber) + fatal("%.200s line %d: Bad number.", filename, + linenum); + switch (toupper(*endofnumber)) { + case '\0': + scale = 1; + break; + case 'K': + scale = 1<<10; + break; + case 'M': + scale = 1<<20; + break; + case 'G': + scale = 1<<30; + break; + default: + fatal("%.200s line %d: Invalid RekeyLimit " + "suffix", filename, linenum); + } + val64 *= scale; + /* detect integer wrap and too-large limits */ + if ((val64 / scale) != orig || val64 > UINT_MAX) + fatal("%.200s line %d: RekeyLimit too large", + filename, linenum); + if (val64 != 0 && val64 < 16) + fatal("%.200s line %d: RekeyLimit too small", + filename, linenum); } - val64 *= scale; - /* detect integer wrap and too-large limits */ - if ((val64 / scale) != orig || val64 > UINT_MAX) - fatal("%.200s line %d: RekeyLimit too large", - filename, linenum); - if (val64 < 16) - fatal("%.200s line %d: RekeyLimit too small", - filename, linenum); if (*activep && options->rekey_limit == -1) options->rekey_limit = (u_int32_t)val64; + if (s != NULL) { /* optional rekey interval present */ + if (strcmp(s, "none") == 0) { + (void)strdelim(&s); /* discard */ + break; + } + intptr = &options->rekey_interval; + goto parse_time; + } break; case oIdentityFile: @@ -1198,6 +1213,7 @@ initialize_options(Options * options) options->no_host_authentication_for_localhost = - 1; options->identities_only = - 1; options->rekey_limit = - 1; + options->rekey_interval = -1; options->verify_host_key_dns = -1; options->server_alive_interval = -1; options->server_alive_count_max = -1; @@ -1331,6 +1347,8 @@ fill_default_options(Options * options) options->enable_ssh_keysign = 0; if (options->rekey_limit == -1) options->rekey_limit = 0; + if (options->rekey_interval == -1) + options->rekey_interval = 0; if (options->verify_host_key_dns == -1) options->verify_host_key_dns = 0; if (options->server_alive_interval == -1) diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h index 841648906c8..e20573090a3 100644 --- a/usr.bin/ssh/readconf.h +++ b/usr.bin/ssh/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.93 2013/02/22 04:45:09 dtucker Exp $ */ +/* $OpenBSD: readconf.h,v 1.94 2013/05/16 02:00:34 dtucker Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -110,6 +110,7 @@ typedef struct { int enable_ssh_keysign; int64_t rekey_limit; + int rekey_interval; int no_host_authentication_for_localhost; int identities_only; int server_alive_interval; diff --git a/usr.bin/ssh/ssh_config b/usr.bin/ssh/ssh_config index 18936740f6e..bb408193633 100644 --- a/usr.bin/ssh/ssh_config +++ b/usr.bin/ssh/ssh_config @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $ +# $OpenBSD: ssh_config,v 1.27 2013/05/16 02:00:34 dtucker Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -45,3 +45,4 @@ # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com +# RekeyLimit 1G 1h diff --git a/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5 index 269529c0082..97897e00e70 100644 --- a/usr.bin/ssh/ssh_config.5 +++ b/usr.bin/ssh/ssh_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.161 2013/01/08 18:49:04 markus Exp $ -.Dd $Mdocdate: January 8 2013 $ +.\" $OpenBSD: ssh_config.5,v 1.162 2013/05/16 02:00:34 dtucker Exp $ +.Dd $Mdocdate: May 16 2013 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -931,8 +931,9 @@ The default is This option applies to protocol version 2 only. .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted before the -session key is renegotiated. -The argument is the number of bytes, with an optional suffix of +session key is renegotiated, optionally followed a maximum amount of +time that may pass before the session key is renegotiated. +The first argument is specified in bytes and may have a suffix of .Sq K , .Sq M , or @@ -943,6 +944,17 @@ The default is between and .Sq 4G , depending on the cipher. +The optional second value is specified in seconds and may use any of the +units documented in the +.Sx TIME FORMATS +section of +.Xr sshd_config 5 . +The default value for +.Cm RekeyLimit +is +.Dq default none , +which means that rekeying is performed after the cipher's default amount +of data has been sent or received and no time based rekeying is done. This option applies to protocol version 2 only. .It Cm RemoteForward Specifies that a TCP port on the remote machine be forwarded over diff --git a/usr.bin/ssh/sshconnect2.c b/usr.bin/ssh/sshconnect2.c index 805348233cc..43716f35315 100644 --- a/usr.bin/ssh/sshconnect2.c +++ b/usr.bin/ssh/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.195 2013/05/10 03:40:07 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.196 2013/05/16 02:00:34 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -191,8 +191,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) if (options.kex_algorithms != NULL) myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; - if (options.rekey_limit) - packet_set_rekey_limit((u_int32_t)options.rekey_limit); + if (options.rekey_limit || options.rekey_interval) + packet_set_rekey_limits((u_int32_t)options.rekey_limit, + (time_t)options.rekey_interval); /* start key exchange */ kex = kex_setup(myproposal); |