aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/mux.c')
-rw-r--r--crypto/openssh/mux.c730
1 files changed, 356 insertions, 374 deletions
diff --git a/crypto/openssh/mux.c b/crypto/openssh/mux.c
index d035fbe75f74..d598a17e2da5 100644
--- a/crypto/openssh/mux.c
+++ b/crypto/openssh/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.77 2018/09/26 07:32:44 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.101 2023/11/23 03:37:05 dtucker Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -18,7 +18,6 @@
/* ssh session multiplexing support */
#include "includes.h"
-__RCSID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
@@ -27,6 +26,7 @@ __RCSID("$FreeBSD$");
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
@@ -68,13 +68,12 @@ __RCSID("$FreeBSD$");
#include "readconf.h"
#include "clientloop.h"
#include "ssherr.h"
+#include "misc.h"
/* from ssh.c */
extern int tty_flag;
extern Options options;
-extern int stdin_null_flag;
extern char *host;
-extern int subsystem_flag;
extern struct sshbuf *command;
extern volatile sig_atomic_t quit_pending;
@@ -188,20 +187,19 @@ static const struct {
{ 0, NULL }
};
-/* Cleanup callback fired on closure of mux slave _session_ channel */
-/* ARGSUSED */
+/* Cleanup callback fired on closure of mux client _session_ channel */
static void
-mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
+mux_master_session_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused)
{
Channel *cc, *c = channel_by_id(ssh, cid);
- debug3("%s: entering for channel %d", __func__, cid);
+ debug3_f("entering for channel %d", cid);
if (c == NULL)
- fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
+ fatal_f("channel_by_id(%i) == NULL", cid);
if (c->ctl_chan != -1) {
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing control channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing control channel %d",
+ c->self, c->ctl_chan);
c->ctl_chan = -1;
cc->remote_id = 0;
cc->have_remote_id = 0;
@@ -210,26 +208,25 @@ mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
channel_cancel_cleanup(ssh, c->self);
}
-/* Cleanup callback fired on closure of mux slave _control_ channel */
-/* ARGSUSED */
+/* Cleanup callback fired on closure of mux client _control_ channel */
static void
-mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
+mux_master_control_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused)
{
Channel *sc, *c = channel_by_id(ssh, cid);
- debug3("%s: entering for channel %d", __func__, cid);
+ debug3_f("entering for channel %d", cid);
if (c == NULL)
- fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
+ fatal_f("channel_by_id(%i) == NULL", cid);
if (c->have_remote_id) {
if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
- fatal("%s: channel %d missing session channel %u",
- __func__, c->self, c->remote_id);
+ fatal_f("channel %d missing session channel %u",
+ c->self, c->remote_id);
c->remote_id = 0;
c->have_remote_id = 0;
sc->ctl_chan = -1;
if (sc->type != SSH_CHANNEL_OPEN &&
sc->type != SSH_CHANNEL_OPENING) {
- debug2("%s: channel %d: not open", __func__, sc->self);
+ debug2_f("channel %d: not open", sc->self);
chan_mark_dead(ssh, sc);
} else {
if (sc->istate == CHAN_INPUT_OPEN)
@@ -243,16 +240,17 @@ mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
/* Check mux client environment variables before passing them to mux master. */
static int
-env_permitted(char *env)
+env_permitted(const char *env)
{
- int i, ret;
+ u_int i;
+ int 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)) {
- error("%s: name '%.100s...' too long", __func__, env);
+ error_f("name '%.100s...' too long", env);
return 0;
}
@@ -274,21 +272,21 @@ mux_master_process_hello(struct ssh *ssh, u_int rid,
int r;
if (state == NULL)
- fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
+ fatal_f("channel %d: c->mux_ctx == NULL", c->self);
if (state->hello_rcvd) {
- error("%s: HELLO received twice", __func__);
+ error_f("HELLO received twice");
return -1;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0) {
- error("%s: malformed message: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
return -1;
}
if (ver != SSHMUX_VER) {
- error("%s: unsupported multiplexing protocol version %u "
- "(expected %u)", __func__, ver, SSHMUX_VER);
+ error_f("unsupported multiplexing protocol version %u "
+ "(expected %u)", ver, SSHMUX_VER);
return -1;
}
- debug2("%s: channel %d slave version %u", __func__, c->self, ver);
+ debug2_f("channel %d client version %u", c->self, ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
@@ -297,12 +295,11 @@ mux_master_process_hello(struct ssh *ssh, u_int rid,
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) {
- error("%s: malformed extension: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse extension");
return -1;
}
- debug2("%s: Unrecognised extension \"%s\" length %zu",
- __func__, name, value_len);
+ debug2_f("Unrecognised extension \"%s\" length %zu",
+ name, value_len);
free(name);
}
state->hello_rcvd = 1;
@@ -317,7 +314,7 @@ reply_ok(struct sshbuf *reply, u_int rid)
if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
}
/* Enqueue an error response to the reply buffer */
@@ -329,7 +326,7 @@ reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg)
if ((r = sshbuf_put_u32(reply, type)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_cstring(reply, msg)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
}
static int
@@ -364,7 +361,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
free(cctx->env);
free(cctx->term);
free(cctx);
- error("%s: malformed message", __func__);
+ error_f("malformed message");
return -1;
}
@@ -381,29 +378,28 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
cctx->env[env_len++] = cp;
cctx->env[env_len] = NULL;
if (env_len > MUX_MAX_ENV_VARS) {
- error("%s: >%d environment variables received, "
- "ignoring additional", __func__, MUX_MAX_ENV_VARS);
+ error_f(">%d environment variables received, "
+ "ignoring additional", MUX_MAX_ENV_VARS);
break;
}
}
- debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
- "term \"%s\", cmd \"%s\", env %u", __func__, c->self,
+ debug2_f("channel %d: request tty %d, X %d, agent %d, subsys %d, "
+ "term \"%s\", cmd \"%s\", env %u", c->self,
cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
cctx->want_subsys, cctx->term, cmd, env_len);
if ((cctx->cmd = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0)
- fatal("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
free(cmd);
cmd = NULL;
/* Gather fds from client */
for(i = 0; i < 3; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
- error("%s: failed to receive fd %d from slave",
- __func__, i);
+ error_f("failed to receive fd %d from client", i);
for (j = 0; j < i; j++)
close(new_fd[j]);
for (j = 0; j < env_len; j++)
@@ -418,12 +414,12 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
}
}
- debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
+ debug3_f("got fds stdin %d, stdout %d, stderr %d",
new_fd[0], new_fd[1], new_fd[2]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
- debug2("%s: session already open", __func__);
+ debug2_f("session already open");
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
@@ -444,7 +440,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow shared connection to %s? ", host)) {
- debug2("%s: session refused by user", __func__);
+ debug2_f("session refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
@@ -453,15 +449,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
/* 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));
-
- /* 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]);
+ error_f("tcgetattr: %s", strerror(errno));
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
@@ -472,10 +460,10 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
- CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
+ CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO);
nc->ctl_chan = c->self; /* link session -> control channel */
- c->remote_id = nc->self; /* link control -> session channel */
+ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
if (cctx->want_tty && escape_char != 0xffffffff) {
@@ -485,8 +473,8 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
client_new_escape_filter_ctx((int)escape_char));
}
- debug2("%s: channel_new: %d linked to control channel %d",
- __func__, nc->self, nc->ctl_chan);
+ debug2_f("channel_new: %d linked to control channel %d",
+ nc->self, nc->ctl_chan);
channel_send_open(ssh, nc->self);
channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
@@ -504,13 +492,13 @@ mux_master_process_alive_check(struct ssh *ssh, u_int rid,
{
int r;
- debug2("%s: channel %d: alive check", __func__, c->self);
+ debug2_f("channel %d: alive check", c->self);
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply, (u_int)getpid())) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
return 0;
}
@@ -519,13 +507,13 @@ static int
mux_master_process_terminate(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
- debug2("%s: channel %d: terminate request", __func__, c->self);
+ debug2_f("channel %d: terminate request", c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Terminate shared connection to %s? ",
host)) {
- debug2("%s: termination refused by user", __func__);
+ debug2_f("termination refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
@@ -557,7 +545,7 @@ format_forward(u_int ftype, struct Forward *fwd)
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
(fwd->listen_host == NULL) ?
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
- fwd->listen_host, fwd->listen_port);
+ fwd->listen_host, fwd->listen_port);
break;
case MUX_FWD_REMOTE:
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
@@ -569,7 +557,7 @@ format_forward(u_int ftype, struct Forward *fwd)
fwd->connect_host, fwd->connect_port);
break;
default:
- fatal("%s: unknown forward type %u", __func__, ftype);
+ fatal_f("unknown forward type %u", ftype);
}
return ret;
}
@@ -611,15 +599,16 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
struct Forward *rfwd;
Channel *c;
struct sshbuf *out;
+ u_int port;
int r;
if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
/* no channel for reply */
- error("%s: unknown channel", __func__);
+ error_f("unknown channel");
return;
}
if ((out = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (fctx->fid >= options.num_remote_forwards ||
(options.remote_forwards[fctx->fid].connect_path == NULL &&
options.remote_forwards[fctx->fid].connect_host == NULL)) {
@@ -627,13 +616,20 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
goto fail;
}
rfwd = &options.remote_forwards[fctx->fid];
- debug("%s: %s for: listen %d, connect %s:%d", __func__,
+ debug_f("%s for: listen %d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) {
- rfwd->allocated_port = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &port)) != 0)
+ fatal_fr(r, "parse port");
+ if (port > 65535) {
+ fatal("Invalid allocated port %u for "
+ "mux remote forward to %s:%d", port,
+ rfwd->connect_host, rfwd->connect_port);
+ }
+ rfwd->allocated_port = (int)port;
debug("Allocated port %u for mux remote forward"
" to %s:%d", rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port);
@@ -642,9 +638,9 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
(r = sshbuf_put_u32(out, fctx->rid)) != 0 ||
(r = sshbuf_put_u32(out,
rfwd->allocated_port)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
channel_update_permission(ssh, rfwd->handle,
- rfwd->allocated_port);
+ rfwd->allocated_port);
} else {
reply_ok(out, fctx->rid);
}
@@ -659,8 +655,8 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
- debug2("%s: clearing registered forwarding for listen %d, "
- "connect %s:%d", __func__, rfwd->listen_port,
+ debug2_f("clearing registered forwarding for listen %d, "
+ "connect %s:%d", rfwd->listen_port,
rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
@@ -671,15 +667,15 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
memset(rfwd, 0, sizeof(*rfwd));
}
fail:
- error("%s: %s", __func__, failmsg);
+ error_f("%s", failmsg);
reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg);
free(failmsg);
out:
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(out);
if (c->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, c->mux_pause);
+ fatal_f("mux_pause %d", c->mux_pause);
c->mux_pause = 0; /* start processing messages again */
}
@@ -704,7 +700,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
- error("%s: malformed message", __func__);
+ error_f("malformed message");
ret = -1;
goto out;
}
@@ -729,12 +725,12 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
else
fwd.connect_host = connect_addr;
- debug2("%s: channel %d: request %s", __func__, c->self,
+ debug2_f("channel %d: request %s", c->self,
(fwd_desc = format_forward(ftype, &fwd)));
if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE &&
ftype != MUX_FWD_DYNAMIC) {
- logit("%s: invalid forwarding type %u", __func__, ftype);
+ logit_f("invalid forwarding type %u", ftype);
invalid:
free(listen_addr);
free(connect_addr);
@@ -743,26 +739,25 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
return 0;
}
if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
- logit("%s: streamlocal and dynamic forwards "
- "are mutually exclusive", __func__);
+ logit_f("streamlocal and dynamic forwards "
+ "are mutually exclusive");
goto invalid;
}
if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
- logit("%s: invalid listen port %u", __func__,
- fwd.listen_port);
+ logit_f("invalid listen port %u", fwd.listen_port);
goto invalid;
}
if ((fwd.connect_port != PORT_STREAMLOCAL &&
fwd.connect_port >= 65536) ||
(ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
fwd.connect_port == 0)) {
- logit("%s: invalid connect port %u", __func__,
+ logit_f("invalid connect port %u",
fwd.connect_port);
goto invalid;
}
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
fwd.connect_path == NULL) {
- logit("%s: missing connect host", __func__);
+ logit_f("missing connect host");
goto invalid;
}
@@ -774,8 +769,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (compare_forward(&fwd,
options.local_forwards + i)) {
exists:
- debug2("%s: found existing forwarding",
- __func__);
+ debug2_f("found existing forwarding");
reply_ok(reply, rid);
goto out;
}
@@ -787,13 +781,13 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
continue;
if (fwd.listen_port != 0)
goto exists;
- debug2("%s: found allocated port", __func__);
+ debug2_f("found allocated port");
if ((r = sshbuf_put_u32(reply,
MUX_S_REMOTE_PORT)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply,
options.remote_forwards[i].allocated_port)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply FWD_REMOTE");
goto out;
}
break;
@@ -802,7 +796,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
- debug2("%s: forwarding refused by user", __func__);
+ debug2_f("forwarding refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto out;
@@ -813,7 +807,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
fail:
- logit("%s: requested %s failed", __func__, fwd_desc);
+ logit_f("requested %s failed", fwd_desc);
reply_error(reply, MUX_S_FAILURE, rid,
"Port forwarding failed");
goto out;
@@ -871,7 +865,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
- error("%s: malformed message", __func__);
+ error_f("malformed message");
ret = -1;
goto out;
}
@@ -897,7 +891,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
else
fwd.connect_host = connect_addr;
- debug2("%s: channel %d: request cancel %s", __func__, c->self,
+ debug2_f("channel %d: request cancel %s", c->self,
(fwd_desc = format_forward(ftype, &fwd)));
/* make sure this has been requested */
@@ -968,26 +962,33 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
{
Channel *nc;
char *chost = NULL;
- u_int cport, i, j;
- int r, new_fd[2];
+ u_int _cport, i, j;
+ int ok = 0, cport, r, new_fd[2];
struct mux_stdio_confirm_ctx *cctx;
if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
- (r = sshbuf_get_u32(m, &cport)) != 0) {
+ (r = sshbuf_get_u32(m, &_cport)) != 0) {
+ free(chost);
+ error_f("malformed message");
+ return -1;
+ }
+ if (_cport == (u_int)PORT_STREAMLOCAL)
+ cport = PORT_STREAMLOCAL;
+ else if (_cport <= INT_MAX)
+ cport = (int)_cport;
+ else {
free(chost);
- error("%s: malformed message", __func__);
+ error_f("invalid port 0x%x", _cport);
return -1;
}
- debug2("%s: channel %d: request stdio fwd to %s:%u",
- __func__, c->self, chost, cport);
+ debug2_f("channel %d: stdio fwd to %s:%d", c->self, chost, cport);
/* Gather fds from client */
for(i = 0; i < 2; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
- error("%s: failed to receive fd %d from slave",
- __func__, i);
+ error_f("failed to receive fd %d from client", i);
for (j = 0; j < i; j++)
close(new_fd[j]);
free(chost);
@@ -999,12 +1000,11 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
}
}
- debug3("%s: got fds stdin %d, stdout %d", __func__,
- new_fd[0], new_fd[1]);
+ debug3_f("got fds stdin %d, stdout %d", new_fd[0], new_fd[1]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
- debug2("%s: session already open", __func__);
+ debug2_f("session already open");
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
@@ -1016,30 +1016,29 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
- if (!ask_permission("Allow forward to %s:%u? ",
- chost, cport)) {
- debug2("%s: stdio fwd refused by user", __func__);
+ if (cport == PORT_STREAMLOCAL) {
+ ok = ask_permission("Allow forward to path %s", chost);
+ } else {
+ ok = ask_permission("Allow forward to [%s]:%d? ",
+ chost, cport);
+ }
+ if (!ok) {
+ debug2_f("stdio fwd refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
}
}
- /* enable nonblocking unless tty */
- if (!isatty(new_fd[0]))
- set_nonblock(new_fd[0]);
- if (!isatty(new_fd[1]))
- set_nonblock(new_fd[1]);
-
- nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
+ nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1],
+ CHANNEL_NONBLOCK_STDIO);
free(chost);
nc->ctl_chan = c->self; /* link session -> control channel */
- c->remote_id = nc->self; /* link control -> session channel */
+ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
- debug2("%s: channel_new: %d linked to control channel %d",
- __func__, nc->self, nc->ctl_chan);
+ debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan);
channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
@@ -1063,38 +1062,38 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
int r;
if (cctx == NULL)
- fatal("%s: cctx == NULL", __func__);
+ fatal_f("cctx == NULL");
if ((c = channel_by_id(ssh, id)) == NULL)
- fatal("%s: no channel for id %d", __func__, id);
+ fatal_f("no channel for id %d", id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d lacks control channel %d", __func__,
+ fatal_f("channel %d lacks control channel %d",
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (!success) {
- debug3("%s: sending failure reply", __func__);
+ debug3_f("sending failure reply");
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
/* prepare reply */
goto done;
}
- debug3("%s: sending success reply", __func__);
+ debug3_f("sending success reply");
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(reply);
if (cc->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, cc->mux_pause);
+ fatal_f("mux_pause %d", cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
free(cctx);
@@ -1104,13 +1103,13 @@ static int
mux_master_process_stop_listening(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
- debug("%s: channel %d: stop listening", __func__, c->self);
+ debug_f("channel %d: stop listening", c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Disable further multiplexing on shared "
"connection to %s? ", host)) {
- debug2("%s: stop listen refused by user", __func__);
+ debug2_f("stop listen refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
@@ -1136,17 +1135,17 @@ mux_master_process_proxy(struct ssh *ssh, u_int rid,
{
int r;
- debug("%s: channel %d: proxy request", __func__, c->self);
+ debug_f("channel %d: proxy request", c->self);
c->mux_rcb = channel_proxy_downstream;
if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
return 0;
}
-/* Channel callbacks fired on read/write from mux slave fd */
+/* Channel callbacks fired on read/write from mux client fd */
static int
mux_master_read_cb(struct ssh *ssh, Channel *c)
{
@@ -1156,7 +1155,7 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
int r, ret = -1;
if ((out = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
/* Setup ctx and */
if (c->mux_ctx == NULL) {
@@ -1168,12 +1167,11 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
/* Send hello */
if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(out, SSHMUX_VER)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
/* no extensions */
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s",
- __func__, ssh_err(r));
- debug3("%s: channel %d: hello sent", __func__, c->self);
+ fatal_fr(r, "enqueue");
+ debug3_f("channel %d: hello sent", c->self);
ret = 0;
goto out;
}
@@ -1181,21 +1179,21 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
/* Channel code ensures that we receive whole packets */
if ((r = sshbuf_froms(c->input, &in)) != 0) {
malf:
- error("%s: malformed message", __func__);
+ error_f("malformed message");
goto out;
}
if ((r = sshbuf_get_u32(in, &type)) != 0)
goto malf;
- debug3("%s: channel %d packet type 0x%08x len %zu",
- __func__, c->self, type, sshbuf_len(in));
+ debug3_f("channel %d packet type 0x%08x len %zu", c->self,
+ type, sshbuf_len(in));
if (type == MUX_MSG_HELLO)
rid = 0;
else {
if (!state->hello_rcvd) {
- error("%s: expected MUX_MSG_HELLO(0x%08x), "
- "received 0x%08x", __func__, MUX_MSG_HELLO, type);
+ error_f("expected MUX_MSG_HELLO(0x%08x), "
+ "received 0x%08x", MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(in, &rid)) != 0)
@@ -1210,16 +1208,14 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
}
}
if (mux_master_handlers[i].handler == NULL) {
- error("%s: unsupported mux message 0x%08x", __func__, type);
+ error_f("unsupported mux message 0x%08x", type);
reply_error(out, MUX_S_FAILURE, rid, "unsupported request");
ret = 0;
}
/* Enqueue reply packet */
- if (sshbuf_len(out) != 0) {
- if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s",
- __func__, ssh_err(r));
- }
+ if (sshbuf_len(out) != 0 &&
+ (r = sshbuf_put_stringb(c->output, out)) != 0)
+ fatal_fr(r, "enqueue");
out:
sshbuf_free(in);
sshbuf_free(out);
@@ -1233,21 +1229,19 @@ mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
Channel *mux_chan;
int r;
- debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
- exitval);
+ debug3_f("channel %d: exit message, exitval %d", c->self, exitval);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing mux channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing mux %d", c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_u32(m, exitval)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
sshbuf_free(m);
}
@@ -1258,19 +1252,18 @@ mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
Channel *mux_chan;
int r;
- debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
+ debug3_f("channel %d: TTY alloc failed", c->self);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing mux channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing mux %d", c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
sshbuf_free(m);
}
@@ -1305,7 +1298,7 @@ muxserver_listen(struct ssh *ssh)
rbuf[sizeof(rbuf) - 1] = '\0';
options.control_path = NULL;
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
- debug3("%s: temporary control path %s", __func__, options.control_path);
+ debug3_f("temporary control path %s", options.control_path);
old_umask = umask(0177);
muxserver_sock = unix_listener(options.control_path, 64, 0);
@@ -1334,7 +1327,7 @@ muxserver_listen(struct ssh *ssh)
/* Now atomically "move" the mux socket into position */
if (link(options.control_path, orig_control_path) != 0) {
if (errno != EEXIST) {
- fatal("%s: link mux listener %s => %s: %s", __func__,
+ fatal_f("link mux listener %s => %s: %s",
options.control_path, orig_control_path,
strerror(errno));
}
@@ -1354,7 +1347,7 @@ muxserver_listen(struct ssh *ssh)
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, options.control_path, 1);
mux_listener_channel->mux_rcb = mux_master_read_cb;
- debug3("%s: mux listener channel %d fd %d", __func__,
+ debug3_f("mux listener channel %d fd %d",
mux_listener_channel->self, mux_listener_channel->sock);
}
@@ -1369,17 +1362,17 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
struct sshbuf *reply;
if (cctx == NULL)
- fatal("%s: cctx == NULL", __func__);
+ fatal_f("cctx == NULL");
if ((c = channel_by_id(ssh, id)) == NULL)
- fatal("%s: no channel for id %d", __func__, id);
+ fatal_f("no channel for id %d", id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d lacks control channel %d", __func__,
+ fatal_f("channel %d lacks control channel %d",
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (!success) {
- debug3("%s: sending failure reply", __func__);
+ debug3_f("sending failure reply");
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
goto done;
@@ -1407,27 +1400,28 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
if (cctx->want_agent_fwd && options.forward_agent) {
debug("Requesting authentication agent forwarding.");
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "send");
}
client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env);
- debug3("%s: sending success reply", __func__);
+ debug3_f("sending success reply");
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(reply);
if (cc->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, cc->mux_pause);
+ fatal_f("mux_pause %d", cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
sshbuf_free(cctx->cmd);
@@ -1465,31 +1459,31 @@ control_client_sigrelay(int signo)
}
static int
-mux_client_read(int fd, struct sshbuf *b, size_t need)
+mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms)
{
size_t have;
ssize_t len;
u_char *p;
- struct pollfd pfd;
int r;
- pfd.fd = fd;
- pfd.events = POLLIN;
if ((r = sshbuf_reserve(b, need, &p)) != 0)
- fatal("%s: reserve: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
for (have = 0; have < need; ) {
if (muxclient_terminate) {
errno = EINTR;
return -1;
}
len = read(fd, p + have, need - have);
- if (len < 0) {
+ if (len == -1) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EAGAIN:
- (void)poll(&pfd, 1, -1);
+ if (waitrfd(fd, &timeout_ms,
+ &muxclient_terminate) == -1 &&
+ errno != EINTR)
+ return -1; /* timeout */
/* FALLTHROUGH */
case EINTR:
continue;
@@ -1518,9 +1512,9 @@ mux_client_write_packet(int fd, struct sshbuf *m)
pfd.fd = fd;
pfd.events = POLLOUT;
if ((queue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_stringb(queue, m)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
need = sshbuf_len(queue);
ptr = sshbuf_ptr(queue);
@@ -1532,7 +1526,7 @@ mux_client_write_packet(int fd, struct sshbuf *m)
return -1;
}
len = write(fd, ptr + have, need - have);
- if (len < 0) {
+ if (len == -1) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
@@ -1561,7 +1555,7 @@ mux_client_write_packet(int fd, struct sshbuf *m)
}
static int
-mux_client_read_packet(int fd, struct sshbuf *m)
+mux_client_read_packet_timeout(int fd, struct sshbuf *m, int timeout_ms)
{
struct sshbuf *queue;
size_t need, have;
@@ -1569,80 +1563,84 @@ mux_client_read_packet(int fd, struct sshbuf *m)
int r, oerrno;
if ((queue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
- if (mux_client_read(fd, queue, 4) != 0) {
+ fatal_f("sshbuf_new");
+ if (mux_client_read(fd, queue, 4, timeout_ms) != 0) {
if ((oerrno = errno) == EPIPE)
- debug3("%s: read header failed: %s", __func__,
+ debug3_f("read header failed: %s",
strerror(errno));
sshbuf_free(queue);
errno = oerrno;
return -1;
}
need = PEEK_U32(sshbuf_ptr(queue));
- if (mux_client_read(fd, queue, need) != 0) {
+ if (mux_client_read(fd, queue, need, timeout_ms) != 0) {
oerrno = errno;
- debug3("%s: read body failed: %s", __func__, strerror(errno));
+ debug3_f("read body failed: %s", strerror(errno));
sshbuf_free(queue);
errno = oerrno;
return -1;
}
if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 ||
(r = sshbuf_put(m, ptr, have)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "dequeue");
sshbuf_free(queue);
return 0;
}
static int
-mux_client_hello_exchange(int fd)
+mux_client_read_packet(int fd, struct sshbuf *m)
+{
+ return mux_client_read_packet_timeout(fd, m, -1);
+}
+
+static int
+mux_client_hello_exchange(int fd, int timeout_ms)
{
struct sshbuf *m;
u_int type, ver;
int r, ret = -1;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(m, SSHMUX_VER)) != 0)
- fatal("%s: hello: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble hello");
/* no extensions */
if (mux_client_write_packet(fd, m) != 0) {
- debug("%s: write packet: %s", __func__, strerror(errno));
+ debug_f("write packet: %s", strerror(errno));
goto out;
}
sshbuf_reset(m);
/* Read their HELLO */
- if (mux_client_read_packet(fd, m) != 0) {
- debug("%s: read packet failed", __func__);
+ if (mux_client_read_packet_timeout(fd, m, timeout_ms) != 0) {
+ debug_f("read packet failed");
goto out;
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != MUX_MSG_HELLO) {
- error("%s: expected HELLO (%u) received %u",
- __func__, MUX_MSG_HELLO, type);
+ error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0)
- fatal("%s: decode version: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse version");
if (ver != SSHMUX_VER) {
error("Unsupported multiplexing protocol version %d "
"(expected %d)", ver, SSHMUX_VER);
goto out;
}
- debug2("%s: master version %u", __func__, ver);
+ debug2_f("master version %u", ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
char *name = NULL;
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_skip_string(m)) != 0) { /* value */
- error("%s: malformed extension: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse extension");
goto out;
}
debug2("Unrecognised master extension \"%s\"", name);
@@ -1663,16 +1661,16 @@ mux_client_request_alive(int fd)
u_int pid, type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1683,23 +1681,23 @@ mux_client_request_alive(int fd)
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != MUX_S_ALIVE) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
if ((r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode remote ID: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse remote ID");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
if ((r = sshbuf_get_u32(m, &pid)) != 0)
- fatal("%s: decode PID: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse PID");
sshbuf_free(m);
- debug3("%s: done pid = %u", __func__, pid);
+ debug3_f("done pid = %u", pid);
muxclient_request_id++;
@@ -1714,16 +1712,16 @@ mux_client_request_terminate(int fd)
u_int type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1734,30 +1732,28 @@ mux_client_request_terminate(int fd)
sshbuf_free(m);
return;
}
- fatal("%s: read from master failed: %s",
- __func__, strerror(errno));
+ fatal_f("read from master failed: %s", strerror(errno));
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
fatal("Master refused termination request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: termination request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("termination request failed: %s", e);
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
muxclient_request_id++;
@@ -1795,7 +1791,7 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
chost = fwd->connect_host;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, type)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_u32(m, ftype)) != 0 ||
@@ -1803,10 +1799,10 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
(r = sshbuf_put_u32(m, fwd->listen_port)) != 0 ||
(r = sshbuf_put_cstring(m, chost)) != 0 ||
(r = sshbuf_put_u32(m, fwd->connect_port)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1818,19 +1814,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_REMOTE_PORT:
if (cancel_flag)
- fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
+ fatal_f("got MUX_S_REMOTE_PORT for cancel");
if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0)
- fatal("%s: decode port: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse port");
verbose("Allocated port %u for remote forward to %s:%d",
fwd->allocated_port,
fwd->connect_host ? fwd->connect_host : "",
@@ -1840,19 +1836,18 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
error("Master refused forwarding request: %s", e);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
- error("%s: forwarding request failed: %s", __func__, e);
+ error_f("forwarding request failed: %s", e);
return -1;
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
@@ -1865,7 +1860,7 @@ mux_client_forwards(int fd, int cancel_flag)
{
int i, ret = 0;
- debug3("%s: %s forwardings: %d local, %d remote", __func__,
+ debug3_f("%s forwardings: %d local, %d remote",
cancel_flag ? "cancel" : "request",
options.num_local_forwards, options.num_remote_forwards);
@@ -1890,48 +1885,44 @@ mux_client_request_session(int fd)
{
struct sshbuf *m;
char *e;
- const char *term;
- u_int echar, rid, sid, esid, exitval, type, exitval_seen;
+ const char *term = NULL;
+ u_int i, echar, rid, sid, esid, exitval, type, exitval_seen;
extern char **environ;
- int r, i, devnull, rawmode;
+ int r, rawmode = 0;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
- error("%s: master alive request failed", __func__);
+ error_f("master alive request failed");
return -1;
}
- signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGPIPE, SIG_IGN);
- if (stdin_null_flag) {
- if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
+ fatal_f("stdfd_devnull failed");
+
+ if ((term = lookup_env_in_list("TERM", options.setenv,
+ options.num_setenv)) == NULL || *term == '\0')
+ term = getenv("TERM");
- if ((term = getenv("TERM")) == NULL)
- term = "";
echar = 0xffffffff;
if (options.escape_char != SSH_ESCAPECHAR_NONE)
echar = (u_int)options.escape_char;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_u32(m, tty_flag)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_x11)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_agent)) != 0 ||
- (r = sshbuf_put_u32(m, subsystem_flag)) != 0 ||
+ (r = sshbuf_put_u32(m, options.session_type == SESSION_TYPE_SUBSYSTEM)) != 0 ||
(r = sshbuf_put_u32(m, echar)) != 0 ||
- (r = sshbuf_put_cstring(m, term)) != 0 ||
+ (r = sshbuf_put_cstring(m, term == NULL ? "" : term)) != 0 ||
(r = sshbuf_put_stringb(m, command)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
/* Pass environment */
if (options.num_send_env > 0 && environ != NULL) {
@@ -1939,78 +1930,83 @@ mux_client_request_session(int fd)
if (!env_permitted(environ[i]))
continue;
if ((r = sshbuf_put_cstring(m, environ[i])) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request sendenv");
}
}
for (i = 0; i < options.num_setenv; i++) {
if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request setenv");
}
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1 ||
mm_send_fd(fd, STDERR_FILENO) == -1)
- fatal("%s: send fds failed", __func__);
+ fatal_f("send fds failed");
- debug3("%s: session request sent", __func__);
+ debug3_f("session request sent");
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
- error("%s: read from master failed: %s",
- __func__, strerror(errno));
+ error_f("read from master failed: %s", strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
- fatal("%s: decode ID: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
+ debug_f("master session id: %u", sid);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
error("Master refused session request: %s", e);
sshbuf_free(m);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- error("%s: session request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ error_f("session request failed: %s", e);
sshbuf_free(m);
return -1;
default:
sshbuf_free(m);
- error("%s: unexpected response from master 0x%08x",
- __func__, type);
+ error_f("unexpected response from master 0x%08x", type);
return -1;
}
muxclient_request_id++;
if (pledge("stdio proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
platform_pledge_mux();
- signal(SIGHUP, control_client_sighandler);
- signal(SIGINT, control_client_sighandler);
- signal(SIGTERM, control_client_sighandler);
- signal(SIGWINCH, control_client_sigrelay);
+ ssh_signal(SIGHUP, control_client_sighandler);
+ ssh_signal(SIGINT, control_client_sighandler);
+ ssh_signal(SIGTERM, control_client_sighandler);
+ ssh_signal(SIGWINCH, control_client_sigrelay);
- rawmode = tty_flag;
- if (tty_flag)
- enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
+ if (options.fork_after_authentication)
+ daemon(1, 1);
+ else {
+ rawmode = tty_flag;
+ if (tty_flag) {
+ enter_raw_mode(
+ options.request_tty == REQUEST_TTY_FORCE);
+ }
+ }
/*
* Stick around until the controlee closes the client_fd.
@@ -2024,40 +2020,34 @@ mux_client_request_session(int fd)
if (mux_client_read_packet(fd, m) != 0)
break;
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
switch (type) {
case MUX_S_TTY_ALLOC_FAIL:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
- fatal("%s: decode ID: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
if (esid != sid)
- fatal("%s: tty alloc fail on unknown session: "
- "my id %u theirs %u",
- __func__, sid, esid);
+ fatal_f("tty alloc fail on unknown session: "
+ "my id %u theirs %u", sid, esid);
leave_raw_mode(options.request_tty ==
REQUEST_TTY_FORCE);
rawmode = 0;
continue;
case MUX_S_EXIT_MESSAGE:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
- fatal("%s: decode ID: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
if (esid != sid)
- fatal("%s: exit on unknown session: "
- "my id %u theirs %u",
- __func__, sid, esid);
+ fatal_f("exit on unknown session: "
+ "my id %u theirs %u", sid, esid);
if (exitval_seen)
- fatal("%s: exitval sent twice", __func__);
+ fatal_f("exitval sent twice");
if ((r = sshbuf_get_u32(m, &exitval)) != 0)
- fatal("%s: decode exit value: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse exitval");
exitval_seen = 1;
continue;
default:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s",
- __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
}
@@ -2074,7 +2064,7 @@ mux_client_request_session(int fd)
} else
debug2("Received exit status from master %d", exitval);
- if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
+ if (tty_flag && options.log_level >= SYSLOG_LEVEL_INFO)
fprintf(stderr, "Shared connection to %s closed.\r\n", host);
exit(exitval);
@@ -2089,12 +2079,12 @@ mux_client_proxy(int fd)
int r;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -2105,18 +2095,18 @@ mux_client_proxy(int fd)
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
if (type != MUX_S_PROXY) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
sshbuf_free(m);
- debug3("%s: done", __func__);
+ debug3_f("done");
muxclient_request_id++;
return 0;
}
@@ -2127,93 +2117,85 @@ mux_client_request_stdio_fwd(int fd)
struct sshbuf *m;
char *e;
u_int type, rid, sid;
- int r, devnull;
+ int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
- error("%s: master alive request failed", __func__);
+ error_f("master alive request failed");
return -1;
}
- signal(SIGPIPE, SIG_IGN);
+ ssh_signal(SIGPIPE, SIG_IGN);
- if (stdin_null_flag) {
- if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
+ fatal_f("stdfd_devnull failed");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 ||
(r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1)
- fatal("%s: send fds failed", __func__);
+ fatal_f("send fds failed");
if (pledge("stdio proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
platform_pledge_mux();
- debug3("%s: stdio forward request sent", __func__);
+ debug3_f("stdio forward request sent");
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
- error("%s: read from master failed: %s",
- __func__, strerror(errno));
+ error_f("read from master failed: %s", strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
- fatal("%s: decode ID: %s", __func__, ssh_err(r));
- debug("%s: master session id: %u", __func__, sid);
+ fatal_fr(r, "parse session ID");
+ debug_f("master session id: %u", sid);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
fatal("Stdio forwarding request failed: %s", e);
default:
sshbuf_free(m);
- error("%s: unexpected response from master 0x%08x",
- __func__, type);
+ error_f("unexpected response from master 0x%08x", type);
return -1;
}
muxclient_request_id++;
- signal(SIGHUP, control_client_sighandler);
- signal(SIGINT, control_client_sighandler);
- signal(SIGTERM, control_client_sighandler);
- signal(SIGWINCH, control_client_sigrelay);
+ ssh_signal(SIGHUP, control_client_sighandler);
+ ssh_signal(SIGINT, control_client_sighandler);
+ ssh_signal(SIGTERM, control_client_sighandler);
+ ssh_signal(SIGWINCH, control_client_sigrelay);
/*
* Stick around until the controlee closes the client_fd.
@@ -2223,10 +2205,9 @@ mux_client_request_stdio_fwd(int fd)
if (errno == EPIPE ||
(errno == EINTR && muxclient_terminate != 0))
return 0;
- fatal("%s: mux_client_read_packet: %s",
- __func__, strerror(errno));
+ fatal_f("mux_client_read_packet: %s", strerror(errno));
}
- fatal("%s: master returned unexpected message %u", __func__, type);
+ fatal_f("master returned unexpected message %u", type);
}
static void
@@ -2237,45 +2218,43 @@ mux_client_request_stop_listening(int fd)
u_int type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0)
- fatal("%s: read from master failed: %s",
- __func__, strerror(errno));
+ fatal_f("read from master failed: %s", strerror(errno));
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
fatal("Master refused stop listening request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: stop listening request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("stop listening request failed: %s", e);
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
muxclient_request_id++;
@@ -2286,7 +2265,7 @@ int
muxclient(const char *path)
{
struct sockaddr_un addr;
- int sock;
+ int sock, timeout = options.connection_timeout, timeout_ms = -1;
u_int pid;
if (muxclient_command == 0) {
@@ -2299,7 +2278,7 @@ muxclient(const char *path)
switch (options.control_master) {
case SSHCTL_MASTER_AUTO:
case SSHCTL_MASTER_AUTO_ASK:
- debug("auto-mux: Trying existing master");
+ debug("auto-mux: Trying existing master at '%s'", path);
/* FALLTHROUGH */
case SSHCTL_MASTER_NO:
break;
@@ -2313,10 +2292,10 @@ muxclient(const char *path)
if (strlcpy(addr.sun_path, path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
fatal("ControlPath too long ('%s' >= %u bytes)", path,
- (unsigned int)sizeof(addr.sun_path));
+ (unsigned int)sizeof(addr.sun_path));
- if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
- fatal("%s socket(): %s", __func__, strerror(errno));
+ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+ fatal_f("socket(): %s", strerror(errno));
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
switch (muxclient_command) {
@@ -2342,8 +2321,12 @@ muxclient(const char *path)
}
set_nonblock(sock);
- if (mux_client_hello_exchange(sock) != 0) {
- error("%s: master hello exchange failed", __func__);
+ /* Timeout on initial connection only. */
+ if (timeout > 0 && timeout < INT_MAX / 1000)
+ timeout_ms = timeout * 1000;
+
+ if (mux_client_hello_exchange(sock, timeout_ms) != 0) {
+ error_f("master hello exchange failed");
close(sock);
return -1;
}
@@ -2351,7 +2334,7 @@ muxclient(const char *path)
switch (muxclient_command) {
case SSHMUX_COMMAND_ALIVE_CHECK:
if ((pid = mux_client_request_alive(sock)) == 0)
- fatal("%s: master alive check failed", __func__);
+ fatal_f("master alive check failed");
fprintf(stderr, "Master running (pid=%u)\r\n", pid);
exit(0);
case SSHMUX_COMMAND_TERMINATE:
@@ -2361,11 +2344,11 @@ muxclient(const char *path)
exit(0);
case SSHMUX_COMMAND_FORWARD:
if (mux_client_forwards(sock, 0) != 0)
- fatal("%s: master forward request failed", __func__);
+ fatal_f("master forward request failed");
exit(0);
case SSHMUX_COMMAND_OPEN:
if (mux_client_forwards(sock, 0) != 0) {
- error("%s: master forward request failed", __func__);
+ error_f("master forward request failed");
return -1;
}
mux_client_request_session(sock);
@@ -2380,8 +2363,7 @@ muxclient(const char *path)
exit(0);
case SSHMUX_COMMAND_CANCEL_FWD:
if (mux_client_forwards(sock, 1) != 0)
- error("%s: master cancel forward request failed",
- __func__);
+ error_f("master cancel forward request failed");
exit(0);
case SSHMUX_COMMAND_PROXY:
mux_client_proxy(sock);