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