serverloop.c revision 57429
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Created: Sun Sep 10 00:30:37 1995 ylo
6 * Server main loop for handling the interactive session.
7 */
8
9#include "includes.h"
10#include "xmalloc.h"
11#include "ssh.h"
12#include "packet.h"
13#include "buffer.h"
14#include "servconf.h"
15#include "pty.h"
16
17static Buffer stdin_buffer;	/* Buffer for stdin data. */
18static Buffer stdout_buffer;	/* Buffer for stdout data. */
19static Buffer stderr_buffer;	/* Buffer for stderr data. */
20static int fdin;		/* Descriptor for stdin (for writing) */
21static int fdout;		/* Descriptor for stdout (for reading);
22				   May be same number as fdin. */
23static int fderr;		/* Descriptor for stderr.  May be -1. */
24static long stdin_bytes = 0;	/* Number of bytes written to stdin. */
25static long stdout_bytes = 0;	/* Number of stdout bytes sent to client. */
26static long stderr_bytes = 0;	/* Number of stderr bytes sent to client. */
27static long fdout_bytes = 0;	/* Number of stdout bytes read from program. */
28static int stdin_eof = 0;	/* EOF message received from client. */
29static int fdout_eof = 0;	/* EOF encountered reading from fdout. */
30static int fderr_eof = 0;	/* EOF encountered readung from fderr. */
31static int connection_in;	/* Connection to client (input). */
32static int connection_out;	/* Connection to client (output). */
33static unsigned int buffer_high;/* "Soft" max buffer size. */
34static int max_fd;		/* Max file descriptor number for select(). */
35
36/*
37 * This SIGCHLD kludge is used to detect when the child exits.  The server
38 * will exit after that, as soon as forwarded connections have terminated.
39 */
40
41static int child_pid;			/* Pid of the child. */
42static volatile int child_terminated;	/* The child has terminated. */
43static volatile int child_wait_status;	/* Status from wait(). */
44
45void
46sigchld_handler(int sig)
47{
48	int save_errno = errno;
49	int wait_pid;
50	debug("Received SIGCHLD.");
51	wait_pid = wait((int *) &child_wait_status);
52	if (wait_pid != -1) {
53		if (wait_pid != child_pid)
54			error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
55			      wait_pid, child_pid);
56		if (WIFEXITED(child_wait_status) ||
57		    WIFSIGNALED(child_wait_status))
58			child_terminated = 1;
59	}
60	signal(SIGCHLD, sigchld_handler);
61	errno = save_errno;
62}
63
64/*
65 * Process any buffered packets that have been received from the client.
66 */
67void
68process_buffered_input_packets()
69{
70	int type;
71	char *data;
72	unsigned int data_len;
73	int row, col, xpixel, ypixel;
74	int payload_len;
75
76	/* Process buffered packets from the client. */
77	while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
78		switch (type) {
79		case SSH_CMSG_STDIN_DATA:
80			/* Stdin data from the client.  Append it to the buffer. */
81			/* Ignore any data if the client has closed stdin. */
82			if (fdin == -1)
83				break;
84			data = packet_get_string(&data_len);
85			packet_integrity_check(payload_len, (4 + data_len), type);
86			buffer_append(&stdin_buffer, data, data_len);
87			memset(data, 0, data_len);
88			xfree(data);
89			break;
90
91		case SSH_CMSG_EOF:
92			/*
93			 * Eof from the client.  The stdin descriptor to the
94			 * program will be closed when all buffered data has
95			 * drained.
96			 */
97			debug("EOF received for stdin.");
98			packet_integrity_check(payload_len, 0, type);
99			stdin_eof = 1;
100			break;
101
102		case SSH_CMSG_WINDOW_SIZE:
103			debug("Window change received.");
104			packet_integrity_check(payload_len, 4 * 4, type);
105			row = packet_get_int();
106			col = packet_get_int();
107			xpixel = packet_get_int();
108			ypixel = packet_get_int();
109			if (fdin != -1)
110				pty_change_window_size(fdin, row, col, xpixel, ypixel);
111			break;
112
113		case SSH_MSG_PORT_OPEN:
114			debug("Received port open request.");
115			channel_input_port_open(payload_len);
116			break;
117
118		case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
119			debug("Received channel open confirmation.");
120			packet_integrity_check(payload_len, 4 + 4, type);
121			channel_input_open_confirmation();
122			break;
123
124		case SSH_MSG_CHANNEL_OPEN_FAILURE:
125			debug("Received channel open failure.");
126			packet_integrity_check(payload_len, 4, type);
127			channel_input_open_failure();
128			break;
129
130		case SSH_MSG_CHANNEL_DATA:
131			channel_input_data(payload_len);
132			break;
133
134		case SSH_MSG_CHANNEL_CLOSE:
135			debug("Received channel close.");
136			packet_integrity_check(payload_len, 4, type);
137			channel_input_close();
138			break;
139
140		case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
141			debug("Received channel close confirmation.");
142			packet_integrity_check(payload_len, 4, type);
143			channel_input_close_confirmation();
144			break;
145
146		default:
147			/*
148			 * In this phase, any unexpected messages cause a
149			 * protocol error.  This is to ease debugging; also,
150			 * since no confirmations are sent messages,
151			 * unprocessed unknown messages could cause strange
152			 * problems.  Any compatible protocol extensions must
153			 * be negotiated before entering the interactive
154			 * session.
155			 */
156			packet_disconnect("Protocol error during session: type %d",
157					  type);
158		}
159	}
160}
161
162/*
163 * Make packets from buffered stderr data, and buffer it for sending
164 * to the client.
165 */
166void
167make_packets_from_stderr_data()
168{
169	int len;
170
171	/* Send buffered stderr data to the client. */
172	while (buffer_len(&stderr_buffer) > 0 &&
173	    packet_not_very_much_data_to_write()) {
174		len = buffer_len(&stderr_buffer);
175		if (packet_is_interactive()) {
176			if (len > 512)
177				len = 512;
178		} else {
179			/* Keep the packets at reasonable size. */
180			if (len > packet_get_maxsize())
181				len = packet_get_maxsize();
182		}
183		packet_start(SSH_SMSG_STDERR_DATA);
184		packet_put_string(buffer_ptr(&stderr_buffer), len);
185		packet_send();
186		buffer_consume(&stderr_buffer, len);
187		stderr_bytes += len;
188	}
189}
190
191/*
192 * Make packets from buffered stdout data, and buffer it for sending to the
193 * client.
194 */
195void
196make_packets_from_stdout_data()
197{
198	int len;
199
200	/* Send buffered stdout data to the client. */
201	while (buffer_len(&stdout_buffer) > 0 &&
202	    packet_not_very_much_data_to_write()) {
203		len = buffer_len(&stdout_buffer);
204		if (packet_is_interactive()) {
205			if (len > 512)
206				len = 512;
207		} else {
208			/* Keep the packets at reasonable size. */
209			if (len > packet_get_maxsize())
210				len = packet_get_maxsize();
211		}
212		packet_start(SSH_SMSG_STDOUT_DATA);
213		packet_put_string(buffer_ptr(&stdout_buffer), len);
214		packet_send();
215		buffer_consume(&stdout_buffer, len);
216		stdout_bytes += len;
217	}
218}
219
220/*
221 * Sleep in select() until we can do something.  This will initialize the
222 * select masks.  Upon return, the masks will indicate which descriptors
223 * have data or can accept data.  Optionally, a maximum time can be specified
224 * for the duration of the wait (0 = infinite).
225 */
226void
227wait_until_can_do_something(fd_set * readset, fd_set * writeset,
228			    unsigned int max_time_milliseconds)
229{
230	struct timeval tv, *tvp;
231	int ret;
232
233	/* When select fails we restart from here. */
234retry_select:
235
236	/* Initialize select() masks. */
237	FD_ZERO(readset);
238
239	/*
240	 * Read packets from the client unless we have too much buffered
241	 * stdin or channel data.
242	 */
243	if (buffer_len(&stdin_buffer) < 4096 &&
244	    channel_not_very_much_buffered_data())
245		FD_SET(connection_in, readset);
246
247	/*
248	 * If there is not too much data already buffered going to the
249	 * client, try to get some more data from the program.
250	 */
251	if (packet_not_very_much_data_to_write()) {
252		if (!fdout_eof)
253			FD_SET(fdout, readset);
254		if (!fderr_eof)
255			FD_SET(fderr, readset);
256	}
257	FD_ZERO(writeset);
258
259	/* Set masks for channel descriptors. */
260	channel_prepare_select(readset, writeset);
261
262	/*
263	 * If we have buffered packet data going to the client, mark that
264	 * descriptor.
265	 */
266	if (packet_have_data_to_write())
267		FD_SET(connection_out, writeset);
268
269	/* If we have buffered data, try to write some of that data to the
270	   program. */
271	if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
272		FD_SET(fdin, writeset);
273
274	/* Update the maximum descriptor number if appropriate. */
275	if (channel_max_fd() > max_fd)
276		max_fd = channel_max_fd();
277
278	/*
279	 * If child has terminated and there is enough buffer space to read
280	 * from it, then read as much as is available and exit.
281	 */
282	if (child_terminated && packet_not_very_much_data_to_write())
283		if (max_time_milliseconds == 0)
284			max_time_milliseconds = 100;
285
286	if (max_time_milliseconds == 0)
287		tvp = NULL;
288	else {
289		tv.tv_sec = max_time_milliseconds / 1000;
290		tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
291		tvp = &tv;
292	}
293
294	/* Wait for something to happen, or the timeout to expire. */
295	ret = select(max_fd + 1, readset, writeset, NULL, tvp);
296
297	if (ret < 0) {
298		if (errno != EINTR)
299			error("select: %.100s", strerror(errno));
300		else
301			goto retry_select;
302	}
303}
304
305/*
306 * Processes input from the client and the program.  Input data is stored
307 * in buffers and processed later.
308 */
309void
310process_input(fd_set * readset)
311{
312	int len;
313	char buf[16384];
314
315	/* Read and buffer any input data from the client. */
316	if (FD_ISSET(connection_in, readset)) {
317		len = read(connection_in, buf, sizeof(buf));
318		if (len == 0) {
319			verbose("Connection closed by remote host.");
320			fatal_cleanup();
321		}
322		/*
323		 * There is a kernel bug on Solaris that causes select to
324		 * sometimes wake up even though there is no data available.
325		 */
326		if (len < 0 && errno == EAGAIN)
327			len = 0;
328
329		if (len < 0) {
330			verbose("Read error from remote host: %.100s", strerror(errno));
331			fatal_cleanup();
332		}
333		/* Buffer any received data. */
334		packet_process_incoming(buf, len);
335	}
336	/* Read and buffer any available stdout data from the program. */
337	if (!fdout_eof && FD_ISSET(fdout, readset)) {
338		len = read(fdout, buf, sizeof(buf));
339		if (len <= 0)
340			fdout_eof = 1;
341		else {
342			buffer_append(&stdout_buffer, buf, len);
343			fdout_bytes += len;
344		}
345	}
346	/* Read and buffer any available stderr data from the program. */
347	if (!fderr_eof && FD_ISSET(fderr, readset)) {
348		len = read(fderr, buf, sizeof(buf));
349		if (len <= 0)
350			fderr_eof = 1;
351		else
352			buffer_append(&stderr_buffer, buf, len);
353	}
354}
355
356/*
357 * Sends data from internal buffers to client program stdin.
358 */
359void
360process_output(fd_set * writeset)
361{
362	int len;
363
364	/* Write buffered data to program stdin. */
365	if (fdin != -1 && FD_ISSET(fdin, writeset)) {
366		len = write(fdin, buffer_ptr(&stdin_buffer),
367		    buffer_len(&stdin_buffer));
368		if (len <= 0) {
369#ifdef USE_PIPES
370			close(fdin);
371#else
372			if (fdout == -1)
373				close(fdin);
374			else
375				shutdown(fdin, SHUT_WR); /* We will no longer send. */
376#endif
377			fdin = -1;
378		} else {
379			/* Successful write.  Consume the data from the buffer. */
380			buffer_consume(&stdin_buffer, len);
381			/* Update the count of bytes written to the program. */
382			stdin_bytes += len;
383		}
384	}
385	/* Send any buffered packet data to the client. */
386	if (FD_ISSET(connection_out, writeset))
387		packet_write_poll();
388}
389
390/*
391 * Wait until all buffered output has been sent to the client.
392 * This is used when the program terminates.
393 */
394void
395drain_output()
396{
397	/* Send any buffered stdout data to the client. */
398	if (buffer_len(&stdout_buffer) > 0) {
399		packet_start(SSH_SMSG_STDOUT_DATA);
400		packet_put_string(buffer_ptr(&stdout_buffer),
401				  buffer_len(&stdout_buffer));
402		packet_send();
403		/* Update the count of sent bytes. */
404		stdout_bytes += buffer_len(&stdout_buffer);
405	}
406	/* Send any buffered stderr data to the client. */
407	if (buffer_len(&stderr_buffer) > 0) {
408		packet_start(SSH_SMSG_STDERR_DATA);
409		packet_put_string(buffer_ptr(&stderr_buffer),
410				  buffer_len(&stderr_buffer));
411		packet_send();
412		/* Update the count of sent bytes. */
413		stderr_bytes += buffer_len(&stderr_buffer);
414	}
415	/* Wait until all buffered data has been written to the client. */
416	packet_write_wait();
417}
418
419/*
420 * Performs the interactive session.  This handles data transmission between
421 * the client and the program.  Note that the notion of stdin, stdout, and
422 * stderr in this function is sort of reversed: this function writes to
423 * stdin (of the child program), and reads from stdout and stderr (of the
424 * child program).
425 */
426void
427server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
428{
429	int wait_status, wait_pid;	/* Status and pid returned by wait(). */
430	int waiting_termination = 0;	/* Have displayed waiting close message. */
431	unsigned int max_time_milliseconds;
432	unsigned int previous_stdout_buffer_bytes;
433	unsigned int stdout_buffer_bytes;
434	int type;
435
436	debug("Entering interactive session.");
437
438	/* Initialize the SIGCHLD kludge. */
439	child_pid = pid;
440	child_terminated = 0;
441	signal(SIGCHLD, sigchld_handler);
442
443	/* Initialize our global variables. */
444	fdin = fdin_arg;
445	fdout = fdout_arg;
446	fderr = fderr_arg;
447	connection_in = packet_get_connection_in();
448	connection_out = packet_get_connection_out();
449
450	previous_stdout_buffer_bytes = 0;
451
452	/* Set approximate I/O buffer size. */
453	if (packet_is_interactive())
454		buffer_high = 4096;
455	else
456		buffer_high = 64 * 1024;
457
458	/* Initialize max_fd to the maximum of the known file descriptors. */
459	max_fd = fdin;
460	if (fdout > max_fd)
461		max_fd = fdout;
462	if (fderr != -1 && fderr > max_fd)
463		max_fd = fderr;
464	if (connection_in > max_fd)
465		max_fd = connection_in;
466	if (connection_out > max_fd)
467		max_fd = connection_out;
468
469	/* Initialize Initialize buffers. */
470	buffer_init(&stdin_buffer);
471	buffer_init(&stdout_buffer);
472	buffer_init(&stderr_buffer);
473
474	/*
475	 * If we have no separate fderr (which is the case when we have a pty
476	 * - there we cannot make difference between data sent to stdout and
477	 * stderr), indicate that we have seen an EOF from stderr.  This way
478	 * we don\'t need to check the descriptor everywhere.
479	 */
480	if (fderr == -1)
481		fderr_eof = 1;
482
483	/* Main loop of the server for the interactive session mode. */
484	for (;;) {
485		fd_set readset, writeset;
486
487		/* Process buffered packets from the client. */
488		process_buffered_input_packets();
489
490		/*
491		 * If we have received eof, and there is no more pending
492		 * input data, cause a real eof by closing fdin.
493		 */
494		if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
495#ifdef USE_PIPES
496			close(fdin);
497#else
498			if (fdout == -1)
499				close(fdin);
500			else
501				shutdown(fdin, SHUT_WR); /* We will no longer send. */
502#endif
503			fdin = -1;
504		}
505		/* Make packets from buffered stderr data to send to the client. */
506		make_packets_from_stderr_data();
507
508		/*
509		 * Make packets from buffered stdout data to send to the
510		 * client. If there is very little to send, this arranges to
511		 * not send them now, but to wait a short while to see if we
512		 * are getting more data. This is necessary, as some systems
513		 * wake up readers from a pty after each separate character.
514		 */
515		max_time_milliseconds = 0;
516		stdout_buffer_bytes = buffer_len(&stdout_buffer);
517		if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
518		    stdout_buffer_bytes != previous_stdout_buffer_bytes) {
519			/* try again after a while */
520			max_time_milliseconds = 10;
521		} else {
522			/* Send it now. */
523			make_packets_from_stdout_data();
524		}
525		previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
526
527		/* Send channel data to the client. */
528		if (packet_not_very_much_data_to_write())
529			channel_output_poll();
530
531		/*
532		 * Bail out of the loop if the program has closed its output
533		 * descriptors, and we have no more data to send to the
534		 * client, and there is no pending buffered data.
535		 */
536		if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
537		    buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
538			if (!channel_still_open())
539				goto quit;
540			if (!waiting_termination) {
541				const char *s = "Waiting for forwarded connections to terminate...\r\n";
542				char *cp;
543				waiting_termination = 1;
544				buffer_append(&stderr_buffer, s, strlen(s));
545
546				/* Display list of open channels. */
547				cp = channel_open_message();
548				buffer_append(&stderr_buffer, cp, strlen(cp));
549				xfree(cp);
550			}
551		}
552		/* Sleep in select() until we can do something. */
553		wait_until_can_do_something(&readset, &writeset,
554					    max_time_milliseconds);
555
556		/* Process any channel events. */
557		channel_after_select(&readset, &writeset);
558
559		/* Process input from the client and from program stdout/stderr. */
560		process_input(&readset);
561
562		/* Process output to the client and to program stdin. */
563		process_output(&writeset);
564	}
565
566quit:
567	/* Cleanup and termination code. */
568
569	/* Wait until all output has been sent to the client. */
570	drain_output();
571
572	debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
573	      stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
574
575	/* Free and clear the buffers. */
576	buffer_free(&stdin_buffer);
577	buffer_free(&stdout_buffer);
578	buffer_free(&stderr_buffer);
579
580	/* Close the file descriptors. */
581	if (fdout != -1)
582		close(fdout);
583	fdout = -1;
584	fdout_eof = 1;
585	if (fderr != -1)
586		close(fderr);
587	fderr = -1;
588	fderr_eof = 1;
589	if (fdin != -1)
590		close(fdin);
591	fdin = -1;
592
593	/* Stop listening for channels; this removes unix domain sockets. */
594	channel_stop_listening();
595
596	/* Wait for the child to exit.  Get its exit status. */
597	wait_pid = wait(&wait_status);
598	if (wait_pid < 0) {
599		/*
600		 * It is possible that the wait was handled by SIGCHLD
601		 * handler.  This may result in either: this call
602		 * returning with EINTR, or: this call returning ECHILD.
603		 */
604		if (child_terminated)
605			wait_status = child_wait_status;
606		else
607			packet_disconnect("wait: %.100s", strerror(errno));
608	} else {
609		/* Check if it matches the process we forked. */
610		if (wait_pid != pid)
611			error("Strange, wait returned pid %d, expected %d",
612			       wait_pid, pid);
613	}
614
615	/* We no longer want our SIGCHLD handler to be called. */
616	signal(SIGCHLD, SIG_DFL);
617
618	/* Check if it exited normally. */
619	if (WIFEXITED(wait_status)) {
620		/* Yes, normal exit.  Get exit status and send it to the client. */
621		debug("Command exited with status %d.", WEXITSTATUS(wait_status));
622		packet_start(SSH_SMSG_EXITSTATUS);
623		packet_put_int(WEXITSTATUS(wait_status));
624		packet_send();
625		packet_write_wait();
626
627		/*
628		 * Wait for exit confirmation.  Note that there might be
629		 * other packets coming before it; however, the program has
630		 * already died so we just ignore them.  The client is
631		 * supposed to respond with the confirmation when it receives
632		 * the exit status.
633		 */
634		do {
635			int plen;
636			type = packet_read(&plen);
637		}
638		while (type != SSH_CMSG_EXIT_CONFIRMATION);
639
640		debug("Received exit confirmation.");
641		return;
642	}
643	/* Check if the program terminated due to a signal. */
644	if (WIFSIGNALED(wait_status))
645		packet_disconnect("Command terminated on signal %d.",
646				  WTERMSIG(wait_status));
647
648	/* Some weird exit cause.  Just exit. */
649	packet_disconnect("wait returned status %04x.", wait_status);
650	/* NOTREACHED */
651}
652