summaryrefslogtreecommitdiffstats
path: root/packet.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2016-09-30 09:19:13 +0000
committerDamien Miller <djm@mindrot.org>2016-10-01 02:45:10 +1000
commit8d0578478586e283e751ca51e7b0690631da139a (patch)
tree3621da2b97213f8ff0b434f5fd239dfd4f50d83d /packet.c
parentb7689155f3f5c4999846c07a852b1c7a43b09cec (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 'packet.c')
-rw-r--r--packet.c93
1 files changed, 91 insertions, 2 deletions
diff --git a/packet.c b/packet.c
index 50de0267..783ae5bd 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.241 2016/09/28 21:44:52 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.242 2016/09/30 09:19:13 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -204,6 +204,9 @@ struct session_state {
/* Used in packet_send2 */
int rekeying;
+ /* Used in ssh_packet_send_mux() */
+ int mux;
+
/* Used in packet_set_interactive */
int set_interactive_called;
@@ -325,6 +328,19 @@ ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
state->packet_timeout_ms = timeout * count * 1000;
}
+void
+ssh_packet_set_mux(struct ssh *ssh)
+{
+ ssh->state->mux = 1;
+ ssh->state->rekeying = 0;
+}
+
+int
+ssh_packet_get_mux(struct ssh *ssh)
+{
+ return ssh->state->mux;
+}
+
int
ssh_packet_stop_discard(struct ssh *ssh)
{
@@ -1078,7 +1094,7 @@ ssh_packet_enable_delayed_compress(struct ssh *ssh)
}
/* Used to mute debug logging for noisy packet types */
-static int
+int
ssh_packet_log_type(u_char type)
{
switch (type) {
@@ -1623,6 +1639,44 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
return r;
}
+static int
+ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
+{
+ struct session_state *state = ssh->state;
+ const u_char *cp;
+ size_t need;
+ int r;
+
+ if (ssh->kex)
+ return SSH_ERR_INTERNAL_ERROR;
+ *typep = SSH_MSG_NONE;
+ cp = sshbuf_ptr(state->input);
+ if (state->packlen == 0) {
+ if (sshbuf_len(state->input) < 4 + 1)
+ return 0; /* packet is incomplete */
+ state->packlen = PEEK_U32(cp);
+ if (state->packlen < 4 + 1 ||
+ state->packlen > PACKET_MAX_SIZE)
+ return SSH_ERR_MESSAGE_INCOMPLETE;
+ }
+ need = state->packlen + 4;
+ if (sshbuf_len(state->input) < need)
+ return 0; /* packet is incomplete */
+ sshbuf_reset(state->incoming_packet);
+ if ((r = sshbuf_put(state->incoming_packet, cp + 4,
+ state->packlen)) != 0 ||
+ (r = sshbuf_consume(state->input, need)) != 0 ||
+ (r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 ||
+ (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
+ return r;
+ if (ssh_packet_log_type(*typep))
+ debug3("%s: type %u", __func__, *typep);
+ /* sshbuf_dump(state->incoming_packet, stderr); */
+ /* reset for next packet */
+ state->packlen = 0;
+ return r;
+}
+
int
ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
@@ -1635,6 +1689,9 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
struct sshcomp *comp = NULL;
int r;
+ if (state->mux)
+ return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p);
+
*typep = SSH_MSG_NONE;
if (state->packet_discard)
@@ -2875,11 +2932,43 @@ sshpkt_start(struct ssh *ssh, u_char type)
return sshbuf_put(ssh->state->outgoing_packet, buf, len);
}
+static int
+ssh_packet_send_mux(struct ssh *ssh)
+{
+ struct session_state *state = ssh->state;
+ u_char type, *cp;
+ size_t len;
+ int r;
+
+ if (ssh->kex)
+ return SSH_ERR_INTERNAL_ERROR;
+ len = sshbuf_len(state->outgoing_packet);
+ if (len < 6)
+ return SSH_ERR_INTERNAL_ERROR;
+ cp = sshbuf_mutable_ptr(state->outgoing_packet);
+ type = cp[5];
+ if (ssh_packet_log_type(type))
+ debug3("%s: type %u", __func__, type);
+ /* drop everything, but the connection protocol */
+ if (type >= SSH2_MSG_CONNECTION_MIN &&
+ type <= SSH2_MSG_CONNECTION_MAX) {
+ POKE_U32(cp, len - 4);
+ if ((r = sshbuf_putb(state->output,
+ state->outgoing_packet)) != 0)
+ return r;
+ /* sshbuf_dump(state->output, stderr); */
+ }
+ sshbuf_reset(state->outgoing_packet);
+ return 0;
+}
+
/* send it */
int
sshpkt_send(struct ssh *ssh)
{
+ if (ssh->state && ssh->state->mux)
+ return ssh_packet_send_mux(ssh);
if (compat20)
return ssh_packet_send2(ssh);
else