summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2013-05-16 20:28:16 +1000
committerDarren Tucker <dtucker@zip.com.au>2013-05-16 20:28:16 +1000
commitc53c2af173cf67fd1c26f98e7900299b1b65b6ec (patch)
tree1c83d4abcdec31e4be6d8a2955fdad33b985b976
parent64c6fceecd27e1739040b42de8f3759454260b39 (diff)
- dtucker@cvs.openbsd.org 2013/05/16 02:00:34
[ssh_config sshconnect2.c packet.c readconf.h readconf.c clientloop.c ssh_config.5 packet.h] 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--ChangeLog6
-rw-r--r--clientloop.c23
-rw-r--r--packet.c33
-rw-r--r--packet.h5
-rw-r--r--readconf.c80
-rw-r--r--readconf.h3
-rw-r--r--ssh_config3
-rw-r--r--ssh_config.520
-rw-r--r--sshconnect2.c7
9 files changed, 129 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 7f4249222..85a5edcce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,12 @@
22 - dtucker@cvs.openbsd.org 2013/05/10 10:13:50 22 - dtucker@cvs.openbsd.org 2013/05/10 10:13:50
23 [ssh-pkcs11-helper.c] 23 [ssh-pkcs11-helper.c]
24 remove unused extern optarg. ok markus@ 24 remove unused extern optarg. ok markus@
25 - dtucker@cvs.openbsd.org 2013/05/16 02:00:34
26 [ssh_config sshconnect2.c packet.c readconf.h readconf.c clientloop.c
27 ssh_config.5 packet.h]
28 Add an optional second argument to RekeyLimit in the client to allow
29 rekeying based on elapsed time in addition to amount of traffic.
30 with djm@ jmc@, ok djm
25 31
2620130510 3220130510
27 - (dtucker) [configure.ac] Enable -Wsizeof-pointer-memaccess if the compiler 33 - (dtucker) [configure.ac] Enable -Wsizeof-pointer-memaccess if the compiler
diff --git a/clientloop.c b/clientloop.c
index c1d1d4472..f1b108fcd 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.248 2013/01/02 00:32:07 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.249 2013/05/16 02:00:34 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -583,7 +583,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
583{ 583{
584 struct timeval tv, *tvp; 584 struct timeval tv, *tvp;
585 int timeout_secs; 585 int timeout_secs;
586 time_t minwait_secs = 0; 586 time_t minwait_secs = 0, server_alive_time = 0, now = time(NULL);
587 int ret; 587 int ret;
588 588
589 /* Add any selections by the channel mechanism. */ 589 /* Add any selections by the channel mechanism. */
@@ -632,12 +632,16 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
632 */ 632 */
633 633
634 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ 634 timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
635 if (options.server_alive_interval > 0 && compat20) 635 if (options.server_alive_interval > 0 && compat20) {
636 timeout_secs = options.server_alive_interval; 636 timeout_secs = options.server_alive_interval;
637 server_alive_time = now + options.server_alive_interval;
638 }
639 if (options.rekey_interval > 0 && compat20 && !rekeying)
640 timeout_secs = MIN(timeout_secs, packet_get_rekey_timeout());
637 set_control_persist_exit_time(); 641 set_control_persist_exit_time();
638 if (control_persist_exit_time > 0) { 642 if (control_persist_exit_time > 0) {
639 timeout_secs = MIN(timeout_secs, 643 timeout_secs = MIN(timeout_secs,
640 control_persist_exit_time - time(NULL)); 644 control_persist_exit_time - now);
641 if (timeout_secs < 0) 645 if (timeout_secs < 0)
642 timeout_secs = 0; 646 timeout_secs = 0;
643 } 647 }
@@ -669,8 +673,15 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
669 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); 673 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
670 buffer_append(&stderr_buffer, buf, strlen(buf)); 674 buffer_append(&stderr_buffer, buf, strlen(buf));
671 quit_pending = 1; 675 quit_pending = 1;
672 } else if (ret == 0) 676 } else if (ret == 0) {
673 server_alive_check(); 677 /*
678 * Timeout. Could have been either keepalive or rekeying.
679 * Keepalive we check here, rekeying is checked in clientloop.
680 */
681 if (server_alive_time != 0 && server_alive_time <= time(NULL))
682 server_alive_check();
683 }
684
674} 685}
675 686
676static void 687static void
diff --git a/packet.c b/packet.c
index 3c97383ec..dd9d26f5d 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.183 2013/04/19 01:06:50 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.184 2013/05/16 02:00:34 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
58#include <string.h> 58#include <string.h>
59#include <unistd.h> 59#include <unistd.h>
60#include <signal.h> 60#include <signal.h>
61#include <time.h>
61 62
62#include "xmalloc.h" 63#include "xmalloc.h"
63#include "buffer.h" 64#include "buffer.h"
@@ -165,9 +166,14 @@ struct session_state {
165 Newkeys *newkeys[MODE_MAX]; 166 Newkeys *newkeys[MODE_MAX];
166 struct packet_state p_read, p_send; 167 struct packet_state p_read, p_send;
167 168
169 /* Volume-based rekeying */
168 u_int64_t max_blocks_in, max_blocks_out; 170 u_int64_t max_blocks_in, max_blocks_out;
169 u_int32_t rekey_limit; 171 u_int32_t rekey_limit;
170 172
173 /* Time-based rekeying */
174 time_t rekey_interval; /* how often in seconds */
175 time_t rekey_time; /* time of last rekeying */
176
171 /* Session key for protocol v1 */ 177 /* Session key for protocol v1 */
172 u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 178 u_char ssh1_key[SSH_SESSION_KEY_LENGTH];
173 u_int ssh1_keylen; 179 u_int ssh1_keylen;
@@ -1009,6 +1015,7 @@ packet_send2(void)
1009 /* after a NEWKEYS message we can send the complete queue */ 1015 /* after a NEWKEYS message we can send the complete queue */
1010 if (type == SSH2_MSG_NEWKEYS) { 1016 if (type == SSH2_MSG_NEWKEYS) {
1011 active_state->rekeying = 0; 1017 active_state->rekeying = 0;
1018 active_state->rekey_time = time(NULL);
1012 while ((p = TAILQ_FIRST(&active_state->outgoing))) { 1019 while ((p = TAILQ_FIRST(&active_state->outgoing))) {
1013 type = p->type; 1020 type = p->type;
1014 debug("dequeue packet: %u", type); 1021 debug("dequeue packet: %u", type);
@@ -1933,13 +1940,33 @@ packet_need_rekeying(void)
1933 (active_state->max_blocks_out && 1940 (active_state->max_blocks_out &&
1934 (active_state->p_send.blocks > active_state->max_blocks_out)) || 1941 (active_state->p_send.blocks > active_state->max_blocks_out)) ||
1935 (active_state->max_blocks_in && 1942 (active_state->max_blocks_in &&
1936 (active_state->p_read.blocks > active_state->max_blocks_in)); 1943 (active_state->p_read.blocks > active_state->max_blocks_in)) ||
1944 (active_state->rekey_interval != 0 && active_state->rekey_time +
1945 active_state->rekey_interval <= time(NULL));
1937} 1946}
1938 1947
1939void 1948void
1940packet_set_rekey_limit(u_int32_t bytes) 1949packet_set_rekey_limits(u_int32_t bytes, time_t seconds)
1941{ 1950{
1951 debug3("rekey after %lld bytes, %d seconds", (long long)bytes,
1952 (int)seconds);
1942 active_state->rekey_limit = bytes; 1953 active_state->rekey_limit = bytes;
1954 active_state->rekey_interval = seconds;
1955 /*
1956 * We set the time here so that in post-auth privsep slave we count
1957 * from the completion of the authentication.
1958 */
1959 active_state->rekey_time = time(NULL);
1960}
1961
1962time_t
1963packet_get_rekey_timeout(void)
1964{
1965 time_t seconds;
1966
1967 seconds = active_state->rekey_time + active_state->rekey_interval -
1968 time(NULL);
1969 return (seconds < 0 ? 0 : seconds);
1943} 1970}
1944 1971
1945void 1972void
diff --git a/packet.h b/packet.h
index 09ba07951..bc548f2b1 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.h,v 1.57 2012/01/25 19:40:09 markus Exp $ */ 1/* $OpenBSD: packet.h,v 1.58 2013/05/16 02:00:34 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -115,7 +115,8 @@ do { \
115} while (0) 115} while (0)
116 116
117int packet_need_rekeying(void); 117int packet_need_rekeying(void);
118void packet_set_rekey_limit(u_int32_t); 118void packet_set_rekey_limits(u_int32_t, time_t);
119time_t packet_get_rekey_timeout(void);
119 120
120void packet_backup_state(void); 121void packet_backup_state(void);
121void packet_restore_state(void); 122void packet_restore_state(void);
diff --git a/readconf.c b/readconf.c
index 6e708e02e..d8898a029 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.c,v 1.197 2013/03/06 23:36:53 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.198 2013/05/16 02:00:34 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -562,39 +562,54 @@ parse_yesnoask:
562 case oRekeyLimit: 562 case oRekeyLimit:
563 arg = strdelim(&s); 563 arg = strdelim(&s);
564 if (!arg || *arg == '\0') 564 if (!arg || *arg == '\0')
565 fatal("%.200s line %d: Missing argument.", filename, linenum); 565 fatal("%.200s line %d: Missing argument.", filename,
566 if (arg[0] < '0' || arg[0] > '9') 566 linenum);
567 fatal("%.200s line %d: Bad number.", filename, linenum); 567 if (strcmp(arg, "default") == 0) {
568 orig = val64 = strtoll(arg, &endofnumber, 10); 568 val64 = 0;
569 if (arg == endofnumber) 569 } else {
570 fatal("%.200s line %d: Bad number.", filename, linenum); 570 if (arg[0] < '0' || arg[0] > '9')
571 switch (toupper(*endofnumber)) { 571 fatal("%.200s line %d: Bad number.", filename,
572 case '\0': 572 linenum);
573 scale = 1; 573 orig = val64 = strtoll(arg, &endofnumber, 10);
574 break; 574 if (arg == endofnumber)
575 case 'K': 575 fatal("%.200s line %d: Bad number.", filename,
576 scale = 1<<10; 576 linenum);
577 break; 577 switch (toupper(*endofnumber)) {
578 case 'M': 578 case '\0':
579 scale = 1<<20; 579 scale = 1;
580 break; 580 break;
581 case 'G': 581 case 'K':
582 scale = 1<<30; 582 scale = 1<<10;
583 break; 583 break;
584 default: 584 case 'M':
585 fatal("%.200s line %d: Invalid RekeyLimit suffix", 585 scale = 1<<20;
586 filename, linenum); 586 break;
587 case 'G':
588 scale = 1<<30;
589 break;
590 default:
591 fatal("%.200s line %d: Invalid RekeyLimit "
592 "suffix", filename, linenum);
593 }
594 val64 *= scale;
595 /* detect integer wrap and too-large limits */
596 if ((val64 / scale) != orig || val64 > UINT_MAX)
597 fatal("%.200s line %d: RekeyLimit too large",
598 filename, linenum);
599 if (val64 != 0 && val64 < 16)
600 fatal("%.200s line %d: RekeyLimit too small",
601 filename, linenum);
587 } 602 }
588 val64 *= scale;
589 /* detect integer wrap and too-large limits */
590 if ((val64 / scale) != orig || val64 > UINT_MAX)
591 fatal("%.200s line %d: RekeyLimit too large",
592 filename, linenum);
593 if (val64 < 16)
594 fatal("%.200s line %d: RekeyLimit too small",
595 filename, linenum);
596 if (*activep && options->rekey_limit == -1) 603 if (*activep && options->rekey_limit == -1)
597 options->rekey_limit = (u_int32_t)val64; 604 options->rekey_limit = (u_int32_t)val64;
605 if (s != NULL) { /* optional rekey interval present */
606 if (strcmp(s, "none") == 0) {
607 (void)strdelim(&s); /* discard */
608 break;
609 }
610 intptr = &options->rekey_interval;
611 goto parse_time;
612 }
598 break; 613 break;
599 614
600 case oIdentityFile: 615 case oIdentityFile:
@@ -1202,6 +1217,7 @@ initialize_options(Options * options)
1202 options->no_host_authentication_for_localhost = - 1; 1217 options->no_host_authentication_for_localhost = - 1;
1203 options->identities_only = - 1; 1218 options->identities_only = - 1;
1204 options->rekey_limit = - 1; 1219 options->rekey_limit = - 1;
1220 options->rekey_interval = -1;
1205 options->verify_host_key_dns = -1; 1221 options->verify_host_key_dns = -1;
1206 options->server_alive_interval = -1; 1222 options->server_alive_interval = -1;
1207 options->server_alive_count_max = -1; 1223 options->server_alive_count_max = -1;
@@ -1337,6 +1353,8 @@ fill_default_options(Options * options)
1337 options->enable_ssh_keysign = 0; 1353 options->enable_ssh_keysign = 0;
1338 if (options->rekey_limit == -1) 1354 if (options->rekey_limit == -1)
1339 options->rekey_limit = 0; 1355 options->rekey_limit = 0;
1356 if (options->rekey_interval == -1)
1357 options->rekey_interval = 0;
1340 if (options->verify_host_key_dns == -1) 1358 if (options->verify_host_key_dns == -1)
1341 options->verify_host_key_dns = 0; 1359 options->verify_host_key_dns = 0;
1342 if (options->server_alive_interval == -1) 1360 if (options->server_alive_interval == -1)
diff --git a/readconf.h b/readconf.h
index 841648906..e20573090 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.93 2013/02/22 04:45:09 dtucker Exp $ */ 1/* $OpenBSD: readconf.h,v 1.94 2013/05/16 02:00:34 dtucker Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -110,6 +110,7 @@ typedef struct {
110 110
111 int enable_ssh_keysign; 111 int enable_ssh_keysign;
112 int64_t rekey_limit; 112 int64_t rekey_limit;
113 int rekey_interval;
113 int no_host_authentication_for_localhost; 114 int no_host_authentication_for_localhost;
114 int identities_only; 115 int identities_only;
115 int server_alive_interval; 116 int server_alive_interval;
diff --git a/ssh_config b/ssh_config
index 18936740f..bb4081936 100644
--- a/ssh_config
+++ b/ssh_config
@@ -1,4 +1,4 @@
1# $OpenBSD: ssh_config,v 1.26 2010/01/11 01:39:46 dtucker Exp $ 1# $OpenBSD: ssh_config,v 1.27 2013/05/16 02:00:34 dtucker Exp $
2 2
3# This is the ssh client system-wide configuration file. See 3# This is the ssh client system-wide configuration file. See
4# ssh_config(5) for more information. This file provides defaults for 4# ssh_config(5) for more information. This file provides defaults for
@@ -45,3 +45,4 @@
45# PermitLocalCommand no 45# PermitLocalCommand no
46# VisualHostKey no 46# VisualHostKey no
47# ProxyCommand ssh -q -W %h:%p gateway.example.com 47# ProxyCommand ssh -q -W %h:%p gateway.example.com
48# RekeyLimit 1G 1h
diff --git a/ssh_config.5 b/ssh_config.5
index 269529c00..97897e00e 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.161 2013/01/08 18:49:04 markus Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.162 2013/05/16 02:00:34 dtucker Exp $
37.Dd $Mdocdate: January 8 2013 $ 37.Dd $Mdocdate: May 16 2013 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -931,8 +931,9 @@ The default is
931This option applies to protocol version 2 only. 931This option applies to protocol version 2 only.
932.It Cm RekeyLimit 932.It Cm RekeyLimit
933Specifies the maximum amount of data that may be transmitted before the 933Specifies the maximum amount of data that may be transmitted before the
934session key is renegotiated. 934session key is renegotiated, optionally followed a maximum amount of
935The argument is the number of bytes, with an optional suffix of 935time that may pass before the session key is renegotiated.
936The first argument is specified in bytes and may have a suffix of
936.Sq K , 937.Sq K ,
937.Sq M , 938.Sq M ,
938or 939or
@@ -943,6 +944,17 @@ The default is between
943and 944and
944.Sq 4G , 945.Sq 4G ,
945depending on the cipher. 946depending on the cipher.
947The optional second value is specified in seconds and may use any of the
948units documented in the
949.Sx TIME FORMATS
950section of
951.Xr sshd_config 5 .
952The default value for
953.Cm RekeyLimit
954is
955.Dq default none ,
956which means that rekeying is performed after the cipher's default amount
957of data has been sent or received and no time based rekeying is done.
946This option applies to protocol version 2 only. 958This option applies to protocol version 2 only.
947.It Cm RemoteForward 959.It Cm RemoteForward
948Specifies that a TCP port on the remote machine be forwarded over 960Specifies that a TCP port on the remote machine be forwarded over
diff --git a/sshconnect2.c b/sshconnect2.c
index c01efe38c..7b83c591b 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.195 2013/05/10 03:40:07 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.196 2013/05/16 02:00:34 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -197,8 +197,9 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
197 if (options.kex_algorithms != NULL) 197 if (options.kex_algorithms != NULL)
198 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 198 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
199 199
200 if (options.rekey_limit) 200 if (options.rekey_limit || options.rekey_interval)
201 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 201 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
202 (time_t)options.rekey_interval);
202 203
203 /* start key exchange */ 204 /* start key exchange */
204 kex = kex_setup(myproposal); 205 kex = kex_setup(myproposal);