diff options
Diffstat (limited to 'mux.c')
-rw-r--r-- | mux.c | 78 |
1 files changed, 68 insertions, 10 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.60 2016/06/03 03:14:41 dtucker Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.63 2016/10/19 23:21:56 dtucker 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)); |
@@ -2138,7 +2190,8 @@ muxclient(const char *path) | |||
2138 | 2190 | ||
2139 | if (strlcpy(addr.sun_path, path, | 2191 | if (strlcpy(addr.sun_path, path, |
2140 | sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) | 2192 | sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) |
2141 | fatal("ControlPath too long"); | 2193 | fatal("ControlPath too long ('%s' >= %u bytes)", path, |
2194 | (unsigned int)sizeof(addr.sun_path)); | ||
2142 | 2195 | ||
2143 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | 2196 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) |
2144 | fatal("%s socket(): %s", __func__, strerror(errno)); | 2197 | fatal("%s socket(): %s", __func__, strerror(errno)); |
@@ -2163,14 +2216,14 @@ muxclient(const char *path) | |||
2163 | strerror(errno)); | 2216 | strerror(errno)); |
2164 | } | 2217 | } |
2165 | close(sock); | 2218 | close(sock); |
2166 | return; | 2219 | return -1; |
2167 | } | 2220 | } |
2168 | set_nonblock(sock); | 2221 | set_nonblock(sock); |
2169 | 2222 | ||
2170 | if (mux_client_hello_exchange(sock) != 0) { | 2223 | if (mux_client_hello_exchange(sock) != 0) { |
2171 | error("%s: master hello exchange failed", __func__); | 2224 | error("%s: master hello exchange failed", __func__); |
2172 | close(sock); | 2225 | close(sock); |
2173 | return; | 2226 | return -1; |
2174 | } | 2227 | } |
2175 | 2228 | ||
2176 | switch (muxclient_command) { | 2229 | switch (muxclient_command) { |
@@ -2181,7 +2234,8 @@ muxclient(const char *path) | |||
2181 | exit(0); | 2234 | exit(0); |
2182 | case SSHMUX_COMMAND_TERMINATE: | 2235 | case SSHMUX_COMMAND_TERMINATE: |
2183 | mux_client_request_terminate(sock); | 2236 | mux_client_request_terminate(sock); |
2184 | fprintf(stderr, "Exit request sent.\r\n"); | 2237 | if (options.log_level != SYSLOG_LEVEL_QUIET) |
2238 | fprintf(stderr, "Exit request sent.\r\n"); | ||
2185 | exit(0); | 2239 | exit(0); |
2186 | case SSHMUX_COMMAND_FORWARD: | 2240 | case SSHMUX_COMMAND_FORWARD: |
2187 | if (mux_client_forwards(sock, 0) != 0) | 2241 | if (mux_client_forwards(sock, 0) != 0) |
@@ -2190,22 +2244,26 @@ muxclient(const char *path) | |||
2190 | case SSHMUX_COMMAND_OPEN: | 2244 | case SSHMUX_COMMAND_OPEN: |
2191 | if (mux_client_forwards(sock, 0) != 0) { | 2245 | if (mux_client_forwards(sock, 0) != 0) { |
2192 | error("%s: master forward request failed", __func__); | 2246 | error("%s: master forward request failed", __func__); |
2193 | return; | 2247 | return -1; |
2194 | } | 2248 | } |
2195 | mux_client_request_session(sock); | 2249 | mux_client_request_session(sock); |
2196 | return; | 2250 | return -1; |
2197 | case SSHMUX_COMMAND_STDIO_FWD: | 2251 | case SSHMUX_COMMAND_STDIO_FWD: |
2198 | mux_client_request_stdio_fwd(sock); | 2252 | mux_client_request_stdio_fwd(sock); |
2199 | exit(0); | 2253 | exit(0); |
2200 | case SSHMUX_COMMAND_STOP: | 2254 | case SSHMUX_COMMAND_STOP: |
2201 | mux_client_request_stop_listening(sock); | 2255 | mux_client_request_stop_listening(sock); |
2202 | fprintf(stderr, "Stop listening request sent.\r\n"); | 2256 | if (options.log_level != SYSLOG_LEVEL_QUIET) |
2257 | fprintf(stderr, "Stop listening request sent.\r\n"); | ||
2203 | exit(0); | 2258 | exit(0); |
2204 | case SSHMUX_COMMAND_CANCEL_FWD: | 2259 | case SSHMUX_COMMAND_CANCEL_FWD: |
2205 | if (mux_client_forwards(sock, 1) != 0) | 2260 | if (mux_client_forwards(sock, 1) != 0) |
2206 | error("%s: master cancel forward request failed", | 2261 | error("%s: master cancel forward request failed", |
2207 | __func__); | 2262 | __func__); |
2208 | exit(0); | 2263 | exit(0); |
2264 | case SSHMUX_COMMAND_PROXY: | ||
2265 | mux_client_proxy(sock); | ||
2266 | return (sock); | ||
2209 | default: | 2267 | default: |
2210 | fatal("unrecognised muxclient_command %d", muxclient_command); | 2268 | fatal("unrecognised muxclient_command %d", muxclient_command); |
2211 | } | 2269 | } |