From 8d0578478586e283e751ca51e7b0690631da139a Mon Sep 17 00:00:00 2001 From: "markus@openbsd.org" Date: Fri, 30 Sep 2016 09:19:13 +0000 Subject: 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 --- mux.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 7 deletions(-) (limited to 'mux.c') diff --git a/mux.c b/mux.c index a8a753b5..ec42bf52 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.61 2016/08/08 22:40:57 dtucker Exp $ */ +/* $OpenBSD: mux.c,v 1.62 2016/09/30 09:19:13 markus Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -79,6 +79,7 @@ #include "key.h" #include "readconf.h" #include "clientloop.h" +#include "ssherr.h" /* from ssh.c */ extern int tty_flag; @@ -144,6 +145,7 @@ struct mux_master_state { #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 +#define MUX_C_PROXY 0x1000000f #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 @@ -152,6 +154,7 @@ struct mux_master_state { #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 +#define MUX_S_PROXY 0x8000000f /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ #define MUX_FWD_LOCAL 1 @@ -169,6 +172,7 @@ static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); +static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *); static const struct { u_int type; @@ -182,6 +186,7 @@ static const struct { { MUX_C_CLOSE_FWD, process_mux_close_fwd }, { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, { MUX_C_STOP_LISTENING, process_mux_stop_listening }, + { MUX_C_PROXY, process_mux_proxy }, { 0, NULL } }; @@ -1110,6 +1115,18 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) return 0; } +static int +process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) +{ + debug("%s: channel %d: proxy request", __func__, c->self); + + c->mux_rcb = channel_proxy_downstream; + buffer_put_int(r, MUX_S_PROXY); + buffer_put_int(r, rid); + + return 0; +} + /* Channel callbacks fired on read/write from mux slave fd */ static int mux_master_read_cb(Channel *c) @@ -1959,6 +1976,41 @@ mux_client_request_session(int fd) exit(exitval); } +static int +mux_client_proxy(int fd) +{ + Buffer m; + char *e; + u_int type, rid; + + buffer_init(&m); + buffer_put_int(&m, MUX_C_PROXY); + buffer_put_int(&m, muxclient_request_id); + if (mux_client_write_packet(fd, &m) != 0) + fatal("%s: write packet: %s", __func__, strerror(errno)); + + buffer_clear(&m); + + /* Read their reply */ + if (mux_client_read_packet(fd, &m) != 0) { + buffer_free(&m); + return 0; + } + type = buffer_get_int(&m); + if (type != MUX_S_PROXY) { + e = buffer_get_string(&m, NULL); + fatal("%s: master returned error: %s", __func__, e); + } + if ((rid = buffer_get_int(&m)) != muxclient_request_id) + fatal("%s: out of sequence reply: my id %u theirs %u", + __func__, muxclient_request_id, rid); + buffer_free(&m); + + debug3("%s: done", __func__); + muxclient_request_id++; + return 0; +} + static int mux_client_request_stdio_fwd(int fd) { @@ -2105,7 +2157,7 @@ mux_client_request_stop_listening(int fd) } /* Multiplex client main loop. */ -void +int muxclient(const char *path) { struct sockaddr_un addr; @@ -2128,7 +2180,7 @@ muxclient(const char *path) case SSHCTL_MASTER_NO: break; default: - return; + return -1; } memset(&addr, '\0', sizeof(addr)); @@ -2164,14 +2216,14 @@ muxclient(const char *path) strerror(errno)); } close(sock); - return; + return -1; } set_nonblock(sock); if (mux_client_hello_exchange(sock) != 0) { error("%s: master hello exchange failed", __func__); close(sock); - return; + return -1; } switch (muxclient_command) { @@ -2191,10 +2243,10 @@ muxclient(const char *path) case SSHMUX_COMMAND_OPEN: if (mux_client_forwards(sock, 0) != 0) { error("%s: master forward request failed", __func__); - return; + return -1; } mux_client_request_session(sock); - return; + return -1; case SSHMUX_COMMAND_STDIO_FWD: mux_client_request_stdio_fwd(sock); exit(0); @@ -2207,6 +2259,9 @@ muxclient(const char *path) error("%s: master cancel forward request failed", __func__); exit(0); + case SSHMUX_COMMAND_PROXY: + mux_client_proxy(sock); + return (sock); default: fatal("unrecognised muxclient_command %d", muxclient_command); } -- cgit v1.2.1