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