summaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/mux.c b/mux.c
index 5c3857ee8..c010b614e 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.22 2010/09/20 07:19:27 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -1026,6 +1026,9 @@ muxserver_listen(void)
1026 struct sockaddr_un addr; 1026 struct sockaddr_un addr;
1027 socklen_t sun_len; 1027 socklen_t sun_len;
1028 mode_t old_umask; 1028 mode_t old_umask;
1029 char *orig_control_path = options.control_path;
1030 char rbuf[16+1];
1031 u_int i, r;
1029 1032
1030 if (options.control_path == NULL || 1033 if (options.control_path == NULL ||
1031 options.control_master == SSHCTL_MASTER_NO) 1034 options.control_master == SSHCTL_MASTER_NO)
@@ -1033,6 +1036,23 @@ muxserver_listen(void)
1033 1036
1034 debug("setting up multiplex master socket"); 1037 debug("setting up multiplex master socket");
1035 1038
1039 /*
1040 * Use a temporary path before listen so we can pseudo-atomically
1041 * establish the listening socket in its final location to avoid
1042 * other processes racing in between bind() and listen() and hitting
1043 * an unready socket.
1044 */
1045 for (i = 0; i < sizeof(rbuf) - 1; i++) {
1046 r = arc4random_uniform(26+26+10);
1047 rbuf[i] = (r < 26) ? 'a' + r :
1048 (r < 26*2) ? 'A' + r - 26 :
1049 '0' + r - 26 - 26;
1050 }
1051 rbuf[sizeof(rbuf) - 1] = '\0';
1052 options.control_path = NULL;
1053 xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
1054 debug3("%s: temporary control path %s", __func__, options.control_path);
1055
1036 memset(&addr, '\0', sizeof(addr)); 1056 memset(&addr, '\0', sizeof(addr));
1037 addr.sun_family = AF_UNIX; 1057 addr.sun_family = AF_UNIX;
1038 sun_len = offsetof(struct sockaddr_un, sun_path) + 1058 sun_len = offsetof(struct sockaddr_un, sun_path) +
@@ -1051,6 +1071,7 @@ muxserver_listen(void)
1051 if (errno == EINVAL || errno == EADDRINUSE) { 1071 if (errno == EINVAL || errno == EADDRINUSE) {
1052 error("ControlSocket %s already exists, " 1072 error("ControlSocket %s already exists, "
1053 "disabling multiplexing", options.control_path); 1073 "disabling multiplexing", options.control_path);
1074 disable_mux_master:
1054 close(muxserver_sock); 1075 close(muxserver_sock);
1055 muxserver_sock = -1; 1076 muxserver_sock = -1;
1056 xfree(options.control_path); 1077 xfree(options.control_path);
@@ -1065,12 +1086,29 @@ muxserver_listen(void)
1065 if (listen(muxserver_sock, 64) == -1) 1086 if (listen(muxserver_sock, 64) == -1)
1066 fatal("%s listen(): %s", __func__, strerror(errno)); 1087 fatal("%s listen(): %s", __func__, strerror(errno));
1067 1088
1089 /* Now atomically "move" the mux socket into position */
1090 if (link(options.control_path, orig_control_path) != 0) {
1091 if (errno != EEXIST) {
1092 fatal("%s: link mux listener %s => %s: %s", __func__,
1093 options.control_path, orig_control_path,
1094 strerror(errno));
1095 }
1096 error("ControlSocket %s already exists, disabling multiplexing",
1097 orig_control_path);
1098 xfree(orig_control_path);
1099 unlink(options.control_path);
1100 goto disable_mux_master;
1101 }
1102 unlink(options.control_path);
1103 xfree(options.control_path);
1104 options.control_path = orig_control_path;
1105
1068 set_nonblock(muxserver_sock); 1106 set_nonblock(muxserver_sock);
1069 1107
1070 mux_listener_channel = channel_new("mux listener", 1108 mux_listener_channel = channel_new("mux listener",
1071 SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, 1109 SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
1072 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 1110 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1073 0, addr.sun_path, 1); 1111 0, options.control_path, 1);
1074 mux_listener_channel->mux_rcb = mux_master_read_cb; 1112 mux_listener_channel->mux_rcb = mux_master_read_cb;
1075 debug3("%s: mux listener channel %d fd %d", __func__, 1113 debug3("%s: mux listener channel %d fd %d", __func__,
1076 mux_listener_channel->self, mux_listener_channel->sock); 1114 mux_listener_channel->self, mux_listener_channel->sock);
@@ -1823,9 +1861,13 @@ muxclient(const char *path)
1823 fatal("Control socket connect(%.100s): %s", path, 1861 fatal("Control socket connect(%.100s): %s", path,
1824 strerror(errno)); 1862 strerror(errno));
1825 } 1863 }
1826 if (errno == ENOENT) 1864 if (errno == ECONNREFUSED &&
1865 options.control_master != SSHCTL_MASTER_NO) {
1866 debug("Stale control socket %.100s, unlinking", path);
1867 unlink(path);
1868 } else if (errno == ENOENT) {
1827 debug("Control socket \"%.100s\" does not exist", path); 1869 debug("Control socket \"%.100s\" does not exist", path);
1828 else { 1870 } else {
1829 error("Control socket connect(%.100s): %s", path, 1871 error("Control socket connect(%.100s): %s", path,
1830 strerror(errno)); 1872 strerror(errno));
1831 } 1873 }