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) | |
download | openssh-git-8d0578478586e283e751ca51e7b0690631da139a.tar.gz |
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 @@ -/* $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 <djm@openbsd.org> * @@ -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) @@ -1960,6 +1977,41 @@ mux_client_request_session(int fd) } 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) { Buffer m; @@ -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); } |