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

Annotation of src/usr.bin/ssh/channel.c, Revision 1.2

1.1       markus      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:  * This file contains functions for generic socket connection forwarding.
                      6:  * There is also code for initiating connection forwarding for X11 connections,
                      7:  * arbitrary tcp/ip connections, and the authentication agent connection.
                      8:  *
                      9:  * As far as I am concerned, the code I have written for this software
                     10:  * can be used freely for any purpose.  Any derived versions of this
                     11:  * software must be clearly marked as such, and if the derived work is
                     12:  * incompatible with the protocol description in the RFC file, it must be
                     13:  * called by a name other than "ssh" or "Secure Shell".
                     14:  *
                     15:  *
                     16:  * SSH2 support added by Markus Friedl.
                     17:  * Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.
                     18:  * Copyright (c) 1999 Dug Song.  All rights reserved.
                     19:  * Copyright (c) 1999 Theo de Raadt.  All rights reserved.
                     20:  *
                     21:  * Redistribution and use in source and binary forms, with or without
                     22:  * modification, are permitted provided that the following conditions
                     23:  * are met:
                     24:  * 1. Redistributions of source code must retain the above copyright
                     25:  *    notice, this list of conditions and the following disclaimer.
                     26:  * 2. Redistributions in binary form must reproduce the above copyright
                     27:  *    notice, this list of conditions and the following disclaimer in the
                     28:  *    documentation and/or other materials provided with the distribution.
                     29:  *
                     30:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     31:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     32:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     33:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     34:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     35:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     36:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     37:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     38:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     39:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: #include "includes.h"
1.2     ! markus     43: RCSID("$OpenBSD: channel.c,v 1.1 2001/05/30 12:55:08 markus Exp $");
1.1       markus     44:
                     45: #include "ssh2.h"
                     46: #include "packet.h"
                     47: #include "xmalloc.h"
                     48: #include "log.h"
                     49: #include "misc.h"
                     50: #include "channel.h"
                     51: #include "compat.h"
                     52:
                     53: /*
                     54:  * Pointer to an array containing all allocated channels.  The array is
                     55:  * dynamically extended as needed.
                     56:  */
                     57: Channel **channels = NULL;
                     58:
                     59: /*
                     60:  * Size of the channel array.  All slots of the array must always be
                     61:  * initialized (at least the type field); unused slots set to NULL
                     62:  */
                     63: int channels_alloc = 0;
                     64:
                     65: /*
                     66:  * Maximum file descriptor value used in any of the channels.  This is
                     67:  * updated in channel_new.
                     68:  */
                     69: int channel_max_fd = 0;
                     70:
                     71:
                     72: Channel *
                     73: channel_lookup(int id)
                     74: {
                     75:        Channel *c;
                     76:
                     77:        if (id < 0 || id > channels_alloc) {
                     78:                log("channel_lookup: %d: bad id", id);
                     79:                return NULL;
                     80:        }
                     81:        c = channels[id];
                     82:        if (c == NULL) {
                     83:                log("channel_lookup: %d: bad id: channel free", id);
                     84:                return NULL;
                     85:        }
                     86:        return c;
                     87: }
                     88:
                     89: /*
                     90:  * Register filedescriptors for a channel, used when allocating a channel or
                     91:  * when the channel consumer/producer is ready, e.g. shell exec'd
                     92:  */
                     93:
                     94: void
                     95: channel_register_fds(Channel *c, int rfd, int wfd, int efd,
                     96:     int extusage, int nonblock)
                     97: {
                     98:        /* Update the maximum file descriptor value. */
                     99:        channel_max_fd = MAX(channel_max_fd, rfd);
                    100:        channel_max_fd = MAX(channel_max_fd, wfd);
                    101:        channel_max_fd = MAX(channel_max_fd, efd);
                    102:
                    103:        /* XXX set close-on-exec -markus */
                    104:
                    105:        c->rfd = rfd;
                    106:        c->wfd = wfd;
                    107:        c->sock = (rfd == wfd) ? rfd : -1;
                    108:        c->efd = efd;
                    109:        c->extended_usage = extusage;
                    110:
                    111:        /* XXX ugly hack: nonblock is only set by the server */
                    112:        if (nonblock && isatty(c->rfd)) {
                    113:                debug("channel %d: rfd %d isatty", c->self, c->rfd);
                    114:                c->isatty = 1;
                    115:                if (!isatty(c->wfd)) {
                    116:                        error("channel %d: wfd %d is not a tty?",
                    117:                            c->self, c->wfd);
                    118:                }
                    119:        } else {
                    120:                c->isatty = 0;
                    121:        }
                    122:
                    123:        /* enable nonblocking mode */
                    124:        if (nonblock) {
                    125:                if (rfd != -1)
                    126:                        set_nonblock(rfd);
                    127:                if (wfd != -1)
                    128:                        set_nonblock(wfd);
                    129:                if (efd != -1)
                    130:                        set_nonblock(efd);
                    131:        }
                    132: }
                    133:
                    134: /*
                    135:  * Allocate a new channel object and set its type and socket. This will cause
                    136:  * remote_name to be freed.
                    137:  */
                    138:
                    139: Channel *
                    140: channel_new(char *ctype, int type, int rfd, int wfd, int efd,
                    141:     int window, int maxpack, int extusage, char *remote_name, int nonblock)
                    142: {
                    143:        int i, found;
                    144:        Channel *c;
                    145:
                    146:        /* Do initial allocation if this is the first call. */
                    147:        if (channels_alloc == 0) {
                    148:                chan_init();
                    149:                channels_alloc = 10;
                    150:                channels = xmalloc(channels_alloc * sizeof(Channel *));
                    151:                for (i = 0; i < channels_alloc; i++)
                    152:                        channels[i] = NULL;
                    153:                /*
                    154:                 * Kludge: arrange a call to channel_stop_listening if we
                    155:                 * terminate with fatal().
                    156:                 */
                    157:                fatal_add_cleanup((void (*) (void *)) channel_stop_listening, NULL);
                    158:        }
                    159:        /* Try to find a free slot where to put the new channel. */
                    160:        for (found = -1, i = 0; i < channels_alloc; i++)
                    161:                if (channels[i] == NULL) {
                    162:                        /* Found a free slot. */
                    163:                        found = i;
                    164:                        break;
                    165:                }
                    166:        if (found == -1) {
                    167:                /* There are no free slots.  Take last+1 slot and expand the array.  */
                    168:                found = channels_alloc;
                    169:                channels_alloc += 10;
                    170:                debug2("channel: expanding %d", channels_alloc);
                    171:                channels = xrealloc(channels, channels_alloc * sizeof(Channel *));
                    172:                for (i = found; i < channels_alloc; i++)
                    173:                        channels[i] = NULL;
                    174:        }
                    175:        /* Initialize and return new channel. */
                    176:        c = channels[found] = xmalloc(sizeof(Channel));
                    177:        buffer_init(&c->input);
                    178:        buffer_init(&c->output);
                    179:        buffer_init(&c->extended);
                    180:        chan_init_iostates(c);
                    181:        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
                    182:        c->self = found;
                    183:        c->type = type;
                    184:        c->ctype = ctype;
                    185:        c->local_window = window;
                    186:        c->local_window_max = window;
                    187:        c->local_consumed = 0;
                    188:        c->local_maxpacket = maxpack;
                    189:        c->remote_id = -1;
                    190:        c->remote_name = remote_name;
                    191:        c->remote_window = 0;
                    192:        c->remote_maxpacket = 0;
                    193:        c->cb_fn = NULL;
                    194:        c->cb_arg = NULL;
                    195:        c->cb_event = 0;
                    196:        c->dettach_user = NULL;
                    197:        c->input_filter = NULL;
                    198:        debug("channel %d: new [%s]", found, remote_name);
                    199:        return c;
                    200: }
                    201:
                    202: /* Close all channel fd/socket. */
                    203:
                    204: void
                    205: channel_close_fds(Channel *c)
                    206: {
                    207:        debug3("channel_close_fds: channel %d: r %d w %d e %d",
                    208:            c->self, c->rfd, c->wfd, c->efd);
                    209:
                    210:        if (c->sock != -1) {
                    211:                close(c->sock);
                    212:                c->sock = -1;
                    213:        }
                    214:        if (c->rfd != -1) {
                    215:                close(c->rfd);
                    216:                c->rfd = -1;
                    217:        }
                    218:        if (c->wfd != -1) {
                    219:                close(c->wfd);
                    220:                c->wfd = -1;
                    221:        }
                    222:        if (c->efd != -1) {
                    223:                close(c->efd);
                    224:                c->efd = -1;
                    225:        }
                    226: }
                    227:
                    228: /* Free the channel and close its fd/socket. */
                    229:
                    230: void
                    231: channel_free(Channel *c)
                    232: {
                    233:        char *s;
                    234:        int i, n;
                    235:
                    236:        for (n = 0, i = 0; i < channels_alloc; i++)
                    237:                if (channels[i])
                    238:                        n++;
                    239:        debug("channel_free: channel %d: %s, nchannels %d", c->self,
                    240:            c->remote_name ? c->remote_name : "???", n);
                    241:
                    242:        s = channel_open_message();
                    243:        debug3("channel_free: status: %s", s);
                    244:        xfree(s);
                    245:
                    246:        if (c->dettach_user != NULL) {
                    247:                debug("channel_free: channel %d: dettaching channel user", c->self);
                    248:                c->dettach_user(c->self, NULL);
                    249:        }
                    250:        if (c->sock != -1)
                    251:                shutdown(c->sock, SHUT_RDWR);
                    252:        channel_close_fds(c);
                    253:        buffer_free(&c->input);
                    254:        buffer_free(&c->output);
                    255:        buffer_free(&c->extended);
                    256:        if (c->remote_name) {
                    257:                xfree(c->remote_name);
                    258:                c->remote_name = NULL;
                    259:        }
                    260:        channels[c->self] = NULL;
                    261:        xfree(c);
                    262: }
                    263:
                    264:
                    265: /*
                    266:  * Stops listening for channels, and removes any unix domain sockets that we
                    267:  * might have.
                    268:  */
                    269:
                    270: void
                    271: channel_stop_listening()
                    272: {
                    273:        int i;
                    274:        Channel *c;
                    275:
                    276:        for (i = 0; i < channels_alloc; i++) {
                    277:                c = channels[i];
                    278:                if (c != NULL) {
                    279:                        switch (c->type) {
                    280:                        case SSH_CHANNEL_AUTH_SOCKET:
                    281:                                close(c->sock);
                    282:                                unlink(c->path);
                    283:                                channel_free(c);
                    284:                                break;
                    285:                        case SSH_CHANNEL_PORT_LISTENER:
                    286:                        case SSH_CHANNEL_RPORT_LISTENER:
                    287:                        case SSH_CHANNEL_X11_LISTENER:
                    288:                                close(c->sock);
                    289:                                channel_free(c);
                    290:                                break;
                    291:                        default:
                    292:                                break;
                    293:                        }
                    294:                }
                    295:        }
                    296: }
                    297:
                    298: /*
                    299:  * Closes the sockets/fds of all channels.  This is used to close extra file
                    300:  * descriptors after a fork.
                    301:  */
                    302:
                    303: void
                    304: channel_close_all()
                    305: {
                    306:        int i;
                    307:
                    308:        for (i = 0; i < channels_alloc; i++)
                    309:                if (channels[i] != NULL)
                    310:                        channel_close_fds(channels[i]);
                    311: }
                    312:
                    313: /*
                    314:  * Returns true if no channel has too much buffered data, and false if one or
                    315:  * more channel is overfull.
                    316:  */
                    317:
                    318: int
                    319: channel_not_very_much_buffered_data()
                    320: {
                    321:        u_int i;
                    322:        Channel *c;
                    323:
                    324:        for (i = 0; i < channels_alloc; i++) {
                    325:                c = channels[i];
                    326:                if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
                    327:                        if (!compat20 && buffer_len(&c->input) > packet_get_maxsize()) {
                    328:                                debug("channel %d: big input buffer %d",
                    329:                                    c->self, buffer_len(&c->input));
                    330:                                return 0;
                    331:                        }
                    332:                        if (buffer_len(&c->output) > packet_get_maxsize()) {
                    333:                                debug("channel %d: big output buffer %d",
                    334:                                    c->self, buffer_len(&c->output));
                    335:                                return 0;
                    336:                        }
                    337:                }
                    338:        }
                    339:        return 1;
                    340: }
                    341:
                    342: /* Returns true if any channel is still open. */
                    343:
                    344: int
                    345: channel_still_open()
                    346: {
                    347:        int i;
                    348:        Channel *c;
                    349:
                    350:        for (i = 0; i < channels_alloc; i++) {
                    351:                c = channels[i];
                    352:                if (c == NULL)
                    353:                        continue;
                    354:                switch (c->type) {
                    355:                case SSH_CHANNEL_X11_LISTENER:
                    356:                case SSH_CHANNEL_PORT_LISTENER:
                    357:                case SSH_CHANNEL_RPORT_LISTENER:
                    358:                case SSH_CHANNEL_CLOSED:
                    359:                case SSH_CHANNEL_AUTH_SOCKET:
                    360:                case SSH_CHANNEL_DYNAMIC:
                    361:                case SSH_CHANNEL_CONNECTING:
                    362:                case SSH_CHANNEL_ZOMBIE:
                    363:                        continue;
                    364:                case SSH_CHANNEL_LARVAL:
                    365:                        if (!compat20)
                    366:                                fatal("cannot happen: SSH_CHANNEL_LARVAL");
                    367:                        continue;
                    368:                case SSH_CHANNEL_OPENING:
                    369:                case SSH_CHANNEL_OPEN:
                    370:                case SSH_CHANNEL_X11_OPEN:
                    371:                        return 1;
                    372:                case SSH_CHANNEL_INPUT_DRAINING:
                    373:                case SSH_CHANNEL_OUTPUT_DRAINING:
                    374:                        if (!compat13)
                    375:                                fatal("cannot happen: OUT_DRAIN");
                    376:                        return 1;
                    377:                default:
                    378:                        fatal("channel_still_open: bad channel type %d", c->type);
                    379:                        /* NOTREACHED */
                    380:                }
                    381:        }
                    382:        return 0;
                    383: }
                    384:
                    385: /* Returns the id of an open channel suitable for keepaliving */
                    386:
                    387: int
                    388: channel_find_open()
                    389: {
                    390:        int i;
                    391:        Channel *c;
                    392:
                    393:        for (i = 0; i < channels_alloc; i++) {
                    394:                c = channels[i];
                    395:                if (c == NULL)
                    396:                        continue;
                    397:                switch (c->type) {
                    398:                case SSH_CHANNEL_CLOSED:
                    399:                case SSH_CHANNEL_DYNAMIC:
                    400:                case SSH_CHANNEL_X11_LISTENER:
                    401:                case SSH_CHANNEL_PORT_LISTENER:
                    402:                case SSH_CHANNEL_RPORT_LISTENER:
                    403:                case SSH_CHANNEL_OPENING:
                    404:                case SSH_CHANNEL_CONNECTING:
                    405:                case SSH_CHANNEL_ZOMBIE:
                    406:                        continue;
                    407:                case SSH_CHANNEL_LARVAL:
                    408:                case SSH_CHANNEL_AUTH_SOCKET:
                    409:                case SSH_CHANNEL_OPEN:
                    410:                case SSH_CHANNEL_X11_OPEN:
                    411:                        return i;
                    412:                case SSH_CHANNEL_INPUT_DRAINING:
                    413:                case SSH_CHANNEL_OUTPUT_DRAINING:
                    414:                        if (!compat13)
                    415:                                fatal("cannot happen: OUT_DRAIN");
                    416:                        return i;
                    417:                default:
                    418:                        fatal("channel_find_open: bad channel type %d", c->type);
                    419:                        /* NOTREACHED */
                    420:                }
                    421:        }
                    422:        return -1;
                    423: }
                    424:
                    425:
                    426: /*
                    427:  * Returns a message describing the currently open forwarded connections,
                    428:  * suitable for sending to the client.  The message contains crlf pairs for
                    429:  * newlines.
                    430:  */
                    431:
                    432: char *
                    433: channel_open_message()
                    434: {
                    435:        Buffer buffer;
                    436:        Channel *c;
                    437:        char buf[1024], *cp;
                    438:        int i;
                    439:
                    440:        buffer_init(&buffer);
                    441:        snprintf(buf, sizeof buf, "The following connections are open:\r\n");
                    442:        buffer_append(&buffer, buf, strlen(buf));
                    443:        for (i = 0; i < channels_alloc; i++) {
                    444:                c = channels[i];
                    445:                if (c == NULL)
                    446:                        continue;
                    447:                switch (c->type) {
                    448:                case SSH_CHANNEL_X11_LISTENER:
                    449:                case SSH_CHANNEL_PORT_LISTENER:
                    450:                case SSH_CHANNEL_RPORT_LISTENER:
                    451:                case SSH_CHANNEL_CLOSED:
                    452:                case SSH_CHANNEL_AUTH_SOCKET:
                    453:                case SSH_CHANNEL_ZOMBIE:
                    454:                        continue;
                    455:                case SSH_CHANNEL_LARVAL:
                    456:                case SSH_CHANNEL_OPENING:
                    457:                case SSH_CHANNEL_CONNECTING:
                    458:                case SSH_CHANNEL_DYNAMIC:
                    459:                case SSH_CHANNEL_OPEN:
                    460:                case SSH_CHANNEL_X11_OPEN:
                    461:                case SSH_CHANNEL_INPUT_DRAINING:
                    462:                case SSH_CHANNEL_OUTPUT_DRAINING:
                    463:                        snprintf(buf, sizeof buf, "  #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n",
                    464:                            c->self, c->remote_name,
                    465:                            c->type, c->remote_id,
                    466:                            c->istate, buffer_len(&c->input),
                    467:                            c->ostate, buffer_len(&c->output),
                    468:                            c->rfd, c->wfd);
                    469:                        buffer_append(&buffer, buf, strlen(buf));
                    470:                        continue;
                    471:                default:
                    472:                        fatal("channel_open_message: bad channel type %d", c->type);
                    473:                        /* NOTREACHED */
                    474:                }
                    475:        }
                    476:        buffer_append(&buffer, "\0", 1);
                    477:        cp = xstrdup(buffer_ptr(&buffer));
                    478:        buffer_free(&buffer);
                    479:        return cp;
                    480: }
                    481:
                    482: void
1.2     ! markus    483: channel_send_open(int id)
1.1       markus    484: {
                    485:        Channel *c = channel_lookup(id);
                    486:        if (c == NULL) {
1.2     ! markus    487:                log("channel_send_open: %d: bad id", id);
1.1       markus    488:                return;
                    489:        }
                    490:        debug("send channel open %d", id);
                    491:        packet_start(SSH2_MSG_CHANNEL_OPEN);
                    492:        packet_put_cstring(c->ctype);
                    493:        packet_put_int(c->self);
                    494:        packet_put_int(c->local_window);
                    495:        packet_put_int(c->local_maxpacket);
                    496:        packet_send();
                    497: }
1.2     ! markus    498:
1.1       markus    499: void
                    500: channel_request(int id, char *service, int wantconfirm)
                    501: {
                    502:        channel_request_start(id, service, wantconfirm);
                    503:        packet_send();
                    504:        debug("channel request %d: %s", id, service) ;
                    505: }
                    506: void
                    507: channel_request_start(int id, char *service, int wantconfirm)
                    508: {
                    509:        Channel *c = channel_lookup(id);
                    510:        if (c == NULL) {
                    511:                log("channel_request: %d: bad id", id);
                    512:                return;
                    513:        }
                    514:        packet_start(SSH2_MSG_CHANNEL_REQUEST);
                    515:        packet_put_int(c->remote_id);
                    516:        packet_put_cstring(service);
                    517:        packet_put_char(wantconfirm);
                    518: }
                    519: void
                    520: channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg)
                    521: {
                    522:        Channel *c = channel_lookup(id);
                    523:        if (c == NULL) {
                    524:                log("channel_register_callback: %d: bad id", id);
                    525:                return;
                    526:        }
                    527:        c->cb_event = mtype;
                    528:        c->cb_fn = fn;
                    529:        c->cb_arg = arg;
                    530: }
                    531: void
                    532: channel_register_cleanup(int id, channel_callback_fn *fn)
                    533: {
                    534:        Channel *c = channel_lookup(id);
                    535:        if (c == NULL) {
                    536:                log("channel_register_cleanup: %d: bad id", id);
                    537:                return;
                    538:        }
                    539:        c->dettach_user = fn;
                    540: }
                    541: void
                    542: channel_cancel_cleanup(int id)
                    543: {
                    544:        Channel *c = channel_lookup(id);
                    545:        if (c == NULL) {
                    546:                log("channel_cancel_cleanup: %d: bad id", id);
                    547:                return;
                    548:        }
                    549:        c->dettach_user = NULL;
                    550: }
                    551: void
                    552: channel_register_filter(int id, channel_filter_fn *fn)
                    553: {
                    554:        Channel *c = channel_lookup(id);
                    555:        if (c == NULL) {
                    556:                log("channel_register_filter: %d: bad id", id);
                    557:                return;
                    558:        }
                    559:        c->input_filter = fn;
                    560: }
                    561:
                    562: void
                    563: channel_set_fds(int id, int rfd, int wfd, int efd,
                    564:     int extusage, int nonblock)
                    565: {
                    566:        Channel *c = channel_lookup(id);
                    567:        if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
                    568:                fatal("channel_activate for non-larval channel %d.", id);
                    569:        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
                    570:        c->type = SSH_CHANNEL_OPEN;
                    571:        /* XXX window size? */
                    572:        c->local_window = c->local_window_max = c->local_maxpacket * 2;
                    573:        packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
                    574:        packet_put_int(c->remote_id);
                    575:        packet_put_int(c->local_window);
                    576:        packet_send();
                    577: }