summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c84
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"
38RCSID("$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
59extern ServerOptions options; 81extern 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*/
145static void 168static void
146sigchld_handler(int sig) 169sigchld_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*/
158static void 181static void
159sigterm_handler(int sig) 182sigterm_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 */
350static void 385static void
351process_input(fd_set * readset) 386process_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 */
409static void 458static void
410process_output(fd_set * writeset) 459process_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)
873static void 923static void
874server_input_window_size(int type, u_int32_t seq, void *ctxt) 924server_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
1097static void 1149static void
1098server_input_channel_req(int type, u_int32_t seq, void *ctxt) 1150server_input_channel_req(int type, u_int32_t seq, void *ctxt)
1099{ 1151{