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