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

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

1.2     ! djm         1: /* $OpenBSD: mux.c,v 1.1 2008/05/09 14:18:44 djm Exp $ */
1.1       djm         2: /*
                      3:  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: /* ssh session multiplexing support */
                     19:
1.2     ! djm        20: /*
        !            21:  * TODO:
        !            22:  *   1. partial reads in muxserver_accept_control (maybe make channels
        !            23:  *      from accepted connections)
        !            24:  *   2. Better signalling from master to slave, especially passing of
        !            25:  *      error messages
        !            26:  *   3. Better fall-back from mux slave error to new connection.
        !            27:  *   3. Add/delete forwardings via slave
        !            28:  *   4. ExitOnForwardingFailure (after #3 obviously)
        !            29:  *   5. Maybe extension mechanisms for multi-X11/multi-agent forwarding
        !            30:  *   6. Document the mux mini-protocol somewhere.
        !            31:  *   6. Support ~^Z in mux slaves.
        !            32:  */
        !            33:
1.1       djm        34: #include <sys/types.h>
                     35: #include <sys/param.h>
                     36: #include <sys/queue.h>
                     37: #include <sys/stat.h>
                     38: #include <sys/socket.h>
                     39: #include <sys/un.h>
                     40:
                     41: #include <errno.h>
                     42: #include <fcntl.h>
                     43: #include <signal.h>
                     44: #include <stdarg.h>
                     45: #include <stddef.h>
                     46: #include <stdlib.h>
                     47: #include <stdio.h>
                     48: #include <string.h>
                     49: #include <unistd.h>
                     50: #include <util.h>
                     51: #include <paths.h>
                     52:
                     53: #include "xmalloc.h"
                     54: #include "log.h"
                     55: #include "ssh.h"
                     56: #include "pathnames.h"
                     57: #include "misc.h"
                     58: #include "match.h"
                     59: #include "buffer.h"
                     60: #include "channels.h"
                     61: #include "msg.h"
                     62: #include "packet.h"
                     63: #include "monitor_fdpass.h"
                     64: #include "sshpty.h"
                     65: #include "key.h"
                     66: #include "readconf.h"
                     67: #include "clientloop.h"
                     68:
                     69: /* from ssh.c */
                     70: extern int tty_flag;
                     71: extern Options options;
                     72: extern int stdin_null_flag;
                     73: extern char *host;
                     74: int subsystem_flag;
                     75: extern Buffer command;
                     76:
1.2     ! djm        77: /* Context for session open confirmation callback */
        !            78: struct mux_session_confirm_ctx {
        !            79:        int want_tty;
        !            80:        int want_subsys;
        !            81:        int want_x_fwd;
        !            82:        int want_agent_fwd;
        !            83:        Buffer cmd;
        !            84:        char *term;
        !            85:        struct termios tio;
        !            86:        char **env;
        !            87: };
        !            88:
1.1       djm        89: /* fd to control socket */
                     90: int muxserver_sock = -1;
                     91:
                     92: /* Multiplexing control command */
                     93: u_int muxclient_command = 0;
                     94:
                     95: /* Set when signalled. */
                     96: static volatile sig_atomic_t muxclient_terminate = 0;
                     97:
                     98: /* PID of multiplex server */
                     99: static u_int muxserver_pid = 0;
                    100:
                    101:
                    102: /* ** Multiplexing master support */
                    103:
                    104: /* Prepare a mux master to listen on a Unix domain socket. */
                    105: void
                    106: muxserver_listen(void)
                    107: {
                    108:        struct sockaddr_un addr;
                    109:        mode_t old_umask;
                    110:
                    111:        if (options.control_path == NULL ||
                    112:            options.control_master == SSHCTL_MASTER_NO)
                    113:                return;
                    114:
                    115:        debug("setting up multiplex master socket");
                    116:
                    117:        memset(&addr, '\0', sizeof(addr));
                    118:        addr.sun_family = AF_UNIX;
                    119:        addr.sun_len = offsetof(struct sockaddr_un, sun_path) +
                    120:            strlen(options.control_path) + 1;
                    121:
                    122:        if (strlcpy(addr.sun_path, options.control_path,
                    123:            sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
                    124:                fatal("ControlPath too long");
                    125:
                    126:        if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
                    127:                fatal("%s socket(): %s", __func__, strerror(errno));
                    128:
                    129:        old_umask = umask(0177);
                    130:        if (bind(muxserver_sock, (struct sockaddr *)&addr, addr.sun_len) == -1) {
                    131:                muxserver_sock = -1;
                    132:                if (errno == EINVAL || errno == EADDRINUSE)
                    133:                        fatal("ControlSocket %s already exists",
                    134:                            options.control_path);
                    135:                else
                    136:                        fatal("%s bind(): %s", __func__, strerror(errno));
                    137:        }
                    138:        umask(old_umask);
                    139:
                    140:        if (listen(muxserver_sock, 64) == -1)
                    141:                fatal("%s listen(): %s", __func__, strerror(errno));
                    142:
                    143:        set_nonblock(muxserver_sock);
                    144: }
                    145:
                    146: /* Callback on open confirmation in mux master for a mux client session. */
                    147: static void
1.2     ! djm       148: mux_session_confirm(int id, void *arg)
1.1       djm       149: {
                    150:        struct mux_session_confirm_ctx *cctx = arg;
                    151:        const char *display;
                    152:        Channel *c;
                    153:        int i;
                    154:
                    155:        if (cctx == NULL)
                    156:                fatal("%s: cctx == NULL", __func__);
                    157:        if ((c = channel_lookup(id)) == NULL)
                    158:                fatal("%s: no channel for id %d", __func__, id);
                    159:
                    160:        display = getenv("DISPLAY");
                    161:        if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
                    162:                char *proto, *data;
                    163:                /* Get reasonable local authentication information. */
                    164:                client_x11_get_proto(display, options.xauth_location,
                    165:                    options.forward_x11_trusted, &proto, &data);
                    166:                /* Request forwarding with authentication spoofing. */
                    167:                debug("Requesting X11 forwarding with authentication spoofing.");
                    168:                x11_request_forwarding_with_spoofing(id, display, proto, data);
                    169:                /* XXX wait for reply */
                    170:        }
                    171:
                    172:        if (cctx->want_agent_fwd && options.forward_agent) {
                    173:                debug("Requesting authentication agent forwarding.");
                    174:                channel_request_start(id, "auth-agent-req@openssh.com", 0);
                    175:                packet_send();
                    176:        }
                    177:
                    178:        client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
                    179:            cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
                    180:
                    181:        c->open_confirm_ctx = NULL;
                    182:        buffer_free(&cctx->cmd);
                    183:        xfree(cctx->term);
                    184:        if (cctx->env != NULL) {
                    185:                for (i = 0; cctx->env[i] != NULL; i++)
                    186:                        xfree(cctx->env[i]);
                    187:                xfree(cctx->env);
                    188:        }
                    189:        xfree(cctx);
                    190: }
                    191:
                    192: /*
                    193:  * Accept a connection on the mux master socket and process the
                    194:  * client's request. Returns flag indicating whether mux master should
                    195:  * begin graceful close.
                    196:  */
                    197: int
                    198: muxserver_accept_control(void)
                    199: {
                    200:        Buffer m;
                    201:        Channel *c;
                    202:        int client_fd, new_fd[3], ver, allowed, window, packetmax;
                    203:        socklen_t addrlen;
                    204:        struct sockaddr_storage addr;
                    205:        struct mux_session_confirm_ctx *cctx;
                    206:        char *cmd;
1.2     ! djm       207:        u_int i, j, len, env_len, mux_command, flags, escape_char;
1.1       djm       208:        uid_t euid;
                    209:        gid_t egid;
                    210:        int start_close = 0;
                    211:
                    212:        /*
                    213:         * Accept connection on control socket
                    214:         */
                    215:        memset(&addr, 0, sizeof(addr));
                    216:        addrlen = sizeof(addr);
                    217:        if ((client_fd = accept(muxserver_sock,
                    218:            (struct sockaddr*)&addr, &addrlen)) == -1) {
                    219:                error("%s accept: %s", __func__, strerror(errno));
                    220:                return 0;
                    221:        }
                    222:
                    223:        if (getpeereid(client_fd, &euid, &egid) < 0) {
                    224:                error("%s getpeereid failed: %s", __func__, strerror(errno));
                    225:                close(client_fd);
                    226:                return 0;
                    227:        }
                    228:        if ((euid != 0) && (getuid() != euid)) {
                    229:                error("control mode uid mismatch: peer euid %u != uid %u",
                    230:                    (u_int) euid, (u_int) getuid());
                    231:                close(client_fd);
                    232:                return 0;
                    233:        }
                    234:
                    235:        /* XXX handle asynchronously */
                    236:        unset_nonblock(client_fd);
                    237:
                    238:        /* Read command */
                    239:        buffer_init(&m);
                    240:        if (ssh_msg_recv(client_fd, &m) == -1) {
                    241:                error("%s: client msg_recv failed", __func__);
                    242:                close(client_fd);
                    243:                buffer_free(&m);
                    244:                return 0;
                    245:        }
                    246:        if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
                    247:                error("%s: wrong client version %d", __func__, ver);
                    248:                buffer_free(&m);
                    249:                close(client_fd);
                    250:                return 0;
                    251:        }
                    252:
                    253:        allowed = 1;
                    254:        mux_command = buffer_get_int(&m);
                    255:        flags = buffer_get_int(&m);
                    256:
                    257:        buffer_clear(&m);
                    258:
                    259:        switch (mux_command) {
                    260:        case SSHMUX_COMMAND_OPEN:
                    261:                if (options.control_master == SSHCTL_MASTER_ASK ||
                    262:                    options.control_master == SSHCTL_MASTER_AUTO_ASK)
                    263:                        allowed = ask_permission("Allow shared connection "
                    264:                            "to %s? ", host);
                    265:                /* continue below */
                    266:                break;
                    267:        case SSHMUX_COMMAND_TERMINATE:
                    268:                if (options.control_master == SSHCTL_MASTER_ASK ||
                    269:                    options.control_master == SSHCTL_MASTER_AUTO_ASK)
                    270:                        allowed = ask_permission("Terminate shared connection "
                    271:                            "to %s? ", host);
                    272:                if (allowed)
                    273:                        start_close = 1;
                    274:                /* FALLTHROUGH */
                    275:        case SSHMUX_COMMAND_ALIVE_CHECK:
                    276:                /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */
                    277:                buffer_clear(&m);
                    278:                buffer_put_int(&m, allowed);
                    279:                buffer_put_int(&m, getpid());
                    280:                if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
                    281:                        error("%s: client msg_send failed", __func__);
                    282:                        close(client_fd);
                    283:                        buffer_free(&m);
                    284:                        return start_close;
                    285:                }
                    286:                buffer_free(&m);
                    287:                close(client_fd);
                    288:                return start_close;
                    289:        default:
                    290:                error("Unsupported command %d", mux_command);
                    291:                buffer_free(&m);
                    292:                close(client_fd);
                    293:                return 0;
                    294:        }
                    295:
                    296:        /* Reply for SSHMUX_COMMAND_OPEN */
                    297:        buffer_clear(&m);
                    298:        buffer_put_int(&m, allowed);
                    299:        buffer_put_int(&m, getpid());
                    300:        if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
                    301:                error("%s: client msg_send failed", __func__);
                    302:                close(client_fd);
                    303:                buffer_free(&m);
                    304:                return 0;
                    305:        }
                    306:
                    307:        if (!allowed) {
                    308:                error("Refused control connection");
                    309:                close(client_fd);
                    310:                buffer_free(&m);
                    311:                return 0;
                    312:        }
                    313:
                    314:        buffer_clear(&m);
                    315:        if (ssh_msg_recv(client_fd, &m) == -1) {
                    316:                error("%s: client msg_recv failed", __func__);
                    317:                close(client_fd);
                    318:                buffer_free(&m);
                    319:                return 0;
                    320:        }
                    321:        if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
                    322:                error("%s: wrong client version %d", __func__, ver);
                    323:                buffer_free(&m);
                    324:                close(client_fd);
                    325:                return 0;
                    326:        }
                    327:
                    328:        cctx = xcalloc(1, sizeof(*cctx));
                    329:        cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
                    330:        cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
                    331:        cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
                    332:        cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
                    333:        cctx->term = buffer_get_string(&m, &len);
1.2     ! djm       334:        escape_char = buffer_get_int(&m);
1.1       djm       335:
                    336:        cmd = buffer_get_string(&m, &len);
                    337:        buffer_init(&cctx->cmd);
                    338:        buffer_append(&cctx->cmd, cmd, strlen(cmd));
                    339:
                    340:        env_len = buffer_get_int(&m);
                    341:        env_len = MIN(env_len, 4096);
                    342:        debug3("%s: receiving %d env vars", __func__, env_len);
                    343:        if (env_len != 0) {
                    344:                cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env));
                    345:                for (i = 0; i < env_len; i++)
                    346:                        cctx->env[i] = buffer_get_string(&m, &len);
                    347:                cctx->env[i] = NULL;
                    348:        }
                    349:
                    350:        debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__,
                    351:            cctx->want_tty, cctx->want_subsys, cmd);
                    352:        xfree(cmd);
                    353:
                    354:        /* Gather fds from client */
                    355:        for(i = 0; i < 3; i++) {
                    356:                if ((new_fd[i] = mm_receive_fd(client_fd)) == -1) {
                    357:                        error("%s: failed to receive fd %d from slave",
                    358:                            __func__, i);
                    359:                        for (j = 0; j < i; j++)
                    360:                                close(new_fd[j]);
                    361:                        for (j = 0; j < env_len; j++)
                    362:                                xfree(cctx->env[j]);
                    363:                        if (env_len > 0)
                    364:                                xfree(cctx->env);
                    365:                        xfree(cctx->term);
                    366:                        buffer_free(&cctx->cmd);
                    367:                        close(client_fd);
                    368:                        xfree(cctx);
                    369:                        return 0;
                    370:                }
                    371:        }
                    372:
                    373:        debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
                    374:            new_fd[0], new_fd[1], new_fd[2]);
                    375:
                    376:        /* Try to pick up ttymodes from client before it goes raw */
                    377:        if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
                    378:                error("%s: tcgetattr: %s", __func__, strerror(errno));
                    379:
                    380:        /* This roundtrip is just for synchronisation of ttymodes */
                    381:        buffer_clear(&m);
                    382:        if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
                    383:                error("%s: client msg_send failed", __func__);
                    384:                close(client_fd);
                    385:                close(new_fd[0]);
                    386:                close(new_fd[1]);
                    387:                close(new_fd[2]);
                    388:                buffer_free(&m);
                    389:                xfree(cctx->term);
                    390:                if (env_len != 0) {
                    391:                        for (i = 0; i < env_len; i++)
                    392:                                xfree(cctx->env[i]);
                    393:                        xfree(cctx->env);
                    394:                }
                    395:                return 0;
                    396:        }
                    397:        buffer_free(&m);
                    398:
                    399:        /* enable nonblocking unless tty */
                    400:        if (!isatty(new_fd[0]))
                    401:                set_nonblock(new_fd[0]);
                    402:        if (!isatty(new_fd[1]))
                    403:                set_nonblock(new_fd[1]);
                    404:        if (!isatty(new_fd[2]))
                    405:                set_nonblock(new_fd[2]);
                    406:
                    407:        set_nonblock(client_fd);
                    408:
                    409:        window = CHAN_SES_WINDOW_DEFAULT;
                    410:        packetmax = CHAN_SES_PACKET_DEFAULT;
                    411:        if (cctx->want_tty) {
                    412:                window >>= 1;
                    413:                packetmax >>= 1;
                    414:        }
                    415:
                    416:        c = channel_new("session", SSH_CHANNEL_OPENING,
                    417:            new_fd[0], new_fd[1], new_fd[2], window, packetmax,
                    418:            CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
                    419:
                    420:        c->ctl_fd = client_fd;
1.2     ! djm       421:        if (cctx->want_tty && escape_char != 0xffffffff) {
        !           422:                channel_register_filter(c->self,
        !           423:                    client_simple_escape_filter, NULL,
        !           424:                    client_new_escape_filter_ctx((int)escape_char));
        !           425:        }
1.1       djm       426:
                    427:        debug3("%s: channel_new: %d", __func__, c->self);
                    428:
                    429:        channel_send_open(c->self);
1.2     ! djm       430:        channel_register_open_confirm(c->self, mux_session_confirm, cctx);
1.1       djm       431:        return 0;
                    432: }
                    433:
                    434: /* ** Multiplexing client support */
                    435:
                    436: /* Exit signal handler */
                    437: static void
                    438: control_client_sighandler(int signo)
                    439: {
                    440:        muxclient_terminate = signo;
                    441: }
                    442:
                    443: /*
                    444:  * Relay signal handler - used to pass some signals from mux client to
                    445:  * mux master.
                    446:  */
                    447: static void
                    448: control_client_sigrelay(int signo)
                    449: {
                    450:        int save_errno = errno;
                    451:
                    452:        if (muxserver_pid > 1)
                    453:                kill(muxserver_pid, signo);
                    454:
                    455:        errno = save_errno;
                    456: }
                    457:
                    458: /* Check mux client environment variables before passing them to mux master. */
                    459: static int
                    460: env_permitted(char *env)
                    461: {
                    462:        int i, ret;
                    463:        char name[1024], *cp;
                    464:
                    465:        if ((cp = strchr(env, '=')) == NULL || cp == env)
                    466:                return (0);
                    467:        ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
                    468:        if (ret <= 0 || (size_t)ret >= sizeof(name))
                    469:                fatal("env_permitted: name '%.100s...' too long", env);
                    470:
                    471:        for (i = 0; i < options.num_send_env; i++)
                    472:                if (match_pattern(name, options.send_env[i]))
                    473:                        return (1);
                    474:
                    475:        return (0);
                    476: }
                    477:
                    478: /* Multiplex client main loop. */
                    479: void
                    480: muxclient(const char *path)
                    481: {
                    482:        struct sockaddr_un addr;
                    483:        int i, r, fd, sock, exitval[2], num_env;
                    484:        Buffer m;
                    485:        char *term;
                    486:        extern char **environ;
                    487:        u_int  flags;
                    488:
                    489:        if (muxclient_command == 0)
                    490:                muxclient_command = SSHMUX_COMMAND_OPEN;
                    491:
                    492:        switch (options.control_master) {
                    493:        case SSHCTL_MASTER_AUTO:
                    494:        case SSHCTL_MASTER_AUTO_ASK:
                    495:                debug("auto-mux: Trying existing master");
                    496:                /* FALLTHROUGH */
                    497:        case SSHCTL_MASTER_NO:
                    498:                break;
                    499:        default:
                    500:                return;
                    501:        }
                    502:
                    503:        memset(&addr, '\0', sizeof(addr));
                    504:        addr.sun_family = AF_UNIX;
                    505:        addr.sun_len = offsetof(struct sockaddr_un, sun_path) +
                    506:            strlen(path) + 1;
                    507:
                    508:        if (strlcpy(addr.sun_path, path,
                    509:            sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
                    510:                fatal("ControlPath too long");
                    511:
                    512:        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
                    513:                fatal("%s socket(): %s", __func__, strerror(errno));
                    514:
                    515:        if (connect(sock, (struct sockaddr *)&addr, addr.sun_len) == -1) {
                    516:                if (muxclient_command != SSHMUX_COMMAND_OPEN) {
                    517:                        fatal("Control socket connect(%.100s): %s", path,
                    518:                            strerror(errno));
                    519:                }
                    520:                if (errno == ENOENT)
                    521:                        debug("Control socket \"%.100s\" does not exist", path);
                    522:                else {
                    523:                        error("Control socket connect(%.100s): %s", path,
                    524:                            strerror(errno));
                    525:                }
                    526:                close(sock);
                    527:                return;
                    528:        }
                    529:
                    530:        if (stdin_null_flag) {
                    531:                if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
                    532:                        fatal("open(/dev/null): %s", strerror(errno));
                    533:                if (dup2(fd, STDIN_FILENO) == -1)
                    534:                        fatal("dup2: %s", strerror(errno));
                    535:                if (fd > STDERR_FILENO)
                    536:                        close(fd);
                    537:        }
                    538:
                    539:        term = getenv("TERM");
                    540:
                    541:        flags = 0;
                    542:        if (tty_flag)
                    543:                flags |= SSHMUX_FLAG_TTY;
                    544:        if (subsystem_flag)
                    545:                flags |= SSHMUX_FLAG_SUBSYS;
                    546:        if (options.forward_x11)
                    547:                flags |= SSHMUX_FLAG_X11_FWD;
                    548:        if (options.forward_agent)
                    549:                flags |= SSHMUX_FLAG_AGENT_FWD;
                    550:
                    551:        signal(SIGPIPE, SIG_IGN);
                    552:
                    553:        buffer_init(&m);
                    554:
                    555:        /* Send our command to server */
                    556:        buffer_put_int(&m, muxclient_command);
                    557:        buffer_put_int(&m, flags);
                    558:        if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1)
                    559:                fatal("%s: msg_send", __func__);
                    560:        buffer_clear(&m);
                    561:
                    562:        /* Get authorisation status and PID of controlee */
                    563:        if (ssh_msg_recv(sock, &m) == -1)
                    564:                fatal("%s: msg_recv", __func__);
                    565:        if (buffer_get_char(&m) != SSHMUX_VER)
                    566:                fatal("%s: wrong version", __func__);
                    567:        if (buffer_get_int(&m) != 1)
                    568:                fatal("Connection to master denied");
                    569:        muxserver_pid = buffer_get_int(&m);
                    570:
                    571:        buffer_clear(&m);
                    572:
                    573:        switch (muxclient_command) {
                    574:        case SSHMUX_COMMAND_ALIVE_CHECK:
                    575:                fprintf(stderr, "Master running (pid=%d)\r\n",
                    576:                    muxserver_pid);
                    577:                exit(0);
                    578:        case SSHMUX_COMMAND_TERMINATE:
                    579:                fprintf(stderr, "Exit request sent.\r\n");
                    580:                exit(0);
                    581:        case SSHMUX_COMMAND_OPEN:
1.2     ! djm       582:                buffer_put_cstring(&m, term ? term : "");
        !           583:                if (options.escape_char == SSH_ESCAPECHAR_NONE)
        !           584:                        buffer_put_int(&m, 0xffffffff);
        !           585:                else
        !           586:                        buffer_put_int(&m, options.escape_char);
        !           587:                buffer_append(&command, "\0", 1);
        !           588:                buffer_put_cstring(&m, buffer_ptr(&command));
        !           589:
        !           590:                if (options.num_send_env == 0 || environ == NULL) {
        !           591:                        buffer_put_int(&m, 0);
        !           592:                } else {
        !           593:                        /* Pass environment */
        !           594:                        num_env = 0;
        !           595:                        for (i = 0; environ[i] != NULL; i++) {
        !           596:                                if (env_permitted(environ[i]))
        !           597:                                        num_env++; /* Count */
        !           598:                        }
        !           599:                        buffer_put_int(&m, num_env);
        !           600:                for (i = 0; environ[i] != NULL && num_env >= 0; i++) {
        !           601:                                if (env_permitted(environ[i])) {
        !           602:                                        num_env--;
        !           603:                                        buffer_put_cstring(&m, environ[i]);
        !           604:                                }
        !           605:                        }
        !           606:                }
1.1       djm       607:                break;
                    608:        default:
1.2     ! djm       609:                fatal("unrecognised muxclient_command %d", muxclient_command);
1.1       djm       610:        }
                    611:
                    612:        if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1)
                    613:                fatal("%s: msg_send", __func__);
                    614:
                    615:        if (mm_send_fd(sock, STDIN_FILENO) == -1 ||
                    616:            mm_send_fd(sock, STDOUT_FILENO) == -1 ||
                    617:            mm_send_fd(sock, STDERR_FILENO) == -1)
                    618:                fatal("%s: send fds failed", __func__);
                    619:
                    620:        /* Wait for reply, so master has a chance to gather ttymodes */
                    621:        buffer_clear(&m);
                    622:        if (ssh_msg_recv(sock, &m) == -1)
                    623:                fatal("%s: msg_recv", __func__);
                    624:        if (buffer_get_char(&m) != SSHMUX_VER)
                    625:                fatal("%s: wrong version", __func__);
                    626:        buffer_free(&m);
                    627:
                    628:        signal(SIGHUP, control_client_sighandler);
                    629:        signal(SIGINT, control_client_sighandler);
                    630:        signal(SIGTERM, control_client_sighandler);
                    631:        signal(SIGWINCH, control_client_sigrelay);
                    632:
                    633:        if (tty_flag)
                    634:                enter_raw_mode();
                    635:
                    636:        /*
                    637:         * Stick around until the controlee closes the client_fd.
                    638:         * Before it does, it is expected to write this process' exit
                    639:         * value (one int). This process must read the value and wait for
                    640:         * the closure of the client_fd; if this one closes early, the
                    641:         * multiplex master will terminate early too (possibly losing data).
                    642:         */
                    643:        exitval[0] = 0;
                    644:        for (i = 0; !muxclient_terminate && i < (int)sizeof(exitval);) {
                    645:                r = read(sock, (char *)exitval + i, sizeof(exitval) - i);
                    646:                if (r == 0) {
                    647:                        debug2("Received EOF from master");
                    648:                        break;
                    649:                }
                    650:                if (r == -1) {
                    651:                        if (errno == EINTR)
                    652:                                continue;
                    653:                        fatal("%s: read %s", __func__, strerror(errno));
                    654:                }
                    655:                i += r;
                    656:        }
                    657:
                    658:        close(sock);
                    659:        leave_raw_mode();
                    660:        if (i > (int)sizeof(int))
                    661:                fatal("%s: master returned too much data (%d > %lu)",
                    662:                    __func__, i, sizeof(int));
                    663:        if (muxclient_terminate) {
                    664:                debug2("Exiting on signal %d", muxclient_terminate);
                    665:                exitval[0] = 255;
                    666:        } else if (i < (int)sizeof(int)) {
                    667:                debug2("Control master terminated unexpectedly");
                    668:                exitval[0] = 255;
                    669:        } else
                    670:                debug2("Received exit status from master %d", exitval[0]);
                    671:
                    672:        if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
                    673:                fprintf(stderr, "Shared connection to %s closed.\r\n", host);
                    674:
                    675:        exit(exitval[0]);
                    676: }