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 /* Flag indicating that stdin should be redirected from /dev/null. */ 79 extern int stdin_null_flag; 80 81 /* 82 * Name of the host we are connecting to. This is the name given on the 83 * command line, or the HostName specified for the user-supplied name in a 84 * configuration file. 85 */ 86 extern char *host; 87 88 /* 89 * Flag to indicate that we have received a window change signal which has 90 * not yet been processed. This will cause a message indicating the new 91 * window size to be sent to the server a little later. This is volatile 92 * because this is updated in a signal handler. 93 */ 94 static volatile int received_window_change_signal = 0; 95 96 /* Terminal modes, as saved by enter_raw_mode. */ 97 static struct termios saved_tio; 98 99 /* 100 * Flag indicating whether we are in raw mode. This is used by 101 * enter_raw_mode and leave_raw_mode. 102 */ 103 static int in_raw_mode = 0; 104 105 /* Flag indicating whether the user\'s terminal is in non-blocking mode. */ 106 static int in_non_blocking_mode = 0; 107 108 /* Common data for the client loop code. */ 109 static int quit_pending; /* Set to non-zero to quit the client loop. */ 110 static int escape_char; /* Escape character. */ 111 static int escape_pending; /* Last character was the escape character */ 112 static int last_was_cr; /* Last character was a newline. */ 113 static int exit_status; /* Used to store the exit status of the command. */ 114 static int stdin_eof; /* EOF has been encountered on standard error. */ 115 static Buffer stdin_buffer; /* Buffer for stdin data. */ 116 static Buffer stdout_buffer; /* Buffer for stdout data. */ 117 static Buffer stderr_buffer; /* Buffer for stderr data. */ 118 static unsigned long stdin_bytes, stdout_bytes, stderr_bytes; 119 static unsigned int buffer_high;/* Soft max buffer size. */ 120 static int max_fd; /* Maximum file descriptor number in select(). */ 121 static int connection_in; /* Connection to server (input). */ 122 static int connection_out; /* Connection to server (output). */ 123 124 125 void client_init_dispatch(void); 126 int session_ident = -1; 127 128 /* Returns the user\'s terminal to normal mode if it had been put in raw mode. */ 129 130 void 131 leave_raw_mode() 132 { 133 if (!in_raw_mode) 134 return; 135 in_raw_mode = 0; 136 if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0) 137 perror("tcsetattr"); 138 139 fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL); 140 } 141 142 /* Puts the user\'s terminal in raw mode. */ 143 144 void 145 enter_raw_mode() 146 { 147 struct termios tio; 148 149 if (tcgetattr(fileno(stdin), &tio) < 0) 150 perror("tcgetattr"); 151 saved_tio = tio; 152 tio.c_iflag |= IGNPAR; 153 tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); 154 tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); 155 #ifdef IEXTEN 156 tio.c_lflag &= ~IEXTEN; 157 #endif /* IEXTEN */ 158 tio.c_oflag &= ~OPOST; 159 tio.c_cc[VMIN] = 1; 160 tio.c_cc[VTIME] = 0; 161 if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0) 162 perror("tcsetattr"); 163 in_raw_mode = 1; 164 165 fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL); 166 } 167 168 /* Restores stdin to blocking mode. */ 169 170 void 171 leave_non_blocking() 172 { 173 if (in_non_blocking_mode) { 174 (void) fcntl(fileno(stdin), F_SETFL, 0); 175 in_non_blocking_mode = 0; 176 fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL); 177 } 178 } 179 180 /* Puts stdin terminal in non-blocking mode. */ 181 182 void 183 enter_non_blocking() 184 { 185 in_non_blocking_mode = 1; 186 (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK); 187 fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL); 188 } 189 190 /* 191 * Signal handler for the window change signal (SIGWINCH). This just sets a 192 * flag indicating that the window has changed. 193 */ 194 195 void 196 window_change_handler(int sig) 197 { 198 received_window_change_signal = 1; 199 signal(SIGWINCH, window_change_handler); 200 } 201 202 /* 203 * Signal handler for signals that cause the program to terminate. These 204 * signals must be trapped to restore terminal modes. 205 */ 206 207 void 208 signal_handler(int sig) 209 { 210 if (in_raw_mode) 211 leave_raw_mode(); 212 if (in_non_blocking_mode) 213 leave_non_blocking(); 214 channel_stop_listening(); 215 packet_close(); 216 fatal("Killed by signal %d.", sig); 217 } 218 219 /* 220 * Returns current time in seconds from Jan 1, 1970 with the maximum 221 * available resolution. 222 */ 223 224 double 225 get_current_time() 226 { 227 struct timeval tv; 228 gettimeofday(&tv, NULL); 229 return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; 230 } 231 232 /* 233 * This is called when the interactive is entered. This checks if there is 234 * an EOF coming on stdin. We must check this explicitly, as select() does 235 * not appear to wake up when redirecting from /dev/null. 236 */ 237 238 void 239 client_check_initial_eof_on_stdin() 240 { 241 int len; 242 char buf[1]; 243 244 /* 245 * If standard input is to be "redirected from /dev/null", we simply 246 * mark that we have seen an EOF and send an EOF message to the 247 * server. Otherwise, we try to read a single character; it appears 248 * that for some files, such /dev/null, select() never wakes up for 249 * read for this descriptor, which means that we never get EOF. This 250 * way we will get the EOF if stdin comes from /dev/null or similar. 251 */ 252 if (stdin_null_flag) { 253 /* Fake EOF on stdin. */ 254 debug("Sending eof."); 255 stdin_eof = 1; 256 packet_start(SSH_CMSG_EOF); 257 packet_send(); 258 } else { 259 enter_non_blocking(); 260 261 /* Check for immediate EOF on stdin. */ 262 len = read(fileno(stdin), buf, 1); 263 if (len == 0) { 264 /* EOF. Record that we have seen it and send EOF to server. */ 265 debug("Sending eof."); 266 stdin_eof = 1; 267 packet_start(SSH_CMSG_EOF); 268 packet_send(); 269 } else if (len > 0) { 270 /* 271 * Got data. We must store the data in the buffer, 272 * and also process it as an escape character if 273 * appropriate. 274 */ 275 if ((unsigned char) buf[0] == escape_char) 276 escape_pending = 1; 277 else { 278 buffer_append(&stdin_buffer, buf, 1); 279 stdin_bytes += 1; 280 } 281 } 282 leave_non_blocking(); 283 } 284 } 285 286 287 /* 288 * Make packets from buffered stdin data, and buffer them for sending to the 289 * connection. 290 */ 291 292 void 293 client_make_packets_from_stdin_data() 294 { 295 unsigned int len; 296 297 /* Send buffered stdin data to the server. */ 298 while (buffer_len(&stdin_buffer) > 0 && 299 packet_not_very_much_data_to_write()) { 300 len = buffer_len(&stdin_buffer); 301 /* Keep the packets at reasonable size. */ 302 if (len > packet_get_maxsize()) 303 len = packet_get_maxsize(); 304 packet_start(SSH_CMSG_STDIN_DATA); 305 packet_put_string(buffer_ptr(&stdin_buffer), len); 306 packet_send(); 307 buffer_consume(&stdin_buffer, len); 308 /* If we have a pending EOF, send it now. */ 309 if (stdin_eof && buffer_len(&stdin_buffer) == 0) { 310 packet_start(SSH_CMSG_EOF); 311 packet_send(); 312 } 313 } 314 } 315 316 /* 317 * Checks if the client window has changed, and sends a packet about it to 318 * the server if so. The actual change is detected elsewhere (by a software 319 * interrupt on Unix); this just checks the flag and sends a message if 320 * appropriate. 321 */ 322 323 void 324 client_check_window_change() 325 { 326 struct winsize ws; 327 328 if (! received_window_change_signal) 329 return; 330 /** XXX race */ 331 received_window_change_signal = 0; 332 333 if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) 334 return; 335 336 debug("client_check_window_change: changed"); 337 338 if (compat20) { 339 channel_request_start(session_ident, "window-change", 0); 340 packet_put_int(ws.ws_col); 341 packet_put_int(ws.ws_row); 342 packet_put_int(ws.ws_xpixel); 343 packet_put_int(ws.ws_ypixel); 344 packet_send(); 345 } else { 346 packet_start(SSH_CMSG_WINDOW_SIZE); 347 packet_put_int(ws.ws_row); 348 packet_put_int(ws.ws_col); 349 packet_put_int(ws.ws_xpixel); 350 packet_put_int(ws.ws_ypixel); 351 packet_send(); 352 } 353 } 354 355 /* 356 * Waits until the client can do something (some data becomes available on 357 * one of the file descriptors). 358 */ 359 360 void 361 client_wait_until_can_do_something(fd_set * readset, fd_set * writeset) 362 { 363 /*debug("client_wait_until_can_do_something"); */ 364 365 /* Initialize select masks. */ 366 FD_ZERO(readset); 367 FD_ZERO(writeset); 368 369 if (!compat20) { 370 /* Read from the connection, unless our buffers are full. */ 371 if (buffer_len(&stdout_buffer) < buffer_high && 372 buffer_len(&stderr_buffer) < buffer_high && 373 channel_not_very_much_buffered_data()) 374 FD_SET(connection_in, readset); 375 /* 376 * Read from stdin, unless we have seen EOF or have very much 377 * buffered data to send to the server. 378 */ 379 if (!stdin_eof && packet_not_very_much_data_to_write()) 380 FD_SET(fileno(stdin), readset); 381 382 /* Select stdout/stderr if have data in buffer. */ 383 if (buffer_len(&stdout_buffer) > 0) 384 FD_SET(fileno(stdout), writeset); 385 if (buffer_len(&stderr_buffer) > 0) 386 FD_SET(fileno(stderr), writeset); 387 } else { 388 FD_SET(connection_in, readset); 389 } 390 391 /* Add any selections by the channel mechanism. */ 392 channel_prepare_select(readset, writeset); 393 394 /* Select server connection if have data to write to the server. */ 395 if (packet_have_data_to_write()) 396 FD_SET(connection_out, writeset); 397 398 /* move UP XXX */ 399 /* Update maximum file descriptor number, if appropriate. */ 400 if (channel_max_fd() > max_fd) 401 max_fd = channel_max_fd(); 402 403 /* 404 * Wait for something to happen. This will suspend the process until 405 * some selected descriptor can be read, written, or has some other 406 * event pending. Note: if you want to implement SSH_MSG_IGNORE 407 * messages to fool traffic analysis, this might be the place to do 408 * it: just have a random timeout for the select, and send a random 409 * SSH_MSG_IGNORE packet when the timeout expires. 410 */ 411 412 if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) { 413 char buf[100]; 414 /* Some systems fail to clear these automatically. */ 415 FD_ZERO(readset); 416 FD_ZERO(writeset); 417 if (errno == EINTR) 418 return; 419 /* Note: we might still have data in the buffers. */ 420 snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); 421 buffer_append(&stderr_buffer, buf, strlen(buf)); 422 stderr_bytes += strlen(buf); 423 quit_pending = 1; 424 } 425 } 426 427 void 428 client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) 429 { 430 struct winsize oldws, newws; 431 432 /* Flush stdout and stderr buffers. */ 433 if (buffer_len(bout) > 0) 434 atomicio(write, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); 435 if (buffer_len(berr) > 0) 436 atomicio(write, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); 437 438 leave_raw_mode(); 439 440 /* 441 * Free (and clear) the buffer to reduce the amount of data that gets 442 * written to swap. 443 */ 444 buffer_free(bin); 445 buffer_free(bout); 446 buffer_free(berr); 447 448 /* Save old window size. */ 449 ioctl(fileno(stdin), TIOCGWINSZ, &oldws); 450 451 /* Send the suspend signal to the program itself. */ 452 kill(getpid(), SIGTSTP); 453 454 /* Check if the window size has changed. */ 455 if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && 456 (oldws.ws_row != newws.ws_row || 457 oldws.ws_col != newws.ws_col || 458 oldws.ws_xpixel != newws.ws_xpixel || 459 oldws.ws_ypixel != newws.ws_ypixel)) 460 received_window_change_signal = 1; 461 462 /* OK, we have been continued by the user. Reinitialize buffers. */ 463 buffer_init(bin); 464 buffer_init(bout); 465 buffer_init(berr); 466 467 enter_raw_mode(); 468 } 469 470 void 471 client_process_net_input(fd_set * readset) 472 { 473 int len; 474 char buf[8192]; 475 476 /* 477 * Read input from the server, and add any such data to the buffer of 478 * the packet subsystem. 479 */ 480 if (FD_ISSET(connection_in, readset)) { 481 /* Read as much as possible. */ 482 len = read(connection_in, buf, sizeof(buf)); 483 /*debug("read connection_in len %d", len); XXX */ 484 if (len == 0) { 485 /* Received EOF. The remote host has closed the connection. */ 486 snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n", 487 host); 488 buffer_append(&stderr_buffer, buf, strlen(buf)); 489 stderr_bytes += strlen(buf); 490 quit_pending = 1; 491 return; 492 } 493 /* 494 * There is a kernel bug on Solaris that causes select to 495 * sometimes wake up even though there is no data available. 496 */ 497 if (len < 0 && errno == EAGAIN) 498 len = 0; 499 500 if (len < 0) { 501 /* An error has encountered. Perhaps there is a network problem. */ 502 snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n", 503 host, strerror(errno)); 504 buffer_append(&stderr_buffer, buf, strlen(buf)); 505 stderr_bytes += strlen(buf); 506 quit_pending = 1; 507 return; 508 } 509 packet_process_incoming(buf, len); 510 } 511 } 512 513 /* process the characters one by one */ 514 int 515 process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) 516 { 517 char string[1024]; 518 pid_t pid; 519 int bytes = 0; 520 unsigned int i; 521 unsigned char ch; 522 char *s; 523 524 for (i = 0; i < len; i++) { 525 /* Get one character at a time. */ 526 ch = buf[i]; 527 528 if (escape_pending) { 529 /* We have previously seen an escape character. */ 530 /* Clear the flag now. */ 531 escape_pending = 0; 532 533 /* Process the escaped character. */ 534 switch (ch) { 535 case '.': 536 /* Terminate the connection. */ 537 snprintf(string, sizeof string, "%c.\r\n", escape_char); 538 buffer_append(berr, string, strlen(string)); 539 /*stderr_bytes += strlen(string); XXX*/ 540 541 quit_pending = 1; 542 return -1; 543 544 case 'Z' - 64: 545 /* Suspend the program. */ 546 /* Print a message to that effect to the user. */ 547 snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); 548 buffer_append(berr, string, strlen(string)); 549 /*stderr_bytes += strlen(string); XXX*/ 550 551 /* Restore terminal modes and suspend. */ 552 client_suspend_self(bin, bout, berr); 553 554 /* We have been continued. */ 555 continue; 556 557 case '&': 558 /* XXX does not work yet with proto 2 */ 559 if (compat20) 560 continue; 561 /* 562 * Detach the program (continue to serve connections, 563 * but put in background and no more new connections). 564 */ 565 if (!stdin_eof) { 566 /* 567 * Sending SSH_CMSG_EOF alone does not always appear 568 * to be enough. So we try to send an EOF character 569 * first. 570 */ 571 packet_start(SSH_CMSG_STDIN_DATA); 572 packet_put_string("\004", 1); 573 packet_send(); 574 /* Close stdin. */ 575 stdin_eof = 1; 576 if (buffer_len(bin) == 0) { 577 packet_start(SSH_CMSG_EOF); 578 packet_send(); 579 } 580 } 581 /* Restore tty modes. */ 582 leave_raw_mode(); 583 584 /* Stop listening for new connections. */ 585 channel_stop_listening(); 586 587 printf("%c& [backgrounded]\n", escape_char); 588 589 /* Fork into background. */ 590 pid = fork(); 591 if (pid < 0) { 592 error("fork: %.100s", strerror(errno)); 593 continue; 594 } 595 if (pid != 0) { /* This is the parent. */ 596 /* The parent just exits. */ 597 exit(0); 598 } 599 /* The child continues serving connections. */ 600 continue; /*XXX ? */ 601 602 case '?': 603 snprintf(string, sizeof string, 604 "%c?\r\n\ 605 Supported escape sequences:\r\n\ 606 ~. - terminate connection\r\n\ 607 ~^Z - suspend ssh\r\n\ 608 ~# - list forwarded connections\r\n\ 609 ~& - background ssh (when waiting for connections to terminate)\r\n\ 610 ~? - this message\r\n\ 611 ~~ - send the escape character by typing it twice\r\n\ 612 (Note that escapes are only recognized immediately after newline.)\r\n", 613 escape_char); 614 buffer_append(berr, string, strlen(string)); 615 continue; 616 617 case '#': 618 snprintf(string, sizeof string, "%c#\r\n", escape_char); 619 buffer_append(berr, string, strlen(string)); 620 s = channel_open_message(); 621 buffer_append(berr, s, strlen(s)); 622 xfree(s); 623 continue; 624 625 default: 626 if (ch != escape_char) { 627 buffer_put_char(bin, escape_char); 628 bytes++; 629 } 630 /* Escaped characters fall through here */ 631 break; 632 } 633 } else { 634 /* 635 * The previous character was not an escape char. Check if this 636 * is an escape. 637 */ 638 if (last_was_cr && ch == escape_char) { 639 /* It is. Set the flag and continue to next character. */ 640 escape_pending = 1; 641 continue; 642 } 643 } 644 645 /* 646 * Normal character. Record whether it was a newline, 647 * and append it to the buffer. 648 */ 649 last_was_cr = (ch == '\r' || ch == '\n'); 650 buffer_put_char(bin, ch); 651 bytes++; 652 } 653 return bytes; 654 } 655 656 void 657 client_process_input(fd_set * readset) 658 { 659 int ret; 660 int len; 661 char buf[8192]; 662 663 /* Read input from stdin. */ 664 if (FD_ISSET(fileno(stdin), readset)) { 665 /* Read as much as possible. */ 666 len = read(fileno(stdin), buf, sizeof(buf)); 667 if (len <= 0) { 668 /* 669 * Received EOF or error. They are treated 670 * similarly, except that an error message is printed 671 * if it was an error condition. 672 */ 673 if (len < 0) { 674 snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno)); 675 buffer_append(&stderr_buffer, buf, strlen(buf)); 676 stderr_bytes += strlen(buf); 677 } 678 /* Mark that we have seen EOF. */ 679 stdin_eof = 1; 680 /* 681 * Send an EOF message to the server unless there is 682 * data in the buffer. If there is data in the 683 * buffer, no message will be sent now. Code 684 * elsewhere will send the EOF when the buffer 685 * becomes empty if stdin_eof is set. 686 */ 687 if (buffer_len(&stdin_buffer) == 0) { 688 packet_start(SSH_CMSG_EOF); 689 packet_send(); 690 } 691 } else if (escape_char == -1) { 692 /* 693 * Normal successful read, and no escape character. 694 * Just append the data to buffer. 695 */ 696 buffer_append(&stdin_buffer, buf, len); 697 stdin_bytes += len; 698 } else { 699 /* 700 * Normal, successful read. But we have an escape character 701 * and have to process the characters one by one. 702 */ 703 ret = process_escapes(&stdin_buffer, &stdout_buffer, &stderr_buffer, buf, len); 704 if (ret == -1) 705 return; 706 stdout_bytes += ret; 707 } 708 } 709 } 710 711 void 712 client_process_output(fd_set * writeset) 713 { 714 int len; 715 char buf[100]; 716 717 /* Write buffered output to stdout. */ 718 if (FD_ISSET(fileno(stdout), writeset)) { 719 /* Write as much data as possible. */ 720 len = write(fileno(stdout), buffer_ptr(&stdout_buffer), 721 buffer_len(&stdout_buffer)); 722 if (len <= 0) { 723 if (errno == EAGAIN) 724 len = 0; 725 else { 726 /* 727 * An error or EOF was encountered. Put an 728 * error message to stderr buffer. 729 */ 730 snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno)); 731 buffer_append(&stderr_buffer, buf, strlen(buf)); 732 stderr_bytes += strlen(buf); 733 quit_pending = 1; 734 return; 735 } 736 } 737 /* Consume printed data from the buffer. */ 738 buffer_consume(&stdout_buffer, len); 739 } 740 /* Write buffered output to stderr. */ 741 if (FD_ISSET(fileno(stderr), writeset)) { 742 /* Write as much data as possible. */ 743 len = write(fileno(stderr), buffer_ptr(&stderr_buffer), 744 buffer_len(&stderr_buffer)); 745 if (len <= 0) { 746 if (errno == EAGAIN) 747 len = 0; 748 else { 749 /* EOF or error, but can't even print error message. */ 750 quit_pending = 1; 751 return; 752 } 753 } 754 /* Consume printed characters from the buffer. */ 755 buffer_consume(&stderr_buffer, len); 756 } 757 } 758 759 /* 760 * Get packets from the connection input buffer, and process them as long as 761 * there are packets available. 762 * 763 * Any unknown packets received during the actual 764 * session cause the session to terminate. This is 765 * intended to make debugging easier since no 766 * confirmations are sent. Any compatible protocol 767 * extensions must be negotiated during the 768 * preparatory phase. 769 */ 770 771 void 772 client_process_buffered_input_packets() 773 { 774 dispatch_run(DISPATCH_NONBLOCK, &quit_pending); 775 } 776 777 /* scan buf[] for '~' before sending data to the peer */ 778 779 int 780 simple_escape_filter(Channel *c, char *buf, int len) 781 { 782 /* XXX we assume c->extended is writeable */ 783 return process_escapes(&c->input, &c->output, &c->extended, buf, len); 784 } 785 786 /* 787 * Implements the interactive session with the server. This is called after 788 * the user has been authenticated, and a command has been started on the 789 * remote host. If escape_char != -1, it is the character used as an escape 790 * character for terminating or suspending the session. 791 */ 792 793 int 794 client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 795 { 796 extern Options options; 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 debug("!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) 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) 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) 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) 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) { 1040 int sock; 1041 char *originator; 1042 int originator_port; 1043 originator = packet_get_string(NULL); 1044 if (datafellows & SSH_BUG_X11FWD) { 1045 debug("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")); 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_AGENT_OPEN, &auth_input_open_request); 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 dispatch_set(SSH_SMSG_X11_OPEN, &x11_input_open); 1116 } 1117 void 1118 client_init_dispatch_15() 1119 { 1120 client_init_dispatch_13(); 1121 dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); 1122 dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose); 1123 } 1124 void 1125 client_init_dispatch() 1126 { 1127 if (compat20) 1128 client_init_dispatch_20(); 1129 else if (compat13) 1130 client_init_dispatch_13(); 1131 else 1132 client_init_dispatch_15(); 1133 } 1134 1135 void 1136 client_input_channel_req(int id, void *arg) 1137 { 1138 Channel *c = NULL; 1139 unsigned int len; 1140 int success = 0; 1141 int reply; 1142 char *rtype; 1143 1144 rtype = packet_get_string(&len); 1145 reply = packet_get_char(); 1146 1147 debug("client_input_channel_req: rtype %s reply %d", rtype, reply); 1148 1149 c = channel_lookup(id); 1150 if (c == NULL) 1151 fatal("session_input_channel_req: channel %d: bad channel", id); 1152 1153 if (session_ident == -1) { 1154 error("client_input_channel_req: no channel %d", id); 1155 } else if (id != session_ident) { 1156 error("client_input_channel_req: bad channel %d != %d", 1157 id, session_ident); 1158 } else if (strcmp(rtype, "exit-status") == 0) { 1159 success = 1; 1160 exit_status = packet_get_int(); 1161 packet_done(); 1162 } 1163 if (reply) { 1164 packet_start(success ? 1165 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 1166 packet_put_int(c->remote_id); 1167 packet_send(); 1168 } 1169 xfree(rtype); 1170 } 1171 1172 void 1173 client_set_session_ident(int id) 1174 { 1175 debug("client_set_session_ident: id %d", id); 1176 session_ident = id; 1177 channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST, 1178 client_input_channel_req, (void *)0); 1179 } 1180