From b1cbfa25f1618b277de670b943acb07ff5dbb1ac Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 19 May 2008 16:00:08 +1000 Subject: - djm@cvs.openbsd.org 2008/05/09 14:18:44 [clientloop.c clientloop.h ssh.c mux.c] tidy up session multiplexing code, moving it into its own file and making the function names more consistent - making ssh.c and clientloop.c a fair bit more readable. ok markus@ --- mux.c | 646 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 mux.c (limited to 'mux.c') diff --git a/mux.c b/mux.c new file mode 100644 index 000000000..78ba63153 --- /dev/null +++ b/mux.c @@ -0,0 +1,646 @@ +/* $OpenBSD: mux.c,v 1.1 2008/05/09 14:18:44 djm Exp $ */ +/* + * Copyright (c) 2002-2008 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* ssh session multiplexing support */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "openbsd-compat/sys-queue.h" +#include "xmalloc.h" +#include "log.h" +#include "ssh.h" +#include "pathnames.h" +#include "misc.h" +#include "match.h" +#include "buffer.h" +#include "channels.h" +#include "msg.h" +#include "packet.h" +#include "monitor_fdpass.h" +#include "sshpty.h" +#include "key.h" +#include "readconf.h" +#include "clientloop.h" + +/* from ssh.c */ +extern int tty_flag; +extern Options options; +extern int stdin_null_flag; +extern char *host; +int subsystem_flag; +extern Buffer command; + +/* fd to control socket */ +int muxserver_sock = -1; + +/* Multiplexing control command */ +u_int muxclient_command = 0; + +/* Set when signalled. */ +static volatile sig_atomic_t muxclient_terminate = 0; + +/* PID of multiplex server */ +static u_int muxserver_pid = 0; + + +/* ** Multiplexing master support */ + +/* Prepare a mux master to listen on a Unix domain socket. */ +void +muxserver_listen(void) +{ + struct sockaddr_un addr; + mode_t old_umask; + int addr_len; + + if (options.control_path == NULL || + options.control_master == SSHCTL_MASTER_NO) + return; + + debug("setting up multiplex master socket"); + + memset(&addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + addr_len = offsetof(struct sockaddr_un, sun_path) + + strlen(options.control_path) + 1; + + if (strlcpy(addr.sun_path, options.control_path, + sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) + fatal("ControlPath too long"); + + if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + fatal("%s socket(): %s", __func__, strerror(errno)); + + 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 + fatal("%s bind(): %s", __func__, strerror(errno)); + } + umask(old_umask); + + if (listen(muxserver_sock, 64) == -1) + fatal("%s listen(): %s", __func__, strerror(errno)); + + set_nonblock(muxserver_sock); +} + +/* Callback on open confirmation in mux master for a mux client session. */ +static void +client_extra_session2_setup(int id, void *arg) +{ + struct mux_session_confirm_ctx *cctx = arg; + const char *display; + Channel *c; + int i; + + if (cctx == NULL) + fatal("%s: cctx == NULL", __func__); + if ((c = channel_lookup(id)) == NULL) + fatal("%s: no channel for id %d", __func__, id); + + display = getenv("DISPLAY"); + if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { + char *proto, *data; + /* Get reasonable local authentication information. */ + client_x11_get_proto(display, options.xauth_location, + options.forward_x11_trusted, &proto, &data); + /* Request forwarding with authentication spoofing. */ + debug("Requesting X11 forwarding with authentication spoofing."); + x11_request_forwarding_with_spoofing(id, display, proto, data); + /* XXX wait for reply */ + } + + if (cctx->want_agent_fwd && options.forward_agent) { + debug("Requesting authentication agent forwarding."); + channel_request_start(id, "auth-agent-req@openssh.com", 0); + packet_send(); + } + + client_session2_setup(id, cctx->want_tty, cctx->want_subsys, + cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); + + c->open_confirm_ctx = NULL; + buffer_free(&cctx->cmd); + xfree(cctx->term); + if (cctx->env != NULL) { + for (i = 0; cctx->env[i] != NULL; i++) + xfree(cctx->env[i]); + xfree(cctx->env); + } + xfree(cctx); +} + +/* + * Accept a connection on the mux master socket and process the + * client's request. Returns flag indicating whether mux master should + * begin graceful close. + */ +int +muxserver_accept_control(void) +{ + Buffer m; + Channel *c; + int client_fd, new_fd[3], ver, allowed, window, packetmax; + socklen_t addrlen; + struct sockaddr_storage addr; + struct mux_session_confirm_ctx *cctx; + char *cmd; + u_int i, j, len, env_len, mux_command, flags; + uid_t euid; + gid_t egid; + int start_close = 0; + + /* + * Accept connection on control socket + */ + memset(&addr, 0, sizeof(addr)); + addrlen = sizeof(addr); + if ((client_fd = accept(muxserver_sock, + (struct sockaddr*)&addr, &addrlen)) == -1) { + error("%s accept: %s", __func__, strerror(errno)); + return 0; + } + + if (getpeereid(client_fd, &euid, &egid) < 0) { + error("%s getpeereid failed: %s", __func__, strerror(errno)); + close(client_fd); + return 0; + } + if ((euid != 0) && (getuid() != euid)) { + error("control mode uid mismatch: peer euid %u != uid %u", + (u_int) euid, (u_int) getuid()); + close(client_fd); + return 0; + } + + /* XXX handle asynchronously */ + unset_nonblock(client_fd); + + /* Read command */ + buffer_init(&m); + if (ssh_msg_recv(client_fd, &m) == -1) { + error("%s: client msg_recv failed", __func__); + close(client_fd); + buffer_free(&m); + return 0; + } + if ((ver = buffer_get_char(&m)) != SSHMUX_VER) { + error("%s: wrong client version %d", __func__, ver); + buffer_free(&m); + close(client_fd); + return 0; + } + + allowed = 1; + mux_command = buffer_get_int(&m); + flags = buffer_get_int(&m); + + buffer_clear(&m); + + switch (mux_command) { + case SSHMUX_COMMAND_OPEN: + if (options.control_master == SSHCTL_MASTER_ASK || + options.control_master == SSHCTL_MASTER_AUTO_ASK) + allowed = ask_permission("Allow shared connection " + "to %s? ", host); + /* continue below */ + break; + case SSHMUX_COMMAND_TERMINATE: + if (options.control_master == SSHCTL_MASTER_ASK || + options.control_master == SSHCTL_MASTER_AUTO_ASK) + allowed = ask_permission("Terminate shared connection " + "to %s? ", host); + if (allowed) + start_close = 1; + /* FALLTHROUGH */ + case SSHMUX_COMMAND_ALIVE_CHECK: + /* Reply for SSHMUX_COMMAND_TERMINATE and ALIVE_CHECK */ + buffer_clear(&m); + buffer_put_int(&m, allowed); + buffer_put_int(&m, getpid()); + if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) { + error("%s: client msg_send failed", __func__); + close(client_fd); + buffer_free(&m); + return start_close; + } + buffer_free(&m); + close(client_fd); + return start_close; + default: + error("Unsupported command %d", mux_command); + buffer_free(&m); + close(client_fd); + return 0; + } + + /* Reply for SSHMUX_COMMAND_OPEN */ + buffer_clear(&m); + buffer_put_int(&m, allowed); + buffer_put_int(&m, getpid()); + if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) { + error("%s: client msg_send failed", __func__); + close(client_fd); + buffer_free(&m); + return 0; + } + + if (!allowed) { + error("Refused control connection"); + close(client_fd); + buffer_free(&m); + return 0; + } + + buffer_clear(&m); + if (ssh_msg_recv(client_fd, &m) == -1) { + error("%s: client msg_recv failed", __func__); + close(client_fd); + buffer_free(&m); + return 0; + } + if ((ver = buffer_get_char(&m)) != SSHMUX_VER) { + error("%s: wrong client version %d", __func__, ver); + buffer_free(&m); + close(client_fd); + return 0; + } + + cctx = xcalloc(1, sizeof(*cctx)); + cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0; + cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0; + cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; + cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0; + cctx->term = buffer_get_string(&m, &len); + + cmd = buffer_get_string(&m, &len); + buffer_init(&cctx->cmd); + buffer_append(&cctx->cmd, cmd, strlen(cmd)); + + env_len = buffer_get_int(&m); + env_len = MIN(env_len, 4096); + debug3("%s: receiving %d env vars", __func__, env_len); + if (env_len != 0) { + cctx->env = xcalloc(env_len + 1, sizeof(*cctx->env)); + for (i = 0; i < env_len; i++) + cctx->env[i] = buffer_get_string(&m, &len); + cctx->env[i] = NULL; + } + + debug2("%s: accepted tty %d, subsys %d, cmd %s", __func__, + cctx->want_tty, cctx->want_subsys, cmd); + xfree(cmd); + + /* Gather fds from client */ + for(i = 0; i < 3; i++) { + if ((new_fd[i] = mm_receive_fd(client_fd)) == -1) { + error("%s: failed to receive fd %d from slave", + __func__, i); + for (j = 0; j < i; j++) + close(new_fd[j]); + for (j = 0; j < env_len; j++) + xfree(cctx->env[j]); + if (env_len > 0) + xfree(cctx->env); + xfree(cctx->term); + buffer_free(&cctx->cmd); + close(client_fd); + xfree(cctx); + return 0; + } + } + + debug2("%s: got fds stdin %d, stdout %d, stderr %d", __func__, + new_fd[0], new_fd[1], new_fd[2]); + + /* Try to pick up ttymodes from client before it goes raw */ + if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) + error("%s: tcgetattr: %s", __func__, strerror(errno)); + + /* This roundtrip is just for synchronisation of ttymodes */ + buffer_clear(&m); + if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) { + error("%s: client msg_send failed", __func__); + close(client_fd); + close(new_fd[0]); + close(new_fd[1]); + close(new_fd[2]); + buffer_free(&m); + xfree(cctx->term); + if (env_len != 0) { + for (i = 0; i < env_len; i++) + xfree(cctx->env[i]); + xfree(cctx->env); + } + return 0; + } + buffer_free(&m); + + /* enable nonblocking unless tty */ + if (!isatty(new_fd[0])) + set_nonblock(new_fd[0]); + if (!isatty(new_fd[1])) + set_nonblock(new_fd[1]); + if (!isatty(new_fd[2])) + set_nonblock(new_fd[2]); + + set_nonblock(client_fd); + + window = CHAN_SES_WINDOW_DEFAULT; + packetmax = CHAN_SES_PACKET_DEFAULT; + if (cctx->want_tty) { + window >>= 1; + packetmax >>= 1; + } + + c = channel_new("session", SSH_CHANNEL_OPENING, + new_fd[0], new_fd[1], new_fd[2], window, packetmax, + CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); + + /* XXX */ + c->ctl_fd = client_fd; + + debug3("%s: channel_new: %d", __func__, c->self); + + channel_send_open(c->self); + channel_register_open_confirm(c->self, + client_extra_session2_setup, cctx); + return 0; +} + +/* ** Multiplexing client support */ + +/* Exit signal handler */ +static void +control_client_sighandler(int signo) +{ + muxclient_terminate = signo; +} + +/* + * Relay signal handler - used to pass some signals from mux client to + * mux master. + */ +static void +control_client_sigrelay(int signo) +{ + int save_errno = errno; + + if (muxserver_pid > 1) + kill(muxserver_pid, signo); + + errno = save_errno; +} + +/* Check mux client environment variables before passing them to mux master. */ +static int +env_permitted(char *env) +{ + int i, ret; + char name[1024], *cp; + + if ((cp = strchr(env, '=')) == NULL || cp == env) + return (0); + ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env); + if (ret <= 0 || (size_t)ret >= sizeof(name)) + fatal("env_permitted: name '%.100s...' too long", env); + + for (i = 0; i < options.num_send_env; i++) + if (match_pattern(name, options.send_env[i])) + return (1); + + return (0); +} + +/* Multiplex client main loop. */ +void +muxclient(const char *path) +{ + struct sockaddr_un addr; + int i, r, fd, sock, exitval[2], num_env, addr_len; + Buffer m; + char *term; + extern char **environ; + u_int flags; + + if (muxclient_command == 0) + muxclient_command = SSHMUX_COMMAND_OPEN; + + switch (options.control_master) { + case SSHCTL_MASTER_AUTO: + case SSHCTL_MASTER_AUTO_ASK: + debug("auto-mux: Trying existing master"); + /* FALLTHROUGH */ + case SSHCTL_MASTER_NO: + break; + default: + return; + } + + memset(&addr, '\0', sizeof(addr)); + addr.sun_family = AF_UNIX; + addr_len = offsetof(struct sockaddr_un, sun_path) + + strlen(path) + 1; + + if (strlcpy(addr.sun_path, path, + sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) + fatal("ControlPath too long"); + + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + fatal("%s socket(): %s", __func__, strerror(errno)); + + if (connect(sock, (struct sockaddr *)&addr, addr_len) == -1) { + if (muxclient_command != SSHMUX_COMMAND_OPEN) { + fatal("Control socket connect(%.100s): %s", path, + strerror(errno)); + } + if (errno == ENOENT) + debug("Control socket \"%.100s\" does not exist", path); + else { + error("Control socket connect(%.100s): %s", path, + strerror(errno)); + } + close(sock); + return; + } + + if (stdin_null_flag) { + if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1) + fatal("open(/dev/null): %s", strerror(errno)); + if (dup2(fd, STDIN_FILENO) == -1) + fatal("dup2: %s", strerror(errno)); + if (fd > STDERR_FILENO) + close(fd); + } + + term = getenv("TERM"); + + flags = 0; + if (tty_flag) + flags |= SSHMUX_FLAG_TTY; + if (subsystem_flag) + flags |= SSHMUX_FLAG_SUBSYS; + if (options.forward_x11) + flags |= SSHMUX_FLAG_X11_FWD; + if (options.forward_agent) + flags |= SSHMUX_FLAG_AGENT_FWD; + + signal(SIGPIPE, SIG_IGN); + + buffer_init(&m); + + /* 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__); + 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"); + muxserver_pid = buffer_get_int(&m); + + buffer_clear(&m); + + switch (muxclient_command) { + case SSHMUX_COMMAND_ALIVE_CHECK: + fprintf(stderr, "Master running (pid=%d)\r\n", + muxserver_pid); + exit(0); + case SSHMUX_COMMAND_TERMINATE: + fprintf(stderr, "Exit request sent.\r\n"); + exit(0); + case SSHMUX_COMMAND_OPEN: + /* continue below */ + break; + default: + fatal("silly muxclient_command %d", muxclient_command); + } + + /* SSHMUX_COMMAND_OPEN */ + buffer_put_cstring(&m, term ? term : ""); + buffer_append(&command, "\0", 1); + buffer_put_cstring(&m, buffer_ptr(&command)); + + if (options.num_send_env == 0 || environ == NULL) { + buffer_put_int(&m, 0); + } else { + /* Pass environment */ + num_env = 0; + for (i = 0; environ[i] != NULL; i++) + if (env_permitted(environ[i])) + num_env++; /* Count */ + + buffer_put_int(&m, num_env); + + for (i = 0; environ[i] != NULL && num_env >= 0; i++) + if (env_permitted(environ[i])) { + num_env--; + buffer_put_cstring(&m, environ[i]); + } + } + + if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) + fatal("%s: msg_send", __func__); + + 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__); + + /* Wait for reply, so master has a chance to gather ttymodes */ + buffer_clear(&m); + if (ssh_msg_recv(sock, &m) == -1) + fatal("%s: msg_recv", __func__); + if (buffer_get_char(&m) != SSHMUX_VER) + fatal("%s: wrong version", __func__); + buffer_free(&m); + + signal(SIGHUP, control_client_sighandler); + signal(SIGINT, control_client_sighandler); + signal(SIGTERM, control_client_sighandler); + signal(SIGWINCH, control_client_sigrelay); + + if (tty_flag) + enter_raw_mode(); + + /* + * Stick around until the controlee closes the client_fd. + * Before it does, it is expected to write this process' exit + * value (one int). This process must read the value and wait for + * the closure of the client_fd; if this one closes early, the + * multiplex master will terminate early too (possibly losing data). + */ + exitval[0] = 0; + for (i = 0; !muxclient_terminate && i < (int)sizeof(exitval);) { + r = read(sock, (char *)exitval + i, sizeof(exitval) - i); + if (r == 0) { + debug2("Received EOF from master"); + break; + } + if (r == -1) { + if (errno == EINTR) + continue; + fatal("%s: read %s", __func__, strerror(errno)); + } + i += r; + } + + close(sock); + leave_raw_mode(); + if (i > (int)sizeof(int)) + fatal("%s: master returned too much data (%d > %lu)", + __func__, i, sizeof(int)); + if (muxclient_terminate) { + debug2("Exiting on signal %d", muxclient_terminate); + exitval[0] = 255; + } else if (i < (int)sizeof(int)) { + debug2("Control master terminated unexpectedly"); + exitval[0] = 255; + } else + debug2("Received exit status from master %d", exitval[0]); + + if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) + fprintf(stderr, "Shared connection to %s closed.\r\n", host); + + exit(exitval[0]); +} -- cgit v1.2.3 From a7058ec7c03017b89ba75fc0b9a58ca672aab9e9 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 20 May 2008 08:57:06 +1000 Subject: - (djm) [configure.ac mux.c sftp.c openbsd-compat/Makefile.in] [openbsd-compat/fmt_scaled.c openbsd-compat/openbsd-compat.h] Fix compilation on Linux, including pulling in fmt_scaled(3) implementation from OpenBSD's libutil. --- ChangeLog | 8 +- configure.ac | 6 +- mux.c | 11 +- openbsd-compat/Makefile.in | 4 +- openbsd-compat/fmt_scaled.c | 274 ++++++++++++++++++++++++++++++++++++++++ openbsd-compat/openbsd-compat.h | 7 +- sftp.c | 9 +- 7 files changed, 310 insertions(+), 9 deletions(-) create mode 100644 openbsd-compat/fmt_scaled.c (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index ef7eaf7af..713e09dbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +20080519 + - (djm) [configure.ac mux.c sftp.c openbsd-compat/Makefile.in] + [openbsd-compat/fmt_scaled.c openbsd-compat/openbsd-compat.h] + Fix compilation on Linux, including pulling in fmt_scaled(3) + implementation from OpenBSD's libutil. + 20080518 - (djm) OpenBSD CVS Sync - djm@cvs.openbsd.org 2008/04/04 05:14:38 @@ -4017,4 +4023,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4934 2008/05/19 06:11:56 djm Exp $ +$Id: ChangeLog,v 1.4935 2008/05/19 22:57:06 djm Exp $ diff --git a/configure.ac b/configure.ac index e6e916e82..858aeaf42 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac,v 1.398 2008/05/19 04:47:37 djm Exp $ +# $Id: configure.ac,v 1.399 2008/05/19 22:57:06 djm Exp $ # # Copyright (c) 1999-2004 Damien Miller # @@ -15,7 +15,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org) -AC_REVISION($Revision: 1.398 $) +AC_REVISION($Revision: 1.399 $) AC_CONFIG_SRCDIR([ssh.c]) AC_CONFIG_HEADER(config.h) @@ -1034,7 +1034,7 @@ dnl Checks for libutil functions AC_CHECK_HEADERS(libutil.h) AC_SEARCH_LIBS(login, util bsd, [AC_DEFINE(HAVE_LOGIN, 1, [Define if your libraries define login()])]) -AC_CHECK_FUNCS(logout updwtmp logwtmp) +AC_CHECK_FUNCS(fmt_scaled logout updwtmp logwtmp) AC_FUNC_STRFTIME diff --git a/mux.c b/mux.c index 78ba63153..b4465b017 100644 --- a/mux.c +++ b/mux.c @@ -17,6 +17,8 @@ /* ssh session multiplexing support */ +#include "includes.h" + #include #include #include @@ -32,9 +34,16 @@ #include #include #include -#include #include +#ifdef HAVE_UTIL_H +# include +#endif + +#ifdef HAVE_LIBUTIL_H +# include +#endif + #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "log.h" diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index b44a7851e..d1ec47b6e 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.41 2007/06/25 12:15:13 dtucker Exp $ +# $Id: Makefile.in,v 1.42 2008/05/19 22:57:08 djm Exp $ sysconfdir=@sysconfdir@ piddir=@piddir@ @@ -16,7 +16,7 @@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ -OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o +OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o diff --git a/openbsd-compat/fmt_scaled.c b/openbsd-compat/fmt_scaled.c new file mode 100644 index 000000000..edd682a49 --- /dev/null +++ b/openbsd-compat/fmt_scaled.c @@ -0,0 +1,274 @@ +/* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */ + +/* + * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* OPENBSD ORIGINAL: lib/libutil/fmt_scaled.c */ + +/* + * fmt_scaled: Format numbers scaled for human comprehension + * scan_scaled: Scan numbers in this format. + * + * "Human-readable" output uses 4 digits max, and puts a unit suffix at + * the end. Makes output compact and easy-to-read esp. on huge disks. + * Formatting code was originally in OpenBSD "df", converted to library routine. + * Scanning code written for OpenBSD libutil. + */ + +#include "includes.h" + +#ifndef HAVE_FMT_SCALED + +#include +#include +#include +#include +#include +#include + +typedef enum { + NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 +} unit_type; + +/* These three arrays MUST be in sync! XXX make a struct */ +static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; +static char scale_chars[] = "BKMGTPE"; +static long long scale_factors[] = { + 1LL, + 1024LL, + 1024LL*1024, + 1024LL*1024*1024, + 1024LL*1024*1024*1024, + 1024LL*1024*1024*1024*1024, + 1024LL*1024*1024*1024*1024*1024, +}; +#define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) + +#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ + +/** Convert the given input string "scaled" into numeric in "result". + * Return 0 on success, -1 and errno set on error. + */ +int +scan_scaled(char *scaled, long long *result) +{ + char *p = scaled; + int sign = 0; + unsigned int i, ndigits = 0, fract_digits = 0; + long long scale_fact = 1, whole = 0, fpart = 0; + + /* Skip leading whitespace */ + while (isascii(*p) && isspace(*p)) + ++p; + + /* Then at most one leading + or - */ + while (*p == '-' || *p == '+') { + if (*p == '-') { + if (sign) { + errno = EINVAL; + return -1; + } + sign = -1; + ++p; + } else if (*p == '+') { + if (sign) { + errno = EINVAL; + return -1; + } + sign = +1; + ++p; + } + } + + /* Main loop: Scan digits, find decimal point, if present. + * We don't allow exponentials, so no scientific notation + * (but note that E for Exa might look like e to some!). + * Advance 'p' to end, to get scale factor. + */ + for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) { + if (*p == '.') { + if (fract_digits > 0) { /* oops, more than one '.' */ + errno = EINVAL; + return -1; + } + fract_digits = 1; + continue; + } + + i = (*p) - '0'; /* whew! finally a digit we can use */ + if (fract_digits > 0) { + if (fract_digits >= MAX_DIGITS-1) + /* ignore extra fractional digits */ + continue; + fract_digits++; /* for later scaling */ + fpart *= 10; + fpart += i; + } else { /* normal digit */ + if (++ndigits >= MAX_DIGITS) { + errno = ERANGE; + return -1; + } + whole *= 10; + whole += i; + } + } + + if (sign) { + whole *= sign; + fpart *= sign; + } + + /* If no scale factor given, we're done. fraction is discarded. */ + if (!*p) { + *result = whole; + return 0; + } + + /* Validate scale factor, and scale whole and fraction by it. */ + for (i = 0; i < SCALE_LENGTH; i++) { + + /** Are we there yet? */ + if (*p == scale_chars[i] || + *p == tolower(scale_chars[i])) { + + /* If it ends with alphanumerics after the scale char, bad. */ + if (isalnum(*(p+1))) { + errno = EINVAL; + return -1; + } + scale_fact = scale_factors[i]; + + /* scale whole part */ + whole *= scale_fact; + + /* truncate fpart so it does't overflow. + * then scale fractional part. + */ + while (fpart >= LLONG_MAX / scale_fact) { + fpart /= 10; + fract_digits--; + } + fpart *= scale_fact; + if (fract_digits > 0) { + for (i = 0; i < fract_digits -1; i++) + fpart /= 10; + } + whole += fpart; + *result = whole; + return 0; + } + } + errno = ERANGE; + return -1; +} + +/* Format the given "number" into human-readable form in "result". + * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE. + * Return 0 on success, -1 and errno set if error. + */ +int +fmt_scaled(long long number, char *result) +{ + long long abval, fract = 0; + unsigned int i; + unit_type unit = NONE; + + abval = (number < 0LL) ? -number : number; /* no long long_abs yet */ + + /* Not every negative long long has a positive representation. + * Also check for numbers that are just too darned big to format + */ + if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) { + errno = ERANGE; + return -1; + } + + /* scale whole part; get unscaled fraction */ + for (i = 0; i < SCALE_LENGTH; i++) { + if (abval/1024 < scale_factors[i]) { + unit = units[i]; + fract = (i == 0) ? 0 : abval % scale_factors[i]; + number /= scale_factors[i]; + if (i > 0) + fract /= scale_factors[i - 1]; + break; + } + } + + fract = (10 * fract + 512) / 1024; + /* if the result would be >= 10, round main number */ + if (fract == 10) { + if (number >= 0) + number++; + else + number--; + fract = 0; + } + + if (number == 0) + strlcpy(result, "0B", FMT_SCALED_STRSIZE); + else if (unit == NONE || number >= 100 || number <= -100) { + if (fract >= 5) { + if (number >= 0) + number++; + else + number--; + } + (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", + number, scale_chars[unit]); + } else + (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", + number, fract, scale_chars[unit]); + + return 0; +} + +#ifdef MAIN +/* + * This is the original version of the program in the man page. + * Copy-and-paste whatever you need from it. + */ +int +main(int argc, char **argv) +{ + char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; + long long ninput = 10483892, result; + + if (scan_scaled(cinput, &result) == 0) + printf("\"%s\" -> %lld\n", cinput, result); + else + perror(cinput); + + if (fmt_scaled(ninput, buf) == 0) + printf("%lld -> \"%s\"\n", ninput, buf); + else + fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); + + return 0; +} +#endif + +#endif /* HAVE_FMT_SCALED */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index eb48b362b..0b7d979e0 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -1,4 +1,4 @@ -/* $Id: openbsd-compat.h,v 1.44 2008/05/19 04:47:37 djm Exp $ */ +/* $Id: openbsd-compat.h,v 1.45 2008/05/19 22:57:08 djm Exp $ */ /* * Copyright (c) 1999-2003 Damien Miller. All rights reserved. @@ -101,6 +101,11 @@ int daemon(int nochdir, int noclose); char *dirname(const char *path); #endif +#ifndef HAVE_FMT_SCALED +#define FMT_SCALED_STRSIZE 7 +int fmt_scaled(long long number, char *result); +#endif + #if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA) char *inet_ntoa(struct in_addr in); #endif diff --git a/sftp.c b/sftp.c index 0745baf08..ffc35cb83 100644 --- a/sftp.c +++ b/sftp.c @@ -43,9 +43,16 @@ typedef void EditLine; #include #include #include -#include #include +#ifdef HAVE_UTIL_H +# include +#endif + +#ifdef HAVE_LIBUTIL_H +# include +#endif + #include "xmalloc.h" #include "log.h" #include "pathnames.h" -- cgit v1.2.3 From ce38d8234d6969e4c222a0110e80357c2a61162c Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sat, 7 Jun 2008 06:25:15 +1000 Subject: - (dtucker) [mux.c] Include paths.h inside ifdef HAVE_PATHS_H. --- ChangeLog | 5 ++++- mux.c | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 727767210..c3c849c22 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +20080607 + - (dtucker) [mux.c] Include paths.h inside ifdef HAVE_PATHS_H. + 20080604 - (djm) [openbsd-compat/bsd-arc4random.c] Fix math bug that caused bias in arc4random_uniform with upper_bound in (2^30,2*31). Note that @@ -4028,4 +4031,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4936 2008/06/04 00:54:00 djm Exp $ +$Id: ChangeLog,v 1.4937 2008/06/06 20:25:15 dtucker Exp $ diff --git a/mux.c b/mux.c index b4465b017..8b9105b04 100644 --- a/mux.c +++ b/mux.c @@ -34,7 +34,9 @@ #include #include #include +#ifdef HAVE_PATHS_H #include +#endif #ifdef HAVE_UTIL_H # include -- cgit v1.2.3 From 2fb66caca2c9e69c6a0584060114fcd52e59d5ff Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 13 Jun 2008 04:49:33 +1000 Subject: - djm@cvs.openbsd.org 2008/06/12 03:40:52 [clientloop.h mux.c channels.c clientloop.c channels.h] Enable ~ escapes for multiplex slave sessions; give each channel its own escape state and hook the escape filters up to muxed channels. bz #1331 Mux slaves do not currently support the ~^Z and ~& escapes. NB. this change cranks the mux protocol version, so a new ssh mux client will not be able to connect to a running old ssh mux master. ok dtucker@ --- ChangeLog | 12 ++++- channels.c | 5 +- channels.h | 5 +- clientloop.c | 154 +++++++++++++++++++++++++++++++++++++++++++++-------------- clientloop.h | 22 +++------ mux.c | 93 ++++++++++++++++++++++++------------ 6 files changed, 202 insertions(+), 89 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 27a2a7abc..ca0d8ea57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -68,6 +68,16 @@ [key.c] use an odd number of rows and columns and a separate start marker, looks better; ok grunk@ + - djm@cvs.openbsd.org 2008/06/12 03:40:52 + [clientloop.h mux.c channels.c clientloop.c channels.h] + Enable ~ escapes for multiplex slave sessions; give each channel + its own escape state and hook the escape filters up to muxed + channels. bz #1331 + Mux slaves do not currently support the ~^Z and ~& escapes. + NB. this change cranks the mux protocol version, so a new ssh + mux client will not be able to connect to a running old ssh + mux master. + ok dtucker@ 20080611 - (djm) [channels.c configure.ac] @@ -4230,4 +4240,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4976 2008/06/12 18:48:11 dtucker Exp $ +$Id: ChangeLog,v 1.4977 2008/06/12 18:49:33 dtucker Exp $ diff --git a/channels.c b/channels.c index 233c2247b..c539990f6 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.278 2008/06/10 04:50:25 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.279 2008/06/12 03:40:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -731,7 +731,7 @@ channel_cancel_cleanup(int id) void channel_register_filter(int id, channel_infilter_fn *ifn, - channel_outfilter_fn *ofn) + channel_outfilter_fn *ofn, void *ctx) { Channel *c = channel_lookup(id); @@ -741,6 +741,7 @@ channel_register_filter(int id, channel_infilter_fn *ifn, } c->input_filter = ifn; c->output_filter = ofn; + c->filter_ctx = ctx; } void diff --git a/channels.h b/channels.h index dc1f483ed..450321d43 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.93 2008/06/10 04:50:25 dtucker Exp $ */ +/* $OpenBSD: channels.h,v 1.94 2008/06/12 03:40:52 djm Exp $ */ /* * Author: Tatu Ylonen @@ -131,6 +131,7 @@ struct Channel { /* filter */ channel_infilter_fn *input_filter; channel_outfilter_fn *output_filter; + void *filter_ctx; /* keep boundaries */ int datagram; @@ -195,7 +196,7 @@ void channel_request_start(int, char *, int); void channel_register_cleanup(int, channel_callback_fn *, int); void channel_register_open_confirm(int, channel_callback_fn *, void *); void channel_register_filter(int, channel_infilter_fn *, - channel_outfilter_fn *); + channel_outfilter_fn *, void *); void channel_register_status_confirm(int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(int); diff --git a/clientloop.c b/clientloop.c index 3bc8bb8d0..b45e7298a 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.194 2008/05/19 20:53:52 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.195 2008/06/12 03:40:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -144,8 +144,8 @@ static int in_non_blocking_mode = 0; /* Common data for the client loop code. */ static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ -static int escape_char; /* Escape character. */ -static int escape_pending; /* Last character was the escape character */ +static int escape_char1; /* Escape character. (proto1 only) */ +static int escape_pending1; /* Last character was an escape (proto1 only) */ static int last_was_cr; /* Last character was a newline. */ static int exit_status; /* Used to store the exit status of the command. */ static int stdin_eof; /* EOF has been encountered on standard error. */ @@ -162,6 +162,13 @@ static int session_closed = 0; /* In SSH2: login session closed. */ static void client_init_dispatch(void); int session_ident = -1; +/* Track escape per proto2 channel */ +struct escape_filter_ctx { + int escape_pending; + int escape_char; +}; + +/* Context for channel confirmation replies */ struct channel_reply_ctx { const char *request_type; int id, do_close; @@ -385,8 +392,8 @@ client_check_initial_eof_on_stdin(void) * and also process it as an escape character if * appropriate. */ - if ((u_char) buf[0] == escape_char) - escape_pending = 1; + if ((u_char) buf[0] == escape_char1) + escape_pending1 = 1; else buffer_append(&stdin_buffer, buf, 1); } @@ -813,9 +820,12 @@ out: xfree(fwd.connect_host); } -/* process the characters one by one */ +/* + * Process the characters one by one, call with c==NULL for proto1 case. + */ static int -process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) +process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, + char *buf, int len) { char string[1024]; pid_t pid; @@ -823,7 +833,20 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) u_int i; u_char ch; char *s; + int *escape_pendingp, escape_char; + struct escape_filter_ctx *efc; + if (c == NULL) { + escape_pendingp = &escape_pending1; + escape_char = escape_char1; + } else { + if (c->filter_ctx == NULL) + return 0; + efc = (struct escape_filter_ctx *)c->filter_ctx; + escape_pendingp = &efc->escape_pending; + escape_char = efc->escape_char; + } + if (len <= 0) return (0); @@ -831,25 +854,43 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) /* Get one character at a time. */ ch = buf[i]; - if (escape_pending) { + if (*escape_pendingp) { /* We have previously seen an escape character. */ /* Clear the flag now. */ - escape_pending = 0; + *escape_pendingp = 0; /* Process the escaped character. */ switch (ch) { case '.': /* Terminate the connection. */ - snprintf(string, sizeof string, "%c.\r\n", escape_char); + snprintf(string, sizeof string, "%c.\r\n", + escape_char); buffer_append(berr, string, strlen(string)); - quit_pending = 1; + if (c && c->ctl_fd != -1) { + chan_read_failed(c); + chan_write_failed(c); + return 0; + } else + quit_pending = 1; return -1; case 'Z' - 64: + /* XXX support this for mux clients */ + if (c && c->ctl_fd != -1) { + noescape: + snprintf(string, sizeof string, + "%c%c escape not available to " + "multiplexed sessions\r\n", + escape_char, ch); + buffer_append(berr, string, + strlen(string)); + continue; + } /* Suspend the program. */ /* Print a message to that effect to the user. */ - snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); + snprintf(string, sizeof string, + "%c^Z [suspend ssh]\r\n", escape_char); buffer_append(berr, string, strlen(string)); /* Restore terminal modes and suspend. */ @@ -881,6 +922,8 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) continue; case '&': + if (c && c->ctl_fd != -1) + goto noescape; /* * Detach the program (continue to serve connections, * but put in background and no more new connections). @@ -929,27 +972,50 @@ process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) continue; case '?': - snprintf(string, sizeof string, + if (c && c->ctl_fd != -1) { + snprintf(string, sizeof string, "%c?\r\n\ Supported escape sequences:\r\n\ -%c. - terminate connection\r\n\ -%cB - send a BREAK to the remote system\r\n\ -%cC - open a command line\r\n\ -%cR - Request rekey (SSH protocol 2 only)\r\n\ -%c^Z - suspend ssh\r\n\ -%c# - list forwarded connections\r\n\ -%c& - background ssh (when waiting for connections to terminate)\r\n\ -%c? - this message\r\n\ -%c%c - send the escape character by typing it twice\r\n\ + %c. - terminate session\r\n\ + %cB - send a BREAK to the remote system\r\n\ + %cC - open a command line\r\n\ + %cR - Request rekey (SSH protocol 2 only)\r\n\ + %c# - list forwarded connections\r\n\ + %c? - this message\r\n\ + %c%c - send the escape character by typing it twice\r\n\ (Note that escapes are only recognized immediately after newline.)\r\n", - escape_char, escape_char, escape_char, escape_char, - escape_char, escape_char, escape_char, escape_char, - escape_char, escape_char, escape_char); + escape_char, escape_char, + escape_char, escape_char, + escape_char, escape_char, + escape_char, escape_char, + escape_char); + } else { + snprintf(string, sizeof string, +"%c?\r\n\ +Supported escape sequences:\r\n\ + %c. - terminate connection (and any multiplexed sessions)\r\n\ + %cB - send a BREAK to the remote system\r\n\ + %cC - open a command line\r\n\ + %cR - Request rekey (SSH protocol 2 only)\r\n\ + %c^Z - suspend ssh\r\n\ + %c# - list forwarded connections\r\n\ + %c& - background ssh (when waiting for connections to terminate)\r\n\ + %c? - this message\r\n\ + %c%c - send the escape character by typing it twice\r\n\ +(Note that escapes are only recognized immediately after newline.)\r\n", + escape_char, escape_char, + escape_char, escape_char, + escape_char, escape_char, + escape_char, escape_char, + escape_char, escape_char, + escape_char); + } buffer_append(berr, string, strlen(string)); continue; case '#': - snprintf(string, sizeof string, "%c#\r\n", escape_char); + snprintf(string, sizeof string, "%c#\r\n", + escape_char); buffer_append(berr, string, strlen(string)); s = channel_open_message(); buffer_append(berr, s, strlen(s)); @@ -975,7 +1041,7 @@ Supported escape sequences:\r\n\ */ if (last_was_cr && ch == escape_char) { /* It is. Set the flag and continue to next character. */ - escape_pending = 1; + *escape_pendingp = 1; continue; } } @@ -1026,7 +1092,7 @@ client_process_input(fd_set *readset) packet_start(SSH_CMSG_EOF); packet_send(); } - } else if (escape_char == SSH_ESCAPECHAR_NONE) { + } else if (escape_char1 == SSH_ESCAPECHAR_NONE) { /* * Normal successful read, and no escape character. * Just append the data to buffer. @@ -1037,8 +1103,8 @@ client_process_input(fd_set *readset) * Normal, successful read. But we have an escape character * and have to process the characters one by one. */ - if (process_escapes(&stdin_buffer, &stdout_buffer, - &stderr_buffer, buf, len) == -1) + if (process_escapes(NULL, &stdin_buffer, + &stdout_buffer, &stderr_buffer, buf, len) == -1) return; } } @@ -1113,13 +1179,26 @@ client_process_buffered_input_packets(void) /* scan buf[] for '~' before sending data to the peer */ -static int -simple_escape_filter(Channel *c, char *buf, int len) +/* Helper: allocate a new escape_filter_ctx and fill in its escape char */ +void * +client_new_escape_filter_ctx(int escape_char) +{ + struct escape_filter_ctx *ret; + + ret = xmalloc(sizeof(*ret)); + ret->escape_pending = 0; + ret->escape_char = escape_char; + return (void *)ret; +} + +int +client_simple_escape_filter(Channel *c, char *buf, int len) { if (c->extended_usage != CHAN_EXTENDED_WRITE) return 0; - return process_escapes(&c->input, &c->output, &c->extended, buf, len); + return process_escapes(c, &c->input, &c->output, &c->extended, + buf, len); } static void @@ -1151,7 +1230,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) start_time = get_current_time(); /* Initialize variables. */ - escape_pending = 0; + escape_pending1 = 0; last_was_cr = 1; exit_status = -1; stdin_eof = 0; @@ -1178,7 +1257,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) stdout_bytes = 0; stderr_bytes = 0; quit_pending = 0; - escape_char = escape_char_arg; + escape_char1 = escape_char_arg; /* Initialize buffers. */ buffer_init(&stdin_buffer); @@ -1206,9 +1285,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (compat20) { session_ident = ssh2_chan_id; - if (escape_char != SSH_ESCAPECHAR_NONE) + if (escape_char_arg != SSH_ESCAPECHAR_NONE) channel_register_filter(session_ident, - simple_escape_filter, NULL); + client_simple_escape_filter, NULL, + client_new_escape_filter_ctx(escape_char_arg)); if (session_ident != -1) channel_register_cleanup(session_ident, client_channel_closed, 0); diff --git a/clientloop.h b/clientloop.h index 6f8e70123..cecbfb1a8 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.19 2008/05/09 14:18:44 djm Exp $ */ +/* $OpenBSD: clientloop.h,v 1.20 2008/06/12 03:40:52 djm Exp $ */ /* * Author: Tatu Ylonen @@ -46,8 +46,12 @@ void client_session2_setup(int, int, int, const char *, struct termios *, int, Buffer *, char **); int client_request_tun_fwd(int, int, int); +/* Escape filter for protocol 2 sessions */ +void *client_new_escape_filter_ctx(int); +int client_simple_escape_filter(Channel *, char *, int); + /* Multiplexing protocol version */ -#define SSHMUX_VER 1 +#define SSHMUX_VER 2 /* Multiplexing control protocol flags */ #define SSHMUX_COMMAND_OPEN 1 /* Open new connection */ @@ -59,20 +63,6 @@ int client_request_tun_fwd(int, int, int); #define SSHMUX_FLAG_X11_FWD (1<<2) /* Request X11 forwarding */ #define SSHMUX_FLAG_AGENT_FWD (1<<3) /* Request agent forwarding */ -/* Multiplexing routines */ - -struct mux_session_confirm_ctx { - int want_tty; - int want_subsys; - int want_x_fwd; - int want_agent_fwd; - Buffer cmd; - char *term; - struct termios tio; - char **env; -}; - -/* mux.c */ void muxserver_listen(void); int muxserver_accept_control(void); void muxclient(const char *); diff --git a/mux.c b/mux.c index 8b9105b04..efc3840cb 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.1 2008/05/09 14:18:44 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.2 2008/06/12 03:40:52 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -19,6 +19,20 @@ #include "includes.h" +/* + * TODO: + * 1. partial reads in muxserver_accept_control (maybe make channels + * from accepted connections) + * 2. Better signalling from master to slave, especially passing of + * error messages + * 3. Better fall-back from mux slave error to new connection. + * 3. Add/delete forwardings via slave + * 4. ExitOnForwardingFailure (after #3 obviously) + * 5. Maybe extension mechanisms for multi-X11/multi-agent forwarding + * 6. Document the mux mini-protocol somewhere. + * 6. Support ~^Z in mux slaves. + */ + #include #include #include @@ -71,6 +85,18 @@ extern char *host; int subsystem_flag; extern Buffer command; +/* Context for session open confirmation callback */ +struct mux_session_confirm_ctx { + int want_tty; + int want_subsys; + int want_x_fwd; + int want_agent_fwd; + Buffer cmd; + char *term; + struct termios tio; + char **env; +}; + /* fd to control socket */ int muxserver_sock = -1; @@ -131,7 +157,7 @@ muxserver_listen(void) /* Callback on open confirmation in mux master for a mux client session. */ static void -client_extra_session2_setup(int id, void *arg) +mux_session_confirm(int id, void *arg) { struct mux_session_confirm_ctx *cctx = arg; const char *display; @@ -190,7 +216,7 @@ muxserver_accept_control(void) struct sockaddr_storage addr; struct mux_session_confirm_ctx *cctx; char *cmd; - u_int i, j, len, env_len, mux_command, flags; + u_int i, j, len, env_len, mux_command, flags, escape_char; uid_t euid; gid_t egid; int start_close = 0; @@ -317,6 +343,7 @@ muxserver_accept_control(void) cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0; cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0; cctx->term = buffer_get_string(&m, &len); + escape_char = buffer_get_int(&m); cmd = buffer_get_string(&m, &len); buffer_init(&cctx->cmd); @@ -402,14 +429,17 @@ muxserver_accept_control(void) new_fd[0], new_fd[1], new_fd[2], window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); - /* XXX */ c->ctl_fd = client_fd; + if (cctx->want_tty && escape_char != 0xffffffff) { + channel_register_filter(c->self, + client_simple_escape_filter, NULL, + client_new_escape_filter_ctx((int)escape_char)); + } debug3("%s: channel_new: %d", __func__, c->self); channel_send_open(c->self); - channel_register_open_confirm(c->self, - client_extra_session2_setup, cctx); + channel_register_open_confirm(c->self, mux_session_confirm, cctx); return 0; } @@ -561,33 +591,34 @@ muxclient(const char *path) fprintf(stderr, "Exit request sent.\r\n"); exit(0); case SSHMUX_COMMAND_OPEN: - /* continue below */ + buffer_put_cstring(&m, term ? term : ""); + if (options.escape_char == SSH_ESCAPECHAR_NONE) + buffer_put_int(&m, 0xffffffff); + else + buffer_put_int(&m, options.escape_char); + buffer_append(&command, "\0", 1); + buffer_put_cstring(&m, buffer_ptr(&command)); + + if (options.num_send_env == 0 || environ == NULL) { + buffer_put_int(&m, 0); + } else { + /* Pass environment */ + num_env = 0; + for (i = 0; environ[i] != NULL; i++) { + if (env_permitted(environ[i])) + num_env++; /* Count */ + } + buffer_put_int(&m, num_env); + for (i = 0; environ[i] != NULL && num_env >= 0; i++) { + if (env_permitted(environ[i])) { + num_env--; + buffer_put_cstring(&m, environ[i]); + } + } + } break; default: - fatal("silly muxclient_command %d", muxclient_command); - } - - /* SSHMUX_COMMAND_OPEN */ - buffer_put_cstring(&m, term ? term : ""); - buffer_append(&command, "\0", 1); - buffer_put_cstring(&m, buffer_ptr(&command)); - - if (options.num_send_env == 0 || environ == NULL) { - buffer_put_int(&m, 0); - } else { - /* Pass environment */ - num_env = 0; - for (i = 0; environ[i] != NULL; i++) - if (env_permitted(environ[i])) - num_env++; /* Count */ - - buffer_put_int(&m, num_env); - - for (i = 0; environ[i] != NULL && num_env >= 0; i++) - if (env_permitted(environ[i])) { - num_env--; - buffer_put_cstring(&m, environ[i]); - } + fatal("unrecognised muxclient_command %d", muxclient_command); } if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1) -- cgit v1.2.3 From ba69c7a987ea42b6e26ce512a483d6ba44e3df0c Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 13 Jun 2008 04:54:05 +1000 Subject: - djm@cvs.openbsd.org 2008/06/12 05:32:30 [mux.c] some more TODO for me --- ChangeLog | 5 ++++- mux.c | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index c2b9b37a1..b23311f6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,9 @@ - djm@cvs.openbsd.org 2008/06/12 05:15:41 [PROTOCOL] document tun@openssh.com forwarding method + - djm@cvs.openbsd.org 2008/06/12 05:32:30 + [mux.c] + some more TODO for me 20080611 - (djm) [channels.c configure.ac] @@ -4256,4 +4259,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4981 2008/06/12 18:53:27 dtucker Exp $ +$Id: ChangeLog,v 1.4982 2008/06/12 18:54:05 dtucker Exp $ diff --git a/mux.c b/mux.c index efc3840cb..f5e68f653 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.2 2008/06/12 03:40:52 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.3 2008/06/12 05:32:30 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -30,7 +30,10 @@ * 4. ExitOnForwardingFailure (after #3 obviously) * 5. Maybe extension mechanisms for multi-X11/multi-agent forwarding * 6. Document the mux mini-protocol somewhere. - * 6. Support ~^Z in mux slaves. + * 7. Support ~^Z in mux slaves. + * 8. Inspect or control sessions in master. + * 9. If we ever support the "signal" channel request, send signals on + * sessions in master. */ #include -- cgit v1.2.3 From 84c56f536ca664f79172d595e088fce6aa84be21 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 13 Jun 2008 04:55:46 +1000 Subject: - djm@cvs.openbsd.org 2008/06/12 15:19:17 [clientloop.h channels.h clientloop.c channels.c mux.c] The multiplexing escape char handler commit last night introduced a small memory leak per session; plug it. --- ChangeLog | 6 +++++- channels.c | 9 +++++++-- channels.h | 6 ++++-- clientloop.c | 10 +++++++++- clientloop.h | 3 ++- mux.c | 3 ++- 6 files changed, 29 insertions(+), 8 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 12471ba3b..0aec356d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -108,6 +108,10 @@ We already mark the start of the worm, now also mark the end of the worm in our random art drawings. ok djm@ + - djm@cvs.openbsd.org 2008/06/12 15:19:17 + [clientloop.h channels.h clientloop.c channels.c mux.c] + The multiplexing escape char handler commit last night introduced a + small memory leak per session; plug it. 20080611 - (djm) [channels.c configure.ac] @@ -4270,4 +4274,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4983 2008/06/12 18:55:10 dtucker Exp $ +$Id: ChangeLog,v 1.4984 2008/06/12 18:55:46 dtucker Exp $ diff --git a/channels.c b/channels.c index c539990f6..04cd6b0a7 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.279 2008/06/12 03:40:52 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.280 2008/06/12 15:19:17 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -328,6 +328,8 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->open_confirm_ctx = NULL; c->input_filter = NULL; c->output_filter = NULL; + c->filter_ctx = NULL; + c->filter_cleanup = NULL; TAILQ_INIT(&c->status_confirms); debug("channel %d: new [%s]", found, remote_name); return c; @@ -416,6 +418,8 @@ channel_free(Channel *c) bzero(cc, sizeof(*cc)); xfree(cc); } + if (c->filter_cleanup != NULL && c->filter_ctx != NULL) + c->filter_cleanup(c->self, c->filter_ctx); channels[c->self] = NULL; xfree(c); } @@ -731,7 +735,7 @@ channel_cancel_cleanup(int id) void channel_register_filter(int id, channel_infilter_fn *ifn, - channel_outfilter_fn *ofn, void *ctx) + channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) { Channel *c = channel_lookup(id); @@ -742,6 +746,7 @@ channel_register_filter(int id, channel_infilter_fn *ifn, c->input_filter = ifn; c->output_filter = ofn; c->filter_ctx = ctx; + c->filter_cleanup = cfn; } void diff --git a/channels.h b/channels.h index 450321d43..ec8ea1c40 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.94 2008/06/12 03:40:52 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.95 2008/06/12 15:19:17 djm Exp $ */ /* * Author: Tatu Ylonen @@ -62,6 +62,7 @@ typedef struct Channel Channel; typedef void channel_callback_fn(int, void *); typedef int channel_infilter_fn(struct Channel *, char *, int); +typedef void channel_filter_cleanup_fn(int, void *); typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *); /* Channel success/failure callbacks */ @@ -132,6 +133,7 @@ struct Channel { channel_infilter_fn *input_filter; channel_outfilter_fn *output_filter; void *filter_ctx; + channel_filter_cleanup_fn *filter_cleanup; /* keep boundaries */ int datagram; @@ -196,7 +198,7 @@ void channel_request_start(int, char *, int); void channel_register_cleanup(int, channel_callback_fn *, int); void channel_register_open_confirm(int, channel_callback_fn *, void *); void channel_register_filter(int, channel_infilter_fn *, - channel_outfilter_fn *, void *); + channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); void channel_register_status_confirm(int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(int); diff --git a/clientloop.c b/clientloop.c index 663daae76..d2407ed7e 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.197 2008/06/12 04:17:47 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.198 2008/06/12 15:19:17 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1260,6 +1260,13 @@ client_new_escape_filter_ctx(int escape_char) return (void *)ret; } +/* Free the escape filter context on channel free */ +void +client_filter_cleanup(int cid, void *ctx) +{ + xfree(ctx); +} + int client_simple_escape_filter(Channel *c, char *buf, int len) { @@ -1357,6 +1364,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) if (escape_char_arg != SSH_ESCAPECHAR_NONE) channel_register_filter(session_ident, client_simple_escape_filter, NULL, + client_filter_cleanup, client_new_escape_filter_ctx(escape_char_arg)); if (session_ident != -1) channel_register_cleanup(session_ident, diff --git a/clientloop.h b/clientloop.h index 3353a9a80..8bb874b38 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.21 2008/06/12 04:06:00 djm Exp $ */ +/* $OpenBSD: clientloop.h,v 1.22 2008/06/12 15:19:17 djm Exp $ */ /* * Author: Tatu Ylonen @@ -48,6 +48,7 @@ int client_request_tun_fwd(int, int, int); /* Escape filter for protocol 2 sessions */ void *client_new_escape_filter_ctx(int); +void client_filter_cleanup(int, void *); int client_simple_escape_filter(Channel *, char *, int); /* Global request confirmation callbacks */ diff --git a/mux.c b/mux.c index f5e68f653..8f7bfb793 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.4 2008/06/12 15:19:17 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -436,6 +436,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)); } -- cgit v1.2.3 From ca19bfe2546f280f10795bae5e0ec296623de880 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 13 Jun 2008 10:24:03 +1000 Subject: - djm@cvs.openbsd.org 2008/06/13 00:16:49 [mux.c] fall back to creating a new TCP connection on most multiplexing errors (socket connect fail, invalid version, refused permittion, corrupted messages, etc.); bz #1329 ok dtucker@ --- ChangeLog | 7 ++++++- mux.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 19 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 75f6246ca..052b15bd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -143,6 +143,11 @@ [sftp.h log.h] replace __dead with __attribute__((noreturn)), makes things a little easier to port. Also, add it to sigdie(). ok djm@ + - djm@cvs.openbsd.org 2008/06/13 00:16:49 + [mux.c] + fall back to creating a new TCP connection on most multiplexing errors + (socket connect fail, invalid version, refused permittion, corrupted + messages, etc.); bz #1329 ok dtucker@ - (dtucker) [clientloop.c serverloop.c] channel_register_filter now takes 2 more args. with djm@ @@ -4307,4 +4312,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4994 2008/06/13 00:22:54 dtucker Exp $ +$Id: ChangeLog,v 1.4995 2008/06/13 00:24:03 dtucker Exp $ diff --git a/mux.c b/mux.c index 8f7bfb793..aaa3a4ee2 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.4 2008/06/12 15:19:17 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.5 2008/06/13 00:16:49 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -144,10 +144,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); @@ -500,7 +506,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; @@ -571,17 +577,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: msg_recv", __func__); + goto muxerr; + } + if (buffer_get_char(&m) != SSHMUX_VER) { + error("%s: 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); @@ -625,13 +652,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); -- cgit v1.2.3 From 1adfd368c48f8b9b70a33a7094cff8930bfdf72e Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Fri, 13 Jun 2008 10:58:10 +1000 Subject: - dtucker@cvs.openbsd.org 2008/06/13 00:47:53 [mux.c] upcast size_t to u_long to match format arg; ok djm@ --- ChangeLog | 5 ++++- mux.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 1e173fec3..4e39326b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -148,6 +148,9 @@ fall back to creating a new TCP connection on most multiplexing errors (socket connect fail, invalid version, refused permittion, corrupted messages, etc.); bz #1329 ok dtucker@ + - dtucker@cvs.openbsd.org 2008/06/13 00:47:53 + [mux.c] + upcast size_t to u_long to match format arg; ok djm@ - (dtucker) [clientloop.c serverloop.c] channel_register_filter now takes 2 more args. with djm@ - (dtucker) [defines.h] Bug #1112: __dead is, well dead. Based on a patch @@ -4314,4 +4317,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.4996 2008/06/13 00:28:57 dtucker Exp $ +$Id: ChangeLog,v 1.4997 2008/06/13 00:58:10 dtucker Exp $ diff --git a/mux.c b/mux.c index aaa3a4ee2..ce3015c3f 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.5 2008/06/13 00:16:49 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.6 2008/06/13 00:47:53 dtucker Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -711,7 +711,7 @@ muxclient(const char *path) leave_raw_mode(); 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; -- cgit v1.2.3 From 47e713be94464b6ed7be0186e79c3f7b73f99936 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sat, 14 Jun 2008 09:01:54 +1000 Subject: - dtucker@cvs.openbsd.org 2008/06/13 17:21:20 [mux.c] Friendlier error messages for mux fallback. ok djm@ --- ChangeLog | 5 ++++- mux.c | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'mux.c') diff --git a/ChangeLog b/ChangeLog index 8b18aea38..0b7387c56 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,9 @@ - dtucker@cvs.openbsd.org 2008/06/13 14:18:51 [auth2-pubkey.c auth-rhosts.c] Include unistd.h for close(), prevents warnings in -portable + - dtucker@cvs.openbsd.org 2008/06/13 17:21:20 + [mux.c] + Friendlier error messages for mux fallback. ok djm@ 20080612 - (dtucker) OpenBSD CVS Sync @@ -4350,4 +4353,4 @@ OpenServer 6 and add osr5bigcrypt support so when someone migrates passwords between UnixWare and OpenServer they will still work. OK dtucker@ -$Id: ChangeLog,v 1.5006 2008/06/13 23:01:24 dtucker Exp $ +$Id: ChangeLog,v 1.5007 2008/06/13 23:01:54 dtucker Exp $ diff --git a/mux.c b/mux.c index ce3015c3f..79f83768b 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.6 2008/06/13 00:47:53 dtucker Exp $ */ +/* $OpenBSD: mux.c,v 1.7 2008/06/13 17:21:20 dtucker Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -594,11 +594,11 @@ muxclient(const char *path) /* Get authorisation status and PID of controlee */ if (ssh_msg_recv(sock, &m) == -1) { - error("%s: msg_recv", __func__); + error("%s: Did not receive reply from master", __func__); goto muxerr; } if (buffer_get_char(&m) != SSHMUX_VER) { - error("%s: wrong version", __func__); + error("%s: Master replied with wrong version", __func__); goto muxerr; } if (buffer_get_int_ret(&allowed, &m) != 0) { -- cgit v1.2.3