diff options
Diffstat (limited to 'usr.bin/ssh/serverloop.c')
-rw-r--r-- | usr.bin/ssh/serverloop.c | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index d1a24252d9e..8bd2c000a06 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/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(); } + |