[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.5

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