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