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

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