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

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