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