diff options
author | markus@openbsd.org <markus@openbsd.org> | 2016-09-30 09:19:13 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2016-10-01 02:45:10 +1000 |
commit | 8d0578478586e283e751ca51e7b0690631da139a (patch) | |
tree | 3621da2b97213f8ff0b434f5fd239dfd4f50d83d /mux.c | |
parent | b7689155f3f5c4999846c07a852b1c7a43b09cec (diff) |
upstream commit
ssh proxy mux mode (-O proxy; idea from Simon Tatham): - mux
client speaks the ssh-packet protocol directly over unix-domain socket. - mux
server acts as a proxy, translates channel IDs and relays to the server. - no
filedescriptor passing necessary. - combined with unix-domain forwarding it's
even possible to run mux client and server on different machines. feedback
& ok djm@
Upstream-ID: 666a2fb79f58e5c50e246265fb2b9251e505c25b
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 69 |
1 files changed, 62 insertions, 7 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.61 2016/08/08 22:40:57 dtucker Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.62 2016/09/30 09:19:13 markus 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 | * |
@@ -79,6 +79,7 @@ | |||
79 | #include "key.h" | 79 | #include "key.h" |
80 | #include "readconf.h" | 80 | #include "readconf.h" |
81 | #include "clientloop.h" | 81 | #include "clientloop.h" |
82 | #include "ssherr.h" | ||
82 | 83 | ||
83 | /* from ssh.c */ | 84 | /* from ssh.c */ |
84 | extern int tty_flag; | 85 | extern int tty_flag; |
@@ -144,6 +145,7 @@ struct mux_master_state { | |||
144 | #define MUX_C_CLOSE_FWD 0x10000007 | 145 | #define MUX_C_CLOSE_FWD 0x10000007 |
145 | #define MUX_C_NEW_STDIO_FWD 0x10000008 | 146 | #define MUX_C_NEW_STDIO_FWD 0x10000008 |
146 | #define MUX_C_STOP_LISTENING 0x10000009 | 147 | #define MUX_C_STOP_LISTENING 0x10000009 |
148 | #define MUX_C_PROXY 0x1000000f | ||
147 | #define MUX_S_OK 0x80000001 | 149 | #define MUX_S_OK 0x80000001 |
148 | #define MUX_S_PERMISSION_DENIED 0x80000002 | 150 | #define MUX_S_PERMISSION_DENIED 0x80000002 |
149 | #define MUX_S_FAILURE 0x80000003 | 151 | #define MUX_S_FAILURE 0x80000003 |
@@ -152,6 +154,7 @@ struct mux_master_state { | |||
152 | #define MUX_S_SESSION_OPENED 0x80000006 | 154 | #define MUX_S_SESSION_OPENED 0x80000006 |
153 | #define MUX_S_REMOTE_PORT 0x80000007 | 155 | #define MUX_S_REMOTE_PORT 0x80000007 |
154 | #define MUX_S_TTY_ALLOC_FAIL 0x80000008 | 156 | #define MUX_S_TTY_ALLOC_FAIL 0x80000008 |
157 | #define MUX_S_PROXY 0x8000000f | ||
155 | 158 | ||
156 | /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ | 159 | /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ |
157 | #define MUX_FWD_LOCAL 1 | 160 | #define MUX_FWD_LOCAL 1 |
@@ -169,6 +172,7 @@ static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); | |||
169 | static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); | 172 | static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); |
170 | static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); | 173 | static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); |
171 | static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); | 174 | static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); |
175 | static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *); | ||
172 | 176 | ||
173 | static const struct { | 177 | static const struct { |
174 | u_int type; | 178 | u_int type; |
@@ -182,6 +186,7 @@ static const struct { | |||
182 | { MUX_C_CLOSE_FWD, process_mux_close_fwd }, | 186 | { MUX_C_CLOSE_FWD, process_mux_close_fwd }, |
183 | { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, | 187 | { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, |
184 | { MUX_C_STOP_LISTENING, process_mux_stop_listening }, | 188 | { MUX_C_STOP_LISTENING, process_mux_stop_listening }, |
189 | { MUX_C_PROXY, process_mux_proxy }, | ||
185 | { 0, NULL } | 190 | { 0, NULL } |
186 | }; | 191 | }; |
187 | 192 | ||
@@ -1110,6 +1115,18 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1110 | return 0; | 1115 | return 0; |
1111 | } | 1116 | } |
1112 | 1117 | ||
1118 | static int | ||
1119 | process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) | ||
1120 | { | ||
1121 | debug("%s: channel %d: proxy request", __func__, c->self); | ||
1122 | |||
1123 | c->mux_rcb = channel_proxy_downstream; | ||
1124 | buffer_put_int(r, MUX_S_PROXY); | ||
1125 | buffer_put_int(r, rid); | ||
1126 | |||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1113 | /* Channel callbacks fired on read/write from mux slave fd */ | 1130 | /* Channel callbacks fired on read/write from mux slave fd */ |
1114 | static int | 1131 | static int |
1115 | mux_master_read_cb(Channel *c) | 1132 | mux_master_read_cb(Channel *c) |
@@ -1960,6 +1977,41 @@ mux_client_request_session(int fd) | |||
1960 | } | 1977 | } |
1961 | 1978 | ||
1962 | static int | 1979 | static int |
1980 | mux_client_proxy(int fd) | ||
1981 | { | ||
1982 | Buffer m; | ||
1983 | char *e; | ||
1984 | u_int type, rid; | ||
1985 | |||
1986 | buffer_init(&m); | ||
1987 | buffer_put_int(&m, MUX_C_PROXY); | ||
1988 | buffer_put_int(&m, muxclient_request_id); | ||
1989 | if (mux_client_write_packet(fd, &m) != 0) | ||
1990 | fatal("%s: write packet: %s", __func__, strerror(errno)); | ||
1991 | |||
1992 | buffer_clear(&m); | ||
1993 | |||
1994 | /* Read their reply */ | ||
1995 | if (mux_client_read_packet(fd, &m) != 0) { | ||
1996 | buffer_free(&m); | ||
1997 | return 0; | ||
1998 | } | ||
1999 | type = buffer_get_int(&m); | ||
2000 | if (type != MUX_S_PROXY) { | ||
2001 | e = buffer_get_string(&m, NULL); | ||
2002 | fatal("%s: master returned error: %s", __func__, e); | ||
2003 | } | ||
2004 | if ((rid = buffer_get_int(&m)) != muxclient_request_id) | ||
2005 | fatal("%s: out of sequence reply: my id %u theirs %u", | ||
2006 | __func__, muxclient_request_id, rid); | ||
2007 | buffer_free(&m); | ||
2008 | |||
2009 | debug3("%s: done", __func__); | ||
2010 | muxclient_request_id++; | ||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | static int | ||
1963 | mux_client_request_stdio_fwd(int fd) | 2015 | mux_client_request_stdio_fwd(int fd) |
1964 | { | 2016 | { |
1965 | Buffer m; | 2017 | Buffer m; |
@@ -2105,7 +2157,7 @@ mux_client_request_stop_listening(int fd) | |||
2105 | } | 2157 | } |
2106 | 2158 | ||
2107 | /* Multiplex client main loop. */ | 2159 | /* Multiplex client main loop. */ |
2108 | void | 2160 | int |
2109 | muxclient(const char *path) | 2161 | muxclient(const char *path) |
2110 | { | 2162 | { |
2111 | struct sockaddr_un addr; | 2163 | struct sockaddr_un addr; |
@@ -2128,7 +2180,7 @@ muxclient(const char *path) | |||
2128 | case SSHCTL_MASTER_NO: | 2180 | case SSHCTL_MASTER_NO: |
2129 | break; | 2181 | break; |
2130 | default: | 2182 | default: |
2131 | return; | 2183 | return -1; |
2132 | } | 2184 | } |
2133 | 2185 | ||
2134 | memset(&addr, '\0', sizeof(addr)); | 2186 | memset(&addr, '\0', sizeof(addr)); |
@@ -2164,14 +2216,14 @@ muxclient(const char *path) | |||
2164 | strerror(errno)); | 2216 | strerror(errno)); |
2165 | } | 2217 | } |
2166 | close(sock); | 2218 | close(sock); |
2167 | return; | 2219 | return -1; |
2168 | } | 2220 | } |
2169 | set_nonblock(sock); | 2221 | set_nonblock(sock); |
2170 | 2222 | ||
2171 | if (mux_client_hello_exchange(sock) != 0) { | 2223 | if (mux_client_hello_exchange(sock) != 0) { |
2172 | error("%s: master hello exchange failed", __func__); | 2224 | error("%s: master hello exchange failed", __func__); |
2173 | close(sock); | 2225 | close(sock); |
2174 | return; | 2226 | return -1; |
2175 | } | 2227 | } |
2176 | 2228 | ||
2177 | switch (muxclient_command) { | 2229 | switch (muxclient_command) { |
@@ -2191,10 +2243,10 @@ muxclient(const char *path) | |||
2191 | case SSHMUX_COMMAND_OPEN: | 2243 | case SSHMUX_COMMAND_OPEN: |
2192 | if (mux_client_forwards(sock, 0) != 0) { | 2244 | if (mux_client_forwards(sock, 0) != 0) { |
2193 | error("%s: master forward request failed", __func__); | 2245 | error("%s: master forward request failed", __func__); |
2194 | return; | 2246 | return -1; |
2195 | } | 2247 | } |
2196 | mux_client_request_session(sock); | 2248 | mux_client_request_session(sock); |
2197 | return; | 2249 | return -1; |
2198 | case SSHMUX_COMMAND_STDIO_FWD: | 2250 | case SSHMUX_COMMAND_STDIO_FWD: |
2199 | mux_client_request_stdio_fwd(sock); | 2251 | mux_client_request_stdio_fwd(sock); |
2200 | exit(0); | 2252 | exit(0); |
@@ -2207,6 +2259,9 @@ muxclient(const char *path) | |||
2207 | error("%s: master cancel forward request failed", | 2259 | error("%s: master cancel forward request failed", |
2208 | __func__); | 2260 | __func__); |
2209 | exit(0); | 2261 | exit(0); |
2262 | case SSHMUX_COMMAND_PROXY: | ||
2263 | mux_client_proxy(sock); | ||
2264 | return (sock); | ||
2210 | default: | 2265 | default: |
2211 | fatal("unrecognised muxclient_command %d", muxclient_command); | 2266 | fatal("unrecognised muxclient_command %d", muxclient_command); |
2212 | } | 2267 | } |