summaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2011-09-06 09:45:52 +0100
committerColin Watson <cjwatson@debian.org>2011-09-06 09:45:52 +0100
commitf38224d546cdde55f45c13d3d8225d273a3f920e (patch)
treea91a26b88ac90dc72d0ea3767feabb341eaa50a8 /mux.c
parent338146a3fc257e216fe5c10fe40e6896b40d7739 (diff)
parente90790abaf031e037f444a6658e136e48577ea49 (diff)
merge 5.9p1
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c167
1 files changed, 146 insertions, 21 deletions
diff --git a/mux.c b/mux.c
index e370462db..add0e26b1 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 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 *
@@ -87,7 +87,6 @@
87 87
88/* from ssh.c */ 88/* from ssh.c */
89extern int tty_flag; 89extern int tty_flag;
90extern int force_tty_flag;
91extern Options options; 90extern Options options;
92extern int stdin_null_flag; 91extern int stdin_null_flag;
93extern char *host; 92extern char *host;
@@ -146,6 +145,7 @@ struct mux_master_state {
146#define MUX_C_OPEN_FWD 0x10000006 145#define MUX_C_OPEN_FWD 0x10000006
147#define MUX_C_CLOSE_FWD 0x10000007 146#define MUX_C_CLOSE_FWD 0x10000007
148#define MUX_C_NEW_STDIO_FWD 0x10000008 147#define MUX_C_NEW_STDIO_FWD 0x10000008
148#define MUX_C_STOP_LISTENING 0x10000009
149#define MUX_S_OK 0x80000001 149#define MUX_S_OK 0x80000001
150#define MUX_S_PERMISSION_DENIED 0x80000002 150#define MUX_S_PERMISSION_DENIED 0x80000002
151#define MUX_S_FAILURE 0x80000003 151#define MUX_S_FAILURE 0x80000003
@@ -153,6 +153,7 @@ struct mux_master_state {
153#define MUX_S_ALIVE 0x80000005 153#define MUX_S_ALIVE 0x80000005
154#define MUX_S_SESSION_OPENED 0x80000006 154#define MUX_S_SESSION_OPENED 0x80000006
155#define MUX_S_REMOTE_PORT 0x80000007 155#define MUX_S_REMOTE_PORT 0x80000007
156#define MUX_S_TTY_ALLOC_FAIL 0x80000008
156 157
157/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ 158/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
158#define MUX_FWD_LOCAL 1 159#define MUX_FWD_LOCAL 1
@@ -168,6 +169,7 @@ static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
168static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); 169static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
169static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); 170static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
170static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); 171static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
172static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
171 173
172static const struct { 174static const struct {
173 u_int type; 175 u_int type;
@@ -180,6 +182,7 @@ static const struct {
180 { MUX_C_OPEN_FWD, process_mux_open_fwd }, 182 { MUX_C_OPEN_FWD, process_mux_open_fwd },
181 { MUX_C_CLOSE_FWD, process_mux_close_fwd }, 183 { MUX_C_CLOSE_FWD, process_mux_close_fwd },
182 { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, 184 { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
185 { MUX_C_STOP_LISTENING, process_mux_stop_listening },
183 { 0, NULL } 186 { 0, NULL }
184}; 187};
185 188
@@ -915,6 +918,39 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
915 return 0; 918 return 0;
916} 919}
917 920
921static int
922process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
923{
924 debug("%s: channel %d: stop listening", __func__, c->self);
925
926 if (options.control_master == SSHCTL_MASTER_ASK ||
927 options.control_master == SSHCTL_MASTER_AUTO_ASK) {
928 if (!ask_permission("Disable further multiplexing on shared "
929 "connection to %s? ", host)) {
930 debug2("%s: stop listen refused by user", __func__);
931 buffer_put_int(r, MUX_S_PERMISSION_DENIED);
932 buffer_put_int(r, rid);
933 buffer_put_cstring(r, "Permission denied");
934 return 0;
935 }
936 }
937
938 if (mux_listener_channel != NULL) {
939 channel_free(mux_listener_channel);
940 client_stop_mux();
941 xfree(options.control_path);
942 options.control_path = NULL;
943 mux_listener_channel = NULL;
944 muxserver_sock = -1;
945 }
946
947 /* prepare reply */
948 buffer_put_int(r, MUX_S_OK);
949 buffer_put_int(r, rid);
950
951 return 0;
952}
953
918/* Channel callbacks fired on read/write from mux slave fd */ 954/* Channel callbacks fired on read/write from mux slave fd */
919static int 955static int
920mux_master_read_cb(Channel *c) 956mux_master_read_cb(Channel *c)
@@ -1019,6 +1055,27 @@ mux_exit_message(Channel *c, int exitval)
1019 buffer_free(&m); 1055 buffer_free(&m);
1020} 1056}
1021 1057
1058void
1059mux_tty_alloc_failed(Channel *c)
1060{
1061 Buffer m;
1062 Channel *mux_chan;
1063
1064 debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
1065
1066 if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
1067 fatal("%s: channel %d missing mux channel %d",
1068 __func__, c->self, c->ctl_chan);
1069
1070 /* Append exit message packet to control socket output queue */
1071 buffer_init(&m);
1072 buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
1073 buffer_put_int(&m, c->self);
1074
1075 buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
1076 buffer_free(&m);
1077}
1078
1022/* Prepare a mux master to listen on a Unix domain socket. */ 1079/* Prepare a mux master to listen on a Unix domain socket. */
1023void 1080void
1024muxserver_listen(void) 1081muxserver_listen(void)
@@ -1059,21 +1116,25 @@ muxserver_listen(void)
1059 strlen(options.control_path) + 1; 1116 strlen(options.control_path) + 1;
1060 1117
1061 if (strlcpy(addr.sun_path, options.control_path, 1118 if (strlcpy(addr.sun_path, options.control_path,
1062 sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) 1119 sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
1063 fatal("ControlPath too long"); 1120 error("ControlPath \"%s\" too long for Unix domain socket",
1121 options.control_path);
1122 goto disable_mux_master;
1123 }
1064 1124
1065 if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) 1125 if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1066 fatal("%s socket(): %s", __func__, strerror(errno)); 1126 fatal("%s socket(): %s", __func__, strerror(errno));
1067 1127
1068 old_umask = umask(0177); 1128 old_umask = umask(0177);
1069 if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { 1129 if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) {
1070 muxserver_sock = -1;
1071 if (errno == EINVAL || errno == EADDRINUSE) { 1130 if (errno == EINVAL || errno == EADDRINUSE) {
1072 error("ControlSocket %s already exists, " 1131 error("ControlSocket %s already exists, "
1073 "disabling multiplexing", options.control_path); 1132 "disabling multiplexing", options.control_path);
1074 disable_mux_master: 1133 disable_mux_master:
1075 close(muxserver_sock); 1134 if (muxserver_sock != -1) {
1076 muxserver_sock = -1; 1135 close(muxserver_sock);
1136 muxserver_sock = -1;
1137 }
1077 xfree(options.control_path); 1138 xfree(options.control_path);
1078 options.control_path = NULL; 1139 options.control_path = NULL;
1079 options.control_master = SSHCTL_MASTER_NO; 1140 options.control_master = SSHCTL_MASTER_NO;
@@ -1153,8 +1214,10 @@ mux_session_confirm(int id, int success, void *arg)
1153 /* Request forwarding with authentication spoofing. */ 1214 /* Request forwarding with authentication spoofing. */
1154 debug("Requesting X11 forwarding with authentication " 1215 debug("Requesting X11 forwarding with authentication "
1155 "spoofing."); 1216 "spoofing.");
1156 x11_request_forwarding_with_spoofing(id, display, proto, data); 1217 x11_request_forwarding_with_spoofing(id, display, proto,
1157 /* XXX wait for reply */ 1218 data, 1);
1219 client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
1220 /* XXX exit_on_forward_failure */
1158 } 1221 }
1159 1222
1160 if (cctx->want_agent_fwd && options.forward_agent) { 1223 if (cctx->want_agent_fwd && options.forward_agent) {
@@ -1573,7 +1636,7 @@ mux_client_request_session(int fd)
1573 char *e, *term; 1636 char *e, *term;
1574 u_int i, rid, sid, esid, exitval, type, exitval_seen; 1637 u_int i, rid, sid, esid, exitval, type, exitval_seen;
1575 extern char **environ; 1638 extern char **environ;
1576 int devnull; 1639 int devnull, rawmode;
1577 1640
1578 debug3("%s: entering", __func__); 1641 debug3("%s: entering", __func__);
1579 1642
@@ -1669,8 +1732,9 @@ mux_client_request_session(int fd)
1669 signal(SIGTERM, control_client_sighandler); 1732 signal(SIGTERM, control_client_sighandler);
1670 signal(SIGWINCH, control_client_sigrelay); 1733 signal(SIGWINCH, control_client_sigrelay);
1671 1734
1735 rawmode = tty_flag;
1672 if (tty_flag) 1736 if (tty_flag)
1673 enter_raw_mode(force_tty_flag); 1737 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1674 1738
1675 /* 1739 /*
1676 * Stick around until the controlee closes the client_fd. 1740 * Stick around until the controlee closes the client_fd.
@@ -1684,22 +1748,35 @@ mux_client_request_session(int fd)
1684 if (mux_client_read_packet(fd, &m) != 0) 1748 if (mux_client_read_packet(fd, &m) != 0)
1685 break; 1749 break;
1686 type = buffer_get_int(&m); 1750 type = buffer_get_int(&m);
1687 if (type != MUX_S_EXIT_MESSAGE) { 1751 switch (type) {
1752 case MUX_S_TTY_ALLOC_FAIL:
1753 if ((esid = buffer_get_int(&m)) != sid)
1754 fatal("%s: tty alloc fail on unknown session: "
1755 "my id %u theirs %u",
1756 __func__, sid, esid);
1757 leave_raw_mode(options.request_tty ==
1758 REQUEST_TTY_FORCE);
1759 rawmode = 0;
1760 continue;
1761 case MUX_S_EXIT_MESSAGE:
1762 if ((esid = buffer_get_int(&m)) != sid)
1763 fatal("%s: exit on unknown session: "
1764 "my id %u theirs %u",
1765 __func__, sid, esid);
1766 if (exitval_seen)
1767 fatal("%s: exitval sent twice", __func__);
1768 exitval = buffer_get_int(&m);
1769 exitval_seen = 1;
1770 continue;
1771 default:
1688 e = buffer_get_string(&m, NULL); 1772 e = buffer_get_string(&m, NULL);
1689 fatal("%s: master returned error: %s", __func__, e); 1773 fatal("%s: master returned error: %s", __func__, e);
1690 } 1774 }
1691 if ((esid = buffer_get_int(&m)) != sid)
1692 fatal("%s: exit on unknown session: my id %u theirs %u",
1693 __func__, sid, esid);
1694 debug("%s: master session id: %u", __func__, sid);
1695 if (exitval_seen)
1696 fatal("%s: exitval sent twice", __func__);
1697 exitval = buffer_get_int(&m);
1698 exitval_seen = 1;
1699 } 1775 }
1700 1776
1701 close(fd); 1777 close(fd);
1702 leave_raw_mode(force_tty_flag); 1778 if (rawmode)
1779 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1703 1780
1704 if (muxclient_terminate) { 1781 if (muxclient_terminate) {
1705 debug2("Exiting on signal %d", muxclient_terminate); 1782 debug2("Exiting on signal %d", muxclient_terminate);
@@ -1813,6 +1890,50 @@ mux_client_request_stdio_fwd(int fd)
1813 fatal("%s: master returned unexpected message %u", __func__, type); 1890 fatal("%s: master returned unexpected message %u", __func__, type);
1814} 1891}
1815 1892
1893static void
1894mux_client_request_stop_listening(int fd)
1895{
1896 Buffer m;
1897 char *e;
1898 u_int type, rid;
1899
1900 debug3("%s: entering", __func__);
1901
1902 buffer_init(&m);
1903 buffer_put_int(&m, MUX_C_STOP_LISTENING);
1904 buffer_put_int(&m, muxclient_request_id);
1905
1906 if (mux_client_write_packet(fd, &m) != 0)
1907 fatal("%s: write packet: %s", __func__, strerror(errno));
1908
1909 buffer_clear(&m);
1910
1911 /* Read their reply */
1912 if (mux_client_read_packet(fd, &m) != 0)
1913 fatal("%s: read from master failed: %s",
1914 __func__, strerror(errno));
1915
1916 type = buffer_get_int(&m);
1917 if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1918 fatal("%s: out of sequence reply: my id %u theirs %u",
1919 __func__, muxclient_request_id, rid);
1920 switch (type) {
1921 case MUX_S_OK:
1922 break;
1923 case MUX_S_PERMISSION_DENIED:
1924 e = buffer_get_string(&m, NULL);
1925 fatal("Master refused stop listening request: %s", e);
1926 case MUX_S_FAILURE:
1927 e = buffer_get_string(&m, NULL);
1928 fatal("%s: stop listening request failed: %s", __func__, e);
1929 default:
1930 fatal("%s: unexpected response from master 0x%08x",
1931 __func__, type);
1932 }
1933 buffer_free(&m);
1934 muxclient_request_id++;
1935}
1936
1816/* Multiplex client main loop. */ 1937/* Multiplex client main loop. */
1817void 1938void
1818muxclient(const char *path) 1939muxclient(const char *path)
@@ -1906,6 +2027,10 @@ muxclient(const char *path)
1906 case SSHMUX_COMMAND_STDIO_FWD: 2027 case SSHMUX_COMMAND_STDIO_FWD:
1907 mux_client_request_stdio_fwd(sock); 2028 mux_client_request_stdio_fwd(sock);
1908 exit(0); 2029 exit(0);
2030 case SSHMUX_COMMAND_STOP:
2031 mux_client_request_stop_listening(sock);
2032 fprintf(stderr, "Stop listening request sent.\r\n");
2033 exit(0);
1909 default: 2034 default:
1910 fatal("unrecognised muxclient_command %d", muxclient_command); 2035 fatal("unrecognised muxclient_command %d", muxclient_command);
1911 } 2036 }