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