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

1.10    ! djm         1: /* $OpenBSD: mux.c,v 1.9 2010/01/09 05:04:24 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.10    ! djm        20: // XXX signal of slave passed to master
        !            21:
1.2       djm        22: /*
                     23:  * TODO:
1.10    ! djm        24:  *   - Better signalling from master to slave, especially passing of
1.2       djm        25:  *      error messages
1.10    ! djm        26:  *   - Better fall-back from mux slave error to new connection.
        !            27:  *   - ExitOnForwardingFailure
        !            28:  *   - Maybe extension mechanisms for multi-X11/multi-agent forwarding
        !            29:  *   - Support ~^Z in mux slaves.
        !            30:  *   - Inspect or control sessions in master.
        !            31:  *   - If we ever support the "signal" channel request, send signals on
        !            32:  *     sessions in master.
1.2       djm        33:  */
                     34:
1.1       djm        35: #include <sys/types.h>
                     36: #include <sys/param.h>
                     37: #include <sys/queue.h>
                     38: #include <sys/stat.h>
                     39: #include <sys/socket.h>
                     40: #include <sys/un.h>
                     41:
                     42: #include <errno.h>
                     43: #include <fcntl.h>
1.10    ! djm        44: #include <poll.h>
1.1       djm        45: #include <signal.h>
                     46: #include <stdarg.h>
                     47: #include <stddef.h>
                     48: #include <stdlib.h>
                     49: #include <stdio.h>
                     50: #include <string.h>
                     51: #include <unistd.h>
                     52: #include <util.h>
                     53: #include <paths.h>
                     54:
1.10    ! djm        55: #include "atomicio.h"
1.1       djm        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;
1.10    ! djm        80: extern volatile sig_atomic_t quit_pending;
        !            81: extern char *stdio_forward_host;
        !            82: extern int stdio_forward_port;
1.1       djm        83:
1.2       djm        84: /* Context for session open confirmation callback */
                     85: struct mux_session_confirm_ctx {
1.10    ! djm        86:        u_int want_tty;
        !            87:        u_int want_subsys;
        !            88:        u_int want_x_fwd;
        !            89:        u_int want_agent_fwd;
1.2       djm        90:        Buffer cmd;
                     91:        char *term;
                     92:        struct termios tio;
                     93:        char **env;
                     94: };
                     95:
1.1       djm        96: /* fd to control socket */
                     97: int muxserver_sock = -1;
                     98:
1.10    ! djm        99: /* client request id */
        !           100: u_int muxclient_request_id = 0;
        !           101:
1.1       djm       102: /* Multiplexing control command */
                    103: u_int muxclient_command = 0;
                    104:
                    105: /* Set when signalled. */
                    106: static volatile sig_atomic_t muxclient_terminate = 0;
                    107:
                    108: /* PID of multiplex server */
                    109: static u_int muxserver_pid = 0;
                    110:
1.10    ! djm       111: static Channel *mux_listener_channel = NULL;
        !           112:
        !           113: struct mux_master_state {
        !           114:        int hello_rcvd;
        !           115: };
1.1       djm       116:
1.10    ! djm       117: /* mux protocol messages */
        !           118: #define MUX_MSG_HELLO          0x00000001
        !           119: #define MUX_C_NEW_SESSION      0x10000002
        !           120: #define MUX_C_ALIVE_CHECK      0x10000004
        !           121: #define MUX_C_TERMINATE                0x10000005
        !           122: #define MUX_C_OPEN_FWD         0x10000006
        !           123: #define MUX_C_CLOSE_FWD                0x10000007
        !           124: #define MUX_C_NEW_STDIO_FWD    0x10000008
        !           125: #define MUX_S_OK               0x80000001
        !           126: #define MUX_S_PERMISSION_DENIED        0x80000002
        !           127: #define MUX_S_FAILURE          0x80000003
        !           128: #define MUX_S_EXIT_MESSAGE     0x80000004
        !           129: #define MUX_S_ALIVE            0x80000005
        !           130: #define MUX_S_SESSION_OPENED   0x80000006
        !           131:
        !           132: /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
        !           133: #define MUX_FWD_LOCAL   1
        !           134: #define MUX_FWD_REMOTE  2
        !           135: #define MUX_FWD_DYNAMIC 3
        !           136:
        !           137: static void mux_session_confirm(int, void *);
        !           138:
        !           139: static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
        !           140: static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
        !           141: static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *);
        !           142: static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
        !           143: static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
        !           144: static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
        !           145: static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
        !           146:
        !           147: static const struct {
        !           148:        u_int type;
        !           149:        int (*handler)(u_int, Channel *, Buffer *, Buffer *);
        !           150: } mux_master_handlers[] = {
        !           151:        { MUX_MSG_HELLO, process_mux_master_hello },
        !           152:        { MUX_C_NEW_SESSION, process_mux_new_session },
        !           153:        { MUX_C_ALIVE_CHECK, process_mux_alive_check },
        !           154:        { MUX_C_TERMINATE, process_mux_terminate },
        !           155:        { MUX_C_OPEN_FWD, process_mux_open_fwd },
        !           156:        { MUX_C_CLOSE_FWD, process_mux_close_fwd },
        !           157:        { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
        !           158:        { 0, NULL }
        !           159: };
1.1       djm       160:
1.10    ! djm       161: /* Cleanup callback fired on closure of mux slave _session_ channel */
        !           162: /* ARGSUSED */
        !           163: static void
        !           164: mux_master_session_cleanup_cb(int cid, void *unused)
1.1       djm       165: {
1.10    ! djm       166:        Channel *cc, *c = channel_by_id(cid);
1.1       djm       167:
1.10    ! djm       168:        debug3("%s: entering for channel %d", __func__, cid);
        !           169:        if (c == NULL)
        !           170:                fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
        !           171:        if (c->ctl_chan != -1) {
        !           172:                if ((cc = channel_by_id(c->ctl_chan)) == NULL)
        !           173:                        fatal("%s: channel %d missing control channel %d",
        !           174:                            __func__, c->self, c->ctl_chan);
        !           175:                c->ctl_chan = -1;
        !           176:                cc->remote_id = -1;
        !           177:                chan_rcvd_oclose(cc);
1.1       djm       178:        }
1.10    ! djm       179:        channel_cancel_cleanup(c->self);
1.1       djm       180: }
                    181:
1.10    ! djm       182: /* Cleanup callback fired on closure of mux slave _control_ channel */
        !           183: /* ARGSUSED */
1.1       djm       184: static void
1.10    ! djm       185: mux_master_control_cleanup_cb(int cid, void *unused)
1.1       djm       186: {
1.10    ! djm       187:        Channel *sc, *c = channel_by_id(cid);
1.1       djm       188:
1.10    ! djm       189:        debug3("%s: entering for channel %d", __func__, cid);
        !           190:        if (c == NULL)
        !           191:                fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
        !           192:        if (c->remote_id != -1) {
        !           193:                if ((sc = channel_by_id(c->remote_id)) == NULL)
        !           194:                        debug2("%s: channel %d n session channel %d",
        !           195:                            __func__, c->self, c->remote_id);
        !           196:                c->remote_id = -1;
        !           197:                sc->ctl_chan = -1;
        !           198:                chan_mark_dead(sc);
1.1       djm       199:        }
1.10    ! djm       200:        channel_cancel_cleanup(c->self);
1.1       djm       201: }
                    202:
1.10    ! djm       203: /* Check mux client environment variables before passing them to mux master. */
        !           204: static int
        !           205: env_permitted(char *env)
1.1       djm       206: {
1.10    ! djm       207:        int i, ret;
        !           208:        char name[1024], *cp;
1.1       djm       209:
1.10    ! djm       210:        if ((cp = strchr(env, '=')) == NULL || cp == env)
1.1       djm       211:                return 0;
1.10    ! djm       212:        ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
        !           213:        if (ret <= 0 || (size_t)ret >= sizeof(name)) {
        !           214:                error("env_permitted: name '%.100s...' too long", env);
1.1       djm       215:                return 0;
                    216:        }
                    217:
1.10    ! djm       218:        for (i = 0; i < options.num_send_env; i++)
        !           219:                if (match_pattern(name, options.send_env[i]))
        !           220:                        return 1;
1.1       djm       221:
1.10    ! djm       222:        return 0;
        !           223: }
1.1       djm       224:
1.10    ! djm       225: /* Mux master protocol message handlers */
1.1       djm       226:
1.10    ! djm       227: static int
        !           228: process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
        !           229: {
        !           230:        u_int ver;
        !           231:        struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
1.1       djm       232:
1.10    ! djm       233:        if (state == NULL)
        !           234:                fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
        !           235:        if (state->hello_rcvd) {
        !           236:                error("%s: HELLO received twice", __func__);
        !           237:                return -1;
        !           238:        }
        !           239:        if (buffer_get_int_ret(&ver, m) != 0) {
        !           240:  malf:
        !           241:                error("%s: malformed message", __func__);
        !           242:                return -1;
        !           243:        }
        !           244:        if (ver != SSHMUX_VER) {
        !           245:                error("Unsupported multiplexing protocol version %d "
        !           246:                    "(expected %d)", ver, SSHMUX_VER);
        !           247:                return -1;
        !           248:        }
        !           249:        debug2("%s: channel %d slave version %u", __func__, c->self, ver);
        !           250:
        !           251:        /* No extensions are presently defined */
        !           252:        while (buffer_len(m) > 0) {
        !           253:                char *name = buffer_get_string_ret(m, NULL);
        !           254:                char *value = buffer_get_string_ret(m, NULL);
        !           255:
        !           256:                if (name == NULL || value == NULL) {
        !           257:                        if (name != NULL)
        !           258:                                xfree(name);
        !           259:                        goto malf;
1.1       djm       260:                }
1.10    ! djm       261:                debug2("Unrecognised slave extension \"%s\"", name);
        !           262:                xfree(name);
        !           263:                xfree(value);
1.1       djm       264:        }
1.10    ! djm       265:        state->hello_rcvd = 1;
        !           266:        return 0;
        !           267: }
        !           268:
        !           269: static int
        !           270: process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
        !           271: {
        !           272:        Channel *nc;
        !           273:        struct mux_session_confirm_ctx *cctx;
        !           274:        char *reserved, *cmd, *cp;
        !           275:        u_int i, j, len, env_len, escape_char, window, packetmax;
        !           276:        int new_fd[3];
1.1       djm       277:
                    278:        /* Reply for SSHMUX_COMMAND_OPEN */
1.10    ! djm       279:        cctx = xcalloc(1, sizeof(*cctx));
        !           280:        cctx->term = NULL;
        !           281:        cmd = NULL;
        !           282:        if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
        !           283:            buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
        !           284:            buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
        !           285:            buffer_get_int_ret(&cctx->want_agent_fwd, m) != 0 ||
        !           286:            buffer_get_int_ret(&cctx->want_subsys, m) != 0 ||
        !           287:            buffer_get_int_ret(&escape_char, m) != 0 ||
        !           288:            (cctx->term = buffer_get_string_ret(m, &len)) == NULL ||
        !           289:            (cmd = buffer_get_string_ret(m, &len)) == NULL) {
        !           290:  malf:
        !           291:                if (cctx->term != NULL)
        !           292:                        xfree(cctx->term);
        !           293:                error("%s: malformed message", __func__);
        !           294:                return -1;
1.1       djm       295:        }
1.10    ! djm       296:        xfree(reserved);
1.1       djm       297:
1.10    ! djm       298:        cctx->env = NULL;
        !           299:        env_len = 0;
        !           300:        while (buffer_len(m) > 0) {
        !           301: #define MUX_MAX_ENV_VARS       4096
        !           302:                if ((cp = buffer_get_string_ret(m, &len)) == NULL) {
        !           303:                        xfree(cmd);
        !           304:                        goto malf;
        !           305:                }
        !           306:                if (!env_permitted(cp)) {
        !           307:                        xfree(cp);
        !           308:                        continue;
        !           309:                }
        !           310:                cctx->env = xrealloc(cctx->env, env_len + 2,
        !           311:                    sizeof(*cctx->env));
        !           312:                cctx->env[env_len++] = cp;
        !           313:                cctx->env[env_len] = NULL;
        !           314:                if (env_len > MUX_MAX_ENV_VARS) {
        !           315:                        error(">%d environment variables received, ignoring "
        !           316:                            "additional", MUX_MAX_ENV_VARS);
        !           317:                        break;
        !           318:                }
1.1       djm       319:        }
                    320:
1.10    ! djm       321:        debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
        !           322:            "term \"%s\", cmd \"%s\", env %u", __func__, c->self,
        !           323:            cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
        !           324:            cctx->want_subsys, cctx->term, cmd, env_len);
1.1       djm       325:
                    326:        buffer_init(&cctx->cmd);
                    327:        buffer_append(&cctx->cmd, cmd, strlen(cmd));
                    328:        xfree(cmd);
                    329:
                    330:        /* Gather fds from client */
                    331:        for(i = 0; i < 3; i++) {
1.10    ! djm       332:                if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
1.1       djm       333:                        error("%s: failed to receive fd %d from slave",
                    334:                            __func__, i);
                    335:                        for (j = 0; j < i; j++)
                    336:                                close(new_fd[j]);
                    337:                        for (j = 0; j < env_len; j++)
                    338:                                xfree(cctx->env[j]);
                    339:                        if (env_len > 0)
                    340:                                xfree(cctx->env);
                    341:                        xfree(cctx->term);
                    342:                        buffer_free(&cctx->cmd);
                    343:                        xfree(cctx);
1.10    ! djm       344:
        !           345:                        /* prepare reply */
        !           346:                        buffer_put_int(r, MUX_S_FAILURE);
        !           347:                        buffer_put_int(r, rid);
        !           348:                        buffer_put_cstring(r,
        !           349:                            "did not receive file descriptors");
        !           350:                        return -1;
1.1       djm       351:                }
                    352:        }
                    353:
1.10    ! djm       354:        debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
1.1       djm       355:            new_fd[0], new_fd[1], new_fd[2]);
                    356:
1.10    ! djm       357:        /* XXX support multiple child sessions in future */
        !           358:        if (c->remote_id != -1) {
        !           359:                debug2("%s: session already open", __func__);
        !           360:                /* prepare reply */
        !           361:                buffer_put_int(r, MUX_S_FAILURE);
        !           362:                buffer_put_int(r, rid);
        !           363:                buffer_put_cstring(r, "Multiple sessions not supported");
        !           364:  cleanup:
1.1       djm       365:                close(new_fd[0]);
                    366:                close(new_fd[1]);
                    367:                close(new_fd[2]);
                    368:                xfree(cctx->term);
                    369:                if (env_len != 0) {
                    370:                        for (i = 0; i < env_len; i++)
                    371:                                xfree(cctx->env[i]);
                    372:                        xfree(cctx->env);
                    373:                }
1.10    ! djm       374:                buffer_free(&cctx->cmd);
1.1       djm       375:                return 0;
                    376:        }
1.10    ! djm       377:
        !           378:        if (options.control_master == SSHCTL_MASTER_ASK ||
        !           379:            options.control_master == SSHCTL_MASTER_AUTO_ASK) {
        !           380:                if (!ask_permission("Allow shared connection to %s? ", host)) {
        !           381:                        debug2("%s: session refused by user", __func__);
        !           382:                        /* prepare reply */
        !           383:                        buffer_put_int(r, MUX_S_PERMISSION_DENIED);
        !           384:                        buffer_put_int(r, rid);
        !           385:                        buffer_put_cstring(r, "Permission denied");
        !           386:                        goto cleanup;
        !           387:                }
        !           388:        }
        !           389:
        !           390:        /* Try to pick up ttymodes from client before it goes raw */
        !           391:        if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
        !           392:                error("%s: tcgetattr: %s", __func__, strerror(errno));
1.1       djm       393:
                    394:        /* enable nonblocking unless tty */
                    395:        if (!isatty(new_fd[0]))
                    396:                set_nonblock(new_fd[0]);
                    397:        if (!isatty(new_fd[1]))
                    398:                set_nonblock(new_fd[1]);
                    399:        if (!isatty(new_fd[2]))
                    400:                set_nonblock(new_fd[2]);
                    401:
                    402:        window = CHAN_SES_WINDOW_DEFAULT;
                    403:        packetmax = CHAN_SES_PACKET_DEFAULT;
                    404:        if (cctx->want_tty) {
                    405:                window >>= 1;
                    406:                packetmax >>= 1;
                    407:        }
1.10    ! djm       408:
        !           409:        nc = channel_new("session", SSH_CHANNEL_OPENING,
1.1       djm       410:            new_fd[0], new_fd[1], new_fd[2], window, packetmax,
                    411:            CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
                    412:
1.10    ! djm       413:        nc->ctl_chan = c->self;         /* link session -> control channel */
        !           414:        c->remote_id = nc->self;        /* link control -> session channel */
        !           415:
1.2       djm       416:        if (cctx->want_tty && escape_char != 0xffffffff) {
1.10    ! djm       417:                channel_register_filter(nc->self,
1.2       djm       418:                    client_simple_escape_filter, NULL,
1.4       djm       419:                    client_filter_cleanup,
1.2       djm       420:                    client_new_escape_filter_ctx((int)escape_char));
                    421:        }
1.1       djm       422:
1.10    ! djm       423:        debug2("%s: channel_new: %d linked to control channel %d",
        !           424:            __func__, nc->self, nc->ctl_chan);
        !           425:
        !           426:        channel_send_open(nc->self);
        !           427:        channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
        !           428:        channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0);
        !           429:
        !           430:        /* prepare reply */
        !           431:        /* XXX defer until mux_session_confirm() fires */
        !           432:        buffer_put_int(r, MUX_S_SESSION_OPENED);
        !           433:        buffer_put_int(r, rid);
        !           434:        buffer_put_int(r, nc->self);
1.1       djm       435:
                    436:        return 0;
                    437: }
                    438:
1.10    ! djm       439: static int
        !           440: process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
1.1       djm       441: {
1.10    ! djm       442:        debug2("%s: channel %d: alive check", __func__, c->self);
1.1       djm       443:
1.10    ! djm       444:        /* prepare reply */
        !           445:        buffer_put_int(r, MUX_S_ALIVE);
        !           446:        buffer_put_int(r, rid);
        !           447:        buffer_put_int(r, (u_int)getpid());
1.1       djm       448:
1.10    ! djm       449:        return 0;
1.1       djm       450: }
                    451:
                    452: static int
1.10    ! djm       453: process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
1.1       djm       454: {
1.10    ! djm       455:        debug2("%s: channel %d: terminate request", __func__, c->self);
1.1       djm       456:
1.10    ! djm       457:        if (options.control_master == SSHCTL_MASTER_ASK ||
        !           458:            options.control_master == SSHCTL_MASTER_AUTO_ASK) {
        !           459:                if (!ask_permission("Terminate shared connection to %s? ",
        !           460:                    host)) {
        !           461:                        debug2("%s: termination refused by user", __func__);
        !           462:                        buffer_put_int(r, MUX_S_PERMISSION_DENIED);
        !           463:                        buffer_put_int(r, rid);
        !           464:                        buffer_put_cstring(r, "Permission denied");
        !           465:                        return 0;
        !           466:                }
        !           467:        }
1.1       djm       468:
1.10    ! djm       469:        quit_pending = 1;
        !           470:        buffer_put_int(r, MUX_S_OK);
        !           471:        buffer_put_int(r, rid);
        !           472:        /* XXX exit happens too soon - message never makes it to client */
        !           473:        return 0;
1.1       djm       474: }
                    475:
1.10    ! djm       476: static char *
        !           477: format_forward(u_int ftype, Forward *fwd)
1.1       djm       478: {
1.10    ! djm       479:        char *ret;
1.1       djm       480:
1.10    ! djm       481:        switch (ftype) {
        !           482:        case MUX_FWD_LOCAL:
        !           483:                xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
        !           484:                    (fwd->listen_host == NULL) ?
        !           485:                    (options.gateway_ports ? "*" : "LOCALHOST") :
        !           486:                    fwd->listen_host, fwd->listen_port,
        !           487:                    fwd->connect_host, fwd->connect_port);
        !           488:                break;
        !           489:        case MUX_FWD_DYNAMIC:
        !           490:                xasprintf(&ret, "dynamic forward %.200s:%d -> *",
        !           491:                    (fwd->listen_host == NULL) ?
        !           492:                    (options.gateway_ports ? "*" : "LOCALHOST") :
        !           493:                     fwd->listen_host, fwd->listen_port);
        !           494:                break;
        !           495:        case MUX_FWD_REMOTE:
        !           496:                xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
        !           497:                    (fwd->listen_host == NULL) ?
        !           498:                    "LOCALHOST" : fwd->listen_host,
        !           499:                    fwd->listen_port,
        !           500:                    fwd->connect_host, fwd->connect_port);
1.1       djm       501:                break;
                    502:        default:
1.10    ! djm       503:                fatal("%s: unknown forward type %u", __func__, ftype);
1.1       djm       504:        }
1.10    ! djm       505:        return ret;
        !           506: }
1.1       djm       507:
1.10    ! djm       508: static int
        !           509: compare_host(const char *a, const char *b)
        !           510: {
        !           511:        if (a == NULL && b == NULL)
        !           512:                return 1;
        !           513:        if (a == NULL || b == NULL)
        !           514:                return 0;
        !           515:        return strcmp(a, b) == 0;
        !           516: }
1.1       djm       517:
1.10    ! djm       518: static int
        !           519: compare_forward(Forward *a, Forward *b)
        !           520: {
        !           521:        if (!compare_host(a->listen_host, b->listen_host))
        !           522:                return 0;
        !           523:        if (a->listen_port != b->listen_port)
        !           524:                return 0;
        !           525:        if (!compare_host(a->connect_host, b->connect_host))
        !           526:                return 0;
        !           527:        if (a->connect_port != b->connect_port)
        !           528:                return 0;
1.1       djm       529:
1.10    ! djm       530:        return 1;
        !           531: }
1.1       djm       532:
1.10    ! djm       533: static int
        !           534: process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
        !           535: {
        !           536:        Forward fwd;
        !           537:        char *fwd_desc = NULL;
        !           538:        u_int ftype;
        !           539:        int i, ret = 0, freefwd = 1;
        !           540:
        !           541:        fwd.listen_host = fwd.connect_host = NULL;
        !           542:        if (buffer_get_int_ret(&ftype, m) != 0 ||
        !           543:            (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
        !           544:            buffer_get_int_ret(&fwd.listen_port, m) != 0 ||
        !           545:            (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
        !           546:            buffer_get_int_ret(&fwd.connect_port, m) != 0) {
        !           547:                error("%s: malformed message", __func__);
        !           548:                ret = -1;
        !           549:                goto out;
        !           550:        }
        !           551:
        !           552:        if (*fwd.listen_host == '\0') {
        !           553:                xfree(fwd.listen_host);
        !           554:                fwd.listen_host = NULL;
        !           555:        }
        !           556:        if (*fwd.connect_host == '\0') {
        !           557:                xfree(fwd.connect_host);
        !           558:                fwd.connect_host = NULL;
        !           559:        }
        !           560:
        !           561:        debug2("%s: channel %d: request %s", __func__, c->self,
        !           562:            (fwd_desc = format_forward(ftype, &fwd)));
        !           563:
        !           564:        if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE &&
        !           565:            ftype != MUX_FWD_DYNAMIC) {
        !           566:                logit("%s: invalid forwarding type %u", __func__, ftype);
        !           567:  invalid:
        !           568:                xfree(fwd.listen_host);
        !           569:                xfree(fwd.connect_host);
        !           570:                buffer_put_int(r, MUX_S_FAILURE);
        !           571:                buffer_put_int(r, rid);
        !           572:                buffer_put_cstring(r, "Invalid forwarding request");
        !           573:                return 0;
        !           574:        }
        !           575:        /* XXX support rport0 forwarding with reply of port assigned */
        !           576:        if (fwd.listen_port == 0 || fwd.listen_port >= 65536) {
        !           577:                logit("%s: invalid listen port %u", __func__,
        !           578:                    fwd.listen_port);
        !           579:                goto invalid;
        !           580:        }
        !           581:        if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC &&
        !           582:            ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
        !           583:                logit("%s: invalid connect port %u", __func__,
        !           584:                    fwd.connect_port);
        !           585:                goto invalid;
        !           586:        }
        !           587:        if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) {
        !           588:                logit("%s: missing connect host", __func__);
        !           589:                goto invalid;
        !           590:        }
        !           591:
        !           592:        /* Skip forwards that have already been requested */
        !           593:        switch (ftype) {
        !           594:        case MUX_FWD_LOCAL:
        !           595:        case MUX_FWD_DYNAMIC:
        !           596:                for (i = 0; i < options.num_local_forwards; i++) {
        !           597:                        if (compare_forward(&fwd,
        !           598:                            options.local_forwards + i)) {
        !           599:  exists:
        !           600:                                debug2("%s: found existing forwarding",
        !           601:                                    __func__);
        !           602:                                buffer_put_int(r, MUX_S_OK);
        !           603:                                buffer_put_int(r, rid);
        !           604:                                goto out;
        !           605:                        }
        !           606:                }
        !           607:                break;
        !           608:        case MUX_FWD_REMOTE:
        !           609:                for (i = 0; i < options.num_remote_forwards; i++) {
        !           610:                        if (compare_forward(&fwd,
        !           611:                            options.remote_forwards + i))
        !           612:                                goto exists;
        !           613:                }
        !           614:                break;
        !           615:        }
        !           616:
        !           617:        if (options.control_master == SSHCTL_MASTER_ASK ||
        !           618:            options.control_master == SSHCTL_MASTER_AUTO_ASK) {
        !           619:                if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
        !           620:                        debug2("%s: forwarding refused by user", __func__);
        !           621:                        buffer_put_int(r, MUX_S_PERMISSION_DENIED);
        !           622:                        buffer_put_int(r, rid);
        !           623:                        buffer_put_cstring(r, "Permission denied");
        !           624:                        goto out;
        !           625:                }
        !           626:        }
        !           627:
        !           628:        if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
        !           629:                if (options.num_local_forwards + 1 >=
        !           630:                    SSH_MAX_FORWARDS_PER_DIRECTION ||
        !           631:                    channel_setup_local_fwd_listener(fwd.listen_host,
        !           632:                    fwd.listen_port, fwd.connect_host, fwd.connect_port,
        !           633:                    options.gateway_ports) < 0) {
        !           634:  fail:
        !           635:                        logit("slave-requested %s failed", fwd_desc);
        !           636:                        buffer_put_int(r, MUX_S_FAILURE);
        !           637:                        buffer_put_int(r, rid);
        !           638:                        buffer_put_cstring(r, "Port forwarding failed");
        !           639:                        goto out;
        !           640:                }
        !           641:                add_local_forward(&options, &fwd);
        !           642:                freefwd = 0;
        !           643:        } else {
        !           644:                /* XXX wait for remote to confirm */
        !           645:                if (options.num_remote_forwards + 1 >=
        !           646:                    SSH_MAX_FORWARDS_PER_DIRECTION ||
        !           647:                    channel_request_remote_forwarding(fwd.listen_host,
        !           648:                    fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0)
        !           649:                        goto fail;
        !           650:                add_remote_forward(&options, &fwd);
        !           651:                freefwd = 0;
        !           652:        }
        !           653:        buffer_put_int(r, MUX_S_OK);
        !           654:        buffer_put_int(r, rid);
        !           655:  out:
        !           656:        if (fwd_desc != NULL)
        !           657:                xfree(fwd_desc);
        !           658:        if (freefwd) {
        !           659:                if (fwd.listen_host != NULL)
        !           660:                        xfree(fwd.listen_host);
        !           661:                if (fwd.connect_host != NULL)
        !           662:                        xfree(fwd.connect_host);
        !           663:        }
        !           664:        return ret;
        !           665: }
        !           666:
        !           667: static int
        !           668: process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
        !           669: {
        !           670:        Forward fwd;
        !           671:        char *fwd_desc = NULL;
        !           672:        u_int ftype;
        !           673:        int ret = 0;
        !           674:
        !           675:        fwd.listen_host = fwd.connect_host = NULL;
        !           676:        if (buffer_get_int_ret(&ftype, m) != 0 ||
        !           677:            (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL ||
        !           678:            buffer_get_int_ret(&fwd.listen_port, m) != 0 ||
        !           679:            (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL ||
        !           680:            buffer_get_int_ret(&fwd.connect_port, m) != 0) {
        !           681:                error("%s: malformed message", __func__);
        !           682:                ret = -1;
        !           683:                goto out;
        !           684:        }
        !           685:
        !           686:        if (*fwd.listen_host == '\0') {
        !           687:                xfree(fwd.listen_host);
        !           688:                fwd.listen_host = NULL;
        !           689:        }
        !           690:        if (*fwd.connect_host == '\0') {
        !           691:                xfree(fwd.connect_host);
        !           692:                fwd.connect_host = NULL;
        !           693:        }
        !           694:
        !           695:        debug2("%s: channel %d: request %s", __func__, c->self,
        !           696:            (fwd_desc = format_forward(ftype, &fwd)));
        !           697:
        !           698:        /* XXX implement this */
        !           699:        buffer_put_int(r, MUX_S_FAILURE);
        !           700:        buffer_put_int(r, rid);
        !           701:        buffer_put_cstring(r, "unimplemented");
        !           702:
        !           703:  out:
        !           704:        if (fwd_desc != NULL)
        !           705:                xfree(fwd_desc);
        !           706:        if (fwd.listen_host != NULL)
        !           707:                xfree(fwd.listen_host);
        !           708:        if (fwd.connect_host != NULL)
        !           709:                xfree(fwd.connect_host);
        !           710:
        !           711:        return ret;
        !           712: }
        !           713:
        !           714: static int
        !           715: process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
        !           716: {
        !           717:        Channel *nc;
        !           718:        char *reserved, *chost;
        !           719:        u_int cport, i, j;
        !           720:        int new_fd[2];
        !           721:
        !           722:        if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
        !           723:           (chost = buffer_get_string_ret(m, NULL)) == NULL ||
        !           724:            buffer_get_int_ret(&cport, m) != 0) {
        !           725:                if (chost != NULL)
        !           726:                        xfree(chost);
        !           727:                error("%s: malformed message", __func__);
        !           728:                return -1;
        !           729:        }
        !           730:        xfree(reserved);
        !           731:
        !           732:        debug2("%s: channel %d: request stdio fwd to %s:%u",
        !           733:            __func__, c->self, chost, cport);
        !           734:
        !           735:        /* Gather fds from client */
        !           736:        for(i = 0; i < 2; i++) {
        !           737:                if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
        !           738:                        error("%s: failed to receive fd %d from slave",
        !           739:                            __func__, i);
        !           740:                        for (j = 0; j < i; j++)
        !           741:                                close(new_fd[j]);
        !           742:                        xfree(chost);
        !           743:
        !           744:                        /* prepare reply */
        !           745:                        buffer_put_int(r, MUX_S_FAILURE);
        !           746:                        buffer_put_int(r, rid);
        !           747:                        buffer_put_cstring(r,
        !           748:                            "did not receive file descriptors");
        !           749:                        return -1;
        !           750:                }
        !           751:        }
        !           752:
        !           753:        debug3("%s: got fds stdin %d, stdout %d", __func__,
        !           754:            new_fd[0], new_fd[1]);
        !           755:
        !           756:        /* XXX support multiple child sessions in future */
        !           757:        if (c->remote_id != -1) {
        !           758:                debug2("%s: session already open", __func__);
        !           759:                /* prepare reply */
        !           760:                buffer_put_int(r, MUX_S_FAILURE);
        !           761:                buffer_put_int(r, rid);
        !           762:                buffer_put_cstring(r, "Multiple sessions not supported");
        !           763:  cleanup:
        !           764:                close(new_fd[0]);
        !           765:                close(new_fd[1]);
        !           766:                xfree(chost);
        !           767:                return 0;
        !           768:        }
        !           769:
        !           770:        if (options.control_master == SSHCTL_MASTER_ASK ||
        !           771:            options.control_master == SSHCTL_MASTER_AUTO_ASK) {
        !           772:                if (!ask_permission("Allow forward to to %s:%u? ",
        !           773:                    chost, cport)) {
        !           774:                        debug2("%s: stdio fwd refused by user", __func__);
        !           775:                        /* prepare reply */
        !           776:                        buffer_put_int(r, MUX_S_PERMISSION_DENIED);
        !           777:                        buffer_put_int(r, rid);
        !           778:                        buffer_put_cstring(r, "Permission denied");
        !           779:                        goto cleanup;
        !           780:                }
        !           781:        }
        !           782:
        !           783:        /* enable nonblocking unless tty */
        !           784:        if (!isatty(new_fd[0]))
        !           785:                set_nonblock(new_fd[0]);
        !           786:        if (!isatty(new_fd[1]))
        !           787:                set_nonblock(new_fd[1]);
        !           788:
        !           789:        nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]);
        !           790:
        !           791:        nc->ctl_chan = c->self;         /* link session -> control channel */
        !           792:        c->remote_id = nc->self;        /* link control -> session channel */
        !           793:
        !           794:        debug2("%s: channel_new: %d linked to control channel %d",
        !           795:            __func__, nc->self, nc->ctl_chan);
        !           796:
        !           797:        channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 0);
        !           798:
        !           799:        /* prepare reply */
        !           800:        /* XXX defer until channel confirmed */
        !           801:        buffer_put_int(r, MUX_S_SESSION_OPENED);
        !           802:        buffer_put_int(r, rid);
        !           803:        buffer_put_int(r, nc->self);
        !           804:
        !           805:        return 0;
        !           806: }
        !           807:
        !           808: /* Channel callbacks fired on read/write from mux slave fd */
        !           809: static int
        !           810: mux_master_read_cb(Channel *c)
        !           811: {
        !           812:        struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
        !           813:        Buffer in, out;
        !           814:        void *ptr;
        !           815:        u_int type, rid, have, i;
        !           816:        int ret = -1;
        !           817:
        !           818:        /* Setup ctx and  */
        !           819:        if (c->mux_ctx == NULL) {
        !           820:                state = xcalloc(1, sizeof(state));
        !           821:                c->mux_ctx = state;
        !           822:                channel_register_cleanup(c->self,
        !           823:                    mux_master_control_cleanup_cb, 0);
        !           824:
        !           825:                /* Send hello */
        !           826:                buffer_init(&out);
        !           827:                buffer_put_int(&out, MUX_MSG_HELLO);
        !           828:                buffer_put_int(&out, SSHMUX_VER);
        !           829:                /* no extensions */
        !           830:                buffer_put_string(&c->output, buffer_ptr(&out),
        !           831:                    buffer_len(&out));
        !           832:                buffer_free(&out);
        !           833:                debug3("%s: channel %d: hello sent", __func__, c->self);
        !           834:                return 0;
        !           835:        }
        !           836:
        !           837:        buffer_init(&in);
        !           838:        buffer_init(&out);
        !           839:
        !           840:        /* Channel code ensures that we receive whole packets */
        !           841:        if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) {
        !           842:  malf:
        !           843:                error("%s: malformed message", __func__);
        !           844:                goto out;
        !           845:        }
        !           846:        buffer_append(&in, ptr, have);
        !           847:
        !           848:        if (buffer_get_int_ret(&type, &in) != 0)
        !           849:                goto malf;
        !           850:        debug3("%s: channel %d packet type 0x%08x len %u",
        !           851:            __func__, c->self, type, buffer_len(&in));
        !           852:
        !           853:        if (type == MUX_MSG_HELLO)
        !           854:                rid = 0;
        !           855:        else {
        !           856:                if (!state->hello_rcvd) {
        !           857:                        error("%s: expected MUX_MSG_HELLO(0x%08x), "
        !           858:                            "received 0x%08x", __func__, MUX_MSG_HELLO, type);
        !           859:                        goto out;
1.1       djm       860:                }
1.10    ! djm       861:                if (buffer_get_int_ret(&rid, &in) != 0)
        !           862:                        goto malf;
        !           863:        }
        !           864:
        !           865:        for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
        !           866:                if (type == mux_master_handlers[i].type) {
        !           867:                        ret = mux_master_handlers[i].handler(rid, c, &in, &out);
        !           868:                        break;
1.1       djm       869:                }
1.10    ! djm       870:        }
        !           871:        if (mux_master_handlers[i].handler == NULL) {
        !           872:                error("%s: unsupported mux message 0x%08x", __func__, type);
        !           873:                buffer_put_int(&out, MUX_S_FAILURE);
        !           874:                buffer_put_int(&out, rid);
        !           875:                buffer_put_cstring(&out, "unsupported request");
        !           876:                ret = 0;
        !           877:        }
        !           878:        /* Enqueue reply packet */
        !           879:        if (buffer_len(&out) != 0) {
        !           880:                buffer_put_string(&c->output, buffer_ptr(&out),
        !           881:                    buffer_len(&out));
        !           882:        }
        !           883:  out:
        !           884:        buffer_free(&in);
        !           885:        buffer_free(&out);
        !           886:        return ret;
        !           887: }
        !           888:
        !           889: void
        !           890: mux_exit_message(Channel *c, int exitval)
        !           891: {
        !           892:        Buffer m;
        !           893:        Channel *mux_chan;
        !           894:
        !           895:        debug3("%s: channel %d: exit message, evitval %d", __func__, c->self,
        !           896:            exitval);
        !           897:
        !           898:        if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
        !           899:                fatal("%s: channel %d missing mux channel %d",
        !           900:                    __func__, c->self, c->ctl_chan);
        !           901:
        !           902:        /* Append exit message packet to control socket output queue */
        !           903:        buffer_init(&m);
        !           904:        buffer_put_int(&m, MUX_S_EXIT_MESSAGE);
        !           905:        buffer_put_int(&m, c->self);
        !           906:        buffer_put_int(&m, exitval);
        !           907:
        !           908:        buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
        !           909:        buffer_free(&m);
        !           910: }
        !           911:
        !           912: /* Prepare a mux master to listen on a Unix domain socket. */
        !           913: void
        !           914: muxserver_listen(void)
        !           915: {
        !           916:        struct sockaddr_un addr;
        !           917:        mode_t old_umask;
        !           918:
        !           919:        if (options.control_path == NULL ||
        !           920:            options.control_master == SSHCTL_MASTER_NO)
1.1       djm       921:                return;
1.10    ! djm       922:
        !           923:        debug("setting up multiplex master socket");
        !           924:
        !           925:        memset(&addr, '\0', sizeof(addr));
        !           926:        addr.sun_family = AF_UNIX;
        !           927:        addr.sun_len = offsetof(struct sockaddr_un, sun_path) +
        !           928:            strlen(options.control_path) + 1;
        !           929:
        !           930:        if (strlcpy(addr.sun_path, options.control_path,
        !           931:            sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
        !           932:                fatal("ControlPath too long");
        !           933:
        !           934:        if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        !           935:                fatal("%s socket(): %s", __func__, strerror(errno));
        !           936:
        !           937:        old_umask = umask(0177);
        !           938:        if (bind(muxserver_sock, (struct sockaddr *)&addr, addr.sun_len) == -1) {
        !           939:                muxserver_sock = -1;
        !           940:                if (errno == EINVAL || errno == EADDRINUSE) {
        !           941:                        error("ControlSocket %s already exists, "
        !           942:                            "disabling multiplexing", options.control_path);
        !           943:                        close(muxserver_sock);
        !           944:                        muxserver_sock = -1;
        !           945:                        xfree(options.control_path);
        !           946:                        options.control_path = NULL;
        !           947:                        options.control_master = SSHCTL_MASTER_NO;
        !           948:                        return;
        !           949:                } else
        !           950:                        fatal("%s bind(): %s", __func__, strerror(errno));
        !           951:        }
        !           952:        umask(old_umask);
        !           953:
        !           954:        if (listen(muxserver_sock, 64) == -1)
        !           955:                fatal("%s listen(): %s", __func__, strerror(errno));
        !           956:
        !           957:        set_nonblock(muxserver_sock);
        !           958:
        !           959:        mux_listener_channel = channel_new("mux listener",
        !           960:            SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
        !           961:            CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
        !           962:            0, addr.sun_path, 1);
        !           963:        mux_listener_channel->mux_rcb = mux_master_read_cb;
        !           964:        debug3("%s: mux listener channel %d fd %d", __func__,
        !           965:            mux_listener_channel->self, mux_listener_channel->sock);
        !           966: }
        !           967:
        !           968: /* Callback on open confirmation in mux master for a mux client session. */
        !           969: static void
        !           970: mux_session_confirm(int id, void *arg)
        !           971: {
        !           972:        struct mux_session_confirm_ctx *cctx = arg;
        !           973:        const char *display;
        !           974:        Channel *c;
        !           975:        int i;
        !           976:
        !           977:        if (cctx == NULL)
        !           978:                fatal("%s: cctx == NULL", __func__);
        !           979:        if ((c = channel_by_id(id)) == NULL)
        !           980:                fatal("%s: no channel for id %d", __func__, id);
        !           981:
        !           982:        display = getenv("DISPLAY");
        !           983:        if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
        !           984:                char *proto, *data;
        !           985:                /* Get reasonable local authentication information. */
        !           986:                client_x11_get_proto(display, options.xauth_location,
        !           987:                    options.forward_x11_trusted, &proto, &data);
        !           988:                /* Request forwarding with authentication spoofing. */
        !           989:                debug("Requesting X11 forwarding with authentication spoofing.");
        !           990:                x11_request_forwarding_with_spoofing(id, display, proto, data);
        !           991:                /* XXX wait for reply */
        !           992:        }
        !           993:
        !           994:        if (cctx->want_agent_fwd && options.forward_agent) {
        !           995:                debug("Requesting authentication agent forwarding.");
        !           996:                channel_request_start(id, "auth-agent-req@openssh.com", 0);
        !           997:                packet_send();
        !           998:        }
        !           999:
        !          1000:        client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
        !          1001:            cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
        !          1002:
        !          1003:        c->open_confirm_ctx = NULL;
        !          1004:        buffer_free(&cctx->cmd);
        !          1005:        xfree(cctx->term);
        !          1006:        if (cctx->env != NULL) {
        !          1007:                for (i = 0; cctx->env[i] != NULL; i++)
        !          1008:                        xfree(cctx->env[i]);
        !          1009:                xfree(cctx->env);
1.1       djm      1010:        }
1.10    ! djm      1011:        xfree(cctx);
        !          1012: }
        !          1013:
        !          1014: /* ** Multiplexing client support */
        !          1015:
        !          1016: /* Exit signal handler */
        !          1017: static void
        !          1018: control_client_sighandler(int signo)
        !          1019: {
        !          1020:        muxclient_terminate = signo;
        !          1021: }
        !          1022:
        !          1023: /*
        !          1024:  * Relay signal handler - used to pass some signals from mux client to
        !          1025:  * mux master.
        !          1026:  */
        !          1027: static void
        !          1028: control_client_sigrelay(int signo)
        !          1029: {
        !          1030:        int save_errno = errno;
        !          1031:
        !          1032:        if (muxserver_pid > 1)
        !          1033:                kill(muxserver_pid, signo);
        !          1034:
        !          1035:        errno = save_errno;
        !          1036: }
1.1       djm      1037:
1.10    ! djm      1038: static int
        !          1039: mux_client_read(int fd, Buffer *b, u_int need)
        !          1040: {
        !          1041:        u_int have;
        !          1042:        ssize_t len;
        !          1043:        u_char *p;
        !          1044:        struct pollfd pfd;
        !          1045:
        !          1046:        pfd.fd = fd;
        !          1047:        pfd.events = POLLIN;
        !          1048:        p = buffer_append_space(b, need);
        !          1049:        for (have = 0; have < need; ) {
        !          1050:                if (muxclient_terminate) {
        !          1051:                        errno = EINTR;
        !          1052:                        return -1;
        !          1053:                }
        !          1054:                len = read(fd, p + have, need - have);
        !          1055:                if (len < 0) {
        !          1056:                        switch (errno) {
        !          1057:                        case EAGAIN:
        !          1058:                                (void)poll(&pfd, 1, -1);
        !          1059:                                /* FALLTHROUGH */
        !          1060:                        case EINTR:
        !          1061:                                continue;
        !          1062:                        default:
        !          1063:                                return -1;
        !          1064:                        }
        !          1065:                }
        !          1066:                if (len == 0) {
        !          1067:                        errno = EPIPE;
        !          1068:                        return -1;
        !          1069:                }
        !          1070:                have += (u_int)len;
1.1       djm      1071:        }
1.10    ! djm      1072:        return 0;
        !          1073: }
1.1       djm      1074:
1.10    ! djm      1075: static int
        !          1076: mux_client_write_packet(int fd, Buffer *m)
        !          1077: {
        !          1078:        Buffer queue;
        !          1079:        u_int have, need;
        !          1080:        int oerrno, len;
        !          1081:        u_char *ptr;
        !          1082:        struct pollfd pfd;
        !          1083:
        !          1084:        pfd.fd = fd;
        !          1085:        pfd.events = POLLOUT;
        !          1086:        buffer_init(&queue);
        !          1087:        buffer_put_string(&queue, buffer_ptr(m), buffer_len(m));
        !          1088:
        !          1089:        need = buffer_len(&queue);
        !          1090:        ptr = buffer_ptr(&queue);
        !          1091:
        !          1092:        for (have = 0; have < need; ) {
        !          1093:                if (muxclient_terminate) {
        !          1094:                        buffer_free(&queue);
        !          1095:                        errno = EINTR;
        !          1096:                        return -1;
        !          1097:                }
        !          1098:                len = write(fd, ptr + have, need - have);
        !          1099:                if (len < 0) {
        !          1100:                        switch (errno) {
        !          1101:                        case EAGAIN:
        !          1102:                                (void)poll(&pfd, 1, -1);
        !          1103:                                /* FALLTHROUGH */
        !          1104:                        case EINTR:
        !          1105:                                continue;
        !          1106:                        default:
        !          1107:                                oerrno = errno;
        !          1108:                                buffer_free(&queue);
        !          1109:                                errno = oerrno;
        !          1110:                                return -1;
        !          1111:                        }
        !          1112:                }
        !          1113:                if (len == 0) {
        !          1114:                        buffer_free(&queue);
        !          1115:                        errno = EPIPE;
        !          1116:                        return -1;
        !          1117:                }
        !          1118:                have += (u_int)len;
        !          1119:        }
        !          1120:        buffer_free(&queue);
        !          1121:        return 0;
        !          1122: }
1.1       djm      1123:
1.10    ! djm      1124: static int
        !          1125: mux_client_read_packet(int fd, Buffer *m)
        !          1126: {
        !          1127:        Buffer queue;
        !          1128:        u_int need, have;
        !          1129:        void *ptr;
        !          1130:        int oerrno;
        !          1131:
        !          1132:        buffer_init(&queue);
        !          1133:        if (mux_client_read(fd, &queue, 4) != 0) {
        !          1134:                if ((oerrno = errno) == EPIPE)
        !          1135:                debug3("%s: read header failed: %s", __func__, strerror(errno));
        !          1136:                errno = oerrno;
        !          1137:                return -1;
        !          1138:        }
        !          1139:        need = get_u32(buffer_ptr(&queue));
        !          1140:        if (mux_client_read(fd, &queue, need) != 0) {
        !          1141:                oerrno = errno;
        !          1142:                debug3("%s: read body failed: %s", __func__, strerror(errno));
        !          1143:                errno = oerrno;
        !          1144:                return -1;
        !          1145:        }
        !          1146:        ptr = buffer_get_string_ptr(&queue, &have);
        !          1147:        buffer_append(m, ptr, have);
        !          1148:        buffer_free(&queue);
        !          1149:        return 0;
        !          1150: }
1.1       djm      1151:
1.10    ! djm      1152: static int
        !          1153: mux_client_hello_exchange(int fd)
        !          1154: {
        !          1155:        Buffer m;
        !          1156:        u_int type, ver;
1.1       djm      1157:
                   1158:        buffer_init(&m);
1.10    ! djm      1159:        buffer_put_int(&m, MUX_MSG_HELLO);
        !          1160:        buffer_put_int(&m, SSHMUX_VER);
        !          1161:        /* no extensions */
        !          1162:
        !          1163:        if (mux_client_write_packet(fd, &m) != 0)
        !          1164:                fatal("%s: write packet: %s", __func__, strerror(errno));
1.1       djm      1165:
1.10    ! djm      1166:        buffer_clear(&m);
        !          1167:
        !          1168:        /* Read their HELLO */
        !          1169:        if (mux_client_read_packet(fd, &m) != 0) {
1.5       djm      1170:                buffer_free(&m);
1.10    ! djm      1171:                return -1;
        !          1172:        }
        !          1173:
        !          1174:        type = buffer_get_int(&m);
        !          1175:        if (type != MUX_MSG_HELLO)
        !          1176:                fatal("%s: expected HELLO (%u) received %u",
        !          1177:                    __func__, MUX_MSG_HELLO, type);
        !          1178:        ver = buffer_get_int(&m);
        !          1179:        if (ver != SSHMUX_VER)
        !          1180:                fatal("Unsupported multiplexing protocol version %d "
        !          1181:                    "(expected %d)", ver, SSHMUX_VER);
        !          1182:        debug2("%s: master version %u", __func__, ver);
        !          1183:        /* No extensions are presently defined */
        !          1184:        while (buffer_len(&m) > 0) {
        !          1185:                char *name = buffer_get_string(&m, NULL);
        !          1186:                char *value = buffer_get_string(&m, NULL);
        !          1187:
        !          1188:                debug2("Unrecognised master extension \"%s\"", name);
        !          1189:                xfree(name);
        !          1190:                xfree(value);
1.5       djm      1191:        }
1.10    ! djm      1192:        buffer_free(&m);
        !          1193:        return 0;
        !          1194: }
        !          1195:
        !          1196: static u_int
        !          1197: mux_client_request_alive(int fd)
        !          1198: {
        !          1199:        Buffer m;
        !          1200:        char *e;
        !          1201:        u_int pid, type, rid;
        !          1202:
        !          1203:        debug3("%s: entering", __func__);
        !          1204:
        !          1205:        buffer_init(&m);
        !          1206:        buffer_put_int(&m, MUX_C_ALIVE_CHECK);
        !          1207:        buffer_put_int(&m, muxclient_request_id);
        !          1208:
        !          1209:        if (mux_client_write_packet(fd, &m) != 0)
        !          1210:                fatal("%s: write packet: %s", __func__, strerror(errno));
        !          1211:
1.1       djm      1212:        buffer_clear(&m);
                   1213:
1.10    ! djm      1214:        /* Read their reply */
        !          1215:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1216:                buffer_free(&m);
        !          1217:                return 0;
        !          1218:        }
        !          1219:
        !          1220:        type = buffer_get_int(&m);
        !          1221:        if (type != MUX_S_ALIVE) {
        !          1222:                e = buffer_get_string(&m, NULL);
        !          1223:                fatal("%s: master returned error: %s", __func__, e);
1.5       djm      1224:        }
1.10    ! djm      1225:
        !          1226:        if ((rid = buffer_get_int(&m)) != muxclient_request_id)
        !          1227:                fatal("%s: out of sequence reply: my id %u theirs %u",
        !          1228:                    __func__, muxclient_request_id, rid);
        !          1229:        pid = buffer_get_int(&m);
        !          1230:        buffer_free(&m);
        !          1231:
        !          1232:        debug3("%s: done pid = %u", __func__, pid);
        !          1233:
        !          1234:        muxclient_request_id++;
        !          1235:
        !          1236:        return pid;
        !          1237: }
        !          1238:
        !          1239: static void
        !          1240: mux_client_request_terminate(int fd)
        !          1241: {
        !          1242:        Buffer m;
        !          1243:        char *e;
        !          1244:        u_int type, rid;
        !          1245:
        !          1246:        debug3("%s: entering", __func__);
        !          1247:
        !          1248:        buffer_init(&m);
        !          1249:        buffer_put_int(&m, MUX_C_TERMINATE);
        !          1250:        buffer_put_int(&m, muxclient_request_id);
        !          1251:
        !          1252:        if (mux_client_write_packet(fd, &m) != 0)
        !          1253:                fatal("%s: write packet: %s", __func__, strerror(errno));
1.1       djm      1254:
                   1255:        buffer_clear(&m);
                   1256:
1.10    ! djm      1257:        /* Read their reply */
        !          1258:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1259:                /* Remote end exited already */
        !          1260:                if (errno == EPIPE) {
        !          1261:                        buffer_free(&m);
        !          1262:                        return;
1.2       djm      1263:                }
1.10    ! djm      1264:                fatal("%s: read from master failed: %s",
        !          1265:                    __func__, strerror(errno));
        !          1266:        }
        !          1267:
        !          1268:        type = buffer_get_int(&m);
        !          1269:        if ((rid = buffer_get_int(&m)) != muxclient_request_id)
        !          1270:                fatal("%s: out of sequence reply: my id %u theirs %u",
        !          1271:                    __func__, muxclient_request_id, rid);
        !          1272:        switch (type) {
        !          1273:        case MUX_S_OK:
        !          1274:                break;
        !          1275:        case MUX_S_PERMISSION_DENIED:
        !          1276:                e = buffer_get_string(&m, NULL);
        !          1277:                fatal("Master refused termination request: %s", e);
        !          1278:        case MUX_S_FAILURE:
        !          1279:                e = buffer_get_string(&m, NULL);
        !          1280:                fatal("%s: termination request failed: %s", __func__, e);
        !          1281:        default:
        !          1282:                fatal("%s: unexpected response from master 0x%08x",
        !          1283:                    __func__, type);
        !          1284:        }
        !          1285:        buffer_free(&m);
        !          1286:        muxclient_request_id++;
        !          1287: }
        !          1288:
        !          1289: static int
        !          1290: mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
        !          1291: {
        !          1292:        Buffer m;
        !          1293:        char *e, *fwd_desc;
        !          1294:        u_int type, rid;
        !          1295:
        !          1296:        fwd_desc = format_forward(ftype, fwd);
        !          1297:        debug("Requesting %s", fwd_desc);
        !          1298:        xfree(fwd_desc);
        !          1299:
        !          1300:        buffer_init(&m);
        !          1301:        buffer_put_int(&m, MUX_C_OPEN_FWD);
        !          1302:        buffer_put_int(&m, muxclient_request_id);
        !          1303:        buffer_put_int(&m, ftype);
        !          1304:        buffer_put_cstring(&m,
        !          1305:            fwd->listen_host == NULL ? "" : fwd->listen_host);
        !          1306:        buffer_put_int(&m, fwd->listen_port);
        !          1307:        buffer_put_cstring(&m,
        !          1308:            fwd->connect_host == NULL ? "" : fwd->connect_host);
        !          1309:        buffer_put_int(&m, fwd->connect_port);
        !          1310:
        !          1311:        if (mux_client_write_packet(fd, &m) != 0)
        !          1312:                fatal("%s: write packet: %s", __func__, strerror(errno));
        !          1313:
        !          1314:        buffer_clear(&m);
        !          1315:
        !          1316:        /* Read their reply */
        !          1317:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1318:                buffer_free(&m);
        !          1319:                return -1;
        !          1320:        }
        !          1321:
        !          1322:        type = buffer_get_int(&m);
        !          1323:        if ((rid = buffer_get_int(&m)) != muxclient_request_id)
        !          1324:                fatal("%s: out of sequence reply: my id %u theirs %u",
        !          1325:                    __func__, muxclient_request_id, rid);
        !          1326:        switch (type) {
        !          1327:        case MUX_S_OK:
1.1       djm      1328:                break;
1.10    ! djm      1329:        case MUX_S_PERMISSION_DENIED:
        !          1330:                e = buffer_get_string(&m, NULL);
        !          1331:                buffer_free(&m);
        !          1332:                error("Master refused forwarding request: %s", e);
        !          1333:                return -1;
        !          1334:        case MUX_S_FAILURE:
        !          1335:                e = buffer_get_string(&m, NULL);
        !          1336:                buffer_free(&m);
        !          1337:                error("%s: session request failed: %s", __func__, e);
        !          1338:                return -1;
1.1       djm      1339:        default:
1.10    ! djm      1340:                fatal("%s: unexpected response from master 0x%08x",
        !          1341:                    __func__, type);
        !          1342:        }
        !          1343:        buffer_free(&m);
        !          1344:
        !          1345:        muxclient_request_id++;
        !          1346:        return 0;
        !          1347: }
        !          1348:
        !          1349: static int
        !          1350: mux_client_request_forwards(int fd)
        !          1351: {
        !          1352:        int i;
        !          1353:
        !          1354:        debug3("%s: requesting forwardings: %d local, %d remote", __func__,
        !          1355:            options.num_local_forwards, options.num_remote_forwards);
        !          1356:
        !          1357:        /* XXX ExitOnForwardingFailure */
        !          1358:        for (i = 0; i < options.num_local_forwards; i++) {
        !          1359:                if (mux_client_request_forward(fd,
        !          1360:                    options.local_forwards[i].connect_port == 0 ?
        !          1361:                    MUX_FWD_DYNAMIC : MUX_FWD_LOCAL,
        !          1362:                    options.local_forwards + i) != 0)
        !          1363:                        return -1;
        !          1364:        }
        !          1365:        for (i = 0; i < options.num_remote_forwards; i++) {
        !          1366:                if (mux_client_request_forward(fd, MUX_FWD_REMOTE,
        !          1367:                    options.remote_forwards + i) != 0)
        !          1368:                        return -1;
        !          1369:        }
        !          1370:        return 0;
        !          1371: }
        !          1372:
        !          1373: static int
        !          1374: mux_client_request_session(int fd)
        !          1375: {
        !          1376:        Buffer m;
        !          1377:        char *e, *term;
        !          1378:        u_int i, rid, sid, esid, exitval, type, exitval_seen;
        !          1379:        extern char **environ;
        !          1380:        int devnull;
        !          1381:
        !          1382:        debug3("%s: entering", __func__);
        !          1383:
        !          1384:        if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
        !          1385:                error("%s: master alive request failed", __func__);
        !          1386:                return -1;
1.1       djm      1387:        }
                   1388:
1.10    ! djm      1389:        signal(SIGPIPE, SIG_IGN);
        !          1390:
        !          1391:        if (stdin_null_flag) {
        !          1392:                if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
        !          1393:                        fatal("open(/dev/null): %s", strerror(errno));
        !          1394:                if (dup2(devnull, STDIN_FILENO) == -1)
        !          1395:                        fatal("dup2: %s", strerror(errno));
        !          1396:                if (devnull > STDERR_FILENO)
        !          1397:                        close(devnull);
1.5       djm      1398:        }
1.1       djm      1399:
1.10    ! djm      1400:        term = getenv("TERM");
        !          1401:
        !          1402:        buffer_init(&m);
        !          1403:        buffer_put_int(&m, MUX_C_NEW_SESSION);
        !          1404:        buffer_put_int(&m, muxclient_request_id);
        !          1405:        buffer_put_cstring(&m, ""); /* reserved */
        !          1406:        buffer_put_int(&m, tty_flag);
        !          1407:        buffer_put_int(&m, options.forward_x11);
        !          1408:        buffer_put_int(&m, options.forward_agent);
        !          1409:        buffer_put_int(&m, subsystem_flag);
        !          1410:        buffer_put_int(&m, options.escape_char == SSH_ESCAPECHAR_NONE ?
        !          1411:            0xffffffff : (u_int)options.escape_char);
        !          1412:        buffer_put_cstring(&m, term == NULL ? "" : term);
        !          1413:        buffer_put_string(&m, buffer_ptr(&command), buffer_len(&command));
        !          1414:
        !          1415:        if (options.num_send_env > 0 && environ != NULL) {
        !          1416:                /* Pass environment */
        !          1417:                for (i = 0; environ[i] != NULL; i++) {
        !          1418:                        if (env_permitted(environ[i])) {
        !          1419:                                buffer_put_cstring(&m, environ[i]);
        !          1420:                        }
        !          1421:                }
1.5       djm      1422:        }
                   1423:
1.10    ! djm      1424:        if (mux_client_write_packet(fd, &m) != 0)
        !          1425:                fatal("%s: write packet: %s", __func__, strerror(errno));
        !          1426:
        !          1427:        /* Send the stdio file descriptors */
        !          1428:        if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
        !          1429:            mm_send_fd(fd, STDOUT_FILENO) == -1 ||
        !          1430:            mm_send_fd(fd, STDERR_FILENO) == -1)
        !          1431:                fatal("%s: send fds failed", __func__);
        !          1432:
        !          1433:        debug3("%s: session request sent", __func__);
1.1       djm      1434:
1.10    ! djm      1435:        /* Read their reply */
1.1       djm      1436:        buffer_clear(&m);
1.10    ! djm      1437:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1438:                error("%s: read from master failed: %s",
        !          1439:                    __func__, strerror(errno));
        !          1440:                buffer_free(&m);
        !          1441:                return -1;
        !          1442:        }
        !          1443:
        !          1444:        type = buffer_get_int(&m);
        !          1445:        if ((rid = buffer_get_int(&m)) != muxclient_request_id)
        !          1446:                fatal("%s: out of sequence reply: my id %u theirs %u",
        !          1447:                    __func__, muxclient_request_id, rid);
        !          1448:        switch (type) {
        !          1449:        case MUX_S_SESSION_OPENED:
        !          1450:                sid = buffer_get_int(&m);
        !          1451:                debug("%s: master session id: %u", __func__, sid);
        !          1452:                break;
        !          1453:        case MUX_S_PERMISSION_DENIED:
        !          1454:                e = buffer_get_string(&m, NULL);
        !          1455:                buffer_free(&m);
        !          1456:                error("Master refused forwarding request: %s", e);
        !          1457:                return -1;
        !          1458:        case MUX_S_FAILURE:
        !          1459:                e = buffer_get_string(&m, NULL);
        !          1460:                buffer_free(&m);
        !          1461:                error("%s: forwarding request failed: %s", __func__, e);
        !          1462:                return -1;
        !          1463:        default:
        !          1464:                buffer_free(&m);
        !          1465:                error("%s: unexpected response from master 0x%08x",
        !          1466:                    __func__, type);
        !          1467:                return -1;
        !          1468:        }
        !          1469:        muxclient_request_id++;
1.1       djm      1470:
                   1471:        signal(SIGHUP, control_client_sighandler);
                   1472:        signal(SIGINT, control_client_sighandler);
                   1473:        signal(SIGTERM, control_client_sighandler);
                   1474:        signal(SIGWINCH, control_client_sigrelay);
                   1475:
                   1476:        if (tty_flag)
1.9       djm      1477:                enter_raw_mode(force_tty_flag);
1.1       djm      1478:
                   1479:        /*
                   1480:         * Stick around until the controlee closes the client_fd.
1.10    ! djm      1481:         * Before it does, it is expected to write an exit message.
        !          1482:         * This process must read the value and wait for the closure of
        !          1483:         * the client_fd; if this one closes early, the multiplex master will
        !          1484:         * terminate early too (possibly losing data).
1.1       djm      1485:         */
1.10    ! djm      1486:        for (exitval = 255, exitval_seen = 0;;) {
        !          1487:                buffer_clear(&m);
        !          1488:                if (mux_client_read_packet(fd, &m) != 0)
1.1       djm      1489:                        break;
1.10    ! djm      1490:                type = buffer_get_int(&m);
        !          1491:                if (type != MUX_S_EXIT_MESSAGE) {
        !          1492:                        e = buffer_get_string(&m, NULL);
        !          1493:                        fatal("%s: master returned error: %s", __func__, e);
1.1       djm      1494:                }
1.10    ! djm      1495:                if ((esid = buffer_get_int(&m)) != sid)
        !          1496:                        fatal("%s: exit on unknown session: my id %u theirs %u",
        !          1497:                            __func__, sid, esid);
        !          1498:                debug("%s: master session id: %u", __func__, sid);
        !          1499:                if (exitval_seen)
        !          1500:                        fatal("%s: exitval sent twice", __func__);
        !          1501:                exitval = buffer_get_int(&m);
        !          1502:                exitval_seen = 1;
1.1       djm      1503:        }
                   1504:
1.10    ! djm      1505:        close(fd);
1.9       djm      1506:        leave_raw_mode(force_tty_flag);
1.10    ! djm      1507:
1.1       djm      1508:        if (muxclient_terminate) {
                   1509:                debug2("Exiting on signal %d", muxclient_terminate);
1.10    ! djm      1510:                exitval = 255;
        !          1511:        } else if (!exitval_seen) {
1.1       djm      1512:                debug2("Control master terminated unexpectedly");
1.10    ! djm      1513:                exitval = 255;
1.1       djm      1514:        } else
1.10    ! djm      1515:                debug2("Received exit status from master %d", exitval);
1.1       djm      1516:
                   1517:        if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
                   1518:                fprintf(stderr, "Shared connection to %s closed.\r\n", host);
                   1519:
1.10    ! djm      1520:        exit(exitval);
        !          1521: }
        !          1522:
        !          1523: static int
        !          1524: mux_client_request_stdio_fwd(int fd)
        !          1525: {
        !          1526:        Buffer m;
        !          1527:        char *e;
        !          1528:        u_int type, rid, sid;
        !          1529:        int devnull;
        !          1530:
        !          1531:        debug3("%s: entering", __func__);
        !          1532:
        !          1533:        if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
        !          1534:                error("%s: master alive request failed", __func__);
        !          1535:                return -1;
        !          1536:        }
        !          1537:
        !          1538:        signal(SIGPIPE, SIG_IGN);
        !          1539:
        !          1540:        if (stdin_null_flag) {
        !          1541:                if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
        !          1542:                        fatal("open(/dev/null): %s", strerror(errno));
        !          1543:                if (dup2(devnull, STDIN_FILENO) == -1)
        !          1544:                        fatal("dup2: %s", strerror(errno));
        !          1545:                if (devnull > STDERR_FILENO)
        !          1546:                        close(devnull);
        !          1547:        }
        !          1548:
        !          1549:        buffer_init(&m);
        !          1550:        buffer_put_int(&m, MUX_C_NEW_STDIO_FWD);
        !          1551:        buffer_put_int(&m, muxclient_request_id);
        !          1552:        buffer_put_cstring(&m, ""); /* reserved */
        !          1553:        buffer_put_cstring(&m, stdio_forward_host);
        !          1554:        buffer_put_int(&m, stdio_forward_port);
        !          1555:
        !          1556:        if (mux_client_write_packet(fd, &m) != 0)
        !          1557:                fatal("%s: write packet: %s", __func__, strerror(errno));
        !          1558:
        !          1559:        /* Send the stdio file descriptors */
        !          1560:        if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
        !          1561:            mm_send_fd(fd, STDOUT_FILENO) == -1)
        !          1562:                fatal("%s: send fds failed", __func__);
        !          1563:
        !          1564:        debug3("%s: stdio forward request sent", __func__);
        !          1565:
        !          1566:        /* Read their reply */
        !          1567:        buffer_clear(&m);
        !          1568:
        !          1569:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1570:                error("%s: read from master failed: %s",
        !          1571:                    __func__, strerror(errno));
        !          1572:                buffer_free(&m);
        !          1573:                return -1;
        !          1574:        }
        !          1575:
        !          1576:        type = buffer_get_int(&m);
        !          1577:        if ((rid = buffer_get_int(&m)) != muxclient_request_id)
        !          1578:                fatal("%s: out of sequence reply: my id %u theirs %u",
        !          1579:                    __func__, muxclient_request_id, rid);
        !          1580:        switch (type) {
        !          1581:        case MUX_S_SESSION_OPENED:
        !          1582:                sid = buffer_get_int(&m);
        !          1583:                debug("%s: master session id: %u", __func__, sid);
        !          1584:                break;
        !          1585:        case MUX_S_PERMISSION_DENIED:
        !          1586:                e = buffer_get_string(&m, NULL);
        !          1587:                buffer_free(&m);
        !          1588:                fatal("Master refused forwarding request: %s", e);
        !          1589:        case MUX_S_FAILURE:
        !          1590:                e = buffer_get_string(&m, NULL);
        !          1591:                buffer_free(&m);
        !          1592:                fatal("%s: stdio forwarding request failed: %s", __func__, e);
        !          1593:        default:
        !          1594:                buffer_free(&m);
        !          1595:                error("%s: unexpected response from master 0x%08x",
        !          1596:                    __func__, type);
        !          1597:                return -1;
        !          1598:        }
        !          1599:        muxclient_request_id++;
        !          1600:
        !          1601:        signal(SIGHUP, control_client_sighandler);
        !          1602:        signal(SIGINT, control_client_sighandler);
        !          1603:        signal(SIGTERM, control_client_sighandler);
        !          1604:        signal(SIGWINCH, control_client_sigrelay);
        !          1605:
        !          1606:        /*
        !          1607:         * Stick around until the controlee closes the client_fd.
        !          1608:         */
        !          1609:        buffer_clear(&m);
        !          1610:        if (mux_client_read_packet(fd, &m) != 0) {
        !          1611:                if (errno == EPIPE ||
        !          1612:                    (errno == EINTR && muxclient_terminate != 0))
        !          1613:                        return 0;
        !          1614:                fatal("%s: mux_client_read_packet: %s",
        !          1615:                    __func__, strerror(errno));
        !          1616:        }
        !          1617:        fatal("%s: master returned unexpected message %u", __func__, type);
        !          1618: }
        !          1619:
        !          1620: /* Multiplex client main loop. */
        !          1621: void
        !          1622: muxclient(const char *path)
        !          1623: {
        !          1624:        struct sockaddr_un addr;
        !          1625:        int sock;
        !          1626:        u_int pid;
        !          1627:
        !          1628:        if (muxclient_command == 0) {
        !          1629:                if (stdio_forward_host != NULL)
        !          1630:                        muxclient_command = SSHMUX_COMMAND_STDIO_FWD;
        !          1631:                else
        !          1632:                        muxclient_command = SSHMUX_COMMAND_OPEN;
        !          1633:        }
        !          1634:
        !          1635:        switch (options.control_master) {
        !          1636:        case SSHCTL_MASTER_AUTO:
        !          1637:        case SSHCTL_MASTER_AUTO_ASK:
        !          1638:                debug("auto-mux: Trying existing master");
        !          1639:                /* FALLTHROUGH */
        !          1640:        case SSHCTL_MASTER_NO:
        !          1641:                break;
        !          1642:        default:
        !          1643:                return;
        !          1644:        }
        !          1645:
        !          1646:        memset(&addr, '\0', sizeof(addr));
        !          1647:        addr.sun_family = AF_UNIX;
        !          1648:        addr.sun_len = offsetof(struct sockaddr_un, sun_path) +
        !          1649:            strlen(path) + 1;
        !          1650:
        !          1651:        if (strlcpy(addr.sun_path, path,
        !          1652:            sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
        !          1653:                fatal("ControlPath too long");
        !          1654:
        !          1655:        if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
        !          1656:                fatal("%s socket(): %s", __func__, strerror(errno));
        !          1657:
        !          1658:        if (connect(sock, (struct sockaddr *)&addr, addr.sun_len) == -1) {
        !          1659:                switch (muxclient_command) {
        !          1660:                case SSHMUX_COMMAND_OPEN:
        !          1661:                case SSHMUX_COMMAND_STDIO_FWD:
        !          1662:                        break;
        !          1663:                default:
        !          1664:                        fatal("Control socket connect(%.100s): %s", path,
        !          1665:                            strerror(errno));
        !          1666:                }
        !          1667:                if (errno == ENOENT)
        !          1668:                        debug("Control socket \"%.100s\" does not exist", path);
        !          1669:                else {
        !          1670:                        error("Control socket connect(%.100s): %s", path,
        !          1671:                            strerror(errno));
        !          1672:                }
        !          1673:                close(sock);
        !          1674:                return;
        !          1675:        }
        !          1676:        set_nonblock(sock);
        !          1677:
        !          1678:        if (mux_client_hello_exchange(sock) != 0) {
        !          1679:                error("%s: master hello exchange failed", __func__);
        !          1680:                close(sock);
        !          1681:                return;
        !          1682:        }
        !          1683:
        !          1684:        switch (muxclient_command) {
        !          1685:        case SSHMUX_COMMAND_ALIVE_CHECK:
        !          1686:                if ((pid = mux_client_request_alive(sock)) == 0)
        !          1687:                        fatal("%s: master alive check failed", __func__);
        !          1688:                fprintf(stderr, "Master running (pid=%d)\r\n", pid);
        !          1689:                exit(0);
        !          1690:        case SSHMUX_COMMAND_TERMINATE:
        !          1691:                mux_client_request_terminate(sock);
        !          1692:                fprintf(stderr, "Exit request sent.\r\n");
        !          1693:                exit(0);
        !          1694:        case SSHMUX_COMMAND_OPEN:
        !          1695:                if (mux_client_request_forwards(sock) != 0) {
        !          1696:                        error("%s: master forward request failed", __func__);
        !          1697:                        return;
        !          1698:                }
        !          1699:                mux_client_request_session(sock);
        !          1700:                return;
        !          1701:        case SSHMUX_COMMAND_STDIO_FWD:
        !          1702:                mux_client_request_stdio_fwd(sock);
        !          1703:                exit(0);
        !          1704:        default:
        !          1705:                fatal("unrecognised muxclient_command %d", muxclient_command);
        !          1706:        }
1.1       djm      1707: }