clientloop.c revision 68700
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 * The main loop for the interactive session (client side).
6 *
7 * As far as I am concerned, the code I have written for this software
8 * can be used freely for any purpose.  Any derived versions of this
9 * software must be clearly marked as such, and if the derived work is
10 * incompatible with the protocol description in the RFC file, it must be
11 * called by a name other than "ssh" or "Secure Shell".
12 *
13 *
14 * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 *
37 * SSH2 support added by Markus Friedl.
38 * Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 *    notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 *    notice, this list of conditions and the following disclaimer in the
47 *    documentation and/or other materials provided with the distribution.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
50 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
51 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
54 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
58 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */
60
61#include "includes.h"
62RCSID("$OpenBSD: clientloop.c,v 1.34 2000/09/07 20:40:30 markus Exp $");
63
64#include "xmalloc.h"
65#include "ssh.h"
66#include "packet.h"
67#include "buffer.h"
68#include "readconf.h"
69
70#include "ssh2.h"
71#include "compat.h"
72#include "channels.h"
73#include "dispatch.h"
74
75#include "buffer.h"
76#include "bufaux.h"
77
78extern Options options;
79
80/* Flag indicating that stdin should be redirected from /dev/null. */
81extern int stdin_null_flag;
82
83/*
84 * Name of the host we are connecting to.  This is the name given on the
85 * command line, or the HostName specified for the user-supplied name in a
86 * configuration file.
87 */
88extern char *host;
89
90/*
91 * Flag to indicate that we have received a window change signal which has
92 * not yet been processed.  This will cause a message indicating the new
93 * window size to be sent to the server a little later.  This is volatile
94 * because this is updated in a signal handler.
95 */
96static volatile int received_window_change_signal = 0;
97
98/* Terminal modes, as saved by enter_raw_mode. */
99static struct termios saved_tio;
100
101/*
102 * Flag indicating whether we are in raw mode.  This is used by
103 * enter_raw_mode and leave_raw_mode.
104 */
105static int in_raw_mode = 0;
106
107/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
108static int in_non_blocking_mode = 0;
109
110/* Common data for the client loop code. */
111static int quit_pending;	/* Set to non-zero to quit the client loop. */
112static int escape_char;		/* Escape character. */
113static int escape_pending;	/* Last character was the escape character */
114static int last_was_cr;		/* Last character was a newline. */
115static int exit_status;		/* Used to store the exit status of the command. */
116static int stdin_eof;		/* EOF has been encountered on standard error. */
117static Buffer stdin_buffer;	/* Buffer for stdin data. */
118static Buffer stdout_buffer;	/* Buffer for stdout data. */
119static Buffer stderr_buffer;	/* Buffer for stderr data. */
120static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
121static unsigned int buffer_high;/* Soft max buffer size. */
122static int max_fd;		/* Maximum file descriptor number in select(). */
123static int connection_in;	/* Connection to server (input). */
124static int connection_out;	/* Connection to server (output). */
125
126
127void	client_init_dispatch(void);
128int	session_ident = -1;
129
130/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */
131
132void
133leave_raw_mode()
134{
135	if (!in_raw_mode)
136		return;
137	in_raw_mode = 0;
138	if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
139		perror("tcsetattr");
140
141	fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL);
142}
143
144/* Puts the user\'s terminal in raw mode. */
145
146void
147enter_raw_mode()
148{
149	struct termios tio;
150
151	if (tcgetattr(fileno(stdin), &tio) < 0)
152		perror("tcgetattr");
153	saved_tio = tio;
154	tio.c_iflag |= IGNPAR;
155	tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
156	tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
157#ifdef IEXTEN
158	tio.c_lflag &= ~IEXTEN;
159#endif				/* IEXTEN */
160	tio.c_oflag &= ~OPOST;
161	tio.c_cc[VMIN] = 1;
162	tio.c_cc[VTIME] = 0;
163	if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
164		perror("tcsetattr");
165	in_raw_mode = 1;
166
167	fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL);
168}
169
170/* Restores stdin to blocking mode. */
171
172void
173leave_non_blocking()
174{
175	if (in_non_blocking_mode) {
176		(void) fcntl(fileno(stdin), F_SETFL, 0);
177		in_non_blocking_mode = 0;
178		fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
179	}
180}
181
182/* Puts stdin terminal in non-blocking mode. */
183
184void
185enter_non_blocking()
186{
187	in_non_blocking_mode = 1;
188	(void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
189	fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
190}
191
192/*
193 * Signal handler for the window change signal (SIGWINCH).  This just sets a
194 * flag indicating that the window has changed.
195 */
196
197void
198window_change_handler(int sig)
199{
200	received_window_change_signal = 1;
201	signal(SIGWINCH, window_change_handler);
202}
203
204/*
205 * Signal handler for signals that cause the program to terminate.  These
206 * signals must be trapped to restore terminal modes.
207 */
208
209void
210signal_handler(int sig)
211{
212	if (in_raw_mode)
213		leave_raw_mode();
214	if (in_non_blocking_mode)
215		leave_non_blocking();
216	channel_stop_listening();
217	packet_close();
218	fatal("Killed by signal %d.", sig);
219}
220
221/*
222 * Returns current time in seconds from Jan 1, 1970 with the maximum
223 * available resolution.
224 */
225
226double
227get_current_time()
228{
229	struct timeval tv;
230	gettimeofday(&tv, NULL);
231	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
232}
233
234/*
235 * This is called when the interactive is entered.  This checks if there is
236 * an EOF coming on stdin.  We must check this explicitly, as select() does
237 * not appear to wake up when redirecting from /dev/null.
238 */
239
240void
241client_check_initial_eof_on_stdin()
242{
243	int len;
244	char buf[1];
245
246	/*
247	 * If standard input is to be "redirected from /dev/null", we simply
248	 * mark that we have seen an EOF and send an EOF message to the
249	 * server. Otherwise, we try to read a single character; it appears
250	 * that for some files, such /dev/null, select() never wakes up for
251	 * read for this descriptor, which means that we never get EOF.  This
252	 * way we will get the EOF if stdin comes from /dev/null or similar.
253	 */
254	if (stdin_null_flag) {
255		/* Fake EOF on stdin. */
256		debug("Sending eof.");
257		stdin_eof = 1;
258		packet_start(SSH_CMSG_EOF);
259		packet_send();
260	} else {
261		enter_non_blocking();
262
263		/* Check for immediate EOF on stdin. */
264		len = read(fileno(stdin), buf, 1);
265		if (len == 0) {
266			/* EOF.  Record that we have seen it and send EOF to server. */
267			debug("Sending eof.");
268			stdin_eof = 1;
269			packet_start(SSH_CMSG_EOF);
270			packet_send();
271		} else if (len > 0) {
272			/*
273			 * Got data.  We must store the data in the buffer,
274			 * and also process it as an escape character if
275			 * appropriate.
276			 */
277			if ((unsigned char) buf[0] == escape_char)
278				escape_pending = 1;
279			else {
280				buffer_append(&stdin_buffer, buf, 1);
281				stdin_bytes += 1;
282			}
283		}
284		leave_non_blocking();
285	}
286}
287
288
289/*
290 * Make packets from buffered stdin data, and buffer them for sending to the
291 * connection.
292 */
293
294void
295client_make_packets_from_stdin_data()
296{
297	unsigned int len;
298
299	/* Send buffered stdin data to the server. */
300	while (buffer_len(&stdin_buffer) > 0 &&
301	       packet_not_very_much_data_to_write()) {
302		len = buffer_len(&stdin_buffer);
303		/* Keep the packets at reasonable size. */
304		if (len > packet_get_maxsize())
305			len = packet_get_maxsize();
306		packet_start(SSH_CMSG_STDIN_DATA);
307		packet_put_string(buffer_ptr(&stdin_buffer), len);
308		packet_send();
309		buffer_consume(&stdin_buffer, len);
310		/* If we have a pending EOF, send it now. */
311		if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
312			packet_start(SSH_CMSG_EOF);
313			packet_send();
314		}
315	}
316}
317
318/*
319 * Checks if the client window has changed, and sends a packet about it to
320 * the server if so.  The actual change is detected elsewhere (by a software
321 * interrupt on Unix); this just checks the flag and sends a message if
322 * appropriate.
323 */
324
325void
326client_check_window_change()
327{
328	struct winsize ws;
329
330	if (! received_window_change_signal)
331		return;
332	/** XXX race */
333	received_window_change_signal = 0;
334
335	if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
336		return;
337
338	debug("client_check_window_change: changed");
339
340	if (compat20) {
341		channel_request_start(session_ident, "window-change", 0);
342		packet_put_int(ws.ws_col);
343		packet_put_int(ws.ws_row);
344		packet_put_int(ws.ws_xpixel);
345		packet_put_int(ws.ws_ypixel);
346		packet_send();
347	} else {
348		packet_start(SSH_CMSG_WINDOW_SIZE);
349		packet_put_int(ws.ws_row);
350		packet_put_int(ws.ws_col);
351		packet_put_int(ws.ws_xpixel);
352		packet_put_int(ws.ws_ypixel);
353		packet_send();
354	}
355}
356
357/*
358 * Waits until the client can do something (some data becomes available on
359 * one of the file descriptors).
360 */
361
362void
363client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
364{
365	/*debug("client_wait_until_can_do_something"); */
366
367	/* Initialize select masks. */
368	FD_ZERO(readset);
369	FD_ZERO(writeset);
370
371	if (!compat20) {
372		/* Read from the connection, unless our buffers are full. */
373		if (buffer_len(&stdout_buffer) < buffer_high &&
374		    buffer_len(&stderr_buffer) < buffer_high &&
375		    channel_not_very_much_buffered_data())
376			FD_SET(connection_in, readset);
377		/*
378		 * Read from stdin, unless we have seen EOF or have very much
379		 * buffered data to send to the server.
380		 */
381		if (!stdin_eof && packet_not_very_much_data_to_write())
382			FD_SET(fileno(stdin), readset);
383
384		/* Select stdout/stderr if have data in buffer. */
385		if (buffer_len(&stdout_buffer) > 0)
386			FD_SET(fileno(stdout), writeset);
387		if (buffer_len(&stderr_buffer) > 0)
388			FD_SET(fileno(stderr), writeset);
389	} else {
390		FD_SET(connection_in, readset);
391	}
392
393	/* Add any selections by the channel mechanism. */
394	channel_prepare_select(readset, writeset);
395
396	/* Select server connection if have data to write to the server. */
397	if (packet_have_data_to_write())
398		FD_SET(connection_out, writeset);
399
400/* move UP XXX */
401	/* Update maximum file descriptor number, if appropriate. */
402	if (channel_max_fd() > max_fd)
403		max_fd = channel_max_fd();
404
405	/*
406	 * Wait for something to happen.  This will suspend the process until
407	 * some selected descriptor can be read, written, or has some other
408	 * event pending. Note: if you want to implement SSH_MSG_IGNORE
409	 * messages to fool traffic analysis, this might be the place to do
410	 * it: just have a random timeout for the select, and send a random
411	 * SSH_MSG_IGNORE packet when the timeout expires.
412	 */
413
414	if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) {
415		char buf[100];
416		/* Some systems fail to clear these automatically. */
417		FD_ZERO(readset);
418		FD_ZERO(writeset);
419		if (errno == EINTR)
420			return;
421		/* Note: we might still have data in the buffers. */
422		snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
423		buffer_append(&stderr_buffer, buf, strlen(buf));
424		stderr_bytes += strlen(buf);
425		quit_pending = 1;
426	}
427}
428
429void
430client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
431{
432	struct winsize oldws, newws;
433
434	/* Flush stdout and stderr buffers. */
435	if (buffer_len(bout) > 0)
436		atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
437	if (buffer_len(berr) > 0)
438		atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
439
440	leave_raw_mode();
441
442	/*
443	 * Free (and clear) the buffer to reduce the amount of data that gets
444	 * written to swap.
445	 */
446	buffer_free(bin);
447	buffer_free(bout);
448	buffer_free(berr);
449
450	/* Save old window size. */
451	ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
452
453	/* Send the suspend signal to the program itself. */
454	kill(getpid(), SIGTSTP);
455
456	/* Check if the window size has changed. */
457	if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
458	    (oldws.ws_row != newws.ws_row ||
459	     oldws.ws_col != newws.ws_col ||
460	     oldws.ws_xpixel != newws.ws_xpixel ||
461	     oldws.ws_ypixel != newws.ws_ypixel))
462		received_window_change_signal = 1;
463
464	/* OK, we have been continued by the user. Reinitialize buffers. */
465	buffer_init(bin);
466	buffer_init(bout);
467	buffer_init(berr);
468
469	enter_raw_mode();
470}
471
472void
473client_process_net_input(fd_set * readset)
474{
475	int len;
476	char buf[8192];
477
478	/*
479	 * Read input from the server, and add any such data to the buffer of
480	 * the packet subsystem.
481	 */
482	if (FD_ISSET(connection_in, readset)) {
483		/* Read as much as possible. */
484		len = read(connection_in, buf, sizeof(buf));
485/*debug("read connection_in len %d", len); XXX */
486		if (len == 0) {
487			/* Received EOF.  The remote host has closed the connection. */
488			snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
489				 host);
490			buffer_append(&stderr_buffer, buf, strlen(buf));
491			stderr_bytes += strlen(buf);
492			quit_pending = 1;
493			return;
494		}
495		/*
496		 * There is a kernel bug on Solaris that causes select to
497		 * sometimes wake up even though there is no data available.
498		 */
499		if (len < 0 && errno == EAGAIN)
500			len = 0;
501
502		if (len < 0) {
503			/* An error has encountered.  Perhaps there is a network problem. */
504			snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
505				 host, strerror(errno));
506			buffer_append(&stderr_buffer, buf, strlen(buf));
507			stderr_bytes += strlen(buf);
508			quit_pending = 1;
509			return;
510		}
511		packet_process_incoming(buf, len);
512	}
513}
514
515/* process the characters one by one */
516int
517process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
518{
519	char string[1024];
520	pid_t pid;
521	int bytes = 0;
522	unsigned int i;
523	unsigned char ch;
524	char *s;
525
526	for (i = 0; i < len; i++) {
527		/* Get one character at a time. */
528		ch = buf[i];
529
530		if (escape_pending) {
531			/* We have previously seen an escape character. */
532			/* Clear the flag now. */
533			escape_pending = 0;
534
535			/* Process the escaped character. */
536			switch (ch) {
537			case '.':
538				/* Terminate the connection. */
539				snprintf(string, sizeof string, "%c.\r\n", escape_char);
540				buffer_append(berr, string, strlen(string));
541				/*stderr_bytes += strlen(string); XXX*/
542
543				quit_pending = 1;
544				return -1;
545
546			case 'Z' - 64:
547				/* Suspend the program. */
548				/* Print a message to that effect to the user. */
549				snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);
550				buffer_append(berr, string, strlen(string));
551				/*stderr_bytes += strlen(string); XXX*/
552
553				/* Restore terminal modes and suspend. */
554				client_suspend_self(bin, bout, berr);
555
556				/* We have been continued. */
557				continue;
558
559			case '&':
560				/* XXX does not work yet with proto 2 */
561				if (compat20)
562					continue;
563				/*
564				 * Detach the program (continue to serve connections,
565				 * but put in background and no more new connections).
566				 */
567				if (!stdin_eof) {
568					/*
569					 * Sending SSH_CMSG_EOF alone does not always appear
570					 * to be enough.  So we try to send an EOF character
571					 * first.
572					 */
573					packet_start(SSH_CMSG_STDIN_DATA);
574					packet_put_string("\004", 1);
575					packet_send();
576					/* Close stdin. */
577					stdin_eof = 1;
578					if (buffer_len(bin) == 0) {
579						packet_start(SSH_CMSG_EOF);
580						packet_send();
581					}
582				}
583				/* Restore tty modes. */
584				leave_raw_mode();
585
586				/* Stop listening for new connections. */
587				channel_stop_listening();
588
589				printf("%c& [backgrounded]\n", escape_char);
590
591				/* Fork into background. */
592				pid = fork();
593				if (pid < 0) {
594					error("fork: %.100s", strerror(errno));
595					continue;
596				}
597				if (pid != 0) {	/* This is the parent. */
598					/* The parent just exits. */
599					exit(0);
600				}
601				/* The child continues serving connections. */
602				continue; /*XXX ? */
603
604			case '?':
605				snprintf(string, sizeof string,
606"%c?\r\n\
607Supported escape sequences:\r\n\
608~.  - terminate connection\r\n\
609~^Z - suspend ssh\r\n\
610~#  - list forwarded connections\r\n\
611~&  - background ssh (when waiting for connections to terminate)\r\n\
612~?  - this message\r\n\
613~~  - send the escape character by typing it twice\r\n\
614(Note that escapes are only recognized immediately after newline.)\r\n",
615					 escape_char);
616				buffer_append(berr, string, strlen(string));
617				continue;
618
619			case '#':
620				snprintf(string, sizeof string, "%c#\r\n", escape_char);
621				buffer_append(berr, string, strlen(string));
622				s = channel_open_message();
623				buffer_append(berr, s, strlen(s));
624				xfree(s);
625				continue;
626
627			default:
628				if (ch != escape_char) {
629					buffer_put_char(bin, escape_char);
630					bytes++;
631				}
632				/* Escaped characters fall through here */
633				break;
634			}
635		} else {
636			/*
637			 * The previous character was not an escape char. Check if this
638			 * is an escape.
639			 */
640			if (last_was_cr && ch == escape_char) {
641				/* It is. Set the flag and continue to next character. */
642				escape_pending = 1;
643				continue;
644			}
645		}
646
647		/*
648		 * Normal character.  Record whether it was a newline,
649		 * and append it to the buffer.
650		 */
651		last_was_cr = (ch == '\r' || ch == '\n');
652		buffer_put_char(bin, ch);
653		bytes++;
654	}
655	return bytes;
656}
657
658void
659client_process_input(fd_set * readset)
660{
661	int ret;
662	int len;
663	char buf[8192];
664
665	/* Read input from stdin. */
666	if (FD_ISSET(fileno(stdin), readset)) {
667		/* Read as much as possible. */
668		len = read(fileno(stdin), buf, sizeof(buf));
669		if (len <= 0) {
670			/*
671			 * Received EOF or error.  They are treated
672			 * similarly, except that an error message is printed
673			 * if it was an error condition.
674			 */
675			if (len < 0) {
676				snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
677				buffer_append(&stderr_buffer, buf, strlen(buf));
678				stderr_bytes += strlen(buf);
679			}
680			/* Mark that we have seen EOF. */
681			stdin_eof = 1;
682			/*
683			 * Send an EOF message to the server unless there is
684			 * data in the buffer.  If there is data in the
685			 * buffer, no message will be sent now.  Code
686			 * elsewhere will send the EOF when the buffer
687			 * becomes empty if stdin_eof is set.
688			 */
689			if (buffer_len(&stdin_buffer) == 0) {
690				packet_start(SSH_CMSG_EOF);
691				packet_send();
692			}
693		} else if (escape_char == -1) {
694			/*
695			 * Normal successful read, and no escape character.
696			 * Just append the data to buffer.
697			 */
698			buffer_append(&stdin_buffer, buf, len);
699			stdin_bytes += len;
700		} else {
701			/*
702			 * Normal, successful read.  But we have an escape character
703			 * and have to process the characters one by one.
704			 */
705			ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len);
706			if (ret == -1)
707				return;
708			stdout_bytes += ret;
709		}
710	}
711}
712
713void
714client_process_output(fd_set * writeset)
715{
716	int len;
717	char buf[100];
718
719	/* Write buffered output to stdout. */
720	if (FD_ISSET(fileno(stdout), writeset)) {
721		/* Write as much data as possible. */
722		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
723		    buffer_len(&stdout_buffer));
724		if (len <= 0) {
725			if (errno == EAGAIN)
726				len = 0;
727			else {
728				/*
729				 * An error or EOF was encountered.  Put an
730				 * error message to stderr buffer.
731				 */
732				snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
733				buffer_append(&stderr_buffer, buf, strlen(buf));
734				stderr_bytes += strlen(buf);
735				quit_pending = 1;
736				return;
737			}
738		}
739		/* Consume printed data from the buffer. */
740		buffer_consume(&stdout_buffer, len);
741	}
742	/* Write buffered output to stderr. */
743	if (FD_ISSET(fileno(stderr), writeset)) {
744		/* Write as much data as possible. */
745		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
746		    buffer_len(&stderr_buffer));
747		if (len <= 0) {
748			if (errno == EAGAIN)
749				len = 0;
750			else {
751				/* EOF or error, but can't even print error message. */
752				quit_pending = 1;
753				return;
754			}
755		}
756		/* Consume printed characters from the buffer. */
757		buffer_consume(&stderr_buffer, len);
758	}
759}
760
761/*
762 * Get packets from the connection input buffer, and process them as long as
763 * there are packets available.
764 *
765 * Any unknown packets received during the actual
766 * session cause the session to terminate.  This is
767 * intended to make debugging easier since no
768 * confirmations are sent.  Any compatible protocol
769 * extensions must be negotiated during the
770 * preparatory phase.
771 */
772
773void
774client_process_buffered_input_packets()
775{
776	dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
777}
778
779/* scan buf[] for '~' before sending data to the peer */
780
781int
782simple_escape_filter(Channel *c, char *buf, int len)
783{
784	/* XXX we assume c->extended is writeable */
785	return process_escapes(&c->input, &c->output, &c->extended, buf, len);
786}
787
788/*
789 * Implements the interactive session with the server.  This is called after
790 * the user has been authenticated, and a command has been started on the
791 * remote host.  If escape_char != -1, it is the character used as an escape
792 * character for terminating or suspending the session.
793 */
794
795int
796client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
797{
798	double start_time, total_time;
799	int len;
800	char buf[100];
801
802	debug("Entering interactive session.");
803
804	start_time = get_current_time();
805
806	/* Initialize variables. */
807	escape_pending = 0;
808	last_was_cr = 1;
809	exit_status = -1;
810	stdin_eof = 0;
811	buffer_high = 64 * 1024;
812	connection_in = packet_get_connection_in();
813	connection_out = packet_get_connection_out();
814	max_fd = connection_in;
815	if (connection_out > max_fd)
816		max_fd = connection_out;
817	stdin_bytes = 0;
818	stdout_bytes = 0;
819	stderr_bytes = 0;
820	quit_pending = 0;
821	escape_char = escape_char_arg;
822
823	/* Initialize buffers. */
824	buffer_init(&stdin_buffer);
825	buffer_init(&stdout_buffer);
826	buffer_init(&stderr_buffer);
827
828	client_init_dispatch();
829
830	/* Set signal handlers to restore non-blocking mode.  */
831	signal(SIGINT, signal_handler);
832	signal(SIGQUIT, signal_handler);
833	signal(SIGTERM, signal_handler);
834	signal(SIGPIPE, SIG_IGN);
835	if (have_pty)
836		signal(SIGWINCH, window_change_handler);
837
838	if (have_pty)
839		enter_raw_mode();
840
841	/* Check if we should immediately send eof on stdin. */
842	if (!compat20)
843		client_check_initial_eof_on_stdin();
844
845	if (compat20 && escape_char != -1)
846		channel_register_filter(ssh2_chan_id, simple_escape_filter);
847
848	/* Main loop of the client for the interactive session mode. */
849	while (!quit_pending) {
850		fd_set readset, writeset;
851
852		/* Process buffered packets sent by the server. */
853		client_process_buffered_input_packets();
854
855		if (compat20 && !channel_still_open()) {
856			debug("!channel_still_open.");
857			break;
858		}
859
860		/*
861		 * Make packets of buffered stdin data, and buffer them for
862		 * sending to the server.
863		 */
864		if (!compat20)
865			client_make_packets_from_stdin_data();
866
867		/*
868		 * Make packets from buffered channel data, and buffer them
869		 * for sending to the server.
870		 */
871		if (packet_not_very_much_data_to_write())
872			channel_output_poll();
873
874		/*
875		 * Check if the window size has changed, and buffer a message
876		 * about it to the server if so.
877		 */
878		client_check_window_change();
879
880		if (quit_pending)
881			break;
882
883		/*
884		 * Wait until we have something to do (something becomes
885		 * available on one of the descriptors).
886		 */
887		client_wait_until_can_do_something(&readset, &writeset);
888
889		if (quit_pending)
890			break;
891
892		/* Do channel operations. */
893		channel_after_select(&readset, &writeset);
894
895		/* Buffer input from the connection.  */
896		client_process_net_input(&readset);
897
898		if (quit_pending)
899			break;
900
901		if (!compat20) {
902			/* Buffer data from stdin */
903			client_process_input(&readset);
904			/*
905			 * Process output to stdout and stderr.  Output to
906			 * the connection is processed elsewhere (above).
907			 */
908			client_process_output(&writeset);
909		}
910
911		/* Send as much buffered packet data as possible to the sender. */
912		if (FD_ISSET(connection_out, &writeset))
913			packet_write_poll();
914	}
915
916	/* Terminate the session. */
917
918	/* Stop watching for window change. */
919	if (have_pty)
920		signal(SIGWINCH, SIG_DFL);
921
922	/* Stop listening for connections. */
923	channel_stop_listening();
924
925	/*
926	 * In interactive mode (with pseudo tty) display a message indicating
927	 * that the connection has been closed.
928	 */
929	if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
930		snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
931		buffer_append(&stderr_buffer, buf, strlen(buf));
932		stderr_bytes += strlen(buf);
933	}
934	/* Output any buffered data for stdout. */
935	while (buffer_len(&stdout_buffer) > 0) {
936		len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
937		    buffer_len(&stdout_buffer));
938		if (len <= 0) {
939			error("Write failed flushing stdout buffer.");
940			break;
941		}
942		buffer_consume(&stdout_buffer, len);
943	}
944
945	/* Output any buffered data for stderr. */
946	while (buffer_len(&stderr_buffer) > 0) {
947		len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
948		    buffer_len(&stderr_buffer));
949		if (len <= 0) {
950			error("Write failed flushing stderr buffer.");
951			break;
952		}
953		buffer_consume(&stderr_buffer, len);
954	}
955
956	if (have_pty)
957		leave_raw_mode();
958
959	/* Clear and free any buffers. */
960	memset(buf, 0, sizeof(buf));
961	buffer_free(&stdin_buffer);
962	buffer_free(&stdout_buffer);
963	buffer_free(&stderr_buffer);
964
965	/* Report bytes transferred, and transfer rates. */
966	total_time = get_current_time() - start_time;
967	debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
968	      stdin_bytes, stdout_bytes, stderr_bytes, total_time);
969	if (total_time > 0)
970		debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
971		      stdin_bytes / total_time, stdout_bytes / total_time,
972		      stderr_bytes / total_time);
973
974	/* Return the exit status of the program. */
975	debug("Exit status %d", exit_status);
976	return exit_status;
977}
978
979/*********/
980
981void
982client_input_stdout_data(int type, int plen)
983{
984	unsigned int data_len;
985	char *data = packet_get_string(&data_len);
986	packet_integrity_check(plen, 4 + data_len, type);
987	buffer_append(&stdout_buffer, data, data_len);
988	stdout_bytes += data_len;
989	memset(data, 0, data_len);
990	xfree(data);
991}
992void
993client_input_stderr_data(int type, int plen)
994{
995	unsigned int data_len;
996	char *data = packet_get_string(&data_len);
997	packet_integrity_check(plen, 4 + data_len, type);
998	buffer_append(&stderr_buffer, data, data_len);
999	stdout_bytes += data_len;
1000	memset(data, 0, data_len);
1001	xfree(data);
1002}
1003void
1004client_input_exit_status(int type, int plen)
1005{
1006	packet_integrity_check(plen, 4, type);
1007	exit_status = packet_get_int();
1008	/* Acknowledge the exit. */
1009	packet_start(SSH_CMSG_EXIT_CONFIRMATION);
1010	packet_send();
1011	/*
1012	 * Must wait for packet to be sent since we are
1013	 * exiting the loop.
1014	 */
1015	packet_write_wait();
1016	/* Flag that we want to exit. */
1017	quit_pending = 1;
1018}
1019
1020/* XXXX move to generic input handler */
1021void
1022client_input_channel_open(int type, int plen)
1023{
1024	Channel *c = NULL;
1025	char *ctype;
1026	int id;
1027	unsigned int len;
1028	int rchan;
1029	int rmaxpack;
1030	int rwindow;
1031
1032	ctype = packet_get_string(&len);
1033	rchan = packet_get_int();
1034	rwindow = packet_get_int();
1035	rmaxpack = packet_get_int();
1036
1037	debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
1038	    ctype, rchan, rwindow, rmaxpack);
1039
1040	if (strcmp(ctype, "x11") == 0 && options.forward_x11) {
1041		int sock;
1042		char *originator;
1043		int originator_port;
1044		originator = packet_get_string(NULL);
1045		if (datafellows & SSH_BUG_X11FWD) {
1046			debug("buggy server: x11 request w/o originator_port");
1047			originator_port = 0;
1048		} else {
1049			originator_port = packet_get_int();
1050		}
1051		packet_done();
1052		/* XXX check permission */
1053		xfree(originator);
1054		/* XXX move to channels.c */
1055		sock = x11_connect_display();
1056		if (sock >= 0) {
1057			id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
1058			    sock, sock, -1, CHAN_X11_WINDOW_DEFAULT,
1059			    CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"));
1060			c = channel_lookup(id);
1061		}
1062	}
1063/* XXX duplicate : */
1064	if (c != NULL) {
1065		debug("confirm %s", ctype);
1066		c->remote_id = rchan;
1067		c->remote_window = rwindow;
1068		c->remote_maxpacket = rmaxpack;
1069
1070		packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1071		packet_put_int(c->remote_id);
1072		packet_put_int(c->self);
1073		packet_put_int(c->local_window);
1074		packet_put_int(c->local_maxpacket);
1075		packet_send();
1076	} else {
1077		debug("failure %s", ctype);
1078		packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1079		packet_put_int(rchan);
1080		packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
1081		packet_put_cstring("bla bla");
1082		packet_put_cstring("");
1083		packet_send();
1084	}
1085	xfree(ctype);
1086}
1087
1088void
1089client_init_dispatch_20()
1090{
1091	dispatch_init(&dispatch_protocol_error);
1092	dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
1093	dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
1094	dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
1095	dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
1096	dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
1097	dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1098	dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1099	dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
1100	dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1101}
1102void
1103client_init_dispatch_13()
1104{
1105	dispatch_init(NULL);
1106	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
1107	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
1108	dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
1109	dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1110	dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1111	dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1112	dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
1113	dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
1114	dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
1115
1116	dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
1117	    &auth_input_open_request : NULL);
1118	dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
1119	    &x11_input_open : NULL);
1120}
1121void
1122client_init_dispatch_15()
1123{
1124	client_init_dispatch_13();
1125	dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
1126	dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
1127}
1128void
1129client_init_dispatch()
1130{
1131	if (compat20)
1132		client_init_dispatch_20();
1133	else if (compat13)
1134		client_init_dispatch_13();
1135	else
1136		client_init_dispatch_15();
1137}
1138
1139void
1140client_input_channel_req(int id, void *arg)
1141{
1142	Channel *c = NULL;
1143	unsigned int len;
1144	int success = 0;
1145	int reply;
1146	char *rtype;
1147
1148	rtype = packet_get_string(&len);
1149	reply = packet_get_char();
1150
1151	debug("client_input_channel_req: rtype %s reply %d", rtype, reply);
1152
1153	c = channel_lookup(id);
1154	if (c == NULL)
1155		fatal("session_input_channel_req: channel %d: bad channel", id);
1156
1157	if (session_ident == -1) {
1158		error("client_input_channel_req: no channel %d", id);
1159	} else if (id != session_ident) {
1160		error("client_input_channel_req: bad channel %d != %d",
1161		    id, session_ident);
1162	} else if (strcmp(rtype, "exit-status") == 0) {
1163		success = 1;
1164		exit_status = packet_get_int();
1165		packet_done();
1166	}
1167	if (reply) {
1168		packet_start(success ?
1169		    SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1170		packet_put_int(c->remote_id);
1171		packet_send();
1172	}
1173	xfree(rtype);
1174}
1175
1176void
1177client_set_session_ident(int id)
1178{
1179	debug("client_set_session_ident: id %d", id);
1180	session_ident = id;
1181	channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
1182	    client_input_channel_req, (void *)0);
1183}
1184