summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@cvs.openbsd.org>2013-05-16 02:00:35 +0000
committerDarren Tucker <dtucker@cvs.openbsd.org>2013-05-16 02:00:35 +0000
commit722d0265fc441f3b3c72fe882be8d4daf4b76180 (patch)
tree804ae16b71f4df528f2cb6e90fd2ff0e57519822
parentcfd6bfe7193d6d95e8ce3e2a98ca29537a900422 (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.c23
-rw-r--r--usr.bin/ssh/packet.c33
-rw-r--r--usr.bin/ssh/packet.h5
-rw-r--r--usr.bin/ssh/readconf.c80
-rw-r--r--usr.bin/ssh/readconf.h3
-rw-r--r--usr.bin/ssh/ssh_config3
-rw-r--r--usr.bin/ssh/ssh_config.520
-rw-r--r--usr.bin/ssh/sshconnect2.c7
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);