diff options
author | Ben Lindstrom <mouring@eviladmin.org> | 2001-04-13 23:28:01 +0000 |
---|---|---|
committer | Ben Lindstrom <mouring@eviladmin.org> | 2001-04-13 23:28:01 +0000 |
commit | 5744dc421d035c701b6660a58bed0d038c211375 (patch) | |
tree | a7c8df98b56a37c9be2fb3e33893e90424a85379 /serverloop.c | |
parent | 402b3319456c1f0da0822319c3813c68e155726d (diff) | |
download | openssh-git-5744dc421d035c701b6660a58bed0d038c211375.tar.gz |
- 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.c | 64 |
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(); } + |