[BACK]Return to clientloop.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/clientloop.c, Revision 1.11

1.1       deraadt     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: */
                     16:
                     17: #include "includes.h"
1.11    ! markus     18: RCSID("$Id: clientloop.c,v 1.10 1999/11/19 19:58:18 markus Exp $");
1.1       deraadt    19:
                     20: #include "xmalloc.h"
                     21: #include "ssh.h"
                     22: #include "packet.h"
                     23: #include "buffer.h"
                     24: #include "authfd.h"
1.8       markus     25: #include "readconf.h"
1.1       deraadt    26:
                     27: /* Flag indicating that stdin should be redirected from /dev/null. */
                     28: extern int stdin_null_flag;
                     29:
                     30: /* Name of the host we are connecting to.  This is the name given on the
                     31:    command line, or the HostName specified for the user-supplied name
                     32:    in a configuration file. */
                     33: extern char *host;
                     34:
                     35: /* Flag to indicate that we have received a window change signal which has
                     36:    not yet been processed.  This will cause a message indicating the new
                     37:    window size to be sent to the server a little later.  This is volatile
                     38:    because this is updated in a signal handler. */
                     39: static volatile int received_window_change_signal = 0;
                     40:
                     41: /* Terminal modes, as saved by enter_raw_mode. */
                     42: static struct termios saved_tio;
                     43:
                     44: /* Flag indicating whether we are in raw mode.  This is used by enter_raw_mode
                     45:    and leave_raw_mode. */
                     46: static int in_raw_mode = 0;
                     47:
                     48: /* Flag indicating whether the user\'s terminal is in non-blocking mode. */
                     49: static int in_non_blocking_mode = 0;
                     50:
                     51: /* Common data for the client loop code. */
1.11    ! markus     52: static int escape_pending;     /* Last character was the escape character */
        !            53: static int last_was_cr;                /* Last character was a newline. */
        !            54: static int exit_status;                /* Used to store the exit status of the command. */
        !            55: static int stdin_eof;          /* EOF has been encountered on standard error. */
        !            56: static Buffer stdin_buffer;    /* Buffer for stdin data. */
        !            57: static Buffer stdout_buffer;   /* Buffer for stdout data. */
        !            58: static Buffer stderr_buffer;   /* Buffer for stderr data. */
        !            59: static unsigned int buffer_high;/* Soft max buffer size. */
        !            60: static int max_fd;             /* Maximum file descriptor number in select(). */
        !            61: static int connection_in;      /* Connection to server (input). */
        !            62: static int connection_out;     /* Connection to server (output). */
1.1       deraadt    63: static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
1.11    ! markus     64: static int quit_pending;       /* Set to non-zero to quit the client loop. */
        !            65: static int escape_char;                /* Escape character. */
1.1       deraadt    66:
1.11    ! markus     67: /* Returns the user\'s terminal to normal mode if it had been put in raw
1.1       deraadt    68:    mode. */
                     69:
1.11    ! markus     70: void
        !            71: leave_raw_mode()
1.1       deraadt    72: {
1.11    ! markus     73:        if (!in_raw_mode)
        !            74:                return;
        !            75:        in_raw_mode = 0;
        !            76:        if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
        !            77:                perror("tcsetattr");
1.1       deraadt    78:
1.11    ! markus     79:        fatal_remove_cleanup((void (*) (void *)) leave_raw_mode, NULL);
1.1       deraadt    80: }
                     81:
                     82: /* Puts the user\'s terminal in raw mode. */
                     83:
1.11    ! markus     84: void
        !            85: enter_raw_mode()
1.1       deraadt    86: {
1.11    ! markus     87:        struct termios tio;
1.1       deraadt    88:
1.11    ! markus     89:        if (tcgetattr(fileno(stdin), &tio) < 0)
        !            90:                perror("tcgetattr");
        !            91:        saved_tio = tio;
        !            92:        tio.c_iflag |= IGNPAR;
        !            93:        tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
        !            94:        tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
1.1       deraadt    95: #ifdef IEXTEN
1.11    ! markus     96:        tio.c_lflag &= ~IEXTEN;
        !            97: #endif                         /* IEXTEN */
        !            98:        tio.c_oflag &= ~OPOST;
        !            99:        tio.c_cc[VMIN] = 1;
        !           100:        tio.c_cc[VTIME] = 0;
        !           101:        if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
        !           102:                perror("tcsetattr");
        !           103:        in_raw_mode = 1;
1.1       deraadt   104:
1.11    ! markus    105:        fatal_add_cleanup((void (*) (void *)) leave_raw_mode, NULL);
        !           106: }
1.1       deraadt   107:
                    108: /* Restores stdin to blocking mode. */
                    109:
1.11    ! markus    110: void
        !           111: leave_non_blocking()
1.1       deraadt   112: {
1.11    ! markus    113:        if (in_non_blocking_mode) {
        !           114:                (void) fcntl(fileno(stdin), F_SETFL, 0);
        !           115:                in_non_blocking_mode = 0;
        !           116:                fatal_remove_cleanup((void (*) (void *)) leave_non_blocking, NULL);
        !           117:        }
1.1       deraadt   118: }
                    119:
1.11    ! markus    120: /* Puts stdin terminal in non-blocking mode. */
        !           121:
        !           122: void
        !           123: enter_non_blocking()
1.1       deraadt   124: {
1.11    ! markus    125:        in_non_blocking_mode = 1;
        !           126:        (void) fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
        !           127:        fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
1.1       deraadt   128: }
                    129:
                    130: /* Signal handler for the window change signal (SIGWINCH).  This just
                    131:    sets a flag indicating that the window has changed. */
                    132:
1.11    ! markus    133: void
        !           134: window_change_handler(int sig)
1.1       deraadt   135: {
1.11    ! markus    136:        received_window_change_signal = 1;
        !           137:        signal(SIGWINCH, window_change_handler);
1.1       deraadt   138: }
                    139:
                    140: /* Signal handler for signals that cause the program to terminate.  These
                    141:    signals must be trapped to restore terminal modes. */
                    142:
1.11    ! markus    143: void
        !           144: signal_handler(int sig)
1.1       deraadt   145: {
1.11    ! markus    146:        if (in_raw_mode)
        !           147:                leave_raw_mode();
        !           148:        if (in_non_blocking_mode)
        !           149:                leave_non_blocking();
        !           150:        channel_stop_listening();
        !           151:        packet_close();
        !           152:        fatal("Killed by signal %d.", sig);
1.1       deraadt   153: }
                    154:
                    155: /* Returns current time in seconds from Jan 1, 1970 with the maximum available
                    156:    resolution. */
                    157:
1.11    ! markus    158: double
        !           159: get_current_time()
1.1       deraadt   160: {
1.11    ! markus    161:        struct timeval tv;
        !           162:        gettimeofday(&tv, NULL);
        !           163:        return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
1.1       deraadt   164: }
                    165:
                    166: /* This is called when the interactive is entered.  This checks if there
                    167:    is an EOF coming on stdin.  We must check this explicitly, as select()
                    168:    does not appear to wake up when redirecting from /dev/null. */
                    169:
1.11    ! markus    170: void
        !           171: client_check_initial_eof_on_stdin()
1.1       deraadt   172: {
1.11    ! markus    173:        int len;
        !           174:        char buf[1];
1.1       deraadt   175:
1.11    ! markus    176:        /* If standard input is to be "redirected from /dev/null", we
        !           177:           simply mark that we have seen an EOF and send an EOF message to
        !           178:           the server. Otherwise, we try to read a single character; it
        !           179:           appears that for some files, such /dev/null, select() never
        !           180:           wakes up for read for this descriptor, which means that we
        !           181:           never get EOF.  This way we will get the EOF if stdin comes
        !           182:           from /dev/null or similar. */
        !           183:        if (stdin_null_flag) {
        !           184:                /* Fake EOF on stdin. */
        !           185:                debug("Sending eof.");
        !           186:                stdin_eof = 1;
        !           187:                packet_start(SSH_CMSG_EOF);
        !           188:                packet_send();
        !           189:        } else {
        !           190:                /* Enter non-blocking mode for stdin. */
        !           191:                enter_non_blocking();
        !           192:
        !           193:                /* Check for immediate EOF on stdin. */
        !           194:                len = read(fileno(stdin), buf, 1);
        !           195:                if (len == 0) {
        !           196:                        /* EOF.  Record that we have seen it and send EOF
        !           197:                           to server. */
        !           198:                        debug("Sending eof.");
        !           199:                        stdin_eof = 1;
        !           200:                        packet_start(SSH_CMSG_EOF);
        !           201:                        packet_send();
        !           202:                } else if (len > 0) {
        !           203:                        /* Got data.  We must store the data in the
        !           204:                           buffer, and also process it as an escape
        !           205:                           character if appropriate. */
        !           206:                        if ((unsigned char) buf[0] == escape_char)
        !           207:                                escape_pending = 1;
        !           208:                        else {
        !           209:                                buffer_append(&stdin_buffer, buf, 1);
        !           210:                                stdin_bytes += 1;
        !           211:                        }
        !           212:                }
        !           213:                /* Leave non-blocking mode. */
        !           214:                leave_non_blocking();
        !           215:        }
1.1       deraadt   216: }
                    217:
                    218: /* Get packets from the connection input buffer, and process them as long
                    219:    as there are packets available. */
                    220:
1.11    ! markus    221: void
        !           222: client_process_buffered_input_packets()
1.1       deraadt   223: {
1.11    ! markus    224:        int type;
        !           225:        char *data;
        !           226:        unsigned int data_len;
        !           227:        int payload_len;
        !           228:
        !           229:        /* Process any buffered packets from the server. */
        !           230:        while (!quit_pending &&
        !           231:               (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
        !           232:                switch (type) {
        !           233:
        !           234:                case SSH_SMSG_STDOUT_DATA:
        !           235:                        data = packet_get_string(&data_len);
        !           236:                        packet_integrity_check(payload_len, 4 + data_len, type);
        !           237:                        buffer_append(&stdout_buffer, data, data_len);
        !           238:                        stdout_bytes += data_len;
        !           239:                        memset(data, 0, data_len);
        !           240:                        xfree(data);
        !           241:                        break;
        !           242:
        !           243:                case SSH_SMSG_STDERR_DATA:
        !           244:                        data = packet_get_string(&data_len);
        !           245:                        packet_integrity_check(payload_len, 4 + data_len, type);
        !           246:                        buffer_append(&stderr_buffer, data, data_len);
        !           247:                        stdout_bytes += data_len;
        !           248:                        memset(data, 0, data_len);
        !           249:                        xfree(data);
        !           250:                        break;
        !           251:
        !           252:                case SSH_SMSG_EXITSTATUS:
        !           253:                        packet_integrity_check(payload_len, 4, type);
        !           254:                        exit_status = packet_get_int();
        !           255:                        /* Acknowledge the exit. */
        !           256:                        packet_start(SSH_CMSG_EXIT_CONFIRMATION);
        !           257:                        packet_send();
        !           258:                        /* Must wait for packet to be sent since we are
        !           259:                           exiting the loop. */
        !           260:                        packet_write_wait();
        !           261:                        /* Flag that we want to exit. */
        !           262:                        quit_pending = 1;
        !           263:                        break;
        !           264:
        !           265:                case SSH_SMSG_X11_OPEN:
        !           266:                        x11_input_open(payload_len);
        !           267:                        break;
        !           268:
        !           269:                case SSH_MSG_PORT_OPEN:
        !           270:                        channel_input_port_open(payload_len);
        !           271:                        break;
        !           272:
        !           273:                case SSH_SMSG_AGENT_OPEN:
        !           274:                        packet_integrity_check(payload_len, 4, type);
        !           275:                        auth_input_open_request();
        !           276:                        break;
        !           277:
        !           278:                case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
        !           279:                        packet_integrity_check(payload_len, 4 + 4, type);
        !           280:                        channel_input_open_confirmation();
        !           281:                        break;
        !           282:
        !           283:                case SSH_MSG_CHANNEL_OPEN_FAILURE:
        !           284:                        packet_integrity_check(payload_len, 4, type);
        !           285:                        channel_input_open_failure();
        !           286:                        break;
        !           287:
        !           288:                case SSH_MSG_CHANNEL_DATA:
        !           289:                        channel_input_data(payload_len);
        !           290:                        break;
        !           291:
        !           292:                case SSH_MSG_CHANNEL_CLOSE:
        !           293:                        packet_integrity_check(payload_len, 4, type);
        !           294:                        channel_input_close();
        !           295:                        break;
        !           296:
        !           297:                case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
        !           298:                        packet_integrity_check(payload_len, 4, type);
        !           299:                        channel_input_close_confirmation();
        !           300:                        break;
        !           301:
        !           302:                default:
        !           303:                        /* Any unknown packets received during the actual
        !           304:                           session cause the session to terminate.  This
        !           305:                           is intended to make debugging easier since no
        !           306:                           confirmations are sent.  Any compatible
        !           307:                           protocol extensions must be negotiated during
        !           308:                           the preparatory phase. */
        !           309:                        packet_disconnect("Protocol error during session: type %d",
        !           310:                                          type);
        !           311:                }
1.1       deraadt   312:        }
                    313: }
                    314:
                    315: /* Make packets from buffered stdin data, and buffer them for sending to
                    316:    the connection. */
                    317:
1.11    ! markus    318: void
        !           319: client_make_packets_from_stdin_data()
1.1       deraadt   320: {
1.11    ! markus    321:        unsigned int len;
1.1       deraadt   322:
1.11    ! markus    323:        /* Send buffered stdin data to the server. */
        !           324:        while (buffer_len(&stdin_buffer) > 0 &&
        !           325:               packet_not_very_much_data_to_write()) {
        !           326:                len = buffer_len(&stdin_buffer);
        !           327:                /* Keep the packets at reasonable size. */
        !           328:                if (len > packet_get_maxsize())
        !           329:                        len = packet_get_maxsize();
        !           330:                packet_start(SSH_CMSG_STDIN_DATA);
        !           331:                packet_put_string(buffer_ptr(&stdin_buffer), len);
        !           332:                packet_send();
        !           333:                buffer_consume(&stdin_buffer, len);
        !           334:                /* If we have a pending EOF, send it now. */
        !           335:                if (stdin_eof && buffer_len(&stdin_buffer) == 0) {
        !           336:                        packet_start(SSH_CMSG_EOF);
        !           337:                        packet_send();
        !           338:                }
1.1       deraadt   339:        }
                    340: }
                    341:
                    342: /* Checks if the client window has changed, and sends a packet about it to
                    343:    the server if so.  The actual change is detected elsewhere (by a software
                    344:    interrupt on Unix); this just checks the flag and sends a message if
                    345:    appropriate. */
                    346:
1.11    ! markus    347: void
        !           348: client_check_window_change()
1.1       deraadt   349: {
1.11    ! markus    350:        /* Send possible window change message to the server. */
        !           351:        if (received_window_change_signal) {
        !           352:                struct winsize ws;
        !           353:
        !           354:                /* Clear the window change indicator. */
        !           355:                received_window_change_signal = 0;
        !           356:
        !           357:                /* Read new window size. */
        !           358:                if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0) {
        !           359:                        /* Successful, send the packet now. */
        !           360:                        packet_start(SSH_CMSG_WINDOW_SIZE);
        !           361:                        packet_put_int(ws.ws_row);
        !           362:                        packet_put_int(ws.ws_col);
        !           363:                        packet_put_int(ws.ws_xpixel);
        !           364:                        packet_put_int(ws.ws_ypixel);
        !           365:                        packet_send();
        !           366:                }
1.1       deraadt   367:        }
                    368: }
                    369:
                    370: /* Waits until the client can do something (some data becomes available on
                    371:    one of the file descriptors). */
                    372:
1.11    ! markus    373: void
        !           374: client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
        !           375: {
        !           376:        /* Initialize select masks. */
        !           377:        FD_ZERO(readset);
        !           378:
        !           379:        /* Read from the connection, unless our buffers are full. */
        !           380:        if (buffer_len(&stdout_buffer) < buffer_high &&
        !           381:            buffer_len(&stderr_buffer) < buffer_high &&
        !           382:            channel_not_very_much_buffered_data())
        !           383:                FD_SET(connection_in, readset);
        !           384:
        !           385:        /* Read from stdin, unless we have seen EOF or have very much
        !           386:           buffered data to send to the server. */
        !           387:        if (!stdin_eof && packet_not_very_much_data_to_write())
        !           388:                FD_SET(fileno(stdin), readset);
        !           389:
        !           390:        FD_ZERO(writeset);
        !           391:
        !           392:        /* Add any selections by the channel mechanism. */
        !           393:        channel_prepare_select(readset, writeset);
        !           394:
        !           395:        /* Select server connection if have data to write to the server. */
        !           396:        if (packet_have_data_to_write())
        !           397:                FD_SET(connection_out, writeset);
        !           398:
        !           399:        /* Select stdout if have data in buffer. */
        !           400:        if (buffer_len(&stdout_buffer) > 0)
        !           401:                FD_SET(fileno(stdout), writeset);
        !           402:
        !           403:        /* Select stderr if have data in buffer. */
        !           404:        if (buffer_len(&stderr_buffer) > 0)
        !           405:                FD_SET(fileno(stderr), writeset);
        !           406:
        !           407:        /* Update maximum file descriptor number, if appropriate. */
        !           408:        if (channel_max_fd() > max_fd)
        !           409:                max_fd = channel_max_fd();
        !           410:
        !           411:        /* Wait for something to happen.  This will suspend the process
        !           412:           until some selected descriptor can be read, written, or has
        !           413:           some other event pending.
        !           414:           Note: if you want to implement SSH_MSG_IGNORE messages to fool
        !           415:           traffic analysis, this might be the place to do it:
        !           416:           just have a random timeout for the select, and send a random
        !           417:           SSH_MSG_IGNORE packet when the timeout expires. */
        !           418:
        !           419:        if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) {
        !           420:                char buf[100];
        !           421:                /* Some systems fail to clear these automatically. */
        !           422:                FD_ZERO(readset);
        !           423:                FD_ZERO(writeset);
        !           424:                if (errno == EINTR)
        !           425:                        return;
        !           426:                /* Note: we might still have data in the buffers. */
        !           427:                snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno));
        !           428:                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           429:                stderr_bytes += strlen(buf);
        !           430:                quit_pending = 1;
        !           431:        }
        !           432: }
        !           433:
        !           434: void
        !           435: client_suspend_self()
1.1       deraadt   436: {
1.11    ! markus    437:        struct winsize oldws, newws;
        !           438:
        !           439:        /* Flush stdout and stderr buffers. */
        !           440:        if (buffer_len(&stdout_buffer) > 0)
        !           441:                write(fileno(stdout),
        !           442:                      buffer_ptr(&stdout_buffer),
        !           443:                      buffer_len(&stdout_buffer));
        !           444:        if (buffer_len(&stderr_buffer) > 0)
        !           445:                write(fileno(stderr),
        !           446:                      buffer_ptr(&stderr_buffer),
        !           447:                      buffer_len(&stderr_buffer));
        !           448:
        !           449:        /* Leave raw mode. */
        !           450:        leave_raw_mode();
        !           451:
        !           452:        /* Free (and clear) the buffer to reduce the amount of data that
        !           453:           gets written to swap. */
        !           454:        buffer_free(&stdin_buffer);
        !           455:        buffer_free(&stdout_buffer);
        !           456:        buffer_free(&stderr_buffer);
        !           457:
        !           458:        /* Save old window size. */
        !           459:        ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
        !           460:
        !           461:        /* Send the suspend signal to the program itself. */
        !           462:        kill(getpid(), SIGTSTP);
        !           463:
        !           464:        /* Check if the window size has changed. */
        !           465:        if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
        !           466:            (oldws.ws_row != newws.ws_row ||
        !           467:             oldws.ws_col != newws.ws_col ||
        !           468:             oldws.ws_xpixel != newws.ws_xpixel ||
        !           469:             oldws.ws_ypixel != newws.ws_ypixel))
        !           470:                received_window_change_signal = 1;
        !           471:
        !           472:        /* OK, we have been continued by the user. Reinitialize buffers. */
        !           473:        buffer_init(&stdin_buffer);
        !           474:        buffer_init(&stdout_buffer);
        !           475:        buffer_init(&stderr_buffer);
        !           476:
        !           477:        /* Re-enter raw mode. */
        !           478:        enter_raw_mode();
        !           479: }
        !           480:
        !           481: void
        !           482: client_process_input(fd_set * readset)
        !           483: {
        !           484:        int len, pid;
        !           485:        char buf[8192], *s;
        !           486:
        !           487:        /* Read input from the server, and add any such data to the buffer
        !           488:           of the packet subsystem. */
        !           489:        if (FD_ISSET(connection_in, readset)) {
        !           490:                /* Read as much as possible. */
        !           491:                len = read(connection_in, buf, sizeof(buf));
        !           492:                if (len == 0) {
        !           493:                        /* Received EOF.  The remote host has closed the connection. */
        !           494:                        snprintf(buf, sizeof buf, "Connection to %.300s closed by remote host.\r\n",
        !           495:                                 host);
1.1       deraadt   496:                        buffer_append(&stderr_buffer, buf, strlen(buf));
                    497:                        stderr_bytes += strlen(buf);
                    498:                        quit_pending = 1;
                    499:                        return;
1.11    ! markus    500:                }
        !           501:                /* There is a kernel bug on Solaris that causes select to
        !           502:                   sometimes wake up even though there is no data
        !           503:                   available. */
        !           504:                if (len < 0 && errno == EAGAIN)
        !           505:                        len = 0;
        !           506:
        !           507:                if (len < 0) {
        !           508:                        /* An error has encountered.  Perhaps there is a network problem. */
        !           509:                        snprintf(buf, sizeof buf, "Read from remote host %.300s: %.100s\r\n",
        !           510:                                 host, strerror(errno));
        !           511:                        buffer_append(&stderr_buffer, buf, strlen(buf));
        !           512:                        stderr_bytes += strlen(buf);
        !           513:                        quit_pending = 1;
        !           514:                        return;
        !           515:                }
        !           516:                packet_process_incoming(buf, len);
        !           517:        }
        !           518:        /* Read input from stdin. */
        !           519:        if (FD_ISSET(fileno(stdin), readset)) {
        !           520:                /* Read as much as possible. */
        !           521:                len = read(fileno(stdin), buf, sizeof(buf));
        !           522:                if (len <= 0) {
        !           523:                        /* Received EOF or error.  They are treated
        !           524:                           similarly, except that an error message is
        !           525:                           printed if it was an error condition. */
        !           526:                        if (len < 0) {
        !           527:                                snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
        !           528:                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           529:                                stderr_bytes += strlen(buf);
        !           530:                        }
        !           531:                        /* Mark that we have seen EOF. */
        !           532:                        stdin_eof = 1;
        !           533:                        /* Send an EOF message to the server unless there
        !           534:                           is data in the buffer.  If there is data in the
        !           535:                           buffer, no message will be sent now.  Code
        !           536:                           elsewhere will send the EOF when the buffer
        !           537:                           becomes empty if stdin_eof is set. */
        !           538:                        if (buffer_len(&stdin_buffer) == 0) {
1.1       deraadt   539:                                packet_start(SSH_CMSG_EOF);
                    540:                                packet_send();
1.11    ! markus    541:                        }
        !           542:                } else if (escape_char == -1) {
        !           543:                        /* Normal successful read, and no escape
        !           544:                           character.  Just append the data to buffer. */
        !           545:                        buffer_append(&stdin_buffer, buf, len);
        !           546:                        stdin_bytes += len;
        !           547:                } else {
        !           548:                        /* Normal, successful read.  But we have an escape
        !           549:                           character and have to process the characters
        !           550:                           one by one. */
        !           551:                        unsigned int i;
        !           552:                        for (i = 0; i < len; i++) {
        !           553:                                unsigned char ch;
        !           554:                                /* Get one character at a time. */
        !           555:                                ch = buf[i];
        !           556:
        !           557:                                /* Check if we have a pending escape
        !           558:                                   character. */
        !           559:                                if (escape_pending) {
        !           560:                                        /* We have previously seen an escape character. */
        !           561:                                        /* Clear the flag now. */
        !           562:                                        escape_pending = 0;
        !           563:                                        /* Process the escaped character. */
        !           564:                                        switch (ch) {
        !           565:                                        case '.':
        !           566:                                                /* Terminate the connection. */
        !           567:                                                snprintf(buf, sizeof buf, "%c.\r\n", escape_char);
        !           568:                                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           569:                                                stderr_bytes += strlen(buf);
        !           570:                                                quit_pending = 1;
        !           571:                                                return;
        !           572:
        !           573:                                        case 'Z' - 64:
        !           574:                                                /* Suspend the program. */
        !           575:                                                /* Print a message to that effect to the user. */
        !           576:                                                snprintf(buf, sizeof buf, "%c^Z\r\n", escape_char);
        !           577:                                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           578:                                                stderr_bytes += strlen(buf);
        !           579:
        !           580:                                                /* Restore terminal modes and suspend. */
        !           581:                                                client_suspend_self();
        !           582:
        !           583:                                                /* We have been continued. */
        !           584:                                                continue;
        !           585:
        !           586:                                        case '&':
        !           587:                                                /* Detach the program (continue to serve connections,
        !           588:                                                   but put in background and no more new connections). */
        !           589:                                                if (!stdin_eof) {
        !           590:                                                        /* Sending SSH_CMSG_EOF alone does not always appear
        !           591:                                                           to be enough.  So we try to send an EOF character
        !           592:                                                           first. */
        !           593:                                                        packet_start(SSH_CMSG_STDIN_DATA);
        !           594:                                                        packet_put_string("\004", 1);
        !           595:                                                        packet_send();
        !           596:                                                        /* Close stdin. */
        !           597:                                                        stdin_eof = 1;
        !           598:                                                        if (buffer_len(&stdin_buffer) == 0) {
        !           599:                                                                packet_start(SSH_CMSG_EOF);
        !           600:                                                                packet_send();
        !           601:                                                        }
        !           602:                                                }
        !           603:                                                /* Restore tty modes. */
        !           604:                                                leave_raw_mode();
        !           605:
        !           606:                                                /* Stop listening for new connections. */
        !           607:                                                channel_stop_listening();
        !           608:
        !           609:                                                printf("%c& [backgrounded]\n", escape_char);
        !           610:
        !           611:                                                /* Fork into background. */
        !           612:                                                pid = fork();
        !           613:                                                if (pid < 0) {
        !           614:                                                        error("fork: %.100s", strerror(errno));
        !           615:                                                        continue;
        !           616:                                                }
        !           617:                                                if (pid != 0) { /* This is the parent. */
        !           618:                                                        /* The parent just exits. */
        !           619:                                                        exit(0);
        !           620:                                                }
        !           621:                                                /* The child continues serving connections. */
        !           622:                                                continue;
        !           623:
        !           624:                                        case '?':
        !           625:                                                snprintf(buf, sizeof buf,
        !           626: "%c?\r\n\
1.1       deraadt   627: Supported escape sequences:\r\n\
                    628: ~.  - terminate connection\r\n\
                    629: ~^Z - suspend ssh\r\n\
                    630: ~#  - list forwarded connections\r\n\
                    631: ~&  - background ssh (when waiting for connections to terminate)\r\n\
                    632: ~?  - this message\r\n\
                    633: ~~  - send the escape character by typing it twice\r\n\
                    634: (Note that escapes are only recognized immediately after newline.)\r\n",
1.11    ! markus    635:                                                         escape_char);
        !           636:                                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           637:                                                continue;
        !           638:
        !           639:                                        case '#':
        !           640:                                                snprintf(buf, sizeof buf, "%c#\r\n", escape_char);
        !           641:                                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           642:                                                s = channel_open_message();
        !           643:                                                buffer_append(&stderr_buffer, s, strlen(s));
        !           644:                                                xfree(s);
        !           645:                                                continue;
        !           646:
        !           647:                                        default:
        !           648:                                                if (ch != escape_char) {
        !           649:                                                        /* Escape character followed by non-special character.
        !           650:                                                           Append both to the input buffer. */
        !           651:                                                        buf[0] = escape_char;
        !           652:                                                        buf[1] = ch;
        !           653:                                                        buffer_append(&stdin_buffer, buf, 2);
        !           654:                                                        stdin_bytes += 2;
        !           655:                                                        continue;
        !           656:                                                }
        !           657:                                                /* Note that escape character typed twice
        !           658:                                                   falls through here; the latter gets processed
        !           659:                                                   as a normal character below. */
        !           660:                                                break;
        !           661:                                        }
        !           662:                                } else {
        !           663:                                        /* The previous character was not an escape char. Check if this
        !           664:                                           is an escape. */
        !           665:                                        if (last_was_cr && ch == escape_char) {
        !           666:                                                /* It is. Set the flag and continue to next character. */
        !           667:                                                escape_pending = 1;
        !           668:                                                continue;
        !           669:                                        }
        !           670:                                }
        !           671:
        !           672:                                /* Normal character.  Record whether it was a newline, and append it to the
        !           673:                                   buffer. */
        !           674:                                last_was_cr = (ch == '\r' || ch == '\n');
        !           675:                                buf[0] = ch;
        !           676:                                buffer_append(&stdin_buffer, buf, 1);
        !           677:                                stdin_bytes += 1;
        !           678:                                continue;
        !           679:                        }
        !           680:                }
        !           681:        }
        !           682: }
        !           683:
        !           684: void
        !           685: client_process_output(fd_set * writeset)
        !           686: {
        !           687:        int len;
        !           688:        char buf[100];
1.1       deraadt   689:
1.11    ! markus    690:        /* Write buffered output to stdout. */
        !           691:        if (FD_ISSET(fileno(stdout), writeset)) {
        !           692:                /* Write as much data as possible. */
        !           693:                len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
        !           694:                            buffer_len(&stdout_buffer));
        !           695:                if (len <= 0) {
        !           696:                        if (errno == EAGAIN)
        !           697:                                len = 0;
        !           698:                        else {
        !           699:                                /* An error or EOF was encountered.  Put
        !           700:                                   an error message to stderr buffer. */
        !           701:                                snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
        !           702:                                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           703:                                stderr_bytes += strlen(buf);
        !           704:                                quit_pending = 1;
        !           705:                                return;
        !           706:                        }
        !           707:                }
        !           708:                /* Consume printed data from the buffer. */
        !           709:                buffer_consume(&stdout_buffer, len);
        !           710:        }
        !           711:        /* Write buffered output to stderr. */
        !           712:        if (FD_ISSET(fileno(stderr), writeset)) {
        !           713:                /* Write as much data as possible. */
        !           714:                len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
        !           715:                            buffer_len(&stderr_buffer));
        !           716:                if (len <= 0) {
        !           717:                        if (errno == EAGAIN)
        !           718:                                len = 0;
        !           719:                        else {
        !           720:                                /* EOF or error, but can't even print
        !           721:                                   error message. */
        !           722:                                quit_pending = 1;
        !           723:                                return;
        !           724:                        }
        !           725:                }
        !           726:                /* Consume printed characters from the buffer. */
        !           727:                buffer_consume(&stderr_buffer, len);
        !           728:        }
1.1       deraadt   729: }
                    730:
                    731: /* Implements the interactive session with the server.  This is called
                    732:    after the user has been authenticated, and a command has been
                    733:    started on the remote host.  If escape_char != -1, it is the character
                    734:    used as an escape character for terminating or suspending the
                    735:    session. */
                    736:
1.11    ! markus    737: int
        !           738: client_loop(int have_pty, int escape_char_arg)
1.1       deraadt   739: {
1.11    ! markus    740:        extern Options options;
        !           741:        double start_time, total_time;
        !           742:        int len;
        !           743:        char buf[100];
        !           744:
        !           745:        debug("Entering interactive session.");
        !           746:
        !           747:        start_time = get_current_time();
        !           748:
        !           749:        /* Initialize variables. */
        !           750:        escape_pending = 0;
        !           751:        last_was_cr = 1;
        !           752:        exit_status = -1;
        !           753:        stdin_eof = 0;
        !           754:        buffer_high = 64 * 1024;
        !           755:        connection_in = packet_get_connection_in();
        !           756:        connection_out = packet_get_connection_out();
        !           757:        max_fd = connection_in;
        !           758:        if (connection_out > max_fd)
        !           759:                max_fd = connection_out;
        !           760:        stdin_bytes = 0;
        !           761:        stdout_bytes = 0;
        !           762:        stderr_bytes = 0;
        !           763:        quit_pending = 0;
        !           764:        escape_char = escape_char_arg;
        !           765:
        !           766:        /* Initialize buffers. */
        !           767:        buffer_init(&stdin_buffer);
        !           768:        buffer_init(&stdout_buffer);
        !           769:        buffer_init(&stderr_buffer);
        !           770:
        !           771:        /* Set signal handlers to restore non-blocking mode.  */
        !           772:        signal(SIGINT, signal_handler);
        !           773:        signal(SIGQUIT, signal_handler);
        !           774:        signal(SIGTERM, signal_handler);
        !           775:        signal(SIGPIPE, SIG_IGN);
        !           776:        if (have_pty)
        !           777:                signal(SIGWINCH, window_change_handler);
        !           778:
        !           779:        /* Enter raw mode if have a pseudo terminal. */
        !           780:        if (have_pty)
        !           781:                enter_raw_mode();
        !           782:
        !           783:        /* Check if we should immediately send of on stdin. */
        !           784:        client_check_initial_eof_on_stdin();
        !           785:
        !           786:        /* Main loop of the client for the interactive session mode. */
        !           787:        while (!quit_pending) {
        !           788:                fd_set readset, writeset;
        !           789:
        !           790:                /* Precess buffered packets sent by the server. */
        !           791:                client_process_buffered_input_packets();
        !           792:
        !           793:                /* Make packets of buffered stdin data, and buffer them
        !           794:                   for sending to the server. */
        !           795:                client_make_packets_from_stdin_data();
        !           796:
        !           797:                /* Make packets from buffered channel data, and buffer
        !           798:                   them for sending to the server. */
        !           799:                if (packet_not_very_much_data_to_write())
        !           800:                        channel_output_poll();
        !           801:
        !           802:                /* Check if the window size has changed, and buffer a
        !           803:                   message about it to the server if so. */
        !           804:                client_check_window_change();
        !           805:
        !           806:                if (quit_pending)
        !           807:                        break;
        !           808:
        !           809:                /* Wait until we have something to do (something becomes
        !           810:                   available on one of the descriptors). */
        !           811:                client_wait_until_can_do_something(&readset, &writeset);
        !           812:
        !           813:                if (quit_pending)
        !           814:                        break;
        !           815:
        !           816:                /* Do channel operations. */
        !           817:                channel_after_select(&readset, &writeset);
        !           818:
        !           819:                /* Process input from the connection and from stdin.
        !           820:                   Buffer any data that is available. */
        !           821:                client_process_input(&readset);
        !           822:
        !           823:                /* Process output to stdout and stderr.   Output to the
        !           824:                   connection is processed elsewhere (above). */
        !           825:                client_process_output(&writeset);
        !           826:
        !           827:                /* Send as much buffered packet data as possible to the
        !           828:                   sender. */
        !           829:                if (FD_ISSET(connection_out, &writeset))
        !           830:                        packet_write_poll();
        !           831:        }
        !           832:
        !           833:        /* Terminate the session. */
        !           834:
        !           835:        /* Stop watching for window change. */
        !           836:        if (have_pty)
        !           837:                signal(SIGWINCH, SIG_DFL);
        !           838:
        !           839:        /* Stop listening for connections. */
        !           840:        channel_stop_listening();
        !           841:
        !           842:        /* In interactive mode (with pseudo tty) display a message
        !           843:           indicating that the connection has been closed. */
        !           844:        if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
        !           845:                snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
        !           846:                buffer_append(&stderr_buffer, buf, strlen(buf));
        !           847:                stderr_bytes += strlen(buf);
        !           848:        }
        !           849:        /* Output any buffered data for stdout. */
        !           850:        while (buffer_len(&stdout_buffer) > 0) {
        !           851:                len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
        !           852:                            buffer_len(&stdout_buffer));
        !           853:                if (len <= 0) {
        !           854:                        error("Write failed flushing stdout buffer.");
        !           855:                        break;
        !           856:                }
        !           857:                buffer_consume(&stdout_buffer, len);
        !           858:        }
        !           859:
        !           860:        /* Output any buffered data for stderr. */
        !           861:        while (buffer_len(&stderr_buffer) > 0) {
        !           862:                len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
        !           863:                            buffer_len(&stderr_buffer));
        !           864:                if (len <= 0) {
        !           865:                        error("Write failed flushing stderr buffer.");
        !           866:                        break;
        !           867:                }
        !           868:                buffer_consume(&stderr_buffer, len);
        !           869:        }
        !           870:
        !           871:        /* Leave raw mode. */
        !           872:        if (have_pty)
        !           873:                leave_raw_mode();
        !           874:
        !           875:        /* Clear and free any buffers. */
        !           876:        memset(buf, 0, sizeof(buf));
        !           877:        buffer_free(&stdin_buffer);
        !           878:        buffer_free(&stdout_buffer);
        !           879:        buffer_free(&stderr_buffer);
        !           880:
        !           881:        /* Report bytes transferred, and transfer rates. */
        !           882:        total_time = get_current_time() - start_time;
        !           883:        debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
        !           884:              stdin_bytes, stdout_bytes, stderr_bytes, total_time);
        !           885:        if (total_time > 0)
        !           886:                debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
        !           887:                      stdin_bytes / total_time, stdout_bytes / total_time,
        !           888:                      stderr_bytes / total_time);
        !           889:
        !           890:        /* Return the exit status of the program. */
        !           891:        debug("Exit status %d", exit_status);
        !           892:        return exit_status;
1.1       deraadt   893: }