1323136Sdes/* $OpenBSD: mux.c,v 1.64 2017/01/21 11:32:04 guenther Exp $ */
2180750Sdes/*
3180750Sdes * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4180750Sdes *
5180750Sdes * Permission to use, copy, modify, and distribute this software for any
6180750Sdes * purpose with or without fee is hereby granted, provided that the above
7180750Sdes * copyright notice and this permission notice appear in all copies.
8180750Sdes *
9180750Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10180750Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11180750Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12180750Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13180750Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14180750Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15180750Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16180750Sdes */
17180750Sdes
18180750Sdes/* ssh session multiplexing support */
19180750Sdes
20180750Sdes/*
21180750Sdes * TODO:
22204917Sdes *   - Better signalling from master to slave, especially passing of
23180750Sdes *      error messages
24204917Sdes *   - Better fall-back from mux slave error to new connection.
25204917Sdes *   - ExitOnForwardingFailure
26204917Sdes *   - Maybe extension mechanisms for multi-X11/multi-agent forwarding
27204917Sdes *   - Support ~^Z in mux slaves.
28204917Sdes *   - Inspect or control sessions in master.
29204917Sdes *   - If we ever support the "signal" channel request, send signals on
30204917Sdes *     sessions in master.
31180750Sdes */
32180750Sdes
33204917Sdes#include "includes.h"
34263691Sdes__RCSID("$FreeBSD: stable/11/crypto/openssh/mux.c 323136 2017-09-02 23:39:51Z des $");
35204917Sdes
36180750Sdes#include <sys/types.h>
37180750Sdes#include <sys/stat.h>
38180750Sdes#include <sys/socket.h>
39180750Sdes#include <sys/un.h>
40180750Sdes
41180750Sdes#include <errno.h>
42180750Sdes#include <fcntl.h>
43180750Sdes#include <signal.h>
44180750Sdes#include <stdarg.h>
45180750Sdes#include <stddef.h>
46180750Sdes#include <stdlib.h>
47180750Sdes#include <stdio.h>
48180750Sdes#include <string.h>
49180750Sdes#include <unistd.h>
50180750Sdes#ifdef HAVE_PATHS_H
51180750Sdes#include <paths.h>
52180750Sdes#endif
53180750Sdes
54204917Sdes#ifdef HAVE_POLL_H
55204917Sdes#include <poll.h>
56204917Sdes#else
57204917Sdes# ifdef HAVE_SYS_POLL_H
58204917Sdes#  include <sys/poll.h>
59204917Sdes# endif
60204917Sdes#endif
61204917Sdes
62180750Sdes#ifdef HAVE_UTIL_H
63180750Sdes# include <util.h>
64180750Sdes#endif
65180750Sdes
66180750Sdes#include "openbsd-compat/sys-queue.h"
67180750Sdes#include "xmalloc.h"
68180750Sdes#include "log.h"
69180750Sdes#include "ssh.h"
70215116Sdes#include "ssh2.h"
71180750Sdes#include "pathnames.h"
72180750Sdes#include "misc.h"
73180750Sdes#include "match.h"
74180750Sdes#include "buffer.h"
75180750Sdes#include "channels.h"
76180750Sdes#include "msg.h"
77180750Sdes#include "packet.h"
78180750Sdes#include "monitor_fdpass.h"
79180750Sdes#include "sshpty.h"
80180750Sdes#include "key.h"
81180750Sdes#include "readconf.h"
82180750Sdes#include "clientloop.h"
83323134Sdes#include "ssherr.h"
84180750Sdes
85180750Sdes/* from ssh.c */
86180750Sdesextern int tty_flag;
87180750Sdesextern Options options;
88180750Sdesextern int stdin_null_flag;
89180750Sdesextern char *host;
90204917Sdesextern int subsystem_flag;
91180750Sdesextern Buffer command;
92204917Sdesextern volatile sig_atomic_t quit_pending;
93180750Sdes
94180750Sdes/* Context for session open confirmation callback */
95180750Sdesstruct mux_session_confirm_ctx {
96204917Sdes	u_int want_tty;
97204917Sdes	u_int want_subsys;
98204917Sdes	u_int want_x_fwd;
99204917Sdes	u_int want_agent_fwd;
100180750Sdes	Buffer cmd;
101180750Sdes	char *term;
102180750Sdes	struct termios tio;
103180750Sdes	char **env;
104215116Sdes	u_int rid;
105180750Sdes};
106180750Sdes
107294328Sdes/* Context for stdio fwd open confirmation callback */
108294328Sdesstruct mux_stdio_confirm_ctx {
109294328Sdes	u_int rid;
110294328Sdes};
111294328Sdes
112215116Sdes/* Context for global channel callback */
113215116Sdesstruct mux_channel_confirm_ctx {
114215116Sdes	u_int cid;	/* channel id */
115215116Sdes	u_int rid;	/* request id */
116215116Sdes	int fid;	/* forward id */
117215116Sdes};
118215116Sdes
119180750Sdes/* fd to control socket */
120180750Sdesint muxserver_sock = -1;
121180750Sdes
122204917Sdes/* client request id */
123204917Sdesu_int muxclient_request_id = 0;
124204917Sdes
125180750Sdes/* Multiplexing control command */
126180750Sdesu_int muxclient_command = 0;
127180750Sdes
128180750Sdes/* Set when signalled. */
129180750Sdesstatic volatile sig_atomic_t muxclient_terminate = 0;
130180750Sdes
131180750Sdes/* PID of multiplex server */
132180750Sdesstatic u_int muxserver_pid = 0;
133180750Sdes
134204917Sdesstatic Channel *mux_listener_channel = NULL;
135180750Sdes
136204917Sdesstruct mux_master_state {
137204917Sdes	int hello_rcvd;
138204917Sdes};
139180750Sdes
140204917Sdes/* mux protocol messages */
141204917Sdes#define MUX_MSG_HELLO		0x00000001
142204917Sdes#define MUX_C_NEW_SESSION	0x10000002
143204917Sdes#define MUX_C_ALIVE_CHECK	0x10000004
144204917Sdes#define MUX_C_TERMINATE		0x10000005
145204917Sdes#define MUX_C_OPEN_FWD		0x10000006
146204917Sdes#define MUX_C_CLOSE_FWD		0x10000007
147204917Sdes#define MUX_C_NEW_STDIO_FWD	0x10000008
148226046Sdes#define MUX_C_STOP_LISTENING	0x10000009
149323134Sdes#define MUX_C_PROXY		0x1000000f
150204917Sdes#define MUX_S_OK		0x80000001
151204917Sdes#define MUX_S_PERMISSION_DENIED	0x80000002
152204917Sdes#define MUX_S_FAILURE		0x80000003
153204917Sdes#define MUX_S_EXIT_MESSAGE	0x80000004
154204917Sdes#define MUX_S_ALIVE		0x80000005
155204917Sdes#define MUX_S_SESSION_OPENED	0x80000006
156215116Sdes#define MUX_S_REMOTE_PORT	0x80000007
157226046Sdes#define MUX_S_TTY_ALLOC_FAIL	0x80000008
158323134Sdes#define MUX_S_PROXY		0x8000000f
159204917Sdes
160204917Sdes/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
161204917Sdes#define MUX_FWD_LOCAL   1
162204917Sdes#define MUX_FWD_REMOTE  2
163204917Sdes#define MUX_FWD_DYNAMIC 3
164204917Sdes
165215116Sdesstatic void mux_session_confirm(int, int, void *);
166294328Sdesstatic void mux_stdio_confirm(int, int, void *);
167204917Sdes
168204917Sdesstatic int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
169204917Sdesstatic int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
170204917Sdesstatic int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *);
171204917Sdesstatic int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
172204917Sdesstatic int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
173204917Sdesstatic int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
174204917Sdesstatic int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
175226046Sdesstatic int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
176323134Sdesstatic int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *);
177204917Sdes
178204917Sdesstatic const struct {
179204917Sdes	u_int type;
180204917Sdes	int (*handler)(u_int, Channel *, Buffer *, Buffer *);
181204917Sdes} mux_master_handlers[] = {
182204917Sdes	{ MUX_MSG_HELLO, process_mux_master_hello },
183204917Sdes	{ MUX_C_NEW_SESSION, process_mux_new_session },
184204917Sdes	{ MUX_C_ALIVE_CHECK, process_mux_alive_check },
185204917Sdes	{ MUX_C_TERMINATE, process_mux_terminate },
186204917Sdes	{ MUX_C_OPEN_FWD, process_mux_open_fwd },
187204917Sdes	{ MUX_C_CLOSE_FWD, process_mux_close_fwd },
188204917Sdes	{ MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
189226046Sdes	{ MUX_C_STOP_LISTENING, process_mux_stop_listening },
190323134Sdes	{ MUX_C_PROXY, process_mux_proxy },
191204917Sdes	{ 0, NULL }
192204917Sdes};
193204917Sdes
194204917Sdes/* Cleanup callback fired on closure of mux slave _session_ channel */
195204917Sdes/* ARGSUSED */
196255767Sdesstatic void
197204917Sdesmux_master_session_cleanup_cb(int cid, void *unused)
198204917Sdes{
199204917Sdes	Channel *cc, *c = channel_by_id(cid);
200204917Sdes
201204917Sdes	debug3("%s: entering for channel %d", __func__, cid);
202204917Sdes	if (c == NULL)
203204917Sdes		fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
204204917Sdes	if (c->ctl_chan != -1) {
205204917Sdes		if ((cc = channel_by_id(c->ctl_chan)) == NULL)
206204917Sdes			fatal("%s: channel %d missing control channel %d",
207204917Sdes			    __func__, c->self, c->ctl_chan);
208204917Sdes		c->ctl_chan = -1;
209204917Sdes		cc->remote_id = -1;
210204917Sdes		chan_rcvd_oclose(cc);
211204917Sdes	}
212204917Sdes	channel_cancel_cleanup(c->self);
213204917Sdes}
214204917Sdes
215204917Sdes/* Cleanup callback fired on closure of mux slave _control_ channel */
216204917Sdes/* ARGSUSED */
217204917Sdesstatic void
218204917Sdesmux_master_control_cleanup_cb(int cid, void *unused)
219204917Sdes{
220204917Sdes	Channel *sc, *c = channel_by_id(cid);
221204917Sdes
222204917Sdes	debug3("%s: entering for channel %d", __func__, cid);
223204917Sdes	if (c == NULL)
224204917Sdes		fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
225204917Sdes	if (c->remote_id != -1) {
226204917Sdes		if ((sc = channel_by_id(c->remote_id)) == NULL)
227215116Sdes			fatal("%s: channel %d missing session channel %d",
228204917Sdes			    __func__, c->self, c->remote_id);
229204917Sdes		c->remote_id = -1;
230204917Sdes		sc->ctl_chan = -1;
231255767Sdes		if (sc->type != SSH_CHANNEL_OPEN &&
232255767Sdes		    sc->type != SSH_CHANNEL_OPENING) {
233204917Sdes			debug2("%s: channel %d: not open", __func__, sc->self);
234204917Sdes			chan_mark_dead(sc);
235204917Sdes		} else {
236204917Sdes			if (sc->istate == CHAN_INPUT_OPEN)
237204917Sdes				chan_read_failed(sc);
238204917Sdes			if (sc->ostate == CHAN_OUTPUT_OPEN)
239204917Sdes				chan_write_failed(sc);
240204917Sdes		}
241204917Sdes	}
242204917Sdes	channel_cancel_cleanup(c->self);
243204917Sdes}
244204917Sdes
245204917Sdes/* Check mux client environment variables before passing them to mux master. */
246204917Sdesstatic int
247204917Sdesenv_permitted(char *env)
248204917Sdes{
249204917Sdes	int i, ret;
250204917Sdes	char name[1024], *cp;
251204917Sdes
252204917Sdes	if ((cp = strchr(env, '=')) == NULL || cp == env)
253204917Sdes		return 0;
254204917Sdes	ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
255204917Sdes	if (ret <= 0 || (size_t)ret >= sizeof(name)) {
256204917Sdes		error("env_permitted: name '%.100s...' too long", env);
257204917Sdes		return 0;
258204917Sdes	}
259204917Sdes
260204917Sdes	for (i = 0; i < options.num_send_env; i++)
261204917Sdes		if (match_pattern(name, options.send_env[i]))
262204917Sdes			return 1;
263204917Sdes
264204917Sdes	return 0;
265204917Sdes}
266204917Sdes
267204917Sdes/* Mux master protocol message handlers */
268204917Sdes
269204917Sdesstatic int
270204917Sdesprocess_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
271204917Sdes{
272204917Sdes	u_int ver;
273204917Sdes	struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
274204917Sdes
275204917Sdes	if (state == NULL)
276204917Sdes		fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
277204917Sdes	if (state->hello_rcvd) {
278204917Sdes		error("%s: HELLO received twice", __func__);
279204917Sdes		return -1;
280204917Sdes	}
281204917Sdes	if (buffer_get_int_ret(&ver, m) != 0) {
282204917Sdes malf:
283204917Sdes		error("%s: malformed message", __func__);
284204917Sdes		return -1;
285204917Sdes	}
286204917Sdes	if (ver != SSHMUX_VER) {
287204917Sdes		error("Unsupported multiplexing protocol version %d "
288204917Sdes		    "(expected %d)", ver, SSHMUX_VER);
289204917Sdes		return -1;
290204917Sdes	}
291204917Sdes	debug2("%s: channel %d slave version %u", __func__, c->self, ver);
292204917Sdes
293204917Sdes	/* No extensions are presently defined */
294204917Sdes	while (buffer_len(m) > 0) {
295204917Sdes		char *name = buffer_get_string_ret(m, NULL);
296204917Sdes		char *value = buffer_get_string_ret(m, NULL);
297204917Sdes
298204917Sdes		if (name == NULL || value == NULL) {
299255767Sdes			free(name);
300255767Sdes			free(value);
301204917Sdes			goto malf;
302204917Sdes		}
303204917Sdes		debug2("Unrecognised slave extension \"%s\"", name);
304255767Sdes		free(name);
305255767Sdes		free(value);
306204917Sdes	}
307204917Sdes	state->hello_rcvd = 1;
308204917Sdes	return 0;
309204917Sdes}
310204917Sdes
311204917Sdesstatic int
312204917Sdesprocess_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
313204917Sdes{
314204917Sdes	Channel *nc;
315204917Sdes	struct mux_session_confirm_ctx *cctx;
316204917Sdes	char *reserved, *cmd, *cp;
317204917Sdes	u_int i, j, len, env_len, escape_char, window, packetmax;
318204917Sdes	int new_fd[3];
319204917Sdes
320204917Sdes	/* Reply for SSHMUX_COMMAND_OPEN */
321204917Sdes	cctx = xcalloc(1, sizeof(*cctx));
322204917Sdes	cctx->term = NULL;
323215116Sdes	cctx->rid = rid;
324204917Sdes	cmd = reserved = NULL;
325240075Sdes	cctx->env = NULL;
326240075Sdes	env_len = 0;
327204917Sdes	if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
328204917Sdes	    buffer_get_int_ret(&cctx->want_tty, m) != 0 ||
329204917Sdes	    buffer_get_int_ret(&cctx->want_x_fwd, m) != 0 ||
330204917Sdes	    buffer_get_int_ret(&cctx->want_agent_fwd, m) != 0 ||
331204917Sdes	    buffer_get_int_ret(&cctx->want_subsys, m) != 0 ||
332204917Sdes	    buffer_get_int_ret(&escape_char, m) != 0 ||
333204917Sdes	    (cctx->term = buffer_get_string_ret(m, &len)) == NULL ||
334204917Sdes	    (cmd = buffer_get_string_ret(m, &len)) == NULL) {
335204917Sdes malf:
336255767Sdes		free(cmd);
337255767Sdes		free(reserved);
338240075Sdes		for (j = 0; j < env_len; j++)
339255767Sdes			free(cctx->env[j]);
340255767Sdes		free(cctx->env);
341255767Sdes		free(cctx->term);
342255767Sdes		free(cctx);
343204917Sdes		error("%s: malformed message", __func__);
344204917Sdes		return -1;
345204917Sdes	}
346255767Sdes	free(reserved);
347204917Sdes	reserved = NULL;
348204917Sdes
349204917Sdes	while (buffer_len(m) > 0) {
350204917Sdes#define MUX_MAX_ENV_VARS	4096
351240075Sdes		if ((cp = buffer_get_string_ret(m, &len)) == NULL)
352204917Sdes			goto malf;
353204917Sdes		if (!env_permitted(cp)) {
354255767Sdes			free(cp);
355204917Sdes			continue;
356204917Sdes		}
357294336Sdes		cctx->env = xreallocarray(cctx->env, env_len + 2,
358204917Sdes		    sizeof(*cctx->env));
359204917Sdes		cctx->env[env_len++] = cp;
360204917Sdes		cctx->env[env_len] = NULL;
361204917Sdes		if (env_len > MUX_MAX_ENV_VARS) {
362204917Sdes			error(">%d environment variables received, ignoring "
363204917Sdes			    "additional", MUX_MAX_ENV_VARS);
364204917Sdes			break;
365204917Sdes		}
366204917Sdes	}
367204917Sdes
368204917Sdes	debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
369204917Sdes	    "term \"%s\", cmd \"%s\", env %u", __func__, c->self,
370204917Sdes	    cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
371204917Sdes	    cctx->want_subsys, cctx->term, cmd, env_len);
372204917Sdes
373204917Sdes	buffer_init(&cctx->cmd);
374204917Sdes	buffer_append(&cctx->cmd, cmd, strlen(cmd));
375255767Sdes	free(cmd);
376204917Sdes	cmd = NULL;
377204917Sdes
378204917Sdes	/* Gather fds from client */
379204917Sdes	for(i = 0; i < 3; i++) {
380204917Sdes		if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
381204917Sdes			error("%s: failed to receive fd %d from slave",
382204917Sdes			    __func__, i);
383204917Sdes			for (j = 0; j < i; j++)
384204917Sdes				close(new_fd[j]);
385204917Sdes			for (j = 0; j < env_len; j++)
386255767Sdes				free(cctx->env[j]);
387255767Sdes			free(cctx->env);
388255767Sdes			free(cctx->term);
389204917Sdes			buffer_free(&cctx->cmd);
390255767Sdes			free(cctx);
391204917Sdes
392204917Sdes			/* prepare reply */
393204917Sdes			buffer_put_int(r, MUX_S_FAILURE);
394204917Sdes			buffer_put_int(r, rid);
395204917Sdes			buffer_put_cstring(r,
396204917Sdes			    "did not receive file descriptors");
397204917Sdes			return -1;
398204917Sdes		}
399204917Sdes	}
400204917Sdes
401204917Sdes	debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
402204917Sdes	    new_fd[0], new_fd[1], new_fd[2]);
403204917Sdes
404204917Sdes	/* XXX support multiple child sessions in future */
405204917Sdes	if (c->remote_id != -1) {
406204917Sdes		debug2("%s: session already open", __func__);
407204917Sdes		/* prepare reply */
408204917Sdes		buffer_put_int(r, MUX_S_FAILURE);
409204917Sdes		buffer_put_int(r, rid);
410204917Sdes		buffer_put_cstring(r, "Multiple sessions not supported");
411204917Sdes cleanup:
412204917Sdes		close(new_fd[0]);
413204917Sdes		close(new_fd[1]);
414204917Sdes		close(new_fd[2]);
415255767Sdes		free(cctx->term);
416204917Sdes		if (env_len != 0) {
417204917Sdes			for (i = 0; i < env_len; i++)
418255767Sdes				free(cctx->env[i]);
419255767Sdes			free(cctx->env);
420204917Sdes		}
421204917Sdes		buffer_free(&cctx->cmd);
422255767Sdes		free(cctx);
423204917Sdes		return 0;
424204917Sdes	}
425204917Sdes
426204917Sdes	if (options.control_master == SSHCTL_MASTER_ASK ||
427204917Sdes	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
428204917Sdes		if (!ask_permission("Allow shared connection to %s? ", host)) {
429204917Sdes			debug2("%s: session refused by user", __func__);
430204917Sdes			/* prepare reply */
431204917Sdes			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
432204917Sdes			buffer_put_int(r, rid);
433204917Sdes			buffer_put_cstring(r, "Permission denied");
434204917Sdes			goto cleanup;
435204917Sdes		}
436204917Sdes	}
437204917Sdes
438204917Sdes	/* Try to pick up ttymodes from client before it goes raw */
439204917Sdes	if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
440204917Sdes		error("%s: tcgetattr: %s", __func__, strerror(errno));
441204917Sdes
442204917Sdes	/* enable nonblocking unless tty */
443204917Sdes	if (!isatty(new_fd[0]))
444204917Sdes		set_nonblock(new_fd[0]);
445204917Sdes	if (!isatty(new_fd[1]))
446204917Sdes		set_nonblock(new_fd[1]);
447204917Sdes	if (!isatty(new_fd[2]))
448204917Sdes		set_nonblock(new_fd[2]);
449204917Sdes
450204917Sdes	window = CHAN_SES_WINDOW_DEFAULT;
451204917Sdes	packetmax = CHAN_SES_PACKET_DEFAULT;
452204917Sdes	if (cctx->want_tty) {
453204917Sdes		window >>= 1;
454204917Sdes		packetmax >>= 1;
455204917Sdes	}
456204917Sdes
457204917Sdes	nc = channel_new("session", SSH_CHANNEL_OPENING,
458204917Sdes	    new_fd[0], new_fd[1], new_fd[2], window, packetmax,
459204917Sdes	    CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
460204917Sdes
461204917Sdes	nc->ctl_chan = c->self;		/* link session -> control channel */
462204917Sdes	c->remote_id = nc->self; 	/* link control -> session channel */
463204917Sdes
464204917Sdes	if (cctx->want_tty && escape_char != 0xffffffff) {
465204917Sdes		channel_register_filter(nc->self,
466204917Sdes		    client_simple_escape_filter, NULL,
467204917Sdes		    client_filter_cleanup,
468204917Sdes		    client_new_escape_filter_ctx((int)escape_char));
469204917Sdes	}
470204917Sdes
471204917Sdes	debug2("%s: channel_new: %d linked to control channel %d",
472204917Sdes	    __func__, nc->self, nc->ctl_chan);
473204917Sdes
474204917Sdes	channel_send_open(nc->self);
475204917Sdes	channel_register_open_confirm(nc->self, mux_session_confirm, cctx);
476215116Sdes	c->mux_pause = 1; /* stop handling messages until open_confirm done */
477215116Sdes	channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
478204917Sdes
479215116Sdes	/* reply is deferred, sent by mux_session_confirm */
480204917Sdes	return 0;
481204917Sdes}
482204917Sdes
483204917Sdesstatic int
484204917Sdesprocess_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
485204917Sdes{
486204917Sdes	debug2("%s: channel %d: alive check", __func__, c->self);
487204917Sdes
488204917Sdes	/* prepare reply */
489204917Sdes	buffer_put_int(r, MUX_S_ALIVE);
490204917Sdes	buffer_put_int(r, rid);
491204917Sdes	buffer_put_int(r, (u_int)getpid());
492204917Sdes
493204917Sdes	return 0;
494204917Sdes}
495204917Sdes
496204917Sdesstatic int
497204917Sdesprocess_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
498204917Sdes{
499204917Sdes	debug2("%s: channel %d: terminate request", __func__, c->self);
500204917Sdes
501204917Sdes	if (options.control_master == SSHCTL_MASTER_ASK ||
502204917Sdes	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
503204917Sdes		if (!ask_permission("Terminate shared connection to %s? ",
504204917Sdes		    host)) {
505204917Sdes			debug2("%s: termination refused by user", __func__);
506204917Sdes			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
507204917Sdes			buffer_put_int(r, rid);
508204917Sdes			buffer_put_cstring(r, "Permission denied");
509204917Sdes			return 0;
510204917Sdes		}
511204917Sdes	}
512204917Sdes
513204917Sdes	quit_pending = 1;
514204917Sdes	buffer_put_int(r, MUX_S_OK);
515204917Sdes	buffer_put_int(r, rid);
516204917Sdes	/* XXX exit happens too soon - message never makes it to client */
517204917Sdes	return 0;
518204917Sdes}
519204917Sdes
520204917Sdesstatic char *
521294328Sdesformat_forward(u_int ftype, struct Forward *fwd)
522204917Sdes{
523204917Sdes	char *ret;
524204917Sdes
525204917Sdes	switch (ftype) {
526204917Sdes	case MUX_FWD_LOCAL:
527204917Sdes		xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
528294328Sdes		    (fwd->listen_path != NULL) ? fwd->listen_path :
529204917Sdes		    (fwd->listen_host == NULL) ?
530294328Sdes		    (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
531204917Sdes		    fwd->listen_host, fwd->listen_port,
532294328Sdes		    (fwd->connect_path != NULL) ? fwd->connect_path :
533204917Sdes		    fwd->connect_host, fwd->connect_port);
534204917Sdes		break;
535204917Sdes	case MUX_FWD_DYNAMIC:
536204917Sdes		xasprintf(&ret, "dynamic forward %.200s:%d -> *",
537204917Sdes		    (fwd->listen_host == NULL) ?
538294328Sdes		    (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
539204917Sdes		     fwd->listen_host, fwd->listen_port);
540204917Sdes		break;
541204917Sdes	case MUX_FWD_REMOTE:
542204917Sdes		xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
543294328Sdes		    (fwd->listen_path != NULL) ? fwd->listen_path :
544204917Sdes		    (fwd->listen_host == NULL) ?
545204917Sdes		    "LOCALHOST" : fwd->listen_host,
546204917Sdes		    fwd->listen_port,
547294328Sdes		    (fwd->connect_path != NULL) ? fwd->connect_path :
548204917Sdes		    fwd->connect_host, fwd->connect_port);
549204917Sdes		break;
550204917Sdes	default:
551204917Sdes		fatal("%s: unknown forward type %u", __func__, ftype);
552204917Sdes	}
553204917Sdes	return ret;
554204917Sdes}
555204917Sdes
556204917Sdesstatic int
557204917Sdescompare_host(const char *a, const char *b)
558204917Sdes{
559204917Sdes	if (a == NULL && b == NULL)
560204917Sdes		return 1;
561204917Sdes	if (a == NULL || b == NULL)
562204917Sdes		return 0;
563204917Sdes	return strcmp(a, b) == 0;
564204917Sdes}
565204917Sdes
566204917Sdesstatic int
567294328Sdescompare_forward(struct Forward *a, struct Forward *b)
568204917Sdes{
569204917Sdes	if (!compare_host(a->listen_host, b->listen_host))
570204917Sdes		return 0;
571294328Sdes	if (!compare_host(a->listen_path, b->listen_path))
572294328Sdes		return 0;
573204917Sdes	if (a->listen_port != b->listen_port)
574204917Sdes		return 0;
575204917Sdes	if (!compare_host(a->connect_host, b->connect_host))
576204917Sdes		return 0;
577294328Sdes	if (!compare_host(a->connect_path, b->connect_path))
578294328Sdes		return 0;
579204917Sdes	if (a->connect_port != b->connect_port)
580204917Sdes		return 0;
581204917Sdes
582204917Sdes	return 1;
583204917Sdes}
584204917Sdes
585215116Sdesstatic void
586215116Sdesmux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
587215116Sdes{
588215116Sdes	struct mux_channel_confirm_ctx *fctx = ctxt;
589215116Sdes	char *failmsg = NULL;
590294328Sdes	struct Forward *rfwd;
591215116Sdes	Channel *c;
592215116Sdes	Buffer out;
593215116Sdes
594215116Sdes	if ((c = channel_by_id(fctx->cid)) == NULL) {
595215116Sdes		/* no channel for reply */
596215116Sdes		error("%s: unknown channel", __func__);
597215116Sdes		return;
598215116Sdes	}
599215116Sdes	buffer_init(&out);
600294336Sdes	if (fctx->fid >= options.num_remote_forwards ||
601294336Sdes	    (options.remote_forwards[fctx->fid].connect_path == NULL &&
602294336Sdes	    options.remote_forwards[fctx->fid].connect_host == NULL)) {
603215116Sdes		xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid);
604215116Sdes		goto fail;
605215116Sdes	}
606215116Sdes	rfwd = &options.remote_forwards[fctx->fid];
607215116Sdes	debug("%s: %s for: listen %d, connect %s:%d", __func__,
608215116Sdes	    type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
609294328Sdes	    rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
610294328Sdes	    rfwd->connect_host, rfwd->connect_port);
611215116Sdes	if (type == SSH2_MSG_REQUEST_SUCCESS) {
612215116Sdes		if (rfwd->listen_port == 0) {
613215116Sdes			rfwd->allocated_port = packet_get_int();
614294336Sdes			debug("Allocated port %u for mux remote forward"
615215116Sdes			    " to %s:%d", rfwd->allocated_port,
616215116Sdes			    rfwd->connect_host, rfwd->connect_port);
617215116Sdes			buffer_put_int(&out, MUX_S_REMOTE_PORT);
618215116Sdes			buffer_put_int(&out, fctx->rid);
619215116Sdes			buffer_put_int(&out, rfwd->allocated_port);
620240075Sdes			channel_update_permitted_opens(rfwd->handle,
621240075Sdes			   rfwd->allocated_port);
622215116Sdes		} else {
623215116Sdes			buffer_put_int(&out, MUX_S_OK);
624215116Sdes			buffer_put_int(&out, fctx->rid);
625215116Sdes		}
626215116Sdes		goto out;
627215116Sdes	} else {
628240075Sdes		if (rfwd->listen_port == 0)
629240075Sdes			channel_update_permitted_opens(rfwd->handle, -1);
630294328Sdes		if (rfwd->listen_path != NULL)
631294328Sdes			xasprintf(&failmsg, "remote port forwarding failed for "
632294328Sdes			    "listen path %s", rfwd->listen_path);
633294328Sdes		else
634294328Sdes			xasprintf(&failmsg, "remote port forwarding failed for "
635294328Sdes			    "listen port %d", rfwd->listen_port);
636294336Sdes
637294336Sdes                debug2("%s: clearing registered forwarding for listen %d, "
638294336Sdes		    "connect %s:%d", __func__, rfwd->listen_port,
639294336Sdes		    rfwd->connect_path ? rfwd->connect_path :
640294336Sdes		    rfwd->connect_host, rfwd->connect_port);
641294336Sdes
642294336Sdes		free(rfwd->listen_host);
643294336Sdes		free(rfwd->listen_path);
644294336Sdes		free(rfwd->connect_host);
645294336Sdes		free(rfwd->connect_path);
646294336Sdes		memset(rfwd, 0, sizeof(*rfwd));
647215116Sdes	}
648215116Sdes fail:
649215116Sdes	error("%s: %s", __func__, failmsg);
650215116Sdes	buffer_put_int(&out, MUX_S_FAILURE);
651215116Sdes	buffer_put_int(&out, fctx->rid);
652215116Sdes	buffer_put_cstring(&out, failmsg);
653255767Sdes	free(failmsg);
654215116Sdes out:
655215116Sdes	buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out));
656215116Sdes	buffer_free(&out);
657215116Sdes	if (c->mux_pause <= 0)
658215116Sdes		fatal("%s: mux_pause %d", __func__, c->mux_pause);
659215116Sdes	c->mux_pause = 0; /* start processing messages again */
660215116Sdes}
661215116Sdes
662204917Sdesstatic int
663204917Sdesprocess_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
664204917Sdes{
665294328Sdes	struct Forward fwd;
666204917Sdes	char *fwd_desc = NULL;
667294328Sdes	char *listen_addr, *connect_addr;
668204917Sdes	u_int ftype;
669255767Sdes	u_int lport, cport;
670204917Sdes	int i, ret = 0, freefwd = 1;
671204917Sdes
672294496Sdes	memset(&fwd, 0, sizeof(fwd));
673294496Sdes
674294328Sdes	/* XXX - lport/cport check redundant */
675204917Sdes	if (buffer_get_int_ret(&ftype, m) != 0 ||
676294328Sdes	    (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
677255767Sdes	    buffer_get_int_ret(&lport, m) != 0 ||
678294328Sdes	    (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
679255767Sdes	    buffer_get_int_ret(&cport, m) != 0 ||
680294328Sdes	    (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
681294328Sdes	    (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
682204917Sdes		error("%s: malformed message", __func__);
683204917Sdes		ret = -1;
684204917Sdes		goto out;
685204917Sdes	}
686294328Sdes	if (*listen_addr == '\0') {
687294328Sdes		free(listen_addr);
688294328Sdes		listen_addr = NULL;
689204917Sdes	}
690294328Sdes	if (*connect_addr == '\0') {
691294328Sdes		free(connect_addr);
692294328Sdes		connect_addr = NULL;
693204917Sdes	}
694204917Sdes
695294328Sdes	memset(&fwd, 0, sizeof(fwd));
696294328Sdes	fwd.listen_port = lport;
697294328Sdes	if (fwd.listen_port == PORT_STREAMLOCAL)
698294328Sdes		fwd.listen_path = listen_addr;
699294328Sdes	else
700294328Sdes		fwd.listen_host = listen_addr;
701294328Sdes	fwd.connect_port = cport;
702294328Sdes	if (fwd.connect_port == PORT_STREAMLOCAL)
703294328Sdes		fwd.connect_path = connect_addr;
704294328Sdes	else
705294328Sdes		fwd.connect_host = connect_addr;
706294328Sdes
707204917Sdes	debug2("%s: channel %d: request %s", __func__, c->self,
708204917Sdes	    (fwd_desc = format_forward(ftype, &fwd)));
709204917Sdes
710204917Sdes	if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE &&
711204917Sdes	    ftype != MUX_FWD_DYNAMIC) {
712204917Sdes		logit("%s: invalid forwarding type %u", __func__, ftype);
713204917Sdes invalid:
714294328Sdes		free(listen_addr);
715294328Sdes		free(connect_addr);
716204917Sdes		buffer_put_int(r, MUX_S_FAILURE);
717204917Sdes		buffer_put_int(r, rid);
718204917Sdes		buffer_put_cstring(r, "Invalid forwarding request");
719204917Sdes		return 0;
720204917Sdes	}
721294328Sdes	if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
722294328Sdes		logit("%s: streamlocal and dynamic forwards "
723294328Sdes		    "are mutually exclusive", __func__);
724294328Sdes		goto invalid;
725294328Sdes	}
726294328Sdes	if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
727204917Sdes		logit("%s: invalid listen port %u", __func__,
728204917Sdes		    fwd.listen_port);
729204917Sdes		goto invalid;
730204917Sdes	}
731294328Sdes	if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
732294328Sdes	    || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
733204917Sdes		logit("%s: invalid connect port %u", __func__,
734204917Sdes		    fwd.connect_port);
735204917Sdes		goto invalid;
736204917Sdes	}
737294328Sdes	if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
738204917Sdes		logit("%s: missing connect host", __func__);
739204917Sdes		goto invalid;
740204917Sdes	}
741204917Sdes
742204917Sdes	/* Skip forwards that have already been requested */
743204917Sdes	switch (ftype) {
744204917Sdes	case MUX_FWD_LOCAL:
745204917Sdes	case MUX_FWD_DYNAMIC:
746204917Sdes		for (i = 0; i < options.num_local_forwards; i++) {
747204917Sdes			if (compare_forward(&fwd,
748204917Sdes			    options.local_forwards + i)) {
749204917Sdes exists:
750204917Sdes				debug2("%s: found existing forwarding",
751204917Sdes				    __func__);
752204917Sdes				buffer_put_int(r, MUX_S_OK);
753204917Sdes				buffer_put_int(r, rid);
754204917Sdes				goto out;
755204917Sdes			}
756204917Sdes		}
757204917Sdes		break;
758204917Sdes	case MUX_FWD_REMOTE:
759204917Sdes		for (i = 0; i < options.num_remote_forwards; i++) {
760204917Sdes			if (compare_forward(&fwd,
761215116Sdes			    options.remote_forwards + i)) {
762215116Sdes				if (fwd.listen_port != 0)
763215116Sdes					goto exists;
764215116Sdes				debug2("%s: found allocated port",
765215116Sdes				    __func__);
766215116Sdes				buffer_put_int(r, MUX_S_REMOTE_PORT);
767215116Sdes				buffer_put_int(r, rid);
768215116Sdes				buffer_put_int(r,
769215116Sdes				    options.remote_forwards[i].allocated_port);
770215116Sdes				goto out;
771215116Sdes			}
772204917Sdes		}
773204917Sdes		break;
774204917Sdes	}
775204917Sdes
776204917Sdes	if (options.control_master == SSHCTL_MASTER_ASK ||
777204917Sdes	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
778204917Sdes		if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
779204917Sdes			debug2("%s: forwarding refused by user", __func__);
780204917Sdes			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
781204917Sdes			buffer_put_int(r, rid);
782204917Sdes			buffer_put_cstring(r, "Permission denied");
783204917Sdes			goto out;
784204917Sdes		}
785204917Sdes	}
786204917Sdes
787204917Sdes	if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
788294328Sdes		if (!channel_setup_local_fwd_listener(&fwd,
789294328Sdes		    &options.fwd_opts)) {
790204917Sdes fail:
791204917Sdes			logit("slave-requested %s failed", fwd_desc);
792204917Sdes			buffer_put_int(r, MUX_S_FAILURE);
793204917Sdes			buffer_put_int(r, rid);
794204917Sdes			buffer_put_cstring(r, "Port forwarding failed");
795204917Sdes			goto out;
796204917Sdes		}
797204917Sdes		add_local_forward(&options, &fwd);
798204917Sdes		freefwd = 0;
799204917Sdes	} else {
800215116Sdes		struct mux_channel_confirm_ctx *fctx;
801215116Sdes
802294328Sdes		fwd.handle = channel_request_remote_forwarding(&fwd);
803240075Sdes		if (fwd.handle < 0)
804204917Sdes			goto fail;
805204917Sdes		add_remote_forward(&options, &fwd);
806215116Sdes		fctx = xcalloc(1, sizeof(*fctx));
807215116Sdes		fctx->cid = c->self;
808215116Sdes		fctx->rid = rid;
809215116Sdes		fctx->fid = options.num_remote_forwards - 1;
810215116Sdes		client_register_global_confirm(mux_confirm_remote_forward,
811215116Sdes		    fctx);
812204917Sdes		freefwd = 0;
813215116Sdes		c->mux_pause = 1; /* wait for mux_confirm_remote_forward */
814215116Sdes		/* delayed reply in mux_confirm_remote_forward */
815215116Sdes		goto out;
816204917Sdes	}
817204917Sdes	buffer_put_int(r, MUX_S_OK);
818204917Sdes	buffer_put_int(r, rid);
819204917Sdes out:
820255767Sdes	free(fwd_desc);
821204917Sdes	if (freefwd) {
822255767Sdes		free(fwd.listen_host);
823294328Sdes		free(fwd.listen_path);
824255767Sdes		free(fwd.connect_host);
825294328Sdes		free(fwd.connect_path);
826204917Sdes	}
827204917Sdes	return ret;
828204917Sdes}
829204917Sdes
830204917Sdesstatic int
831204917Sdesprocess_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
832204917Sdes{
833294328Sdes	struct Forward fwd, *found_fwd;
834204917Sdes	char *fwd_desc = NULL;
835240075Sdes	const char *error_reason = NULL;
836294328Sdes	char *listen_addr = NULL, *connect_addr = NULL;
837204917Sdes	u_int ftype;
838294328Sdes	int i, ret = 0;
839255767Sdes	u_int lport, cport;
840204917Sdes
841294496Sdes	memset(&fwd, 0, sizeof(fwd));
842294496Sdes
843204917Sdes	if (buffer_get_int_ret(&ftype, m) != 0 ||
844294328Sdes	    (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
845255767Sdes	    buffer_get_int_ret(&lport, m) != 0 ||
846294328Sdes	    (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
847255767Sdes	    buffer_get_int_ret(&cport, m) != 0 ||
848294328Sdes	    (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
849294328Sdes	    (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
850204917Sdes		error("%s: malformed message", __func__);
851204917Sdes		ret = -1;
852204917Sdes		goto out;
853204917Sdes	}
854204917Sdes
855294328Sdes	if (*listen_addr == '\0') {
856294328Sdes		free(listen_addr);
857294328Sdes		listen_addr = NULL;
858204917Sdes	}
859294328Sdes	if (*connect_addr == '\0') {
860294328Sdes		free(connect_addr);
861294328Sdes		connect_addr = NULL;
862204917Sdes	}
863204917Sdes
864294328Sdes	memset(&fwd, 0, sizeof(fwd));
865294328Sdes	fwd.listen_port = lport;
866294328Sdes	if (fwd.listen_port == PORT_STREAMLOCAL)
867294328Sdes		fwd.listen_path = listen_addr;
868294328Sdes	else
869294328Sdes		fwd.listen_host = listen_addr;
870294328Sdes	fwd.connect_port = cport;
871294328Sdes	if (fwd.connect_port == PORT_STREAMLOCAL)
872294328Sdes		fwd.connect_path = connect_addr;
873294328Sdes	else
874294328Sdes		fwd.connect_host = connect_addr;
875294328Sdes
876240075Sdes	debug2("%s: channel %d: request cancel %s", __func__, c->self,
877204917Sdes	    (fwd_desc = format_forward(ftype, &fwd)));
878204917Sdes
879240075Sdes	/* make sure this has been requested */
880240075Sdes	found_fwd = NULL;
881240075Sdes	switch (ftype) {
882240075Sdes	case MUX_FWD_LOCAL:
883240075Sdes	case MUX_FWD_DYNAMIC:
884240075Sdes		for (i = 0; i < options.num_local_forwards; i++) {
885240075Sdes			if (compare_forward(&fwd,
886240075Sdes			    options.local_forwards + i)) {
887240075Sdes				found_fwd = options.local_forwards + i;
888240075Sdes				break;
889240075Sdes			}
890240075Sdes		}
891240075Sdes		break;
892240075Sdes	case MUX_FWD_REMOTE:
893240075Sdes		for (i = 0; i < options.num_remote_forwards; i++) {
894240075Sdes			if (compare_forward(&fwd,
895240075Sdes			    options.remote_forwards + i)) {
896240075Sdes				found_fwd = options.remote_forwards + i;
897240075Sdes				break;
898240075Sdes			}
899240075Sdes		}
900240075Sdes		break;
901240075Sdes	}
902204917Sdes
903240075Sdes	if (found_fwd == NULL)
904240075Sdes		error_reason = "port not forwarded";
905240075Sdes	else if (ftype == MUX_FWD_REMOTE) {
906240075Sdes		/*
907240075Sdes		 * This shouldn't fail unless we confused the host/port
908240075Sdes		 * between options.remote_forwards and permitted_opens.
909240075Sdes		 * However, for dynamic allocated listen ports we need
910294328Sdes		 * to use the actual listen port.
911240075Sdes		 */
912294328Sdes		if (channel_request_rforward_cancel(found_fwd) == -1)
913240075Sdes			error_reason = "port not in permitted opens";
914240075Sdes	} else {	/* local and dynamic forwards */
915240075Sdes		/* Ditto */
916294328Sdes		if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
917294328Sdes		    &options.fwd_opts) == -1)
918240075Sdes			error_reason = "port not found";
919240075Sdes	}
920240075Sdes
921240075Sdes	if (error_reason == NULL) {
922240075Sdes		buffer_put_int(r, MUX_S_OK);
923240075Sdes		buffer_put_int(r, rid);
924240075Sdes
925255767Sdes		free(found_fwd->listen_host);
926294328Sdes		free(found_fwd->listen_path);
927255767Sdes		free(found_fwd->connect_host);
928294328Sdes		free(found_fwd->connect_path);
929240075Sdes		found_fwd->listen_host = found_fwd->connect_host = NULL;
930294328Sdes		found_fwd->listen_path = found_fwd->connect_path = NULL;
931240075Sdes		found_fwd->listen_port = found_fwd->connect_port = 0;
932240075Sdes	} else {
933240075Sdes		buffer_put_int(r, MUX_S_FAILURE);
934240075Sdes		buffer_put_int(r, rid);
935240075Sdes		buffer_put_cstring(r, error_reason);
936240075Sdes	}
937204917Sdes out:
938255767Sdes	free(fwd_desc);
939294328Sdes	free(listen_addr);
940294328Sdes	free(connect_addr);
941204917Sdes
942204917Sdes	return ret;
943204917Sdes}
944204917Sdes
945204917Sdesstatic int
946204917Sdesprocess_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
947204917Sdes{
948204917Sdes	Channel *nc;
949204917Sdes	char *reserved, *chost;
950204917Sdes	u_int cport, i, j;
951204917Sdes	int new_fd[2];
952294328Sdes	struct mux_stdio_confirm_ctx *cctx;
953204917Sdes
954204917Sdes	chost = reserved = NULL;
955204917Sdes	if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
956204917Sdes	   (chost = buffer_get_string_ret(m, NULL)) == NULL ||
957204917Sdes	    buffer_get_int_ret(&cport, m) != 0) {
958255767Sdes		free(reserved);
959255767Sdes		free(chost);
960204917Sdes		error("%s: malformed message", __func__);
961204917Sdes		return -1;
962204917Sdes	}
963255767Sdes	free(reserved);
964204917Sdes
965204917Sdes	debug2("%s: channel %d: request stdio fwd to %s:%u",
966204917Sdes	    __func__, c->self, chost, cport);
967204917Sdes
968204917Sdes	/* Gather fds from client */
969204917Sdes	for(i = 0; i < 2; i++) {
970204917Sdes		if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
971204917Sdes			error("%s: failed to receive fd %d from slave",
972204917Sdes			    __func__, i);
973204917Sdes			for (j = 0; j < i; j++)
974204917Sdes				close(new_fd[j]);
975255767Sdes			free(chost);
976204917Sdes
977204917Sdes			/* prepare reply */
978204917Sdes			buffer_put_int(r, MUX_S_FAILURE);
979204917Sdes			buffer_put_int(r, rid);
980204917Sdes			buffer_put_cstring(r,
981204917Sdes			    "did not receive file descriptors");
982204917Sdes			return -1;
983204917Sdes		}
984204917Sdes	}
985204917Sdes
986204917Sdes	debug3("%s: got fds stdin %d, stdout %d", __func__,
987204917Sdes	    new_fd[0], new_fd[1]);
988204917Sdes
989204917Sdes	/* XXX support multiple child sessions in future */
990204917Sdes	if (c->remote_id != -1) {
991204917Sdes		debug2("%s: session already open", __func__);
992204917Sdes		/* prepare reply */
993204917Sdes		buffer_put_int(r, MUX_S_FAILURE);
994204917Sdes		buffer_put_int(r, rid);
995204917Sdes		buffer_put_cstring(r, "Multiple sessions not supported");
996204917Sdes cleanup:
997204917Sdes		close(new_fd[0]);
998204917Sdes		close(new_fd[1]);
999255767Sdes		free(chost);
1000204917Sdes		return 0;
1001204917Sdes	}
1002204917Sdes
1003204917Sdes	if (options.control_master == SSHCTL_MASTER_ASK ||
1004204917Sdes	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
1005221420Sdes		if (!ask_permission("Allow forward to %s:%u? ",
1006204917Sdes		    chost, cport)) {
1007204917Sdes			debug2("%s: stdio fwd refused by user", __func__);
1008204917Sdes			/* prepare reply */
1009204917Sdes			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
1010204917Sdes			buffer_put_int(r, rid);
1011204917Sdes			buffer_put_cstring(r, "Permission denied");
1012204917Sdes			goto cleanup;
1013204917Sdes		}
1014204917Sdes	}
1015204917Sdes
1016204917Sdes	/* enable nonblocking unless tty */
1017204917Sdes	if (!isatty(new_fd[0]))
1018204917Sdes		set_nonblock(new_fd[0]);
1019204917Sdes	if (!isatty(new_fd[1]))
1020204917Sdes		set_nonblock(new_fd[1]);
1021204917Sdes
1022204917Sdes	nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]);
1023204917Sdes
1024204917Sdes	nc->ctl_chan = c->self;		/* link session -> control channel */
1025204917Sdes	c->remote_id = nc->self; 	/* link control -> session channel */
1026204917Sdes
1027204917Sdes	debug2("%s: channel_new: %d linked to control channel %d",
1028204917Sdes	    __func__, nc->self, nc->ctl_chan);
1029204917Sdes
1030215116Sdes	channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
1031204917Sdes
1032294328Sdes	cctx = xcalloc(1, sizeof(*cctx));
1033294328Sdes	cctx->rid = rid;
1034294328Sdes	channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx);
1035294328Sdes	c->mux_pause = 1; /* stop handling messages until open_confirm done */
1036204917Sdes
1037294328Sdes	/* reply is deferred, sent by mux_session_confirm */
1038204917Sdes	return 0;
1039204917Sdes}
1040204917Sdes
1041294328Sdes/* Callback on open confirmation in mux master for a mux stdio fwd session. */
1042294328Sdesstatic void
1043294328Sdesmux_stdio_confirm(int id, int success, void *arg)
1044294328Sdes{
1045294328Sdes	struct mux_stdio_confirm_ctx *cctx = arg;
1046294328Sdes	Channel *c, *cc;
1047294328Sdes	Buffer reply;
1048294328Sdes
1049294328Sdes	if (cctx == NULL)
1050294328Sdes		fatal("%s: cctx == NULL", __func__);
1051294328Sdes	if ((c = channel_by_id(id)) == NULL)
1052294328Sdes		fatal("%s: no channel for id %d", __func__, id);
1053294328Sdes	if ((cc = channel_by_id(c->ctl_chan)) == NULL)
1054294328Sdes		fatal("%s: channel %d lacks control channel %d", __func__,
1055294328Sdes		    id, c->ctl_chan);
1056294328Sdes
1057294328Sdes	if (!success) {
1058294328Sdes		debug3("%s: sending failure reply", __func__);
1059294328Sdes		/* prepare reply */
1060294328Sdes		buffer_init(&reply);
1061294328Sdes		buffer_put_int(&reply, MUX_S_FAILURE);
1062294328Sdes		buffer_put_int(&reply, cctx->rid);
1063294328Sdes		buffer_put_cstring(&reply, "Session open refused by peer");
1064294328Sdes		goto done;
1065294328Sdes	}
1066294328Sdes
1067294328Sdes	debug3("%s: sending success reply", __func__);
1068294328Sdes	/* prepare reply */
1069294328Sdes	buffer_init(&reply);
1070294328Sdes	buffer_put_int(&reply, MUX_S_SESSION_OPENED);
1071294328Sdes	buffer_put_int(&reply, cctx->rid);
1072294328Sdes	buffer_put_int(&reply, c->self);
1073294328Sdes
1074294328Sdes done:
1075294328Sdes	/* Send reply */
1076294328Sdes	buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
1077294328Sdes	buffer_free(&reply);
1078294328Sdes
1079294328Sdes	if (cc->mux_pause <= 0)
1080294328Sdes		fatal("%s: mux_pause %d", __func__, cc->mux_pause);
1081294328Sdes	cc->mux_pause = 0; /* start processing messages again */
1082294328Sdes	c->open_confirm_ctx = NULL;
1083294328Sdes	free(cctx);
1084294328Sdes}
1085294328Sdes
1086226046Sdesstatic int
1087226046Sdesprocess_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
1088226046Sdes{
1089226046Sdes	debug("%s: channel %d: stop listening", __func__, c->self);
1090226046Sdes
1091226046Sdes	if (options.control_master == SSHCTL_MASTER_ASK ||
1092226046Sdes	    options.control_master == SSHCTL_MASTER_AUTO_ASK) {
1093226046Sdes		if (!ask_permission("Disable further multiplexing on shared "
1094226046Sdes		    "connection to %s? ", host)) {
1095226046Sdes			debug2("%s: stop listen refused by user", __func__);
1096226046Sdes			buffer_put_int(r, MUX_S_PERMISSION_DENIED);
1097226046Sdes			buffer_put_int(r, rid);
1098226046Sdes			buffer_put_cstring(r, "Permission denied");
1099226046Sdes			return 0;
1100226046Sdes		}
1101226046Sdes	}
1102226046Sdes
1103226046Sdes	if (mux_listener_channel != NULL) {
1104226046Sdes		channel_free(mux_listener_channel);
1105226046Sdes		client_stop_mux();
1106255767Sdes		free(options.control_path);
1107226046Sdes		options.control_path = NULL;
1108226046Sdes		mux_listener_channel = NULL;
1109226046Sdes		muxserver_sock = -1;
1110226046Sdes	}
1111226046Sdes
1112226046Sdes	/* prepare reply */
1113226046Sdes	buffer_put_int(r, MUX_S_OK);
1114226046Sdes	buffer_put_int(r, rid);
1115226046Sdes
1116226046Sdes	return 0;
1117226046Sdes}
1118226046Sdes
1119323134Sdesstatic int
1120323134Sdesprocess_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r)
1121323134Sdes{
1122323134Sdes	debug("%s: channel %d: proxy request", __func__, c->self);
1123323134Sdes
1124323134Sdes	c->mux_rcb = channel_proxy_downstream;
1125323134Sdes	buffer_put_int(r, MUX_S_PROXY);
1126323134Sdes	buffer_put_int(r, rid);
1127323134Sdes
1128323134Sdes	return 0;
1129323134Sdes}
1130323134Sdes
1131204917Sdes/* Channel callbacks fired on read/write from mux slave fd */
1132204917Sdesstatic int
1133204917Sdesmux_master_read_cb(Channel *c)
1134204917Sdes{
1135204917Sdes	struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
1136204917Sdes	Buffer in, out;
1137294328Sdes	const u_char *ptr;
1138204917Sdes	u_int type, rid, have, i;
1139204917Sdes	int ret = -1;
1140204917Sdes
1141204917Sdes	/* Setup ctx and  */
1142204917Sdes	if (c->mux_ctx == NULL) {
1143215116Sdes		state = xcalloc(1, sizeof(*state));
1144204917Sdes		c->mux_ctx = state;
1145204917Sdes		channel_register_cleanup(c->self,
1146204917Sdes		    mux_master_control_cleanup_cb, 0);
1147204917Sdes
1148204917Sdes		/* Send hello */
1149204917Sdes		buffer_init(&out);
1150204917Sdes		buffer_put_int(&out, MUX_MSG_HELLO);
1151204917Sdes		buffer_put_int(&out, SSHMUX_VER);
1152204917Sdes		/* no extensions */
1153204917Sdes		buffer_put_string(&c->output, buffer_ptr(&out),
1154204917Sdes		    buffer_len(&out));
1155204917Sdes		buffer_free(&out);
1156204917Sdes		debug3("%s: channel %d: hello sent", __func__, c->self);
1157204917Sdes		return 0;
1158204917Sdes	}
1159204917Sdes
1160204917Sdes	buffer_init(&in);
1161204917Sdes	buffer_init(&out);
1162204917Sdes
1163204917Sdes	/* Channel code ensures that we receive whole packets */
1164204917Sdes	if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) {
1165204917Sdes malf:
1166204917Sdes		error("%s: malformed message", __func__);
1167204917Sdes		goto out;
1168204917Sdes	}
1169204917Sdes	buffer_append(&in, ptr, have);
1170204917Sdes
1171204917Sdes	if (buffer_get_int_ret(&type, &in) != 0)
1172204917Sdes		goto malf;
1173204917Sdes	debug3("%s: channel %d packet type 0x%08x len %u",
1174204917Sdes	    __func__, c->self, type, buffer_len(&in));
1175204917Sdes
1176204917Sdes	if (type == MUX_MSG_HELLO)
1177204917Sdes		rid = 0;
1178204917Sdes	else {
1179204917Sdes		if (!state->hello_rcvd) {
1180204917Sdes			error("%s: expected MUX_MSG_HELLO(0x%08x), "
1181204917Sdes			    "received 0x%08x", __func__, MUX_MSG_HELLO, type);
1182204917Sdes			goto out;
1183204917Sdes		}
1184204917Sdes		if (buffer_get_int_ret(&rid, &in) != 0)
1185204917Sdes			goto malf;
1186204917Sdes	}
1187204917Sdes
1188204917Sdes	for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
1189204917Sdes		if (type == mux_master_handlers[i].type) {
1190204917Sdes			ret = mux_master_handlers[i].handler(rid, c, &in, &out);
1191204917Sdes			break;
1192204917Sdes		}
1193204917Sdes	}
1194204917Sdes	if (mux_master_handlers[i].handler == NULL) {
1195204917Sdes		error("%s: unsupported mux message 0x%08x", __func__, type);
1196204917Sdes		buffer_put_int(&out, MUX_S_FAILURE);
1197204917Sdes		buffer_put_int(&out, rid);
1198204917Sdes		buffer_put_cstring(&out, "unsupported request");
1199204917Sdes		ret = 0;
1200204917Sdes	}
1201204917Sdes	/* Enqueue reply packet */
1202204917Sdes	if (buffer_len(&out) != 0) {
1203204917Sdes		buffer_put_string(&c->output, buffer_ptr(&out),
1204204917Sdes		    buffer_len(&out));
1205204917Sdes	}
1206204917Sdes out:
1207204917Sdes	buffer_free(&in);
1208204917Sdes	buffer_free(&out);
1209204917Sdes	return ret;
1210204917Sdes}
1211204917Sdes
1212204917Sdesvoid
1213204917Sdesmux_exit_message(Channel *c, int exitval)
1214204917Sdes{
1215204917Sdes	Buffer m;
1216204917Sdes	Channel *mux_chan;
1217204917Sdes
1218255767Sdes	debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
1219204917Sdes	    exitval);
1220204917Sdes
1221204917Sdes	if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
1222204917Sdes		fatal("%s: channel %d missing mux channel %d",
1223204917Sdes		    __func__, c->self, c->ctl_chan);
1224204917Sdes
1225204917Sdes	/* Append exit message packet to control socket output queue */
1226204917Sdes	buffer_init(&m);
1227204917Sdes	buffer_put_int(&m, MUX_S_EXIT_MESSAGE);
1228204917Sdes	buffer_put_int(&m, c->self);
1229204917Sdes	buffer_put_int(&m, exitval);
1230204917Sdes
1231204917Sdes	buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
1232204917Sdes	buffer_free(&m);
1233204917Sdes}
1234204917Sdes
1235226046Sdesvoid
1236226046Sdesmux_tty_alloc_failed(Channel *c)
1237226046Sdes{
1238226046Sdes	Buffer m;
1239226046Sdes	Channel *mux_chan;
1240226046Sdes
1241226046Sdes	debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
1242226046Sdes
1243226046Sdes	if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
1244226046Sdes		fatal("%s: channel %d missing mux channel %d",
1245226046Sdes		    __func__, c->self, c->ctl_chan);
1246226046Sdes
1247226046Sdes	/* Append exit message packet to control socket output queue */
1248226046Sdes	buffer_init(&m);
1249226046Sdes	buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
1250226046Sdes	buffer_put_int(&m, c->self);
1251226046Sdes
1252226046Sdes	buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
1253226046Sdes	buffer_free(&m);
1254226046Sdes}
1255226046Sdes
1256180750Sdes/* Prepare a mux master to listen on a Unix domain socket. */
1257180750Sdesvoid
1258180750Sdesmuxserver_listen(void)
1259180750Sdes{
1260180750Sdes	mode_t old_umask;
1261221420Sdes	char *orig_control_path = options.control_path;
1262221420Sdes	char rbuf[16+1];
1263221420Sdes	u_int i, r;
1264294328Sdes	int oerrno;
1265180750Sdes
1266180750Sdes	if (options.control_path == NULL ||
1267180750Sdes	    options.control_master == SSHCTL_MASTER_NO)
1268180750Sdes		return;
1269180750Sdes
1270180750Sdes	debug("setting up multiplex master socket");
1271180750Sdes
1272221420Sdes	/*
1273221420Sdes	 * Use a temporary path before listen so we can pseudo-atomically
1274221420Sdes	 * establish the listening socket in its final location to avoid
1275221420Sdes	 * other processes racing in between bind() and listen() and hitting
1276221420Sdes	 * an unready socket.
1277221420Sdes	 */
1278221420Sdes	for (i = 0; i < sizeof(rbuf) - 1; i++) {
1279221420Sdes		r = arc4random_uniform(26+26+10);
1280221420Sdes		rbuf[i] = (r < 26) ? 'a' + r :
1281221420Sdes		    (r < 26*2) ? 'A' + r - 26 :
1282221420Sdes		    '0' + r - 26 - 26;
1283221420Sdes	}
1284221420Sdes	rbuf[sizeof(rbuf) - 1] = '\0';
1285221420Sdes	options.control_path = NULL;
1286221420Sdes	xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
1287221420Sdes	debug3("%s: temporary control path %s", __func__, options.control_path);
1288221420Sdes
1289180750Sdes	old_umask = umask(0177);
1290294328Sdes	muxserver_sock = unix_listener(options.control_path, 64, 0);
1291294328Sdes	oerrno = errno;
1292294328Sdes	umask(old_umask);
1293294328Sdes	if (muxserver_sock < 0) {
1294294328Sdes		if (oerrno == EINVAL || oerrno == EADDRINUSE) {
1295180750Sdes			error("ControlSocket %s already exists, "
1296180750Sdes			    "disabling multiplexing", options.control_path);
1297221420Sdes disable_mux_master:
1298226046Sdes			if (muxserver_sock != -1) {
1299226046Sdes				close(muxserver_sock);
1300226046Sdes				muxserver_sock = -1;
1301226046Sdes			}
1302255767Sdes			free(orig_control_path);
1303255767Sdes			free(options.control_path);
1304180750Sdes			options.control_path = NULL;
1305180750Sdes			options.control_master = SSHCTL_MASTER_NO;
1306180750Sdes			return;
1307294328Sdes		} else {
1308294328Sdes			/* unix_listener() logs the error */
1309294328Sdes			cleanup_exit(255);
1310294328Sdes		}
1311180750Sdes	}
1312180750Sdes
1313221420Sdes	/* Now atomically "move" the mux socket into position */
1314221420Sdes	if (link(options.control_path, orig_control_path) != 0) {
1315221420Sdes		if (errno != EEXIST) {
1316323129Sdes			fatal("%s: link mux listener %s => %s: %s", __func__,
1317221420Sdes			    options.control_path, orig_control_path,
1318221420Sdes			    strerror(errno));
1319221420Sdes		}
1320221420Sdes		error("ControlSocket %s already exists, disabling multiplexing",
1321221420Sdes		    orig_control_path);
1322221420Sdes		unlink(options.control_path);
1323221420Sdes		goto disable_mux_master;
1324221420Sdes	}
1325221420Sdes	unlink(options.control_path);
1326255767Sdes	free(options.control_path);
1327221420Sdes	options.control_path = orig_control_path;
1328221420Sdes
1329180750Sdes	set_nonblock(muxserver_sock);
1330204917Sdes
1331204917Sdes	mux_listener_channel = channel_new("mux listener",
1332204917Sdes	    SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
1333204917Sdes	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1334221420Sdes	    0, options.control_path, 1);
1335204917Sdes	mux_listener_channel->mux_rcb = mux_master_read_cb;
1336204917Sdes	debug3("%s: mux listener channel %d fd %d", __func__,
1337204917Sdes	    mux_listener_channel->self, mux_listener_channel->sock);
1338180750Sdes}
1339180750Sdes
1340180750Sdes/* Callback on open confirmation in mux master for a mux client session. */
1341180750Sdesstatic void
1342215116Sdesmux_session_confirm(int id, int success, void *arg)
1343180750Sdes{
1344180750Sdes	struct mux_session_confirm_ctx *cctx = arg;
1345180750Sdes	const char *display;
1346215116Sdes	Channel *c, *cc;
1347180750Sdes	int i;
1348215116Sdes	Buffer reply;
1349180750Sdes
1350180750Sdes	if (cctx == NULL)
1351180750Sdes		fatal("%s: cctx == NULL", __func__);
1352204917Sdes	if ((c = channel_by_id(id)) == NULL)
1353180750Sdes		fatal("%s: no channel for id %d", __func__, id);
1354215116Sdes	if ((cc = channel_by_id(c->ctl_chan)) == NULL)
1355215116Sdes		fatal("%s: channel %d lacks control channel %d", __func__,
1356215116Sdes		    id, c->ctl_chan);
1357180750Sdes
1358215116Sdes	if (!success) {
1359215116Sdes		debug3("%s: sending failure reply", __func__);
1360215116Sdes		/* prepare reply */
1361215116Sdes		buffer_init(&reply);
1362215116Sdes		buffer_put_int(&reply, MUX_S_FAILURE);
1363215116Sdes		buffer_put_int(&reply, cctx->rid);
1364215116Sdes		buffer_put_cstring(&reply, "Session open refused by peer");
1365215116Sdes		goto done;
1366215116Sdes	}
1367215116Sdes
1368180750Sdes	display = getenv("DISPLAY");
1369180750Sdes	if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
1370180750Sdes		char *proto, *data;
1371215116Sdes
1372180750Sdes		/* Get reasonable local authentication information. */
1373296633Sdes		if (client_x11_get_proto(display, options.xauth_location,
1374215116Sdes		    options.forward_x11_trusted, options.forward_x11_timeout,
1375296633Sdes		    &proto, &data) == 0) {
1376296633Sdes			/* Request forwarding with authentication spoofing. */
1377296633Sdes			debug("Requesting X11 forwarding with authentication "
1378296633Sdes			    "spoofing.");
1379296633Sdes			x11_request_forwarding_with_spoofing(id, display, proto,
1380296633Sdes			    data, 1);
1381296633Sdes			/* XXX exit_on_forward_failure */
1382296633Sdes			client_expect_confirm(id, "X11 forwarding",
1383296633Sdes			    CONFIRM_WARN);
1384296633Sdes		}
1385180750Sdes	}
1386180750Sdes
1387180750Sdes	if (cctx->want_agent_fwd && options.forward_agent) {
1388180750Sdes		debug("Requesting authentication agent forwarding.");
1389180750Sdes		channel_request_start(id, "auth-agent-req@openssh.com", 0);
1390180750Sdes		packet_send();
1391180750Sdes	}
1392180750Sdes
1393180750Sdes	client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
1394180750Sdes	    cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
1395180750Sdes
1396215116Sdes	debug3("%s: sending success reply", __func__);
1397215116Sdes	/* prepare reply */
1398215116Sdes	buffer_init(&reply);
1399215116Sdes	buffer_put_int(&reply, MUX_S_SESSION_OPENED);
1400215116Sdes	buffer_put_int(&reply, cctx->rid);
1401215116Sdes	buffer_put_int(&reply, c->self);
1402215116Sdes
1403215116Sdes done:
1404215116Sdes	/* Send reply */
1405215116Sdes	buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
1406215116Sdes	buffer_free(&reply);
1407215116Sdes
1408215116Sdes	if (cc->mux_pause <= 0)
1409215116Sdes		fatal("%s: mux_pause %d", __func__, cc->mux_pause);
1410215116Sdes	cc->mux_pause = 0; /* start processing messages again */
1411180750Sdes	c->open_confirm_ctx = NULL;
1412180750Sdes	buffer_free(&cctx->cmd);
1413255767Sdes	free(cctx->term);
1414180750Sdes	if (cctx->env != NULL) {
1415180750Sdes		for (i = 0; cctx->env[i] != NULL; i++)
1416255767Sdes			free(cctx->env[i]);
1417255767Sdes		free(cctx->env);
1418180750Sdes	}
1419255767Sdes	free(cctx);
1420180750Sdes}
1421180750Sdes
1422204917Sdes/* ** Multiplexing client support */
1423204917Sdes
1424204917Sdes/* Exit signal handler */
1425204917Sdesstatic void
1426204917Sdescontrol_client_sighandler(int signo)
1427204917Sdes{
1428204917Sdes	muxclient_terminate = signo;
1429204917Sdes}
1430204917Sdes
1431180750Sdes/*
1432204917Sdes * Relay signal handler - used to pass some signals from mux client to
1433204917Sdes * mux master.
1434180750Sdes */
1435204917Sdesstatic void
1436204917Sdescontrol_client_sigrelay(int signo)
1437180750Sdes{
1438204917Sdes	int save_errno = errno;
1439180750Sdes
1440204917Sdes	if (muxserver_pid > 1)
1441204917Sdes		kill(muxserver_pid, signo);
1442204917Sdes
1443204917Sdes	errno = save_errno;
1444204917Sdes}
1445204917Sdes
1446204917Sdesstatic int
1447204917Sdesmux_client_read(int fd, Buffer *b, u_int need)
1448204917Sdes{
1449204917Sdes	u_int have;
1450204917Sdes	ssize_t len;
1451204917Sdes	u_char *p;
1452204917Sdes	struct pollfd pfd;
1453204917Sdes
1454204917Sdes	pfd.fd = fd;
1455204917Sdes	pfd.events = POLLIN;
1456204917Sdes	p = buffer_append_space(b, need);
1457204917Sdes	for (have = 0; have < need; ) {
1458204917Sdes		if (muxclient_terminate) {
1459204917Sdes			errno = EINTR;
1460204917Sdes			return -1;
1461204917Sdes		}
1462204917Sdes		len = read(fd, p + have, need - have);
1463204917Sdes		if (len < 0) {
1464204917Sdes			switch (errno) {
1465204917Sdes#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1466204917Sdes			case EWOULDBLOCK:
1467204917Sdes#endif
1468204917Sdes			case EAGAIN:
1469204917Sdes				(void)poll(&pfd, 1, -1);
1470204917Sdes				/* FALLTHROUGH */
1471204917Sdes			case EINTR:
1472204917Sdes				continue;
1473204917Sdes			default:
1474204917Sdes				return -1;
1475204917Sdes			}
1476204917Sdes		}
1477204917Sdes		if (len == 0) {
1478204917Sdes			errno = EPIPE;
1479204917Sdes			return -1;
1480204917Sdes		}
1481204917Sdes		have += (u_int)len;
1482180750Sdes	}
1483204917Sdes	return 0;
1484204917Sdes}
1485180750Sdes
1486204917Sdesstatic int
1487204917Sdesmux_client_write_packet(int fd, Buffer *m)
1488204917Sdes{
1489204917Sdes	Buffer queue;
1490204917Sdes	u_int have, need;
1491204917Sdes	int oerrno, len;
1492204917Sdes	u_char *ptr;
1493204917Sdes	struct pollfd pfd;
1494204917Sdes
1495204917Sdes	pfd.fd = fd;
1496204917Sdes	pfd.events = POLLOUT;
1497204917Sdes	buffer_init(&queue);
1498204917Sdes	buffer_put_string(&queue, buffer_ptr(m), buffer_len(m));
1499204917Sdes
1500204917Sdes	need = buffer_len(&queue);
1501204917Sdes	ptr = buffer_ptr(&queue);
1502204917Sdes
1503204917Sdes	for (have = 0; have < need; ) {
1504204917Sdes		if (muxclient_terminate) {
1505204917Sdes			buffer_free(&queue);
1506204917Sdes			errno = EINTR;
1507204917Sdes			return -1;
1508204917Sdes		}
1509204917Sdes		len = write(fd, ptr + have, need - have);
1510204917Sdes		if (len < 0) {
1511204917Sdes			switch (errno) {
1512204917Sdes#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1513204917Sdes			case EWOULDBLOCK:
1514204917Sdes#endif
1515204917Sdes			case EAGAIN:
1516204917Sdes				(void)poll(&pfd, 1, -1);
1517204917Sdes				/* FALLTHROUGH */
1518204917Sdes			case EINTR:
1519204917Sdes				continue;
1520204917Sdes			default:
1521204917Sdes				oerrno = errno;
1522204917Sdes				buffer_free(&queue);
1523204917Sdes				errno = oerrno;
1524204917Sdes				return -1;
1525204917Sdes			}
1526204917Sdes		}
1527204917Sdes		if (len == 0) {
1528204917Sdes			buffer_free(&queue);
1529204917Sdes			errno = EPIPE;
1530204917Sdes			return -1;
1531204917Sdes		}
1532204917Sdes		have += (u_int)len;
1533180750Sdes	}
1534204917Sdes	buffer_free(&queue);
1535204917Sdes	return 0;
1536204917Sdes}
1537204917Sdes
1538204917Sdesstatic int
1539204917Sdesmux_client_read_packet(int fd, Buffer *m)
1540204917Sdes{
1541204917Sdes	Buffer queue;
1542204917Sdes	u_int need, have;
1543294328Sdes	const u_char *ptr;
1544204917Sdes	int oerrno;
1545204917Sdes
1546204917Sdes	buffer_init(&queue);
1547204917Sdes	if (mux_client_read(fd, &queue, 4) != 0) {
1548204917Sdes		if ((oerrno = errno) == EPIPE)
1549255767Sdes			debug3("%s: read header failed: %s", __func__,
1550255767Sdes			    strerror(errno));
1551255767Sdes		buffer_free(&queue);
1552204917Sdes		errno = oerrno;
1553204917Sdes		return -1;
1554180750Sdes	}
1555204917Sdes	need = get_u32(buffer_ptr(&queue));
1556204917Sdes	if (mux_client_read(fd, &queue, need) != 0) {
1557204917Sdes		oerrno = errno;
1558204917Sdes		debug3("%s: read body failed: %s", __func__, strerror(errno));
1559255767Sdes		buffer_free(&queue);
1560204917Sdes		errno = oerrno;
1561204917Sdes		return -1;
1562204917Sdes	}
1563204917Sdes	ptr = buffer_get_string_ptr(&queue, &have);
1564204917Sdes	buffer_append(m, ptr, have);
1565204917Sdes	buffer_free(&queue);
1566204917Sdes	return 0;
1567204917Sdes}
1568180750Sdes
1569204917Sdesstatic int
1570204917Sdesmux_client_hello_exchange(int fd)
1571204917Sdes{
1572204917Sdes	Buffer m;
1573204917Sdes	u_int type, ver;
1574180750Sdes
1575180750Sdes	buffer_init(&m);
1576204917Sdes	buffer_put_int(&m, MUX_MSG_HELLO);
1577204917Sdes	buffer_put_int(&m, SSHMUX_VER);
1578204917Sdes	/* no extensions */
1579204917Sdes
1580204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
1581204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1582204917Sdes
1583204917Sdes	buffer_clear(&m);
1584204917Sdes
1585204917Sdes	/* Read their HELLO */
1586204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1587180750Sdes		buffer_free(&m);
1588204917Sdes		return -1;
1589180750Sdes	}
1590204917Sdes
1591204917Sdes	type = buffer_get_int(&m);
1592204917Sdes	if (type != MUX_MSG_HELLO)
1593204917Sdes		fatal("%s: expected HELLO (%u) received %u",
1594204917Sdes		    __func__, MUX_MSG_HELLO, type);
1595204917Sdes	ver = buffer_get_int(&m);
1596204917Sdes	if (ver != SSHMUX_VER)
1597204917Sdes		fatal("Unsupported multiplexing protocol version %d "
1598204917Sdes		    "(expected %d)", ver, SSHMUX_VER);
1599204917Sdes	debug2("%s: master version %u", __func__, ver);
1600204917Sdes	/* No extensions are presently defined */
1601204917Sdes	while (buffer_len(&m) > 0) {
1602204917Sdes		char *name = buffer_get_string(&m, NULL);
1603204917Sdes		char *value = buffer_get_string(&m, NULL);
1604204917Sdes
1605204917Sdes		debug2("Unrecognised master extension \"%s\"", name);
1606255767Sdes		free(name);
1607255767Sdes		free(value);
1608204917Sdes	}
1609204917Sdes	buffer_free(&m);
1610204917Sdes	return 0;
1611204917Sdes}
1612204917Sdes
1613204917Sdesstatic u_int
1614204917Sdesmux_client_request_alive(int fd)
1615204917Sdes{
1616204917Sdes	Buffer m;
1617204917Sdes	char *e;
1618204917Sdes	u_int pid, type, rid;
1619204917Sdes
1620204917Sdes	debug3("%s: entering", __func__);
1621204917Sdes
1622204917Sdes	buffer_init(&m);
1623204917Sdes	buffer_put_int(&m, MUX_C_ALIVE_CHECK);
1624204917Sdes	buffer_put_int(&m, muxclient_request_id);
1625204917Sdes
1626204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
1627204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1628204917Sdes
1629204917Sdes	buffer_clear(&m);
1630204917Sdes
1631204917Sdes	/* Read their reply */
1632204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1633180750Sdes		buffer_free(&m);
1634180750Sdes		return 0;
1635180750Sdes	}
1636180750Sdes
1637204917Sdes	type = buffer_get_int(&m);
1638204917Sdes	if (type != MUX_S_ALIVE) {
1639204917Sdes		e = buffer_get_string(&m, NULL);
1640204917Sdes		fatal("%s: master returned error: %s", __func__, e);
1641204917Sdes	}
1642180750Sdes
1643204917Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1644204917Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
1645204917Sdes		    __func__, muxclient_request_id, rid);
1646204917Sdes	pid = buffer_get_int(&m);
1647204917Sdes	buffer_free(&m);
1648204917Sdes
1649204917Sdes	debug3("%s: done pid = %u", __func__, pid);
1650204917Sdes
1651204917Sdes	muxclient_request_id++;
1652204917Sdes
1653204917Sdes	return pid;
1654204917Sdes}
1655204917Sdes
1656204917Sdesstatic void
1657204917Sdesmux_client_request_terminate(int fd)
1658204917Sdes{
1659204917Sdes	Buffer m;
1660204917Sdes	char *e;
1661204917Sdes	u_int type, rid;
1662204917Sdes
1663204917Sdes	debug3("%s: entering", __func__);
1664204917Sdes
1665204917Sdes	buffer_init(&m);
1666204917Sdes	buffer_put_int(&m, MUX_C_TERMINATE);
1667204917Sdes	buffer_put_int(&m, muxclient_request_id);
1668204917Sdes
1669204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
1670204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1671204917Sdes
1672180750Sdes	buffer_clear(&m);
1673180750Sdes
1674204917Sdes	/* Read their reply */
1675204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1676204917Sdes		/* Remote end exited already */
1677204917Sdes		if (errno == EPIPE) {
1678180750Sdes			buffer_free(&m);
1679204917Sdes			return;
1680180750Sdes		}
1681204917Sdes		fatal("%s: read from master failed: %s",
1682204917Sdes		    __func__, strerror(errno));
1683204917Sdes	}
1684204917Sdes
1685204917Sdes	type = buffer_get_int(&m);
1686204917Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1687204917Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
1688204917Sdes		    __func__, muxclient_request_id, rid);
1689204917Sdes	switch (type) {
1690204917Sdes	case MUX_S_OK:
1691204917Sdes		break;
1692204917Sdes	case MUX_S_PERMISSION_DENIED:
1693204917Sdes		e = buffer_get_string(&m, NULL);
1694204917Sdes		fatal("Master refused termination request: %s", e);
1695204917Sdes	case MUX_S_FAILURE:
1696204917Sdes		e = buffer_get_string(&m, NULL);
1697204917Sdes		fatal("%s: termination request failed: %s", __func__, e);
1698180750Sdes	default:
1699204917Sdes		fatal("%s: unexpected response from master 0x%08x",
1700204917Sdes		    __func__, type);
1701180750Sdes	}
1702204917Sdes	buffer_free(&m);
1703204917Sdes	muxclient_request_id++;
1704204917Sdes}
1705180750Sdes
1706204917Sdesstatic int
1707294328Sdesmux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
1708204917Sdes{
1709204917Sdes	Buffer m;
1710204917Sdes	char *e, *fwd_desc;
1711204917Sdes	u_int type, rid;
1712204917Sdes
1713204917Sdes	fwd_desc = format_forward(ftype, fwd);
1714240075Sdes	debug("Requesting %s %s",
1715240075Sdes	    cancel_flag ? "cancellation of" : "forwarding of", fwd_desc);
1716255767Sdes	free(fwd_desc);
1717204917Sdes
1718204917Sdes	buffer_init(&m);
1719240075Sdes	buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
1720204917Sdes	buffer_put_int(&m, muxclient_request_id);
1721204917Sdes	buffer_put_int(&m, ftype);
1722294328Sdes	if (fwd->listen_path != NULL) {
1723294328Sdes		buffer_put_cstring(&m, fwd->listen_path);
1724294328Sdes	} else {
1725294328Sdes		buffer_put_cstring(&m,
1726294332Sdes		    fwd->listen_host == NULL ? "" :
1727294332Sdes		    (*fwd->listen_host == '\0' ? "*" : fwd->listen_host));
1728294328Sdes	}
1729204917Sdes	buffer_put_int(&m, fwd->listen_port);
1730294328Sdes	if (fwd->connect_path != NULL) {
1731294328Sdes		buffer_put_cstring(&m, fwd->connect_path);
1732294328Sdes	} else {
1733294328Sdes		buffer_put_cstring(&m,
1734294328Sdes		    fwd->connect_host == NULL ? "" : fwd->connect_host);
1735294328Sdes	}
1736204917Sdes	buffer_put_int(&m, fwd->connect_port);
1737204917Sdes
1738204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
1739204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1740204917Sdes
1741180750Sdes	buffer_clear(&m);
1742204917Sdes
1743204917Sdes	/* Read their reply */
1744204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1745180750Sdes		buffer_free(&m);
1746204917Sdes		return -1;
1747180750Sdes	}
1748180750Sdes
1749204917Sdes	type = buffer_get_int(&m);
1750204917Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1751204917Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
1752204917Sdes		    __func__, muxclient_request_id, rid);
1753204917Sdes	switch (type) {
1754204917Sdes	case MUX_S_OK:
1755204917Sdes		break;
1756215116Sdes	case MUX_S_REMOTE_PORT:
1757240075Sdes		if (cancel_flag)
1758240075Sdes			fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
1759215116Sdes		fwd->allocated_port = buffer_get_int(&m);
1760294336Sdes		verbose("Allocated port %u for remote forward to %s:%d",
1761215116Sdes		    fwd->allocated_port,
1762215116Sdes		    fwd->connect_host ? fwd->connect_host : "",
1763215116Sdes		    fwd->connect_port);
1764215116Sdes		if (muxclient_command == SSHMUX_COMMAND_FORWARD)
1765296633Sdes			fprintf(stdout, "%i\n", fwd->allocated_port);
1766215116Sdes		break;
1767204917Sdes	case MUX_S_PERMISSION_DENIED:
1768204917Sdes		e = buffer_get_string(&m, NULL);
1769180750Sdes		buffer_free(&m);
1770204917Sdes		error("Master refused forwarding request: %s", e);
1771204917Sdes		return -1;
1772204917Sdes	case MUX_S_FAILURE:
1773204917Sdes		e = buffer_get_string(&m, NULL);
1774204917Sdes		buffer_free(&m);
1775221420Sdes		error("%s: forwarding request failed: %s", __func__, e);
1776204917Sdes		return -1;
1777204917Sdes	default:
1778204917Sdes		fatal("%s: unexpected response from master 0x%08x",
1779204917Sdes		    __func__, type);
1780180750Sdes	}
1781204917Sdes	buffer_free(&m);
1782180750Sdes
1783204917Sdes	muxclient_request_id++;
1784204917Sdes	return 0;
1785204917Sdes}
1786204917Sdes
1787204917Sdesstatic int
1788240075Sdesmux_client_forwards(int fd, int cancel_flag)
1789204917Sdes{
1790240075Sdes	int i, ret = 0;
1791204917Sdes
1792240075Sdes	debug3("%s: %s forwardings: %d local, %d remote", __func__,
1793240075Sdes	    cancel_flag ? "cancel" : "request",
1794204917Sdes	    options.num_local_forwards, options.num_remote_forwards);
1795204917Sdes
1796204917Sdes	/* XXX ExitOnForwardingFailure */
1797204917Sdes	for (i = 0; i < options.num_local_forwards; i++) {
1798240075Sdes		if (mux_client_forward(fd, cancel_flag,
1799204917Sdes		    options.local_forwards[i].connect_port == 0 ?
1800204917Sdes		    MUX_FWD_DYNAMIC : MUX_FWD_LOCAL,
1801204917Sdes		    options.local_forwards + i) != 0)
1802240075Sdes			ret = -1;
1803180750Sdes	}
1804204917Sdes	for (i = 0; i < options.num_remote_forwards; i++) {
1805240075Sdes		if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE,
1806204917Sdes		    options.remote_forwards + i) != 0)
1807240075Sdes			ret = -1;
1808180750Sdes	}
1809240075Sdes	return ret;
1810204917Sdes}
1811180750Sdes
1812204917Sdesstatic int
1813204917Sdesmux_client_request_session(int fd)
1814204917Sdes{
1815204917Sdes	Buffer m;
1816204917Sdes	char *e, *term;
1817204917Sdes	u_int i, rid, sid, esid, exitval, type, exitval_seen;
1818204917Sdes	extern char **environ;
1819226046Sdes	int devnull, rawmode;
1820180750Sdes
1821204917Sdes	debug3("%s: entering", __func__);
1822180750Sdes
1823204917Sdes	if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
1824204917Sdes		error("%s: master alive request failed", __func__);
1825204917Sdes		return -1;
1826180750Sdes	}
1827180750Sdes
1828204917Sdes	signal(SIGPIPE, SIG_IGN);
1829180750Sdes
1830204917Sdes	if (stdin_null_flag) {
1831204917Sdes		if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
1832204917Sdes			fatal("open(/dev/null): %s", strerror(errno));
1833204917Sdes		if (dup2(devnull, STDIN_FILENO) == -1)
1834204917Sdes			fatal("dup2: %s", strerror(errno));
1835204917Sdes		if (devnull > STDERR_FILENO)
1836204917Sdes			close(devnull);
1837180750Sdes	}
1838180750Sdes
1839204917Sdes	term = getenv("TERM");
1840180750Sdes
1841204917Sdes	buffer_init(&m);
1842204917Sdes	buffer_put_int(&m, MUX_C_NEW_SESSION);
1843204917Sdes	buffer_put_int(&m, muxclient_request_id);
1844204917Sdes	buffer_put_cstring(&m, ""); /* reserved */
1845204917Sdes	buffer_put_int(&m, tty_flag);
1846204917Sdes	buffer_put_int(&m, options.forward_x11);
1847204917Sdes	buffer_put_int(&m, options.forward_agent);
1848204917Sdes	buffer_put_int(&m, subsystem_flag);
1849204917Sdes	buffer_put_int(&m, options.escape_char == SSH_ESCAPECHAR_NONE ?
1850204917Sdes	    0xffffffff : (u_int)options.escape_char);
1851204917Sdes	buffer_put_cstring(&m, term == NULL ? "" : term);
1852204917Sdes	buffer_put_string(&m, buffer_ptr(&command), buffer_len(&command));
1853180750Sdes
1854204917Sdes	if (options.num_send_env > 0 && environ != NULL) {
1855204917Sdes		/* Pass environment */
1856204917Sdes		for (i = 0; environ[i] != NULL; i++) {
1857204917Sdes			if (env_permitted(environ[i])) {
1858204917Sdes				buffer_put_cstring(&m, environ[i]);
1859204917Sdes			}
1860180750Sdes		}
1861180750Sdes	}
1862180750Sdes
1863204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
1864204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1865180750Sdes
1866204917Sdes	/* Send the stdio file descriptors */
1867204917Sdes	if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
1868204917Sdes	    mm_send_fd(fd, STDOUT_FILENO) == -1 ||
1869204917Sdes	    mm_send_fd(fd, STDERR_FILENO) == -1)
1870204917Sdes		fatal("%s: send fds failed", __func__);
1871180750Sdes
1872204917Sdes	debug3("%s: session request sent", __func__);
1873204917Sdes
1874204917Sdes	/* Read their reply */
1875204917Sdes	buffer_clear(&m);
1876204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1877204917Sdes		error("%s: read from master failed: %s",
1878204917Sdes		    __func__, strerror(errno));
1879204917Sdes		buffer_free(&m);
1880204917Sdes		return -1;
1881180750Sdes	}
1882180750Sdes
1883204917Sdes	type = buffer_get_int(&m);
1884204917Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1885204917Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
1886204917Sdes		    __func__, muxclient_request_id, rid);
1887204917Sdes	switch (type) {
1888204917Sdes	case MUX_S_SESSION_OPENED:
1889204917Sdes		sid = buffer_get_int(&m);
1890204917Sdes		debug("%s: master session id: %u", __func__, sid);
1891204917Sdes		break;
1892204917Sdes	case MUX_S_PERMISSION_DENIED:
1893204917Sdes		e = buffer_get_string(&m, NULL);
1894204917Sdes		buffer_free(&m);
1895221420Sdes		error("Master refused session request: %s", e);
1896204917Sdes		return -1;
1897204917Sdes	case MUX_S_FAILURE:
1898204917Sdes		e = buffer_get_string(&m, NULL);
1899204917Sdes		buffer_free(&m);
1900221420Sdes		error("%s: session request failed: %s", __func__, e);
1901204917Sdes		return -1;
1902204917Sdes	default:
1903204917Sdes		buffer_free(&m);
1904204917Sdes		error("%s: unexpected response from master 0x%08x",
1905204917Sdes		    __func__, type);
1906204917Sdes		return -1;
1907180750Sdes	}
1908204917Sdes	muxclient_request_id++;
1909180750Sdes
1910296633Sdes	if (pledge("stdio proc tty", NULL) == -1)
1911296633Sdes		fatal("%s pledge(): %s", __func__, strerror(errno));
1912296633Sdes	platform_pledge_mux();
1913296633Sdes
1914204917Sdes	signal(SIGHUP, control_client_sighandler);
1915204917Sdes	signal(SIGINT, control_client_sighandler);
1916204917Sdes	signal(SIGTERM, control_client_sighandler);
1917204917Sdes	signal(SIGWINCH, control_client_sigrelay);
1918180750Sdes
1919226046Sdes	rawmode = tty_flag;
1920204917Sdes	if (tty_flag)
1921226046Sdes		enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1922180750Sdes
1923204917Sdes	/*
1924204917Sdes	 * Stick around until the controlee closes the client_fd.
1925204917Sdes	 * Before it does, it is expected to write an exit message.
1926204917Sdes	 * This process must read the value and wait for the closure of
1927204917Sdes	 * the client_fd; if this one closes early, the multiplex master will
1928204917Sdes	 * terminate early too (possibly losing data).
1929204917Sdes	 */
1930204917Sdes	for (exitval = 255, exitval_seen = 0;;) {
1931204917Sdes		buffer_clear(&m);
1932204917Sdes		if (mux_client_read_packet(fd, &m) != 0)
1933204917Sdes			break;
1934204917Sdes		type = buffer_get_int(&m);
1935226046Sdes		switch (type) {
1936226046Sdes		case MUX_S_TTY_ALLOC_FAIL:
1937226046Sdes			if ((esid = buffer_get_int(&m)) != sid)
1938226046Sdes				fatal("%s: tty alloc fail on unknown session: "
1939226046Sdes				    "my id %u theirs %u",
1940226046Sdes				    __func__, sid, esid);
1941226046Sdes			leave_raw_mode(options.request_tty ==
1942226046Sdes			    REQUEST_TTY_FORCE);
1943226046Sdes			rawmode = 0;
1944226046Sdes			continue;
1945226046Sdes		case MUX_S_EXIT_MESSAGE:
1946226046Sdes			if ((esid = buffer_get_int(&m)) != sid)
1947226046Sdes				fatal("%s: exit on unknown session: "
1948226046Sdes				    "my id %u theirs %u",
1949226046Sdes				    __func__, sid, esid);
1950226046Sdes			if (exitval_seen)
1951226046Sdes				fatal("%s: exitval sent twice", __func__);
1952226046Sdes			exitval = buffer_get_int(&m);
1953226046Sdes			exitval_seen = 1;
1954226046Sdes			continue;
1955226046Sdes		default:
1956204917Sdes			e = buffer_get_string(&m, NULL);
1957204917Sdes			fatal("%s: master returned error: %s", __func__, e);
1958204917Sdes		}
1959204917Sdes	}
1960180750Sdes
1961204917Sdes	close(fd);
1962226046Sdes	if (rawmode)
1963226046Sdes		leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1964180750Sdes
1965204917Sdes	if (muxclient_terminate) {
1966255767Sdes		debug2("Exiting on signal %ld", (long)muxclient_terminate);
1967204917Sdes		exitval = 255;
1968204917Sdes	} else if (!exitval_seen) {
1969204917Sdes		debug2("Control master terminated unexpectedly");
1970204917Sdes		exitval = 255;
1971204917Sdes	} else
1972204917Sdes		debug2("Received exit status from master %d", exitval);
1973180750Sdes
1974204917Sdes	if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
1975204917Sdes		fprintf(stderr, "Shared connection to %s closed.\r\n", host);
1976180750Sdes
1977204917Sdes	exit(exitval);
1978180750Sdes}
1979180750Sdes
1980180750Sdesstatic int
1981323134Sdesmux_client_proxy(int fd)
1982323134Sdes{
1983323134Sdes	Buffer m;
1984323134Sdes	char *e;
1985323134Sdes	u_int type, rid;
1986323134Sdes
1987323134Sdes	buffer_init(&m);
1988323134Sdes	buffer_put_int(&m, MUX_C_PROXY);
1989323134Sdes	buffer_put_int(&m, muxclient_request_id);
1990323134Sdes	if (mux_client_write_packet(fd, &m) != 0)
1991323134Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
1992323134Sdes
1993323134Sdes	buffer_clear(&m);
1994323134Sdes
1995323134Sdes	/* Read their reply */
1996323134Sdes	if (mux_client_read_packet(fd, &m) != 0) {
1997323134Sdes		buffer_free(&m);
1998323134Sdes		return 0;
1999323134Sdes	}
2000323134Sdes	type = buffer_get_int(&m);
2001323134Sdes	if (type != MUX_S_PROXY) {
2002323134Sdes		e = buffer_get_string(&m, NULL);
2003323134Sdes		fatal("%s: master returned error: %s", __func__, e);
2004323134Sdes	}
2005323134Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
2006323134Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
2007323134Sdes		    __func__, muxclient_request_id, rid);
2008323134Sdes	buffer_free(&m);
2009323134Sdes
2010323134Sdes	debug3("%s: done", __func__);
2011323134Sdes	muxclient_request_id++;
2012323134Sdes	return 0;
2013323134Sdes}
2014323134Sdes
2015323134Sdesstatic int
2016204917Sdesmux_client_request_stdio_fwd(int fd)
2017180750Sdes{
2018204917Sdes	Buffer m;
2019204917Sdes	char *e;
2020204917Sdes	u_int type, rid, sid;
2021204917Sdes	int devnull;
2022180750Sdes
2023204917Sdes	debug3("%s: entering", __func__);
2024180750Sdes
2025204917Sdes	if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
2026204917Sdes		error("%s: master alive request failed", __func__);
2027204917Sdes		return -1;
2028204917Sdes	}
2029180750Sdes
2030204917Sdes	signal(SIGPIPE, SIG_IGN);
2031204917Sdes
2032204917Sdes	if (stdin_null_flag) {
2033204917Sdes		if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
2034204917Sdes			fatal("open(/dev/null): %s", strerror(errno));
2035204917Sdes		if (dup2(devnull, STDIN_FILENO) == -1)
2036204917Sdes			fatal("dup2: %s", strerror(errno));
2037204917Sdes		if (devnull > STDERR_FILENO)
2038204917Sdes			close(devnull);
2039204917Sdes	}
2040204917Sdes
2041204917Sdes	buffer_init(&m);
2042204917Sdes	buffer_put_int(&m, MUX_C_NEW_STDIO_FWD);
2043204917Sdes	buffer_put_int(&m, muxclient_request_id);
2044204917Sdes	buffer_put_cstring(&m, ""); /* reserved */
2045323129Sdes	buffer_put_cstring(&m, options.stdio_forward_host);
2046323129Sdes	buffer_put_int(&m, options.stdio_forward_port);
2047204917Sdes
2048204917Sdes	if (mux_client_write_packet(fd, &m) != 0)
2049204917Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
2050204917Sdes
2051204917Sdes	/* Send the stdio file descriptors */
2052204917Sdes	if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
2053204917Sdes	    mm_send_fd(fd, STDOUT_FILENO) == -1)
2054204917Sdes		fatal("%s: send fds failed", __func__);
2055204917Sdes
2056296633Sdes	if (pledge("stdio proc tty", NULL) == -1)
2057296633Sdes		fatal("%s pledge(): %s", __func__, strerror(errno));
2058296633Sdes	platform_pledge_mux();
2059296633Sdes
2060204917Sdes	debug3("%s: stdio forward request sent", __func__);
2061204917Sdes
2062204917Sdes	/* Read their reply */
2063204917Sdes	buffer_clear(&m);
2064204917Sdes
2065204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
2066204917Sdes		error("%s: read from master failed: %s",
2067204917Sdes		    __func__, strerror(errno));
2068204917Sdes		buffer_free(&m);
2069204917Sdes		return -1;
2070204917Sdes	}
2071204917Sdes
2072204917Sdes	type = buffer_get_int(&m);
2073204917Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
2074204917Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
2075204917Sdes		    __func__, muxclient_request_id, rid);
2076204917Sdes	switch (type) {
2077204917Sdes	case MUX_S_SESSION_OPENED:
2078204917Sdes		sid = buffer_get_int(&m);
2079204917Sdes		debug("%s: master session id: %u", __func__, sid);
2080204917Sdes		break;
2081204917Sdes	case MUX_S_PERMISSION_DENIED:
2082204917Sdes		e = buffer_get_string(&m, NULL);
2083204917Sdes		buffer_free(&m);
2084221420Sdes		fatal("Master refused stdio forwarding request: %s", e);
2085204917Sdes	case MUX_S_FAILURE:
2086204917Sdes		e = buffer_get_string(&m, NULL);
2087204917Sdes		buffer_free(&m);
2088294328Sdes		fatal("Stdio forwarding request failed: %s", e);
2089204917Sdes	default:
2090204917Sdes		buffer_free(&m);
2091204917Sdes		error("%s: unexpected response from master 0x%08x",
2092204917Sdes		    __func__, type);
2093204917Sdes		return -1;
2094204917Sdes	}
2095204917Sdes	muxclient_request_id++;
2096204917Sdes
2097204917Sdes	signal(SIGHUP, control_client_sighandler);
2098204917Sdes	signal(SIGINT, control_client_sighandler);
2099204917Sdes	signal(SIGTERM, control_client_sighandler);
2100204917Sdes	signal(SIGWINCH, control_client_sigrelay);
2101204917Sdes
2102204917Sdes	/*
2103204917Sdes	 * Stick around until the controlee closes the client_fd.
2104204917Sdes	 */
2105204917Sdes	buffer_clear(&m);
2106204917Sdes	if (mux_client_read_packet(fd, &m) != 0) {
2107204917Sdes		if (errno == EPIPE ||
2108204917Sdes		    (errno == EINTR && muxclient_terminate != 0))
2109204917Sdes			return 0;
2110204917Sdes		fatal("%s: mux_client_read_packet: %s",
2111204917Sdes		    __func__, strerror(errno));
2112204917Sdes	}
2113204917Sdes	fatal("%s: master returned unexpected message %u", __func__, type);
2114180750Sdes}
2115180750Sdes
2116226046Sdesstatic void
2117226046Sdesmux_client_request_stop_listening(int fd)
2118226046Sdes{
2119226046Sdes	Buffer m;
2120226046Sdes	char *e;
2121226046Sdes	u_int type, rid;
2122226046Sdes
2123226046Sdes	debug3("%s: entering", __func__);
2124226046Sdes
2125226046Sdes	buffer_init(&m);
2126226046Sdes	buffer_put_int(&m, MUX_C_STOP_LISTENING);
2127226046Sdes	buffer_put_int(&m, muxclient_request_id);
2128226046Sdes
2129226046Sdes	if (mux_client_write_packet(fd, &m) != 0)
2130226046Sdes		fatal("%s: write packet: %s", __func__, strerror(errno));
2131226046Sdes
2132226046Sdes	buffer_clear(&m);
2133226046Sdes
2134226046Sdes	/* Read their reply */
2135226046Sdes	if (mux_client_read_packet(fd, &m) != 0)
2136226046Sdes		fatal("%s: read from master failed: %s",
2137226046Sdes		    __func__, strerror(errno));
2138226046Sdes
2139226046Sdes	type = buffer_get_int(&m);
2140226046Sdes	if ((rid = buffer_get_int(&m)) != muxclient_request_id)
2141226046Sdes		fatal("%s: out of sequence reply: my id %u theirs %u",
2142226046Sdes		    __func__, muxclient_request_id, rid);
2143226046Sdes	switch (type) {
2144226046Sdes	case MUX_S_OK:
2145226046Sdes		break;
2146226046Sdes	case MUX_S_PERMISSION_DENIED:
2147226046Sdes		e = buffer_get_string(&m, NULL);
2148226046Sdes		fatal("Master refused stop listening request: %s", e);
2149226046Sdes	case MUX_S_FAILURE:
2150226046Sdes		e = buffer_get_string(&m, NULL);
2151226046Sdes		fatal("%s: stop listening request failed: %s", __func__, e);
2152226046Sdes	default:
2153226046Sdes		fatal("%s: unexpected response from master 0x%08x",
2154226046Sdes		    __func__, type);
2155226046Sdes	}
2156226046Sdes	buffer_free(&m);
2157226046Sdes	muxclient_request_id++;
2158226046Sdes}
2159226046Sdes
2160180750Sdes/* Multiplex client main loop. */
2161323134Sdesint
2162180750Sdesmuxclient(const char *path)
2163180750Sdes{
2164180750Sdes	struct sockaddr_un addr;
2165204917Sdes	int sock;
2166204917Sdes	u_int pid;
2167180750Sdes
2168204917Sdes	if (muxclient_command == 0) {
2169323129Sdes		if (options.stdio_forward_host != NULL)
2170204917Sdes			muxclient_command = SSHMUX_COMMAND_STDIO_FWD;
2171204917Sdes		else
2172204917Sdes			muxclient_command = SSHMUX_COMMAND_OPEN;
2173204917Sdes	}
2174180750Sdes
2175180750Sdes	switch (options.control_master) {
2176180750Sdes	case SSHCTL_MASTER_AUTO:
2177180750Sdes	case SSHCTL_MASTER_AUTO_ASK:
2178180750Sdes		debug("auto-mux: Trying existing master");
2179180750Sdes		/* FALLTHROUGH */
2180180750Sdes	case SSHCTL_MASTER_NO:
2181180750Sdes		break;
2182180750Sdes	default:
2183323134Sdes		return -1;
2184180750Sdes	}
2185180750Sdes
2186180750Sdes	memset(&addr, '\0', sizeof(addr));
2187180750Sdes	addr.sun_family = AF_UNIX;
2188180750Sdes
2189180750Sdes	if (strlcpy(addr.sun_path, path,
2190180750Sdes	    sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
2191323134Sdes		fatal("ControlPath too long ('%s' >= %u bytes)", path,
2192323134Sdes		     (unsigned int)sizeof(addr.sun_path));
2193180750Sdes
2194180750Sdes	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
2195180750Sdes		fatal("%s socket(): %s", __func__, strerror(errno));
2196180750Sdes
2197323136Sdes	if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
2198204917Sdes		switch (muxclient_command) {
2199204917Sdes		case SSHMUX_COMMAND_OPEN:
2200204917Sdes		case SSHMUX_COMMAND_STDIO_FWD:
2201204917Sdes			break;
2202204917Sdes		default:
2203180750Sdes			fatal("Control socket connect(%.100s): %s", path,
2204180750Sdes			    strerror(errno));
2205180750Sdes		}
2206221420Sdes		if (errno == ECONNREFUSED &&
2207221420Sdes		    options.control_master != SSHCTL_MASTER_NO) {
2208221420Sdes			debug("Stale control socket %.100s, unlinking", path);
2209221420Sdes			unlink(path);
2210221420Sdes		} else if (errno == ENOENT) {
2211180750Sdes			debug("Control socket \"%.100s\" does not exist", path);
2212221420Sdes		} else {
2213180750Sdes			error("Control socket connect(%.100s): %s", path,
2214180750Sdes			    strerror(errno));
2215180750Sdes		}
2216180750Sdes		close(sock);
2217323134Sdes		return -1;
2218180750Sdes	}
2219204917Sdes	set_nonblock(sock);
2220180750Sdes
2221204917Sdes	if (mux_client_hello_exchange(sock) != 0) {
2222204917Sdes		error("%s: master hello exchange failed", __func__);
2223180750Sdes		close(sock);
2224323134Sdes		return -1;
2225180750Sdes	}
2226180750Sdes
2227180750Sdes	switch (muxclient_command) {
2228180750Sdes	case SSHMUX_COMMAND_ALIVE_CHECK:
2229204917Sdes		if ((pid = mux_client_request_alive(sock)) == 0)
2230204917Sdes			fatal("%s: master alive check failed", __func__);
2231296633Sdes		fprintf(stderr, "Master running (pid=%u)\r\n", pid);
2232180750Sdes		exit(0);
2233180750Sdes	case SSHMUX_COMMAND_TERMINATE:
2234204917Sdes		mux_client_request_terminate(sock);
2235323134Sdes		if (options.log_level != SYSLOG_LEVEL_QUIET)
2236323134Sdes			fprintf(stderr, "Exit request sent.\r\n");
2237180750Sdes		exit(0);
2238215116Sdes	case SSHMUX_COMMAND_FORWARD:
2239240075Sdes		if (mux_client_forwards(sock, 0) != 0)
2240215116Sdes			fatal("%s: master forward request failed", __func__);
2241215116Sdes		exit(0);
2242180750Sdes	case SSHMUX_COMMAND_OPEN:
2243240075Sdes		if (mux_client_forwards(sock, 0) != 0) {
2244204917Sdes			error("%s: master forward request failed", __func__);
2245323134Sdes			return -1;
2246180750Sdes		}
2247204917Sdes		mux_client_request_session(sock);
2248323134Sdes		return -1;
2249204917Sdes	case SSHMUX_COMMAND_STDIO_FWD:
2250204917Sdes		mux_client_request_stdio_fwd(sock);
2251204917Sdes		exit(0);
2252226046Sdes	case SSHMUX_COMMAND_STOP:
2253226046Sdes		mux_client_request_stop_listening(sock);
2254323134Sdes		if (options.log_level != SYSLOG_LEVEL_QUIET)
2255323134Sdes			fprintf(stderr, "Stop listening request sent.\r\n");
2256226046Sdes		exit(0);
2257240075Sdes	case SSHMUX_COMMAND_CANCEL_FWD:
2258240075Sdes		if (mux_client_forwards(sock, 1) != 0)
2259240075Sdes			error("%s: master cancel forward request failed",
2260240075Sdes			    __func__);
2261240075Sdes		exit(0);
2262323134Sdes	case SSHMUX_COMMAND_PROXY:
2263323134Sdes		mux_client_proxy(sock);
2264323134Sdes		return (sock);
2265180750Sdes	default:
2266180750Sdes		fatal("unrecognised muxclient_command %d", muxclient_command);
2267180750Sdes	}
2268180750Sdes}
2269