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: }