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