aboutsummaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2011-02-17 11:47:40 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2011-02-17 11:47:40 +0000
commit9f6de2d748109e4e479c9259468a79973631e7fc (patch)
tree1d333e32031110bf9bfd5e15980adf8221240df8 /mux.c
parent3a927e69c380468bb32766c99aa7caf86de401a4 (diff)
downloadsrc-9f6de2d748109e4e479c9259468a79973631e7fc.tar.gz
src-9f6de2d748109e4e479c9259468a79973631e7fc.zip
Vendor import of OpenSSH 5.7p1vendor/openssh/5.7p1
Notes
Notes: svn path=/vendor-crypto/openssh/dist/; revision=218767 svn path=/vendor-crypto/openssh/5.7p1/; revision=218768; tag=vendor/openssh/5.7p1
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/mux.c b/mux.c
index 5c3857ee816b..e370462db5a2 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -879,7 +879,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
- if (!ask_permission("Allow forward to to %s:%u? ",
+ if (!ask_permission("Allow forward to %s:%u? ",
chost, cport)) {
debug2("%s: stdio fwd refused by user", __func__);
/* prepare reply */
@@ -1026,6 +1026,9 @@ muxserver_listen(void)
struct sockaddr_un addr;
socklen_t sun_len;
mode_t old_umask;
+ char *orig_control_path = options.control_path;
+ char rbuf[16+1];
+ u_int i, r;
if (options.control_path == NULL ||
options.control_master == SSHCTL_MASTER_NO)
@@ -1033,6 +1036,23 @@ muxserver_listen(void)
debug("setting up multiplex master socket");
+ /*
+ * Use a temporary path before listen so we can pseudo-atomically
+ * establish the listening socket in its final location to avoid
+ * other processes racing in between bind() and listen() and hitting
+ * an unready socket.
+ */
+ for (i = 0; i < sizeof(rbuf) - 1; i++) {
+ r = arc4random_uniform(26+26+10);
+ rbuf[i] = (r < 26) ? 'a' + r :
+ (r < 26*2) ? 'A' + r - 26 :
+ '0' + r - 26 - 26;
+ }
+ 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);
+
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
sun_len = offsetof(struct sockaddr_un, sun_path) +
@@ -1051,6 +1071,7 @@ muxserver_listen(void)
if (errno == EINVAL || errno == EADDRINUSE) {
error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path);
+ disable_mux_master:
close(muxserver_sock);
muxserver_sock = -1;
xfree(options.control_path);
@@ -1065,12 +1086,29 @@ muxserver_listen(void)
if (listen(muxserver_sock, 64) == -1)
fatal("%s listen(): %s", __func__, strerror(errno));
+ /* 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__,
+ options.control_path, orig_control_path,
+ strerror(errno));
+ }
+ error("ControlSocket %s already exists, disabling multiplexing",
+ orig_control_path);
+ xfree(orig_control_path);
+ unlink(options.control_path);
+ goto disable_mux_master;
+ }
+ unlink(options.control_path);
+ xfree(options.control_path);
+ options.control_path = orig_control_path;
+
set_nonblock(muxserver_sock);
mux_listener_channel = channel_new("mux listener",
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
- 0, addr.sun_path, 1);
+ 0, options.control_path, 1);
mux_listener_channel->mux_rcb = mux_master_read_cb;
debug3("%s: mux listener channel %d fd %d", __func__,
mux_listener_channel->self, mux_listener_channel->sock);
@@ -1492,7 +1530,7 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd)
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
- error("%s: session request failed: %s", __func__, e);
+ error("%s: forwarding request failed: %s", __func__, e);
return -1;
default:
fatal("%s: unexpected response from master 0x%08x",
@@ -1611,12 +1649,12 @@ mux_client_request_session(int fd)
case MUX_S_PERMISSION_DENIED:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
- error("Master refused forwarding request: %s", e);
+ error("Master refused session request: %s", e);
return -1;
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
- error("%s: forwarding request failed: %s", __func__, e);
+ error("%s: session request failed: %s", __func__, e);
return -1;
default:
buffer_free(&m);
@@ -1743,7 +1781,7 @@ mux_client_request_stdio_fwd(int fd)
case MUX_S_PERMISSION_DENIED:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
- fatal("Master refused forwarding request: %s", e);
+ fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
e = buffer_get_string(&m, NULL);
buffer_free(&m);
@@ -1823,9 +1861,13 @@ muxclient(const char *path)
fatal("Control socket connect(%.100s): %s", path,
strerror(errno));
}
- if (errno == ENOENT)
+ if (errno == ECONNREFUSED &&
+ options.control_master != SSHCTL_MASTER_NO) {
+ debug("Stale control socket %.100s, unlinking", path);
+ unlink(path);
+ } else if (errno == ENOENT) {
debug("Control socket \"%.100s\" does not exist", path);
- else {
+ } else {
error("Control socket connect(%.100s): %s", path,
strerror(errno));
}