summaryrefslogtreecommitdiff
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 50de0267a..783ae5bd4 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.241 2016/09/28 21:44:52 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.242 2016/09/30 09:19:13 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -204,6 +204,9 @@ struct session_state {
204 /* Used in packet_send2 */ 204 /* Used in packet_send2 */
205 int rekeying; 205 int rekeying;
206 206
207 /* Used in ssh_packet_send_mux() */
208 int mux;
209
207 /* Used in packet_set_interactive */ 210 /* Used in packet_set_interactive */
208 int set_interactive_called; 211 int set_interactive_called;
209 212
@@ -325,6 +328,19 @@ ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
325 state->packet_timeout_ms = timeout * count * 1000; 328 state->packet_timeout_ms = timeout * count * 1000;
326} 329}
327 330
331void
332ssh_packet_set_mux(struct ssh *ssh)
333{
334 ssh->state->mux = 1;
335 ssh->state->rekeying = 0;
336}
337
338int
339ssh_packet_get_mux(struct ssh *ssh)
340{
341 return ssh->state->mux;
342}
343
328int 344int
329ssh_packet_stop_discard(struct ssh *ssh) 345ssh_packet_stop_discard(struct ssh *ssh)
330{ 346{
@@ -1078,7 +1094,7 @@ ssh_packet_enable_delayed_compress(struct ssh *ssh)
1078} 1094}
1079 1095
1080/* Used to mute debug logging for noisy packet types */ 1096/* Used to mute debug logging for noisy packet types */
1081static int 1097int
1082ssh_packet_log_type(u_char type) 1098ssh_packet_log_type(u_char type)
1083{ 1099{
1084 switch (type) { 1100 switch (type) {
@@ -1623,6 +1639,44 @@ ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
1623 return r; 1639 return r;
1624} 1640}
1625 1641
1642static int
1643ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1644{
1645 struct session_state *state = ssh->state;
1646 const u_char *cp;
1647 size_t need;
1648 int r;
1649
1650 if (ssh->kex)
1651 return SSH_ERR_INTERNAL_ERROR;
1652 *typep = SSH_MSG_NONE;
1653 cp = sshbuf_ptr(state->input);
1654 if (state->packlen == 0) {
1655 if (sshbuf_len(state->input) < 4 + 1)
1656 return 0; /* packet is incomplete */
1657 state->packlen = PEEK_U32(cp);
1658 if (state->packlen < 4 + 1 ||
1659 state->packlen > PACKET_MAX_SIZE)
1660 return SSH_ERR_MESSAGE_INCOMPLETE;
1661 }
1662 need = state->packlen + 4;
1663 if (sshbuf_len(state->input) < need)
1664 return 0; /* packet is incomplete */
1665 sshbuf_reset(state->incoming_packet);
1666 if ((r = sshbuf_put(state->incoming_packet, cp + 4,
1667 state->packlen)) != 0 ||
1668 (r = sshbuf_consume(state->input, need)) != 0 ||
1669 (r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 ||
1670 (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
1671 return r;
1672 if (ssh_packet_log_type(*typep))
1673 debug3("%s: type %u", __func__, *typep);
1674 /* sshbuf_dump(state->incoming_packet, stderr); */
1675 /* reset for next packet */
1676 state->packlen = 0;
1677 return r;
1678}
1679
1626int 1680int
1627ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) 1681ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1628{ 1682{
@@ -1635,6 +1689,9 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
1635 struct sshcomp *comp = NULL; 1689 struct sshcomp *comp = NULL;
1636 int r; 1690 int r;
1637 1691
1692 if (state->mux)
1693 return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p);
1694
1638 *typep = SSH_MSG_NONE; 1695 *typep = SSH_MSG_NONE;
1639 1696
1640 if (state->packet_discard) 1697 if (state->packet_discard)
@@ -2875,11 +2932,43 @@ sshpkt_start(struct ssh *ssh, u_char type)
2875 return sshbuf_put(ssh->state->outgoing_packet, buf, len); 2932 return sshbuf_put(ssh->state->outgoing_packet, buf, len);
2876} 2933}
2877 2934
2935static int
2936ssh_packet_send_mux(struct ssh *ssh)
2937{
2938 struct session_state *state = ssh->state;
2939 u_char type, *cp;
2940 size_t len;
2941 int r;
2942
2943 if (ssh->kex)
2944 return SSH_ERR_INTERNAL_ERROR;
2945 len = sshbuf_len(state->outgoing_packet);
2946 if (len < 6)
2947 return SSH_ERR_INTERNAL_ERROR;
2948 cp = sshbuf_mutable_ptr(state->outgoing_packet);
2949 type = cp[5];
2950 if (ssh_packet_log_type(type))
2951 debug3("%s: type %u", __func__, type);
2952 /* drop everything, but the connection protocol */
2953 if (type >= SSH2_MSG_CONNECTION_MIN &&
2954 type <= SSH2_MSG_CONNECTION_MAX) {
2955 POKE_U32(cp, len - 4);
2956 if ((r = sshbuf_putb(state->output,
2957 state->outgoing_packet)) != 0)
2958 return r;
2959 /* sshbuf_dump(state->output, stderr); */
2960 }
2961 sshbuf_reset(state->outgoing_packet);
2962 return 0;
2963}
2964
2878/* send it */ 2965/* send it */
2879 2966
2880int 2967int
2881sshpkt_send(struct ssh *ssh) 2968sshpkt_send(struct ssh *ssh)
2882{ 2969{
2970 if (ssh->state && ssh->state->mux)
2971 return ssh_packet_send_mux(ssh);
2883 if (compat20) 2972 if (compat20)
2884 return ssh_packet_send2(ssh); 2973 return ssh_packet_send2(ssh);
2885 else 2974 else