diff options
author | Colin Watson <cjwatson@debian.org> | 2011-01-24 12:43:25 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2011-01-24 12:43:25 +0000 |
commit | 626f1d986ff72aa514da63e34744e1de9cf21b9a (patch) | |
tree | d215a5280bc2e57251e4a9e08bfd3674ad824a94 /mux.c | |
parent | 6ed622cb6fe8f71bbe0d998cdd12280410bfb420 (diff) | |
parent | 0970072c89b079b022538e3c366fbfa2c53fc821 (diff) |
* New upstream release (http://www.openssh.org/txt/release-5.7):
- Implement Elliptic Curve Cryptography modes for key exchange (ECDH)
and host/user keys (ECDSA) as specified by RFC5656. ECDH and ECDSA
offer better performance than plain DH and DSA at the same equivalent
symmetric key length, as well as much shorter keys.
- sftp(1)/sftp-server(8): add a protocol extension to support a hard
link operation. It is available through the "ln" command in the
client. The old "ln" behaviour of creating a symlink is available
using its "-s" option or through the preexisting "symlink" command.
- scp(1): Add a new -3 option to scp: Copies between two remote hosts
are transferred through the local host (closes: #508613).
- ssh(1): "atomically" create the listening mux socket by binding it on
a temporary name and then linking it into position after listen() has
succeeded. This allows the mux clients to determine that the server
socket is either ready or stale without races (closes: #454784).
Stale server sockets are now automatically removed (closes: #523250).
- ssh(1): install a SIGCHLD handler to reap expired child process
(closes: #594687).
- ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent
temporary directories (closes: #357469, although only if you arrange
for ssh-agent to actually see $TMPDIR since the setgid bit will cause
it to be stripped off).
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 60 |
1 files changed, 51 insertions, 9 deletions
@@ -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.24 2011/01/13 21:54:53 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 | * |
@@ -879,7 +879,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
879 | 879 | ||
880 | if (options.control_master == SSHCTL_MASTER_ASK || | 880 | if (options.control_master == SSHCTL_MASTER_ASK || |
881 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { | 881 | options.control_master == SSHCTL_MASTER_AUTO_ASK) { |
882 | if (!ask_permission("Allow forward to to %s:%u? ", | 882 | if (!ask_permission("Allow forward to %s:%u? ", |
883 | chost, cport)) { | 883 | chost, cport)) { |
884 | debug2("%s: stdio fwd refused by user", __func__); | 884 | debug2("%s: stdio fwd refused by user", __func__); |
885 | /* prepare reply */ | 885 | /* prepare reply */ |
@@ -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); |
@@ -1492,7 +1530,7 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) | |||
1492 | case MUX_S_FAILURE: | 1530 | case MUX_S_FAILURE: |
1493 | e = buffer_get_string(&m, NULL); | 1531 | e = buffer_get_string(&m, NULL); |
1494 | buffer_free(&m); | 1532 | buffer_free(&m); |
1495 | error("%s: session request failed: %s", __func__, e); | 1533 | error("%s: forwarding request failed: %s", __func__, e); |
1496 | return -1; | 1534 | return -1; |
1497 | default: | 1535 | default: |
1498 | fatal("%s: unexpected response from master 0x%08x", | 1536 | fatal("%s: unexpected response from master 0x%08x", |
@@ -1611,12 +1649,12 @@ mux_client_request_session(int fd) | |||
1611 | case MUX_S_PERMISSION_DENIED: | 1649 | case MUX_S_PERMISSION_DENIED: |
1612 | e = buffer_get_string(&m, NULL); | 1650 | e = buffer_get_string(&m, NULL); |
1613 | buffer_free(&m); | 1651 | buffer_free(&m); |
1614 | error("Master refused forwarding request: %s", e); | 1652 | error("Master refused session request: %s", e); |
1615 | return -1; | 1653 | return -1; |
1616 | case MUX_S_FAILURE: | 1654 | case MUX_S_FAILURE: |
1617 | e = buffer_get_string(&m, NULL); | 1655 | e = buffer_get_string(&m, NULL); |
1618 | buffer_free(&m); | 1656 | buffer_free(&m); |
1619 | error("%s: forwarding request failed: %s", __func__, e); | 1657 | error("%s: session request failed: %s", __func__, e); |
1620 | return -1; | 1658 | return -1; |
1621 | default: | 1659 | default: |
1622 | buffer_free(&m); | 1660 | buffer_free(&m); |
@@ -1743,7 +1781,7 @@ mux_client_request_stdio_fwd(int fd) | |||
1743 | case MUX_S_PERMISSION_DENIED: | 1781 | case MUX_S_PERMISSION_DENIED: |
1744 | e = buffer_get_string(&m, NULL); | 1782 | e = buffer_get_string(&m, NULL); |
1745 | buffer_free(&m); | 1783 | buffer_free(&m); |
1746 | fatal("Master refused forwarding request: %s", e); | 1784 | fatal("Master refused stdio forwarding request: %s", e); |
1747 | case MUX_S_FAILURE: | 1785 | case MUX_S_FAILURE: |
1748 | e = buffer_get_string(&m, NULL); | 1786 | e = buffer_get_string(&m, NULL); |
1749 | buffer_free(&m); | 1787 | buffer_free(&m); |
@@ -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 | } |