X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/aacab402991cf3ce8991ada093d5f3058f4170af..51529944e9ab39541ed61a8267e7a4e003b1e271:/mux.c?ds=sidebyside diff --git a/mux.c b/mux.c index f5e68f65..239edd5f 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.3 2008/06/12 05:32:30 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.9 2010/01/09 05:04:24 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -82,10 +82,11 @@ /* from ssh.c */ extern int tty_flag; +extern int force_tty_flag; extern Options options; extern int stdin_null_flag; extern char *host; -int subsystem_flag; +extern int subsystem_flag; extern Buffer command; /* Context for session open confirmation callback */ @@ -144,10 +145,16 @@ muxserver_listen(void) old_umask = umask(0177); if (bind(muxserver_sock, (struct sockaddr *)&addr, addr_len) == -1) { muxserver_sock = -1; - if (errno == EINVAL || errno == EADDRINUSE) - fatal("ControlSocket %s already exists", - options.control_path); - else + if (errno == EINVAL || errno == EADDRINUSE) { + error("ControlSocket %s already exists, " + "disabling multiplexing", options.control_path); + close(muxserver_sock); + muxserver_sock = -1; + xfree(options.control_path); + options.control_path = NULL; + options.control_master = SSHCTL_MASTER_NO; + return; + } else fatal("%s bind(): %s", __func__, strerror(errno)); } umask(old_umask); @@ -436,6 +443,7 @@ muxserver_accept_control(void) if (cctx->want_tty && escape_char != 0xffffffff) { channel_register_filter(c->self, client_simple_escape_filter, NULL, + client_filter_cleanup, client_new_escape_filter_ctx((int)escape_char)); } @@ -499,7 +507,7 @@ muxclient(const char *path) Buffer m; char *term; extern char **environ; - u_int flags; + u_int allowed, flags; if (muxclient_command == 0) muxclient_command = SSHMUX_COMMAND_OPEN; @@ -570,17 +578,38 @@ muxclient(const char *path) /* Send our command to server */ buffer_put_int(&m, muxclient_command); buffer_put_int(&m, flags); - if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) - fatal("%s: msg_send", __func__); + if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) { + error("%s: msg_send", __func__); + muxerr: + close(sock); + buffer_free(&m); + if (muxclient_command != SSHMUX_COMMAND_OPEN) + cleanup_exit(255); + logit("Falling back to non-multiplexed connection"); + xfree(options.control_path); + options.control_path = NULL; + options.control_master = SSHCTL_MASTER_NO; + return; + } buffer_clear(&m); /* Get authorisation status and PID of controlee */ - if (ssh_msg_recv(sock, &m) == -1) - fatal("%s: msg_recv", __func__); - if (buffer_get_char(&m) != SSHMUX_VER) - fatal("%s: wrong version", __func__); - if (buffer_get_int(&m) != 1) - fatal("Connection to master denied"); + if (ssh_msg_recv(sock, &m) == -1) { + error("%s: Did not receive reply from master", __func__); + goto muxerr; + } + if (buffer_get_char(&m) != SSHMUX_VER) { + error("%s: Master replied with wrong version", __func__); + goto muxerr; + } + if (buffer_get_int_ret(&allowed, &m) != 0) { + error("%s: bad server reply", __func__); + goto muxerr; + } + if (allowed != 1) { + error("Connection to master denied"); + goto muxerr; + } muxserver_pid = buffer_get_int(&m); buffer_clear(&m); @@ -624,13 +653,22 @@ muxclient(const char *path) fatal("unrecognised muxclient_command %d", muxclient_command); } - if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) - fatal("%s: msg_send", __func__); + if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) { + error("%s: msg_send", __func__); + goto muxerr; + } if (mm_send_fd(sock, STDIN_FILENO) == -1 || mm_send_fd(sock, STDOUT_FILENO) == -1 || - mm_send_fd(sock, STDERR_FILENO) == -1) - fatal("%s: send fds failed", __func__); + mm_send_fd(sock, STDERR_FILENO) == -1) { + error("%s: send fds failed", __func__); + goto muxerr; + } + + /* + * Mux errors are non-recoverable from this point as the master + * has ownership of the session now. + */ /* Wait for reply, so master has a chance to gather ttymodes */ buffer_clear(&m); @@ -646,7 +684,7 @@ muxclient(const char *path) signal(SIGWINCH, control_client_sigrelay); if (tty_flag) - enter_raw_mode(); + enter_raw_mode(force_tty_flag); /* * Stick around until the controlee closes the client_fd. @@ -671,10 +709,10 @@ muxclient(const char *path) } close(sock); - leave_raw_mode(); + leave_raw_mode(force_tty_flag); if (i > (int)sizeof(int)) fatal("%s: master returned too much data (%d > %lu)", - __func__, i, sizeof(int)); + __func__, i, (u_long)sizeof(int)); if (muxclient_terminate) { debug2("Exiting on signal %d", muxclient_terminate); exitval[0] = 255;