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 /packet.c | |
parent | b7689155f3f5c4999846c07a852b1c7a43b09cec (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.c | 93 |
1 files changed, 91 insertions, 2 deletions
@@ -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 | ||
331 | void | ||
332 | ssh_packet_set_mux(struct ssh *ssh) | ||
333 | { | ||
334 | ssh->state->mux = 1; | ||
335 | ssh->state->rekeying = 0; | ||
336 | } | ||
337 | |||
338 | int | ||
339 | ssh_packet_get_mux(struct ssh *ssh) | ||
340 | { | ||
341 | return ssh->state->mux; | ||
342 | } | ||
343 | |||
328 | int | 344 | int |
329 | ssh_packet_stop_discard(struct ssh *ssh) | 345 | ssh_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 */ |
1081 | static int | 1097 | int |
1082 | ssh_packet_log_type(u_char type) | 1098 | ssh_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 | ||
1642 | static int | ||
1643 | ssh_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 | |||
1626 | int | 1680 | int |
1627 | ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) | 1681 | ssh_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 | ||
2935 | static int | ||
2936 | ssh_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 | ||
2880 | int | 2967 | int |
2881 | sshpkt_send(struct ssh *ssh) | 2968 | sshpkt_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 |