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