diff options
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 84 |
1 files changed, 68 insertions, 16 deletions
diff --git a/serverloop.c b/serverloop.c index f72b73bf8..29ffcfee1 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -1,3 +1,4 @@ | |||
1 | /* $OpenBSD: serverloop.c,v 1.145 2006/10/11 12:38:03 markus Exp $ */ | ||
1 | /* | 2 | /* |
2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +36,25 @@ | |||
35 | */ | 36 | */ |
36 | 37 | ||
37 | #include "includes.h" | 38 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.124 2005/12/13 15:03:02 reyk Exp $"); | 39 | |
40 | #include <sys/types.h> | ||
41 | #include <sys/param.h> | ||
42 | #include <sys/wait.h> | ||
43 | #include <sys/socket.h> | ||
44 | #ifdef HAVE_SYS_TIME_H | ||
45 | # include <sys/time.h> | ||
46 | #endif | ||
47 | |||
48 | #include <netinet/in.h> | ||
49 | |||
50 | #include <errno.h> | ||
51 | #include <fcntl.h> | ||
52 | #include <pwd.h> | ||
53 | #include <signal.h> | ||
54 | #include <string.h> | ||
55 | #include <termios.h> | ||
56 | #include <unistd.h> | ||
57 | #include <stdarg.h> | ||
39 | 58 | ||
40 | #include "xmalloc.h" | 59 | #include "xmalloc.h" |
41 | #include "packet.h" | 60 | #include "packet.h" |
@@ -48,13 +67,16 @@ RCSID("$OpenBSD: serverloop.c,v 1.124 2005/12/13 15:03:02 reyk Exp $"); | |||
48 | #include "compat.h" | 67 | #include "compat.h" |
49 | #include "ssh1.h" | 68 | #include "ssh1.h" |
50 | #include "ssh2.h" | 69 | #include "ssh2.h" |
70 | #include "key.h" | ||
71 | #include "cipher.h" | ||
72 | #include "kex.h" | ||
73 | #include "hostfile.h" | ||
51 | #include "auth.h" | 74 | #include "auth.h" |
52 | #include "session.h" | 75 | #include "session.h" |
53 | #include "dispatch.h" | 76 | #include "dispatch.h" |
54 | #include "auth-options.h" | 77 | #include "auth-options.h" |
55 | #include "serverloop.h" | 78 | #include "serverloop.h" |
56 | #include "misc.h" | 79 | #include "misc.h" |
57 | #include "kex.h" | ||
58 | 80 | ||
59 | extern ServerOptions options; | 81 | extern ServerOptions options; |
60 | 82 | ||
@@ -142,11 +164,11 @@ notify_done(fd_set *readset) | |||
142 | debug2("notify_done: reading"); | 164 | debug2("notify_done: reading"); |
143 | } | 165 | } |
144 | 166 | ||
167 | /*ARGSUSED*/ | ||
145 | static void | 168 | static void |
146 | sigchld_handler(int sig) | 169 | sigchld_handler(int sig) |
147 | { | 170 | { |
148 | int save_errno = errno; | 171 | int save_errno = errno; |
149 | debug("Received SIGCHLD."); | ||
150 | child_terminated = 1; | 172 | child_terminated = 1; |
151 | #ifndef _UNICOS | 173 | #ifndef _UNICOS |
152 | mysignal(SIGCHLD, sigchld_handler); | 174 | mysignal(SIGCHLD, sigchld_handler); |
@@ -155,6 +177,7 @@ sigchld_handler(int sig) | |||
155 | errno = save_errno; | 177 | errno = save_errno; |
156 | } | 178 | } |
157 | 179 | ||
180 | /*ARGSUSED*/ | ||
158 | static void | 181 | static void |
159 | sigterm_handler(int sig) | 182 | sigterm_handler(int sig) |
160 | { | 183 | { |
@@ -225,8 +248,10 @@ client_alive_check(void) | |||
225 | int channel_id; | 248 | int channel_id; |
226 | 249 | ||
227 | /* timeout, check to see how many we have had */ | 250 | /* timeout, check to see how many we have had */ |
228 | if (++client_alive_timeouts > options.client_alive_count_max) | 251 | if (++client_alive_timeouts > options.client_alive_count_max) { |
229 | packet_disconnect("Timeout, your session not responding."); | 252 | logit("Timeout, client not responding."); |
253 | cleanup_exit(255); | ||
254 | } | ||
230 | 255 | ||
231 | /* | 256 | /* |
232 | * send a bogus global/channel request with "wantreply", | 257 | * send a bogus global/channel request with "wantreply", |
@@ -255,6 +280,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
255 | struct timeval tv, *tvp; | 280 | struct timeval tv, *tvp; |
256 | int ret; | 281 | int ret; |
257 | int client_alive_scheduled = 0; | 282 | int client_alive_scheduled = 0; |
283 | int program_alive_scheduled = 0; | ||
258 | 284 | ||
259 | /* | 285 | /* |
260 | * if using client_alive, set the max timeout accordingly, | 286 | * if using client_alive, set the max timeout accordingly, |
@@ -292,6 +318,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
292 | * the client, try to get some more data from the program. | 318 | * the client, try to get some more data from the program. |
293 | */ | 319 | */ |
294 | if (packet_not_very_much_data_to_write()) { | 320 | if (packet_not_very_much_data_to_write()) { |
321 | program_alive_scheduled = child_terminated; | ||
295 | if (!fdout_eof) | 322 | if (!fdout_eof) |
296 | FD_SET(fdout, *readsetp); | 323 | FD_SET(fdout, *readsetp); |
297 | if (!fderr_eof) | 324 | if (!fderr_eof) |
@@ -337,8 +364,16 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
337 | memset(*writesetp, 0, *nallocp); | 364 | memset(*writesetp, 0, *nallocp); |
338 | if (errno != EINTR) | 365 | if (errno != EINTR) |
339 | error("select: %.100s", strerror(errno)); | 366 | error("select: %.100s", strerror(errno)); |
340 | } else if (ret == 0 && client_alive_scheduled) | 367 | } else { |
341 | client_alive_check(); | 368 | if (ret == 0 && client_alive_scheduled) |
369 | client_alive_check(); | ||
370 | if (!compat20 && program_alive_scheduled && fdin_is_tty) { | ||
371 | if (!fdout_eof) | ||
372 | FD_SET(fdout, *readsetp); | ||
373 | if (!fderr_eof) | ||
374 | FD_SET(fderr, *readsetp); | ||
375 | } | ||
376 | } | ||
342 | 377 | ||
343 | notify_done(*readsetp); | 378 | notify_done(*readsetp); |
344 | } | 379 | } |
@@ -348,7 +383,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, | |||
348 | * in buffers and processed later. | 383 | * in buffers and processed later. |
349 | */ | 384 | */ |
350 | static void | 385 | static void |
351 | process_input(fd_set * readset) | 386 | process_input(fd_set *readset) |
352 | { | 387 | { |
353 | int len; | 388 | int len; |
354 | char buf[16384]; | 389 | char buf[16384]; |
@@ -380,10 +415,17 @@ process_input(fd_set * readset) | |||
380 | 415 | ||
381 | /* Read and buffer any available stdout data from the program. */ | 416 | /* Read and buffer any available stdout data from the program. */ |
382 | if (!fdout_eof && FD_ISSET(fdout, readset)) { | 417 | if (!fdout_eof && FD_ISSET(fdout, readset)) { |
418 | errno = 0; | ||
383 | len = read(fdout, buf, sizeof(buf)); | 419 | len = read(fdout, buf, sizeof(buf)); |
384 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) { | 420 | if (len < 0 && (errno == EINTR || |
421 | (errno == EAGAIN && !child_terminated))) { | ||
385 | /* do nothing */ | 422 | /* do nothing */ |
423 | #ifndef PTY_ZEROREAD | ||
386 | } else if (len <= 0) { | 424 | } else if (len <= 0) { |
425 | #else | ||
426 | } else if ((!isatty(fdout) && len <= 0) || | ||
427 | (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) { | ||
428 | #endif | ||
387 | fdout_eof = 1; | 429 | fdout_eof = 1; |
388 | } else { | 430 | } else { |
389 | buffer_append(&stdout_buffer, buf, len); | 431 | buffer_append(&stdout_buffer, buf, len); |
@@ -392,10 +434,17 @@ process_input(fd_set * readset) | |||
392 | } | 434 | } |
393 | /* Read and buffer any available stderr data from the program. */ | 435 | /* Read and buffer any available stderr data from the program. */ |
394 | if (!fderr_eof && FD_ISSET(fderr, readset)) { | 436 | if (!fderr_eof && FD_ISSET(fderr, readset)) { |
437 | errno = 0; | ||
395 | len = read(fderr, buf, sizeof(buf)); | 438 | len = read(fderr, buf, sizeof(buf)); |
396 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) { | 439 | if (len < 0 && (errno == EINTR || |
440 | (errno == EAGAIN && !child_terminated))) { | ||
397 | /* do nothing */ | 441 | /* do nothing */ |
442 | #ifndef PTY_ZEROREAD | ||
398 | } else if (len <= 0) { | 443 | } else if (len <= 0) { |
444 | #else | ||
445 | } else if ((!isatty(fderr) && len <= 0) || | ||
446 | (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) { | ||
447 | #endif | ||
399 | fderr_eof = 1; | 448 | fderr_eof = 1; |
400 | } else { | 449 | } else { |
401 | buffer_append(&stderr_buffer, buf, len); | 450 | buffer_append(&stderr_buffer, buf, len); |
@@ -407,7 +456,7 @@ process_input(fd_set * readset) | |||
407 | * Sends data from internal buffers to client program stdin. | 456 | * Sends data from internal buffers to client program stdin. |
408 | */ | 457 | */ |
409 | static void | 458 | static void |
410 | process_output(fd_set * writeset) | 459 | process_output(fd_set *writeset) |
411 | { | 460 | { |
412 | struct termios tio; | 461 | struct termios tio; |
413 | u_char *data; | 462 | u_char *data; |
@@ -749,6 +798,7 @@ collect_children(void) | |||
749 | sigaddset(&nset, SIGCHLD); | 798 | sigaddset(&nset, SIGCHLD); |
750 | sigprocmask(SIG_BLOCK, &nset, &oset); | 799 | sigprocmask(SIG_BLOCK, &nset, &oset); |
751 | if (child_terminated) { | 800 | if (child_terminated) { |
801 | debug("Received SIGCHLD."); | ||
752 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || | 802 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || |
753 | (pid < 0 && errno == EINTR)) | 803 | (pid < 0 && errno == EINTR)) |
754 | if (pid > 0) | 804 | if (pid > 0) |
@@ -873,10 +923,10 @@ server_input_eof(int type, u_int32_t seq, void *ctxt) | |||
873 | static void | 923 | static void |
874 | server_input_window_size(int type, u_int32_t seq, void *ctxt) | 924 | server_input_window_size(int type, u_int32_t seq, void *ctxt) |
875 | { | 925 | { |
876 | int row = packet_get_int(); | 926 | u_int row = packet_get_int(); |
877 | int col = packet_get_int(); | 927 | u_int col = packet_get_int(); |
878 | int xpixel = packet_get_int(); | 928 | u_int xpixel = packet_get_int(); |
879 | int ypixel = packet_get_int(); | 929 | u_int ypixel = packet_get_int(); |
880 | 930 | ||
881 | debug("Window change received."); | 931 | debug("Window change received."); |
882 | packet_check_eom(); | 932 | packet_check_eom(); |
@@ -937,7 +987,7 @@ server_request_tun(void) | |||
937 | 987 | ||
938 | tun = packet_get_int(); | 988 | tun = packet_get_int(); |
939 | if (forced_tun_device != -1) { | 989 | if (forced_tun_device != -1) { |
940 | if (tun != SSH_TUNID_ANY && forced_tun_device != tun) | 990 | if (tun != SSH_TUNID_ANY && forced_tun_device != tun) |
941 | goto done; | 991 | goto done; |
942 | tun = forced_tun_device; | 992 | tun = forced_tun_device; |
943 | } | 993 | } |
@@ -1085,6 +1135,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) | |||
1085 | 1135 | ||
1086 | success = channel_cancel_rport_listener(cancel_address, | 1136 | success = channel_cancel_rport_listener(cancel_address, |
1087 | cancel_port); | 1137 | cancel_port); |
1138 | xfree(cancel_address); | ||
1088 | } | 1139 | } |
1089 | if (want_reply) { | 1140 | if (want_reply) { |
1090 | packet_start(success ? | 1141 | packet_start(success ? |
@@ -1094,6 +1145,7 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt) | |||
1094 | } | 1145 | } |
1095 | xfree(rtype); | 1146 | xfree(rtype); |
1096 | } | 1147 | } |
1148 | |||
1097 | static void | 1149 | static void |
1098 | server_input_channel_req(int type, u_int32_t seq, void *ctxt) | 1150 | server_input_channel_req(int type, u_int32_t seq, void *ctxt) |
1099 | { | 1151 | { |