]> andersk Git - openssh.git/blob - clientloop.c
- (djm) OpenBSD CVS Sync:
[openssh.git] / clientloop.c
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.46 2001/01/29 16:55:36 markus Exp $");
63
64 #include "ssh.h"
65 #include "ssh1.h"
66 #include "ssh2.h"
67 #include "xmalloc.h"
68 #include "packet.h"
69 #include "buffer.h"
70 #include "compat.h"
71 #include "channels.h"
72 #include "dispatch.h"
73 #include "buffer.h"
74 #include "bufaux.h"
75 #include "key.h"
76 #include "log.h"
77 #include "readconf.h"
78 #include "clientloop.h"
79 #include "authfd.h"
80 #include "atomicio.h"
81
82 /* import options */
83 extern Options options;
84
85 /* Flag indicating that stdin should be redirected from /dev/null. */
86 extern int stdin_null_flag;
87
88 /*
89  * Name of the host we are connecting to.  This is the name given on the
90  * command line, or the HostName specified for the user-supplied name in a
91  * configuration file.
92  */
93 extern char *host;
94
95 /*
96  * Flag to indicate that we have received a window change signal which has
97  * not yet been processed.  This will cause a message indicating the new
98  * window size to be sent to the server a little later.  This is volatile
99  * because this is updated in a signal handler.
100  */
101 static volatile int received_window_change_signal = 0;
102
103 /* Terminal modes, as saved by enter_raw_mode. */
104 static struct termios saved_tio;
105
106 /*
107  * Flag indicating whether we are in raw mode.  This is used by
108  * enter_raw_mode and leave_raw_mode.
109  */
110 static int in_raw_mode = 0;
111
112 /* Flag indicating whether the user\'s terminal is in non-blocking mode. */
113 static int in_non_blocking_mode = 0;
114
115 /* Common data for the client loop code. */
116 static int quit_pending;        /* Set to non-zero to quit the client loop. */
117 static int escape_char;         /* Escape character. */
118 static int escape_pending;      /* Last character was the escape character */
119 static int last_was_cr;         /* Last character was a newline. */
120 static int exit_status;         /* Used to store the exit status of the command. */
121 static int stdin_eof;           /* EOF has been encountered on standard error. */
122 static Buffer stdin_buffer;     /* Buffer for stdin data. */
123 static Buffer stdout_buffer;    /* Buffer for stdout data. */
124 static Buffer stderr_buffer;    /* Buffer for stderr data. */
125 static u_long stdin_bytes, stdout_bytes, stderr_bytes;
126 static u_int buffer_high;/* Soft max buffer size. */
127 static int connection_in;       /* Connection to server (input). */
128 static int connection_out;      /* Connection to server (output). */
129
130
131 void    client_init_dispatch(void);
132 int     session_ident = -1;
133
134 /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */
135
136 void
137 leave_raw_mode()
138 {
139         if (!in_raw_mode)
140                 return;
141         in_raw_mode = 0;
142         if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
143                 perror("tcsetattr");
144
145         fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL);
146 }
147
148 /* Puts the user\'s terminal in raw mode. */
149
150 void
151 enter_raw_mode()
152 {
153         struct termios tio;
154
155         if (tcgetattr(fileno(stdin), &tio) < 0)
156                 perror("tcgetattr");
157         saved_tio = tio;
158         tio.c_iflag |= IGNPAR;
159         tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
160         tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
161 #ifdef IEXTEN
162         tio.c_lflag &= ~IEXTEN;
163 #endif                          /* IEXTEN */
164         tio.c_oflag &= ~OPOST;
165         tio.c_cc[VMIN] = 1;
166         tio.c_cc[VTIME] = 0;
167         if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
168                 perror("tcsetattr");
169         in_raw_mode = 1;
170
171         fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL);
172 }
173
174 /* Restores stdin to blocking mode. */
175
176 void
177 leave_non_blocking()
178 {
179         if (in_non_blocking_mode) {
180                 (void) fcntl(fileno(stdin), F_SETFL, 0);
181                 in_non_blocking_mode = 0;
182                 fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
183         }
184 }
185
186 /* Puts stdin terminal in non-blocking mode. */
187
188 void
189 enter_non_blocking()
190 {
191         in_non_blocking_mode = 1;
192         (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
193         fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
194 }
195
196 /*
197  * Signal handler for the window change signal (SIGWINCH).  This just sets a
198  * flag indicating that the window has changed.
199  */
200
201 void
202 window_change_handler(int sig)
203 {
204         received_window_change_signal = 1;
205         signal(SIGWINCH, window_change_handler);
206 }
207
208 /*
209  * Signal handler for signals that cause the program to terminate.  These
210  * signals must be trapped to restore terminal modes.
211  */
212
213 void
214 signal_handler(int sig)
215 {
216         if (in_raw_mode)
217                 leave_raw_mode();
218         if (in_non_blocking_mode)
219                 leave_non_blocking();
220         channel_stop_listening();
221         packet_close();
222         fatal("Killed by signal %d.", sig);
223 }
224
225 /*
226  * Returns current time in seconds from Jan 1, 1970 with the maximum
227  * available resolution.
228  */
229
230 double
231 get_current_time()
232 {
233         struct timeval tv;
234         gettimeofday(&tv, NULL);
235         return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
236 }
237
238 /*
239  * This is called when the interactive is entered.  This checks if there is
240  * an EOF coming on stdin.  We must check this explicitly, as select() does
241  * not appear to wake up when redirecting from /dev/null.
242  */
243
244 void
245 client_check_initial_eof_on_stdin()
246 {
247         int len;
248         char buf[1];
249
250         /*
251          * If standard input is to be "redirected from /dev/null", we simply
252          * mark that we have seen an EOF and send an EOF message to the
253          * server. Otherwise, we try to read a single character; it appears
254          * that for some files, such /dev/null, select() never wakes up for
255          * read for this descriptor, which means that we never get EOF.  This
256          * way we will get the EOF if stdin comes from /dev/null or similar.
257          */
258         if (stdin_null_flag) {
259                 /* Fake EOF on stdin. */
260                 debug("Sending eof.");
261                 stdin_eof = 1;
262                 packet_start(SSH_CMSG_EOF);
263                 packet_send();
264         } else {
265                 enter_non_blocking();
266
267                 /* Check for immediate EOF on stdin. */
268                 len = read(fileno(stdin), buf, 1);
269                 if (len == 0) {
270                         /* EOF.  Record that we have seen it and send EOF to server. */
271                         debug("Sending eof.");
272                         stdin_eof = 1;
273                         packet_start(SSH_CMSG_EOF);
274                         packet_send();
275                 } else if (len > 0) {
276                         /*
277                          * Got data.  We must store the data in the buffer,
278                          * and also process it as an escape character if
279                          * appropriate.
280                          */
281                         if ((u_char) buf[0] == escape_char)
282                                 escape_pending = 1;
283                         else {
284                                 buffer_append(&stdin_buffer, buf, 1);
285                                 stdin_bytes += 1;
286                         }
287                 }
288                 leave_non_blocking();
289         }
290 }
291
292
293 /*
294  * Make packets from buffered stdin data, and buffer them for sending to the
295  * connection.
296  */
297
298 void
299 client_make_packets_from_stdin_data()
300 {
301         u_int len;
302
303         /* Send buffered stdin data to the server. */
304         while (buffer_len(&stdin_buffer) > 0 &&
305                packet_not_very_much_data_to_write()) {
306                 len = buffer_len(&stdin_buffer);
307                 /* Keep the packets at reasonable size. */
308                 if (len > packet_get_maxsize())
309                         len = packet_get_maxsize();
310                 packet_start(SSH_CMSG_STDIN_DATA);
311                 packet_put_string(buffer_ptr(&stdin_buffer), len);
312                 packet_send();
313                 buffer_consume(&stdin_buffer, len);
314                 /* If we have a pending EOF, send it now. */
315                 if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
316                         packet_start(SSH_CMSG_EOF);
317                         packet_send();
318                 }
319         }
320 }
321
322 /*
323  * Checks if the client window has changed, and sends a packet about it to
324  * the server if so.  The actual change is detected elsewhere (by a software
325  * interrupt on Unix); this just checks the flag and sends a message if
326  * appropriate.
327  */
328
329 void
330 client_check_window_change()
331 {
332         struct winsize ws;
333
334         if (! received_window_change_signal)
335                 return;
336         /** XXX race */
337         received_window_change_signal = 0;
338
339         if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
340                 return;
341
342         debug2("client_check_window_change: changed");
343
344         if (compat20) {
345                 channel_request_start(session_ident, "window-change", 0);
346                 packet_put_int(ws.ws_col);
347                 packet_put_int(ws.ws_row);
348                 packet_put_int(ws.ws_xpixel);
349                 packet_put_int(ws.ws_ypixel);
350                 packet_send();
351         } else {
352                 packet_start(SSH_CMSG_WINDOW_SIZE);
353                 packet_put_int(ws.ws_row);
354                 packet_put_int(ws.ws_col);
355                 packet_put_int(ws.ws_xpixel);
356                 packet_put_int(ws.ws_ypixel);
357                 packet_send();
358         }
359 }
360
361 /*
362  * Waits until the client can do something (some data becomes available on
363  * one of the file descriptors).
364  */
365
366 void
367 client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
368     int *maxfdp)
369 {
370         /* Add any selections by the channel mechanism. */
371         channel_prepare_select(readsetp, writesetp, maxfdp);
372
373         if (!compat20) {
374                 /* Read from the connection, unless our buffers are full. */
375                 if (buffer_len(&stdout_buffer) < buffer_high &&
376                     buffer_len(&stderr_buffer) < buffer_high &&
377                     channel_not_very_much_buffered_data())
378                         FD_SET(connection_in, *readsetp);
379                 /*
380                  * Read from stdin, unless we have seen EOF or have very much
381                  * buffered data to send to the server.
382                  */
383                 if (!stdin_eof && packet_not_very_much_data_to_write())
384                         FD_SET(fileno(stdin), *readsetp);
385
386                 /* Select stdout/stderr if have data in buffer. */
387                 if (buffer_len(&stdout_buffer) > 0)
388                         FD_SET(fileno(stdout), *writesetp);
389                 if (buffer_len(&stderr_buffer) > 0)
390                         FD_SET(fileno(stderr), *writesetp);
391         } else {
392                 FD_SET(connection_in, *readsetp);
393         }
394
395         /* Select server connection if have data to write to the server. */
396         if (packet_have_data_to_write())
397                 FD_SET(connection_out, *writesetp);
398
399         /*
400          * Wait for something to happen.  This will suspend the process until
401          * some selected descriptor can be read, written, or has some other
402          * event pending. Note: if you want to implement SSH_MSG_IGNORE
403          * messages to fool traffic analysis, this might be the place to do
404          * it: just have a random timeout for the select, and send a random
405          * SSH_MSG_IGNORE packet when the timeout expires.
406          */
407
408         if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
409                 char buf[100];
410                 if (errno == EINTR)
411                         return;
412                 /* Note: we might still have data in the buffers. */
413                 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
414                 buffer_append(&stderr_buffer, buf, strlen(buf));
415                 stderr_bytes += strlen(buf);
416                 quit_pending = 1;
417         }
418 }
419
420 void
421 client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
422 {
423         struct winsize oldws, newws;
424
425         /* Flush stdout and stderr buffers. */
426         if (buffer_len(bout) > 0)
427                 atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout));
428         if (buffer_len(berr) > 0)
429                 atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr));
430
431         leave_raw_mode();
432
433         /*
434          * Free (and clear) the buffer to reduce the amount of data that gets
435          * written to swap.
436          */
437         buffer_free(bin);
438         buffer_free(bout);
439         buffer_free(berr);
440
441         /* Save old window size. */
442         ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
443
444         /* Send the suspend signal to the program itself. */
445         kill(getpid(), SIGTSTP);
446
447         /* Check if the window size has changed. */
448         if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
449             (oldws.ws_row != newws.ws_row ||
450              oldws.ws_col != newws.ws_col ||
451              oldws.ws_xpixel != newws.ws_xpixel ||
452              oldws.ws_ypixel != newws.ws_ypixel))
453                 received_window_change_signal = 1;
454
455         /* OK, we have been continued by the user. Reinitialize buffers. */
456         buffer_init(bin);
457         buffer_init(bout);
458         buffer_init(berr);
459
460         enter_raw_mode();
461 }
462
463 void
464 client_process_net_input(fd_set * readset)
465 {
466         int len;
467         char buf[8192];
468
469         /*
470          * Read input from the server, and add any such data to the buffer of
471          * the packet subsystem.
472          */
473         if (FD_ISSET(connection_in, readset)) {
474                 /* Read as much as possible. */
475                 len = read(connection_in, buf, sizeof(buf));
476                 if (len == 0) {
477                         /* Received EOF.  The remote host has closed the connection. */
478                         snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
479                                  host);
480                         buffer_append(&stderr_buffer, buf, strlen(buf));
481                         stderr_bytes += strlen(buf);
482                         quit_pending = 1;
483                         return;
484                 }
485                 /*
486                  * There is a kernel bug on Solaris that causes select to
487                  * sometimes wake up even though there is no data available.
488                  */
489                 if (len < 0 && errno == EAGAIN)
490                         len = 0;
491
492                 if (len < 0) {
493                         /* An error has encountered.  Perhaps there is a network problem. */
494                         snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
495                                  host, strerror(errno));
496                         buffer_append(&stderr_buffer, buf, strlen(buf));
497                         stderr_bytes += strlen(buf);
498                         quit_pending = 1;
499                         return;
500                 }
501                 packet_process_incoming(buf, len);
502         }
503 }
504
505 /* process the characters one by one */
506 int
507 process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len)
508 {
509         char string[1024];
510         pid_t pid;
511         int bytes = 0;
512         u_int i;
513         u_char ch;
514         char *s;
515
516         for (i = 0; i < len; i++) {
517                 /* Get one character at a time. */
518                 ch = buf[i];
519
520                 if (escape_pending) {
521                         /* We have previously seen an escape character. */
522                         /* Clear the flag now. */
523                         escape_pending = 0;
524
525                         /* Process the escaped character. */
526                         switch (ch) {
527                         case '.':
528                                 /* Terminate the connection. */
529                                 snprintf(string, sizeof string, "%c.\r\n", escape_char);
530                                 buffer_append(berr, string, strlen(string));
531                                 /*stderr_bytes += strlen(string); XXX*/
532
533                                 quit_pending = 1;
534                                 return -1;
535
536                         case 'Z' - 64:
537                                 /* Suspend the program. */
538                                 /* Print a message to that effect to the user. */
539                                 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char);
540                                 buffer_append(berr, string, strlen(string));
541                                 /*stderr_bytes += strlen(string); XXX*/
542
543                                 /* Restore terminal modes and suspend. */
544                                 client_suspend_self(bin, bout, berr);
545
546                                 /* We have been continued. */
547                                 continue;
548
549                         case '&':
550                                 /* XXX does not work yet with proto 2 */
551                                 if (compat20)
552                                         continue;
553                                 /*
554                                  * Detach the program (continue to serve connections,
555                                  * but put in background and no more new connections).
556                                  */
557                                 if (!stdin_eof) {
558                                         /*
559                                          * Sending SSH_CMSG_EOF alone does not always appear
560                                          * to be enough.  So we try to send an EOF character
561                                          * first.
562                                          */
563                                         packet_start(SSH_CMSG_STDIN_DATA);
564                                         packet_put_string("\004", 1);
565                                         packet_send();
566                                         /* Close stdin. */
567                                         stdin_eof = 1;
568                                         if (buffer_len(bin) == 0) {
569                                                 packet_start(SSH_CMSG_EOF);
570                                                 packet_send();
571                                         }
572                                 }
573                                 /* Restore tty modes. */
574                                 leave_raw_mode();
575
576                                 /* Stop listening for new connections. */
577                                 channel_stop_listening();
578
579                                 printf("%c& [backgrounded]\n", escape_char);
580
581                                 /* Fork into background. */
582                                 pid = fork();
583                                 if (pid < 0) {
584                                         error("fork: %.100s", strerror(errno));
585                                         continue;
586                                 }
587                                 if (pid != 0) { /* This is the parent. */
588                                         /* The parent just exits. */
589                                         exit(0);
590                                 }
591                                 /* The child continues serving connections. */
592                                 continue; /*XXX ? */
593
594                         case '?':
595                                 snprintf(string, sizeof string,
596 "%c?\r\n\
597 Supported escape sequences:\r\n\
598 ~.  - terminate connection\r\n\
599 ~^Z - suspend ssh\r\n\
600 ~#  - list forwarded connections\r\n\
601 ~&  - background ssh (when waiting for connections to terminate)\r\n\
602 ~?  - this message\r\n\
603 ~~  - send the escape character by typing it twice\r\n\
604 (Note that escapes are only recognized immediately after newline.)\r\n",
605                                          escape_char);
606                                 buffer_append(berr, string, strlen(string));
607                                 continue;
608
609                         case '#':
610                                 snprintf(string, sizeof string, "%c#\r\n", escape_char);
611                                 buffer_append(berr, string, strlen(string));
612                                 s = channel_open_message();
613                                 buffer_append(berr, s, strlen(s));
614                                 xfree(s);
615                                 continue;
616
617                         default:
618                                 if (ch != escape_char) {
619                                         buffer_put_char(bin, escape_char);
620                                         bytes++;
621                                 }
622                                 /* Escaped characters fall through here */
623                                 break;
624                         }
625                 } else {
626                         /*
627                          * The previous character was not an escape char. Check if this
628                          * is an escape.
629                          */
630                         if (last_was_cr && ch == escape_char) {
631                                 /* It is. Set the flag and continue to next character. */
632                                 escape_pending = 1;
633                                 continue;
634                         }
635                 }
636
637                 /*
638                  * Normal character.  Record whether it was a newline,
639                  * and append it to the buffer.
640                  */
641                 last_was_cr = (ch == '\r' || ch == '\n');
642                 buffer_put_char(bin, ch);
643                 bytes++;
644         }
645         return bytes;
646 }
647
648 void
649 client_process_input(fd_set * readset)
650 {
651         int ret;
652         int len;
653         char buf[8192];
654
655         /* Read input from stdin. */
656         if (FD_ISSET(fileno(stdin), readset)) {
657                 /* Read as much as possible. */
658                 len = read(fileno(stdin), buf, sizeof(buf));
659                 if (len <= 0) {
660                         /*
661                          * Received EOF or error.  They are treated
662                          * similarly, except that an error message is printed
663                          * if it was an error condition.
664                          */
665                         if (len < 0) {
666                                 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
667                                 buffer_append(&stderr_buffer, buf, strlen(buf));
668                                 stderr_bytes += strlen(buf);
669                         }
670                         /* Mark that we have seen EOF. */
671                         stdin_eof = 1;
672                         /*
673                          * Send an EOF message to the server unless there is
674                          * data in the buffer.  If there is data in the
675                          * buffer, no message will be sent now.  Code
676                          * elsewhere will send the EOF when the buffer
677                          * becomes empty if stdin_eof is set.
678                          */
679                         if (buffer_len(&stdin_buffer) == 0) {
680                                 packet_start(SSH_CMSG_EOF);
681                                 packet_send();
682                         }
683                 } else if (escape_char == -1) {
684                         /*
685                          * Normal successful read, and no escape character.
686                          * Just append the data to buffer.
687                          */
688                         buffer_append(&stdin_buffer, buf, len);
689                         stdin_bytes += len;
690                 } else {
691                         /*
692                          * Normal, successful read.  But we have an escape character
693                          * and have to process the characters one by one.
694                          */
695                         ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len);
696                         if (ret == -1)
697                                 return;
698                         stdout_bytes += ret;
699                 }
700         }
701 }
702
703 void
704 client_process_output(fd_set * writeset)
705 {
706         int len;
707         char buf[100];
708
709         /* Write buffered output to stdout. */
710         if (FD_ISSET(fileno(stdout), writeset)) {
711                 /* Write as much data as possible. */
712                 len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
713                     buffer_len(&stdout_buffer));
714                 if (len <= 0) {
715                         if (errno == EAGAIN)
716                                 len = 0;
717                         else {
718                                 /*
719                                  * An error or EOF was encountered.  Put an
720                                  * error message to stderr buffer.
721                                  */
722                                 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
723                                 buffer_append(&stderr_buffer, buf, strlen(buf));
724                                 stderr_bytes += strlen(buf);
725                                 quit_pending = 1;
726                                 return;
727                         }
728                 }
729                 /* Consume printed data from the buffer. */
730                 buffer_consume(&stdout_buffer, len);
731         }
732         /* Write buffered output to stderr. */
733         if (FD_ISSET(fileno(stderr), writeset)) {
734                 /* Write as much data as possible. */
735                 len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
736                     buffer_len(&stderr_buffer));
737                 if (len <= 0) {
738                         if (errno == EAGAIN)
739                                 len = 0;
740                         else {
741                                 /* EOF or error, but can't even print error message. */
742                                 quit_pending = 1;
743                                 return;
744                         }
745                 }
746                 /* Consume printed characters from the buffer. */
747                 buffer_consume(&stderr_buffer, len);
748         }
749 }
750
751 /*
752  * Get packets from the connection input buffer, and process them as long as
753  * there are packets available.
754  *
755  * Any unknown packets received during the actual
756  * session cause the session to terminate.  This is
757  * intended to make debugging easier since no
758  * confirmations are sent.  Any compatible protocol
759  * extensions must be negotiated during the
760  * preparatory phase.
761  */
762
763 void
764 client_process_buffered_input_packets()
765 {
766         dispatch_run(DISPATCH_NONBLOCK, &quit_pending, NULL);
767 }
768
769 /* scan buf[] for '~' before sending data to the peer */
770
771 int
772 simple_escape_filter(Channel *c, char *buf, int len)
773 {
774         /* XXX we assume c->extended is writeable */
775         return process_escapes(&c->input, &c->output, &c->extended, buf, len);
776 }
777
778 /*
779  * Implements the interactive session with the server.  This is called after
780  * the user has been authenticated, and a command has been started on the
781  * remote host.  If escape_char != -1, it is the character used as an escape
782  * character for terminating or suspending the session.
783  */
784
785 int
786 client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
787 {
788         fd_set *readset = NULL, *writeset = NULL;
789         int max_fd = 0;
790         double start_time, total_time;
791         int len;
792         char buf[100];
793
794         debug("Entering interactive session.");
795
796         start_time = get_current_time();
797
798         /* Initialize variables. */
799         escape_pending = 0;
800         last_was_cr = 1;
801         exit_status = -1;
802         stdin_eof = 0;
803         buffer_high = 64 * 1024;
804         connection_in = packet_get_connection_in();
805         connection_out = packet_get_connection_out();
806         max_fd = MAX(connection_in, connection_out);
807
808         if (!compat20) {
809                 max_fd = MAX(max_fd, fileno(stdin));
810                 max_fd = MAX(max_fd, fileno(stdout));
811                 max_fd = MAX(max_fd, fileno(stderr));
812         }
813         stdin_bytes = 0;
814         stdout_bytes = 0;
815         stderr_bytes = 0;
816         quit_pending = 0;
817         escape_char = escape_char_arg;
818
819         /* Initialize buffers. */
820         buffer_init(&stdin_buffer);
821         buffer_init(&stdout_buffer);
822         buffer_init(&stderr_buffer);
823
824         client_init_dispatch();
825
826         /* Set signal handlers to restore non-blocking mode.  */
827         signal(SIGINT, signal_handler);
828         signal(SIGQUIT, signal_handler);
829         signal(SIGTERM, signal_handler);
830         signal(SIGPIPE, SIG_IGN);
831         if (have_pty)
832                 signal(SIGWINCH, window_change_handler);
833
834         if (have_pty)
835                 enter_raw_mode();
836
837         /* Check if we should immediately send eof on stdin. */
838         if (!compat20)
839                 client_check_initial_eof_on_stdin();
840
841         if (compat20 && escape_char != -1)
842                 channel_register_filter(ssh2_chan_id, simple_escape_filter);
843
844         /* Main loop of the client for the interactive session mode. */
845         while (!quit_pending) {
846
847                 /* Process buffered packets sent by the server. */
848                 client_process_buffered_input_packets();
849
850                 if (compat20 && !channel_still_open()) {
851                         debug2("!channel_still_open.");
852                         break;
853                 }
854
855                 /*
856                  * Make packets of buffered stdin data, and buffer them for
857                  * sending to the server.
858                  */
859                 if (!compat20)
860                         client_make_packets_from_stdin_data();
861
862                 /*
863                  * Make packets from buffered channel data, and enqueue them
864                  * for sending to the server.
865                  */
866                 if (packet_not_very_much_data_to_write())
867                         channel_output_poll();
868
869                 /*
870                  * Check if the window size has changed, and buffer a message
871                  * about it to the server if so.
872                  */
873                 client_check_window_change();
874
875                 if (quit_pending)
876                         break;
877
878                 /*
879                  * Wait until we have something to do (something becomes
880                  * available on one of the descriptors).
881                  */
882                 client_wait_until_can_do_something(&readset, &writeset, &max_fd);
883
884                 if (quit_pending)
885                         break;
886
887                 /* Do channel operations. */
888                 channel_after_select(readset, writeset);
889
890                 /* Buffer input from the connection.  */
891                 client_process_net_input(readset);
892
893                 if (quit_pending)
894                         break;
895
896                 if (!compat20) {
897                         /* Buffer data from stdin */
898                         client_process_input(readset);
899                         /*
900                          * Process output to stdout and stderr.  Output to
901                          * the connection is processed elsewhere (above).
902                          */
903                         client_process_output(writeset);
904                 }
905
906                 /* Send as much buffered packet data as possible to the sender. */
907                 if (FD_ISSET(connection_out, writeset))
908                         packet_write_poll();
909         }
910         if (readset)
911                 xfree(readset);
912         if (writeset)
913                 xfree(writeset);
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         u_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         u_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 Channel *
1020 client_request_forwarded_tcpip(const char *request_type, int rchan)
1021 {
1022         Channel* c = NULL;
1023         char *listen_address, *originator_address;
1024         int listen_port, originator_port;
1025         int sock, newch;
1026
1027         /* Get rest of the packet */
1028         listen_address = packet_get_string(NULL);
1029         listen_port = packet_get_int();
1030         originator_address = packet_get_string(NULL);
1031         originator_port = packet_get_int();
1032         packet_done();
1033
1034         debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
1035             listen_address, listen_port, originator_address, originator_port);
1036
1037         sock = channel_connect_by_listen_adress(listen_port);
1038         if (sock >= 0) {
1039                 newch = channel_new("forwarded-tcpip",
1040                     SSH_CHANNEL_CONNECTING, sock, sock, -1,
1041                     CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
1042                     xstrdup(originator_address), 1);
1043                 c = channel_lookup(newch);
1044         }
1045         xfree(originator_address);
1046         xfree(listen_address);
1047         return c;
1048 }
1049
1050 Channel*
1051 client_request_x11(const char *request_type, int rchan)
1052 {
1053         Channel *c = NULL;
1054         char *originator;
1055         int originator_port;
1056         int sock, newch;
1057
1058         if (!options.forward_x11) {
1059                 error("Warning: ssh server tried X11 forwarding.");
1060                 error("Warning: this is probably a break in attempt by a malicious server.");
1061                 return NULL;
1062         }
1063         originator = packet_get_string(NULL);
1064         if (datafellows & SSH_BUG_X11FWD) {
1065                 debug2("buggy server: x11 request w/o originator_port");
1066                 originator_port = 0;
1067         } else {
1068                 originator_port = packet_get_int();
1069         }
1070         packet_done();
1071         /* XXX check permission */
1072         sock = x11_connect_display();
1073         if (sock >= 0) {
1074                 newch = channel_new("x11",
1075                     SSH_CHANNEL_X11_OPEN, sock, sock, -1,
1076                     CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,
1077                     xstrdup("x11"), 1);
1078                 c = channel_lookup(newch);
1079         }
1080         xfree(originator);
1081         return c;
1082 }
1083
1084 Channel*
1085 client_request_agent(const char *request_type, int rchan)
1086 {
1087         Channel *c = NULL;
1088         int sock, newch;
1089
1090         if (!options.forward_agent) {
1091                 error("Warning: ssh server tried agent forwarding.");
1092                 error("Warning: this is probably a break in attempt by a malicious server.");
1093                 return NULL;
1094         }
1095         sock =  ssh_get_authentication_socket();
1096         if (sock >= 0) {
1097                 newch = channel_new("authentication agent connection",
1098                     SSH_CHANNEL_OPEN, sock, sock, -1,
1099                     CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
1100                     xstrdup("authentication agent connection"), 1);
1101                 c = channel_lookup(newch);
1102         }
1103         return c;
1104 }
1105
1106 /* XXXX move to generic input handler */
1107 void
1108 client_input_channel_open(int type, int plen, void *ctxt)
1109 {
1110         Channel *c = NULL;
1111         char *ctype;
1112         u_int len;
1113         int rchan;
1114         int rmaxpack;
1115         int rwindow;
1116
1117         ctype = packet_get_string(&len);
1118         rchan = packet_get_int();
1119         rwindow = packet_get_int();
1120         rmaxpack = packet_get_int();
1121
1122         debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
1123             ctype, rchan, rwindow, rmaxpack);
1124
1125         if (strcmp(ctype, "forwarded-tcpip") == 0) {
1126                 c = client_request_forwarded_tcpip(ctype, rchan);
1127         } else if (strcmp(ctype, "x11") == 0) {
1128                 c = client_request_x11(ctype, rchan);
1129         } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
1130                 c = client_request_agent(ctype, rchan);
1131         }
1132 /* XXX duplicate : */
1133         if (c != NULL) {
1134                 debug("confirm %s", ctype);
1135                 c->remote_id = rchan;
1136                 c->remote_window = rwindow;
1137                 c->remote_maxpacket = rmaxpack;
1138
1139                 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1140                 packet_put_int(c->remote_id);
1141                 packet_put_int(c->self);
1142                 packet_put_int(c->local_window);
1143                 packet_put_int(c->local_maxpacket);
1144                 packet_send();
1145         } else {
1146                 debug("failure %s", ctype);
1147                 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1148                 packet_put_int(rchan);
1149                 packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
1150                 packet_put_cstring("bla bla");
1151                 packet_put_cstring("");
1152                 packet_send();
1153         }
1154         xfree(ctype);
1155 }
1156
1157 void
1158 client_init_dispatch_20()
1159 {
1160         dispatch_init(&dispatch_protocol_error);
1161         dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
1162         dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
1163         dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
1164         dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
1165         dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
1166         dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1167         dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1168         dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
1169         dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
1170 }
1171 void
1172 client_init_dispatch_13()
1173 {
1174         dispatch_init(NULL);
1175         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
1176         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
1177         dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
1178         dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
1179         dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
1180         dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
1181         dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
1182         dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
1183         dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
1184
1185         dispatch_set(SSH_SMSG_AGENT_OPEN, options.forward_agent ?
1186             &auth_input_open_request : &deny_input_open);
1187         dispatch_set(SSH_SMSG_X11_OPEN, options.forward_x11 ?
1188             &x11_input_open : &deny_input_open);
1189 }
1190 void
1191 client_init_dispatch_15()
1192 {
1193         client_init_dispatch_13();
1194         dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
1195         dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
1196 }
1197 void
1198 client_init_dispatch()
1199 {
1200         if (compat20)
1201                 client_init_dispatch_20();
1202         else if (compat13)
1203                 client_init_dispatch_13();
1204         else
1205                 client_init_dispatch_15();
1206 }
1207
1208 void
1209 client_input_channel_req(int id, void *arg)
1210 {
1211         Channel *c = NULL;
1212         u_int len;
1213         int success = 0;
1214         int reply;
1215         char *rtype;
1216
1217         rtype = packet_get_string(&len);
1218         reply = packet_get_char();
1219
1220         debug("client_input_channel_req: rtype %s reply %d", rtype, reply);
1221
1222         c = channel_lookup(id);
1223         if (c == NULL)
1224                 fatal("client_input_channel_req: channel %d: bad channel", id);
1225
1226         if (session_ident == -1) {
1227                 error("client_input_channel_req: no channel %d", id);
1228         } else if (id != session_ident) {
1229                 error("client_input_channel_req: bad channel %d != %d",
1230                     id, session_ident);
1231         } else if (strcmp(rtype, "exit-status") == 0) {
1232                 success = 1;
1233                 exit_status = packet_get_int();
1234                 packet_done();
1235         }
1236         if (reply) {
1237                 packet_start(success ?
1238                     SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1239                 packet_put_int(c->remote_id);
1240                 packet_send();
1241         }
1242         xfree(rtype);
1243 }
1244
1245 void
1246 clientloop_set_session_ident(int id)
1247 {
1248         debug2("clientloop_set_session_ident: id %d", id);
1249         session_ident = id;
1250         channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
1251             client_input_channel_req, (void *)0);
1252 }
This page took 0.13464 seconds and 5 git commands to generate.