summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-04-13 23:28:01 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-04-13 23:28:01 +0000
commit5744dc421d035c701b6660a58bed0d038c211375 (patch)
treea7c8df98b56a37c9be2fb3e33893e90424a85379 /serverloop.c
parent402b3319456c1f0da0822319c3813c68e155726d (diff)
- beck@cvs.openbsd.org 2001/04/13 22:46:54
[channels.c channels.h servconf.c servconf.h serverloop.c sshd.8] Add options ClientAliveInterval and ClientAliveCountMax to sshd. This gives the ability to do a "keepalive" via the encrypted channel which can't be spoofed (unlike TCP keepalives). Useful for when you want to use ssh connections to authenticate people for something, and know relatively quickly when they are no longer authenticated. Disabled by default (of course). ok markus@
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/serverloop.c b/serverloop.c
index d6b360d9..5a5b1e37 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: serverloop.c,v 1.60 2001/04/05 23:39:20 markus Exp $");
+RCSID("$OpenBSD: serverloop.c,v 1.61 2001/04/13 22:46:54 beck Exp $");
#include "xmalloc.h"
#include "packet.h"
@@ -91,6 +91,8 @@ static volatile int child_wait_status; /* Status from wait(). */
void server_init_dispatch(void);
+int client_alive_timeouts = 0;
+
void
sigchld_handler(int sig)
{
@@ -190,6 +192,21 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
{
struct timeval tv, *tvp;
int ret;
+ int client_alive_scheduled = 0;
+
+ /*
+ * if using client_alive, set the max timeout accordingly,
+ * and indicate that this particular timeout was for client
+ * alive by setting the client_alive_scheduled flag.
+ *
+ * this could be randomized somewhat to make traffic
+ * analysis more difficult, but we're not doing it yet.
+ */
+ if (max_time_milliseconds == 0 && options.client_alive_interval) {
+ client_alive_scheduled = 1;
+ max_time_milliseconds = options.client_alive_interval * 1000;
+ } else
+ client_alive_scheduled = 0;
/* When select fails we restart from here. */
retry_select:
@@ -239,7 +256,7 @@ retry_select:
* from it, then read as much as is available and exit.
*/
if (child_terminated && packet_not_very_much_data_to_write())
- if (max_time_milliseconds == 0)
+ if (max_time_milliseconds == 0 || client_alive_scheduled)
max_time_milliseconds = 100;
if (max_time_milliseconds == 0)
@@ -255,12 +272,36 @@ retry_select:
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
- if (ret < 0) {
+ if (ret == -1) {
if (errno != EINTR)
error("select: %.100s", strerror(errno));
else
goto retry_select;
}
+ if (ret == 0 && client_alive_scheduled) {
+ /* timeout, check to see how many we have had */
+ client_alive_timeouts++;
+
+ if (client_alive_timeouts > options.client_alive_count_max ) {
+ packet_disconnect(
+ "Timeout, your session not responding.");
+ } else {
+ /*
+ * send a bogus channel request with "wantreply"
+ * we should get back a failure
+ */
+ int id;
+
+ id = channel_find_open();
+ if (id != -1) {
+ channel_request_start(id,
+ "keepalive@openssh.com", 1);
+ packet_send();
+ } else
+ packet_disconnect(
+ "No open channels after timeout!");
+ }
+ }
}
/*
@@ -701,6 +742,19 @@ server_loop2(void)
}
void
+server_input_channel_failure(int type, int plen, void *ctxt)
+{
+ debug("Got CHANNEL_FAILURE for keepalive");
+ /*
+ * reset timeout, since we got a sane answer from the client.
+ * even if this was generated by something other than
+ * the bogus CHANNEL_REQUEST we send for keepalives.
+ */
+ client_alive_timeouts = 0;
+}
+
+
+void
server_input_stdin_data(int type, int plen, void *ctxt)
{
char *data;
@@ -912,7 +966,8 @@ server_init_dispatch_20(void)
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
-
+ /* client_alive */
+ dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure);
/* rekeying */
dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
}
@@ -949,3 +1004,4 @@ server_init_dispatch(void)
else
server_init_dispatch_15();
}
+