2 * Support for SSH connection sharing, i.e. permitting one PuTTY to
3 * open its own channels over the SSH session being run by another.
7 * Discussion and technical documentation
8 * ======================================
10 * The basic strategy for PuTTY's implementation of SSH connection
11 * sharing is to have a single 'upstream' PuTTY process, which manages
12 * the real SSH connection and all the cryptography, and then zero or
13 * more 'downstream' PuTTYs, which never talk to the real host but
14 * only talk to the upstream through local IPC (Unix-domain sockets or
15 * Windows named pipes).
17 * The downstreams communicate with the upstream using a protocol
18 * derived from SSH itself, which I'll document in detail below. In
19 * brief, though: the downstream->upstream protocol uses a trivial
20 * binary packet protocol (just length/type/data) to encapsulate
21 * unencrypted SSH messages, and downstreams talk to the upstream more
22 * or less as if it was an SSH server itself. (So downstreams can
23 * themselves open multiple SSH channels, for example, by sending
24 * multiple SSH2_MSG_CHANNEL_OPENs; they can send CHANNEL_REQUESTs of
25 * their choice within each channel, and they handle their own
26 * WINDOW_ADJUST messages.)
28 * The upstream would ideally handle these downstreams by just putting
29 * their messages into the queue for proper SSH-2 encapsulation and
30 * encryption and sending them straight on to the server. However,
31 * that's not quite feasible as written, because client-side channel
32 * IDs could easily conflict (between multiple downstreams, or between
33 * a downstream and the upstream). To protect against that, the
34 * upstream rewrites the client-side channel IDs in messages it passes
35 * on to the server, so that it's performing what you might describe
36 * as 'channel-number NAT'. Then the upstream remembers which of its
37 * own channel IDs are channels it's managing itself, and which are
38 * placeholders associated with a particular downstream, so that when
39 * replies come in from the server they can be sent on to the relevant
40 * downstream (after un-NATting the channel number, of course).
42 * Global requests from downstreams are only accepted if the upstream
43 * knows what to do about them; currently the only such requests are
44 * the ones having to do with remote-to-local port forwarding (in
45 * which, again, the upstream remembers that some of the forwardings
46 * it's asked the server to set up were on behalf of particular
47 * downstreams, and sends the incoming CHANNEL_OPENs to those
48 * downstreams when connections come in).
50 * Other fiddly pieces of this mechanism are X forwarding and
51 * (OpenSSH-style) agent forwarding. Both of these have a fundamental
52 * problem arising from the protocol design: that the CHANNEL_OPEN
53 * from the server introducing a forwarded connection does not carry
54 * any indication of which session channel gave rise to it; so if
55 * session channels from multiple downstreams enable those forwarding
56 * methods, it's hard for the upstream to know which downstream to
57 * send the resulting connections back to.
59 * For X forwarding, we can work around this in a really painful way
60 * by using the fake X11 authorisation data sent to the server as part
61 * of the forwarding setup: upstream ensures that every X forwarding
62 * request carries distinguishable fake auth data, and then when X
63 * connections come in it waits to see the auth data in the X11 setup
64 * message before it decides which downstream to pass the connection
67 * For agent forwarding, that workaround is unavailable. As a result,
68 * this system (and, as far as I can think of, any other system too)
69 * has the fundamental constraint that it can only forward one SSH
70 * agent - it can't forward two agents to different session channels.
71 * So downstreams can request agent forwarding if they like, but if
72 * they do, they'll get whatever SSH agent is known to the upstream
73 * (if any) forwarded to their sessions.
75 * Downstream-to-upstream protocol
76 * -------------------------------
78 * Here I document in detail the protocol spoken between PuTTY
79 * downstreams and upstreams over local IPC. The IPC mechanism can
80 * vary between host platforms, but the protocol is the same.
82 * The protocol commences with a version exchange which is exactly
83 * like the SSH-2 one, in that each side sends a single line of text
86 * <protocol>-<version>-<softwareversion> [comments] \r\n
88 * The only difference is that in real SSH-2, <protocol> is the string
89 * "SSH", whereas in this protocol the string is
90 * "SSHCONNECTION@putty.projects.tartarus.org".
92 * (The SSH RFCs allow many protocol-level identifier namespaces to be
93 * extended by implementors without central standardisation as long as
94 * they suffix "@" and a domain name they control to their new ids.
95 * RFC 4253 does not define this particular name to be changeable at
96 * all, but I like to think this is obviously how it would have done
97 * so if the working group had foreseen the need :-)
99 * Thereafter, all data exchanged consists of a sequence of binary
100 * packets concatenated end-to-end, each of which is of the form
102 * uint32 length of packet, N
103 * byte[N] N bytes of packet data
105 * and, since these are SSH-2 messages, the first data byte is taken
106 * to be the packet type code.
108 * These messages are interpreted as those of an SSH connection, after
109 * userauth completes, and without any repeat key exchange.
110 * Specifically, any message from the SSH Connection Protocol is
111 * permitted, and also SSH_MSG_IGNORE, SSH_MSG_DEBUG,
112 * SSH_MSG_DISCONNECT and SSH_MSG_UNIMPLEMENTED from the SSH Transport
115 * This protocol imposes a few additional requirements, over and above
116 * those of the standard SSH Connection Protocol:
118 * Message sizes are not permitted to exceed 0x4010 (16400) bytes,
119 * including their length header.
121 * When the server (i.e. really the PuTTY upstream) sends
122 * SSH_MSG_CHANNEL_OPEN with channel type "x11", and the client
123 * (downstream) responds with SSH_MSG_CHANNEL_OPEN_CONFIRMATION, that
124 * confirmation message MUST include an initial window size of at
125 * least 256. (Rationale: this is a bit of a fudge which makes it
126 * easier, by eliminating the possibility of nasty edge cases, for an
127 * upstream to arrange not to pass the CHANNEL_OPEN on to downstream
128 * until after it's seen the X11 auth data to decide which downstream
129 * it needs to go to.)
142 struct ssh_sharing_state
{
143 const struct plug_function_table
*fn
;
144 /* the above variable absolutely *must* be the first in this structure */
146 char *sockname
; /* the socket name, kept for cleanup */
147 Socket listensock
; /* the master listening Socket */
148 tree234
*connections
; /* holds ssh_sharing_connstates */
149 unsigned nextid
; /* preferred id for next connstate */
150 Ssh ssh
; /* instance of the ssh backend */
151 char *server_verstring
; /* server version string after "SSH-" */
154 struct share_globreq
;
156 struct ssh_sharing_connstate
{
157 const struct plug_function_table
*fn
;
158 /* the above variable absolutely *must* be the first in this structure */
160 unsigned id
; /* used to identify this downstream in log messages */
162 Socket sock
; /* the Socket for this connection */
163 struct ssh_sharing_state
*parent
;
165 int crLine
; /* coroutine state for share_receive */
167 int sent_verstring
, got_verstring
, curr_packetlen
;
169 unsigned char recvbuf
[0x4010];
173 * Assorted state we have to remember about this downstream, so
174 * that we can clean it up appropriately when the downstream goes
178 /* Channels which don't have a downstream id, i.e. we've passed a
179 * CHANNEL_OPEN down from the server but not had an
180 * OPEN_CONFIRMATION or OPEN_FAILURE back. If downstream goes
181 * away, we respond to all of these with OPEN_FAILURE. */
182 tree234
*halfchannels
; /* stores 'struct share_halfchannel' */
184 /* Channels which do have a downstream id. We need to index these
185 * by both server id and upstream id, so we can find a channel
186 * when handling either an upward or a downward message referring
188 tree234
*channels_by_us
; /* stores 'struct share_channel' */
189 tree234
*channels_by_server
; /* stores 'struct share_channel' */
191 /* Another class of channel which doesn't have a downstream id.
192 * The difference between these and halfchannels is that xchannels
193 * do have an *upstream* id, because upstream has already accepted
194 * the channel request from the server. This arises in the case of
195 * X forwarding, where we have to accept the request and read the
196 * X authorisation data before we know whether the channel needs
197 * to be forwarded to a downstream. */
198 tree234
*xchannels_by_us
; /* stores 'struct share_xchannel' */
199 tree234
*xchannels_by_server
; /* stores 'struct share_xchannel' */
201 /* Remote port forwarding requests in force. */
202 tree234
*forwardings
; /* stores 'struct share_forwarding' */
204 /* Global requests we've sent on to the server, pending replies. */
205 struct share_globreq
*globreq_head
, *globreq_tail
;
208 struct share_halfchannel
{
212 /* States of a share_channel. */
217 /* Downstream has sent CHANNEL_OPEN but server hasn't replied yet.
218 * If downstream goes away when a channel is in this state, we
219 * must wait for the server's response before starting to send
220 * CLOSE. Channels in this state are also not held in
221 * channels_by_server, because their server_id field is
226 struct share_channel
{
227 unsigned downstream_id
, upstream_id
, server_id
;
228 int downstream_maxpkt
;
231 * Some channels (specifically, channels on which downstream has
232 * sent "x11-req") have the additional function of storing a set
233 * of downstream X authorisation data and a handle to an upstream
236 struct X11FakeAuth
*x11_auth_upstream
;
239 int x11_auth_datalen
;
243 struct share_forwarding
{
246 int active
; /* has the server sent REQUEST_SUCCESS? */
249 struct share_xchannel_message
{
250 struct share_xchannel_message
*next
;
256 struct share_xchannel
{
257 unsigned upstream_id
, server_id
;
260 * xchannels come in two flavours: live and dead. Live ones are
261 * waiting for an OPEN_CONFIRMATION or OPEN_FAILURE from
262 * downstream; dead ones have had an OPEN_FAILURE, so they only
263 * exist as a means of letting us conveniently respond to further
264 * channel messages from the server until such time as the server
265 * sends us CHANNEL_CLOSE.
270 * When we receive OPEN_CONFIRMATION, we will need to send a
271 * WINDOW_ADJUST to the server to synchronise the windows. For
272 * this purpose we need to know what window we have so far offered
273 * the server. We record this as exactly the value in the
274 * OPEN_CONFIRMATION that upstream sent us, adjusted by the amount
275 * by which the two X greetings differed in length.
280 * Linked list of SSH messages from the server relating to this
281 * channel, which we queue up until downstream sends us an
282 * OPEN_CONFIRMATION and we can belatedly send them all on.
284 struct share_xchannel_message
*msghead
, *msgtail
;
288 GLOBREQ_TCPIP_FORWARD
,
289 GLOBREQ_CANCEL_TCPIP_FORWARD
292 struct share_globreq
{
293 struct share_globreq
*next
;
296 struct share_forwarding
*fwd
;
299 static int share_connstate_cmp(void *av
, void *bv
)
301 const struct ssh_sharing_connstate
*a
=
302 (const struct ssh_sharing_connstate
*)av
;
303 const struct ssh_sharing_connstate
*b
=
304 (const struct ssh_sharing_connstate
*)bv
;
308 else if (a
->id
> b
->id
)
314 static unsigned share_find_unused_id
315 (struct ssh_sharing_state
*sharestate
, unsigned first
)
317 int low_orig
, low
, mid
, high
, high_orig
;
318 struct ssh_sharing_connstate
*cs
;
322 * Find the lowest unused downstream ID greater or equal to
325 * Begin by seeing if 'first' itself is available. If it is, we'll
326 * just return it; if it's already in the tree, we'll find the
327 * tree index where it appears and use that for the next stage.
330 struct ssh_sharing_connstate dummy
;
332 cs
= findrelpos234(sharestate
->connections
, &dummy
, NULL
,
333 REL234_GE
, &low_orig
);
339 * Now binary-search using the counted B-tree, to find the largest
340 * ID which is in a contiguous sequence from the beginning of that
344 high
= high_orig
= count234(sharestate
->connections
);
345 while (high
- low
> 1) {
346 mid
= (high
+ low
) / 2;
347 cs
= index234(sharestate
->connections
, mid
);
348 if (cs
->id
== first
+ (mid
- low_orig
))
349 low
= mid
; /* this one is still in the sequence */
351 high
= mid
; /* this one is past the end */
355 * Now low is the tree index of the largest ID in the initial
356 * sequence. So the return value is one more than low's id, and we
357 * know low's id is given by the formula in the binary search loop
360 * (If an SSH connection went on for _enormously_ long, we might
361 * reach a point where all ids from 'first' to UINT_MAX were in
362 * use. In that situation the formula below would wrap round by
363 * one and return zero, which is conveniently the right way to
364 * signal 'no id available' from this function.)
366 ret
= first
+ (low
- low_orig
) + 1;
368 struct ssh_sharing_connstate dummy
;
370 assert(NULL
== find234(sharestate
->connections
, &dummy
, NULL
));
375 static int share_halfchannel_cmp(void *av
, void *bv
)
377 const struct share_halfchannel
*a
= (const struct share_halfchannel
*)av
;
378 const struct share_halfchannel
*b
= (const struct share_halfchannel
*)bv
;
380 if (a
->server_id
< b
->server_id
)
382 else if (a
->server_id
> b
->server_id
)
388 static int share_channel_us_cmp(void *av
, void *bv
)
390 const struct share_channel
*a
= (const struct share_channel
*)av
;
391 const struct share_channel
*b
= (const struct share_channel
*)bv
;
393 if (a
->upstream_id
< b
->upstream_id
)
395 else if (a
->upstream_id
> b
->upstream_id
)
401 static int share_channel_server_cmp(void *av
, void *bv
)
403 const struct share_channel
*a
= (const struct share_channel
*)av
;
404 const struct share_channel
*b
= (const struct share_channel
*)bv
;
406 if (a
->server_id
< b
->server_id
)
408 else if (a
->server_id
> b
->server_id
)
414 static int share_xchannel_us_cmp(void *av
, void *bv
)
416 const struct share_xchannel
*a
= (const struct share_xchannel
*)av
;
417 const struct share_xchannel
*b
= (const struct share_xchannel
*)bv
;
419 if (a
->upstream_id
< b
->upstream_id
)
421 else if (a
->upstream_id
> b
->upstream_id
)
427 static int share_xchannel_server_cmp(void *av
, void *bv
)
429 const struct share_xchannel
*a
= (const struct share_xchannel
*)av
;
430 const struct share_xchannel
*b
= (const struct share_xchannel
*)bv
;
432 if (a
->server_id
< b
->server_id
)
434 else if (a
->server_id
> b
->server_id
)
440 static int share_forwarding_cmp(void *av
, void *bv
)
442 const struct share_forwarding
*a
= (const struct share_forwarding
*)av
;
443 const struct share_forwarding
*b
= (const struct share_forwarding
*)bv
;
446 if ((i
= strcmp(a
->host
, b
->host
)) != 0)
448 else if (a
->port
< b
->port
)
450 else if (a
->port
> b
->port
)
456 static void share_xchannel_free(struct share_xchannel
*xc
)
458 while (xc
->msghead
) {
459 struct share_xchannel_message
*tmp
= xc
->msghead
;
460 xc
->msghead
= tmp
->next
;
466 static void share_connstate_free(struct ssh_sharing_connstate
*cs
)
468 struct share_halfchannel
*hc
;
469 struct share_xchannel
*xc
;
470 struct share_channel
*chan
;
471 struct share_forwarding
*fwd
;
473 while ((hc
= (struct share_halfchannel
*)
474 delpos234(cs
->halfchannels
, 0)) != NULL
)
476 freetree234(cs
->halfchannels
);
478 /* All channels live in 'channels_by_us' but only some in
479 * 'channels_by_server', so we use the former to find the list of
481 freetree234(cs
->channels_by_server
);
482 while ((chan
= (struct share_channel
*)
483 delpos234(cs
->channels_by_us
, 0)) != NULL
)
485 freetree234(cs
->channels_by_us
);
487 /* But every xchannel is in both trees, so it doesn't matter which
488 * we use to free them. */
489 while ((xc
= (struct share_xchannel
*)
490 delpos234(cs
->xchannels_by_us
, 0)) != NULL
)
491 share_xchannel_free(xc
);
492 freetree234(cs
->xchannels_by_us
);
493 freetree234(cs
->xchannels_by_server
);
495 while ((fwd
= (struct share_forwarding
*)
496 delpos234(cs
->forwardings
, 0)) != NULL
)
498 freetree234(cs
->forwardings
);
500 while (cs
->globreq_head
) {
501 struct share_globreq
*globreq
= cs
->globreq_head
;
502 cs
->globreq_head
= cs
->globreq_head
->next
;
512 void sharestate_free(void *v
)
514 struct ssh_sharing_state
*sharestate
= (struct ssh_sharing_state
*)v
;
515 struct ssh_sharing_connstate
*cs
;
517 platform_ssh_share_cleanup(sharestate
->sockname
);
519 while ((cs
= (struct ssh_sharing_connstate
*)
520 delpos234(sharestate
->connections
, 0)) != NULL
) {
521 share_connstate_free(cs
);
523 freetree234(sharestate
->connections
);
524 if (sharestate
->listensock
) {
525 sk_close(sharestate
->listensock
);
526 sharestate
->listensock
= NULL
;
528 sfree(sharestate
->server_verstring
);
529 sfree(sharestate
->sockname
);
533 static struct share_halfchannel
*share_add_halfchannel
534 (struct ssh_sharing_connstate
*cs
, unsigned server_id
)
536 struct share_halfchannel
*hc
= snew(struct share_halfchannel
);
537 hc
->server_id
= server_id
;
538 if (add234(cs
->halfchannels
, hc
) != hc
) {
547 static struct share_halfchannel
*share_find_halfchannel
548 (struct ssh_sharing_connstate
*cs
, unsigned server_id
)
550 struct share_halfchannel dummyhc
;
551 dummyhc
.server_id
= server_id
;
552 return find234(cs
->halfchannels
, &dummyhc
, NULL
);
555 static void share_remove_halfchannel(struct ssh_sharing_connstate
*cs
,
556 struct share_halfchannel
*hc
)
558 del234(cs
->halfchannels
, hc
);
562 static struct share_channel
*share_add_channel
563 (struct ssh_sharing_connstate
*cs
, unsigned downstream_id
,
564 unsigned upstream_id
, unsigned server_id
, int state
, int maxpkt
)
566 struct share_channel
*chan
= snew(struct share_channel
);
567 chan
->downstream_id
= downstream_id
;
568 chan
->upstream_id
= upstream_id
;
569 chan
->server_id
= server_id
;
571 chan
->downstream_maxpkt
= maxpkt
;
572 chan
->x11_auth_upstream
= NULL
;
573 chan
->x11_auth_data
= NULL
;
574 chan
->x11_auth_proto
= -1;
575 chan
->x11_auth_datalen
= 0;
576 chan
->x11_one_shot
= 0;
577 if (add234(cs
->channels_by_us
, chan
) != chan
) {
581 if (chan
->state
!= UNACKNOWLEDGED
) {
582 if (add234(cs
->channels_by_server
, chan
) != chan
) {
583 del234(cs
->channels_by_us
, chan
);
591 static void share_channel_set_server_id(struct ssh_sharing_connstate
*cs
,
592 struct share_channel
*chan
,
593 unsigned server_id
, int newstate
)
595 chan
->server_id
= server_id
;
596 chan
->state
= newstate
;
597 assert(newstate
!= UNACKNOWLEDGED
);
598 add234(cs
->channels_by_server
, chan
);
601 static struct share_channel
*share_find_channel_by_upstream
602 (struct ssh_sharing_connstate
*cs
, unsigned upstream_id
)
604 struct share_channel dummychan
;
605 dummychan
.upstream_id
= upstream_id
;
606 return find234(cs
->channels_by_us
, &dummychan
, NULL
);
609 static struct share_channel
*share_find_channel_by_server
610 (struct ssh_sharing_connstate
*cs
, unsigned server_id
)
612 struct share_channel dummychan
;
613 dummychan
.server_id
= server_id
;
614 return find234(cs
->channels_by_server
, &dummychan
, NULL
);
617 static void share_remove_channel(struct ssh_sharing_connstate
*cs
,
618 struct share_channel
*chan
)
620 del234(cs
->channels_by_us
, chan
);
621 del234(cs
->channels_by_server
, chan
);
622 if (chan
->x11_auth_upstream
)
623 ssh_sharing_remove_x11_display(cs
->parent
->ssh
,
624 chan
->x11_auth_upstream
);
625 sfree(chan
->x11_auth_data
);
629 static struct share_xchannel
*share_add_xchannel
630 (struct ssh_sharing_connstate
*cs
,
631 unsigned upstream_id
, unsigned server_id
)
633 struct share_xchannel
*xc
= snew(struct share_xchannel
);
634 xc
->upstream_id
= upstream_id
;
635 xc
->server_id
= server_id
;
637 xc
->msghead
= xc
->msgtail
= NULL
;
638 if (add234(cs
->xchannels_by_us
, xc
) != xc
) {
642 if (add234(cs
->xchannels_by_server
, xc
) != xc
) {
643 del234(cs
->xchannels_by_us
, xc
);
650 static struct share_xchannel
*share_find_xchannel_by_upstream
651 (struct ssh_sharing_connstate
*cs
, unsigned upstream_id
)
653 struct share_xchannel dummyxc
;
654 dummyxc
.upstream_id
= upstream_id
;
655 return find234(cs
->xchannels_by_us
, &dummyxc
, NULL
);
658 static struct share_xchannel
*share_find_xchannel_by_server
659 (struct ssh_sharing_connstate
*cs
, unsigned server_id
)
661 struct share_xchannel dummyxc
;
662 dummyxc
.server_id
= server_id
;
663 return find234(cs
->xchannels_by_server
, &dummyxc
, NULL
);
666 static void share_remove_xchannel(struct ssh_sharing_connstate
*cs
,
667 struct share_xchannel
*xc
)
669 del234(cs
->xchannels_by_us
, xc
);
670 del234(cs
->xchannels_by_server
, xc
);
671 share_xchannel_free(xc
);
674 static struct share_forwarding
*share_add_forwarding
675 (struct ssh_sharing_connstate
*cs
,
676 const char *host
, int port
)
678 struct share_forwarding
*fwd
= snew(struct share_forwarding
);
679 fwd
->host
= dupstr(host
);
682 if (add234(cs
->forwardings
, fwd
) != fwd
) {
690 static struct share_forwarding
*share_find_forwarding
691 (struct ssh_sharing_connstate
*cs
, const char *host
, int port
)
693 struct share_forwarding dummyfwd
, *ret
;
694 dummyfwd
.host
= dupstr(host
);
695 dummyfwd
.port
= port
;
696 ret
= find234(cs
->forwardings
, &dummyfwd
, NULL
);
697 sfree(dummyfwd
.host
);
701 static void share_remove_forwarding(struct ssh_sharing_connstate
*cs
,
702 struct share_forwarding
*fwd
)
704 del234(cs
->forwardings
, fwd
);
708 static void send_packet_to_downstream(struct ssh_sharing_connstate
*cs
,
709 int type
, const void *pkt
, int pktlen
,
710 struct share_channel
*chan
)
712 if (!cs
->sock
) /* throw away all packets destined for a dead downstream */
715 if (type
== SSH2_MSG_CHANNEL_DATA
) {
717 * Special case which we take care of at a low level, so as to
718 * be sure to apply it in all cases. On rare occasions we
719 * might find that we have a channel for which the
720 * downstream's maximum packet size exceeds the max packet
721 * size we presented to the server on its behalf. (This can
722 * occur in X11 forwarding, where we have to send _our_
723 * CHANNEL_OPEN_CONFIRMATION before we discover which if any
724 * downstream the channel is destined for, so if that
725 * downstream turns out to present a smaller max packet size
726 * then we're in this situation.)
728 * If that happens, we just chop up the packet into pieces and
729 * send them as separate CHANNEL_DATA packets.
731 const char *upkt
= (const char *)pkt
;
732 char header
[13]; /* 4 length + 1 type + 4 channel id + 4 string len */
734 int len
= toint(GET_32BIT(upkt
+ 4));
735 upkt
+= 8; /* skip channel id + length field */
737 if (len
< 0 || len
> pktlen
- 8)
741 int this_len
= (len
> chan
->downstream_maxpkt
?
742 chan
->downstream_maxpkt
: len
);
743 PUT_32BIT(header
, this_len
+ 9);
745 PUT_32BIT(header
+ 5, chan
->downstream_id
);
746 PUT_32BIT(header
+ 9, this_len
);
747 sk_write(cs
->sock
, header
, 13);
748 sk_write(cs
->sock
, upkt
, this_len
);
754 * Just do the obvious thing.
758 PUT_32BIT(header
, pktlen
+ 1);
760 sk_write(cs
->sock
, header
, 5);
761 sk_write(cs
->sock
, pkt
, pktlen
);
765 static void share_try_cleanup(struct ssh_sharing_connstate
*cs
)
768 struct share_halfchannel
*hc
;
769 struct share_channel
*chan
;
770 struct share_forwarding
*fwd
;
773 * Any half-open channels, i.e. those for which we'd received
774 * CHANNEL_OPEN from the server but not passed back a response
775 * from downstream, should be responded to with OPEN_FAILURE.
777 while ((hc
= (struct share_halfchannel
*)
778 index234(cs
->halfchannels
, 0)) != NULL
) {
779 static const char reason
[] = "PuTTY downstream no longer available";
780 static const char lang
[] = "en";
781 unsigned char packet
[256];
784 PUT_32BIT(packet
+ pos
, hc
->server_id
); pos
+= 4;
785 PUT_32BIT(packet
+ pos
, SSH2_OPEN_CONNECT_FAILED
); pos
+= 4;
786 PUT_32BIT(packet
+ pos
, strlen(reason
)); pos
+= 4;
787 memcpy(packet
+ pos
, reason
, strlen(reason
)); pos
+= strlen(reason
);
788 PUT_32BIT(packet
+ pos
, strlen(lang
)); pos
+= 4;
789 memcpy(packet
+ pos
, lang
, strlen(lang
)); pos
+= strlen(lang
);
790 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
791 SSH2_MSG_CHANNEL_OPEN_FAILURE
,
792 packet
, pos
, "cleanup after"
793 " downstream went away");
795 share_remove_halfchannel(cs
, hc
);
799 * Any actually open channels should have a CHANNEL_CLOSE sent for
800 * them, unless we've already done so. We won't be able to
801 * actually clean them up until CHANNEL_CLOSE comes back from the
802 * server, though (unless the server happens to have sent a CLOSE
805 * Another annoying exception is UNACKNOWLEDGED channels, i.e.
806 * we've _sent_ a CHANNEL_OPEN to the server but not received an
807 * OPEN_CONFIRMATION or OPEN_FAILURE. We must wait for a reply
808 * before closing the channel, because until we see that reply we
809 * won't have the server's channel id to put in the close message.
811 for (i
= 0; (chan
= (struct share_channel
*)
812 index234(cs
->channels_by_us
, i
)) != NULL
; i
++) {
813 unsigned char packet
[256];
816 if (chan
->state
!= SENT_CLOSE
&& chan
->state
!= UNACKNOWLEDGED
) {
817 PUT_32BIT(packet
+ pos
, chan
->server_id
); pos
+= 4;
818 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
819 SSH2_MSG_CHANNEL_CLOSE
,
820 packet
, pos
, "cleanup after"
821 " downstream went away");
822 if (chan
->state
!= RCVD_CLOSE
) {
823 chan
->state
= SENT_CLOSE
;
825 /* In this case, we _can_ clear up the channel now. */
826 ssh_delete_sharing_channel(cs
->parent
->ssh
, chan
->upstream_id
);
827 share_remove_channel(cs
, chan
);
828 i
--; /* don't accidentally skip one as a result */
834 * Any remote port forwardings we're managing on behalf of this
835 * downstream should be cancelled. Again, we must defer those for
836 * which we haven't yet seen REQUEST_SUCCESS/FAILURE.
838 * We take a fire-and-forget approach during cleanup, not
839 * bothering to set want_reply.
841 for (i
= 0; (fwd
= (struct share_forwarding
*)
842 index234(cs
->forwardings
, i
)) != NULL
; i
++) {
844 static const char request
[] = "cancel-tcpip-forward";
845 char *packet
= snewn(256 + strlen(fwd
->host
), char);
848 PUT_32BIT(packet
+ pos
, strlen(request
)); pos
+= 4;
849 memcpy(packet
+ pos
, request
, strlen(request
));
850 pos
+= strlen(request
);
852 packet
[pos
++] = 0; /* !want_reply */
854 PUT_32BIT(packet
+ pos
, strlen(fwd
->host
)); pos
+= 4;
855 memcpy(packet
+ pos
, fwd
->host
, strlen(fwd
->host
));
856 pos
+= strlen(fwd
->host
);
858 PUT_32BIT(packet
+ pos
, fwd
->port
); pos
+= 4;
860 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
861 SSH2_MSG_GLOBAL_REQUEST
,
862 packet
, pos
, "cleanup after"
863 " downstream went away");
866 share_remove_forwarding(cs
, fwd
);
867 i
--; /* don't accidentally skip one as a result */
871 if (count234(cs
->halfchannels
) == 0 &&
872 count234(cs
->channels_by_us
) == 0 &&
873 count234(cs
->forwardings
) == 0) {
875 * Now we're _really_ done, so we can get rid of cs completely.
877 del234(cs
->parent
->connections
, cs
);
878 ssh_sharing_downstream_disconnected(cs
->parent
->ssh
, cs
->id
);
879 share_connstate_free(cs
);
883 static void share_begin_cleanup(struct ssh_sharing_connstate
*cs
)
889 share_try_cleanup(cs
);
892 static void share_disconnect(struct ssh_sharing_connstate
*cs
,
895 static const char lang
[] = "en";
896 int msglen
= strlen(message
);
897 char *packet
= snewn(msglen
+ 256, char);
900 PUT_32BIT(packet
+ pos
, SSH2_DISCONNECT_PROTOCOL_ERROR
); pos
+= 4;
902 PUT_32BIT(packet
+ pos
, msglen
); pos
+= 4;
903 memcpy(packet
+ pos
, message
, msglen
);
906 PUT_32BIT(packet
+ pos
, strlen(lang
)); pos
+= 4;
907 memcpy(packet
+ pos
, lang
, strlen(lang
)); pos
+= strlen(lang
);
909 send_packet_to_downstream(cs
, SSH2_MSG_DISCONNECT
, packet
, pos
, NULL
);
911 share_begin_cleanup(cs
);
914 static void share_closing(Plug plug
, const char *error_msg
, int error_code
,
917 struct ssh_sharing_connstate
*cs
= (struct ssh_sharing_connstate
*)plug
;
920 #ifdef BROKEN_PIPE_ERROR_CODE
922 * Most of the time, we log what went wrong when a downstream
923 * disappears with a socket error. One exception, though, is
924 * receiving EPIPE when we haven't received a protocol version
925 * string from the downstream, because that can happen as a result
926 * of plink -shareexists (opening the connection and instantly
927 * closing it again without bothering to read our version string).
928 * So that one case is not treated as a log-worthy error.
930 if (error_code
== BROKEN_PIPE_ERROR_CODE
&& !cs
->got_verstring
)
934 ssh_sharing_logf(cs
->parent
->ssh
, cs
->id
,
935 "Socket error: %s", error_msg
);
937 share_begin_cleanup(cs
);
940 static int getstring_inner(const void *vdata
, int datalen
,
941 char **out
, int *outlen
)
943 const unsigned char *data
= (const unsigned char *)vdata
;
949 len
= toint(GET_32BIT(data
));
950 if (len
< 0 || len
> datalen
- 4)
954 *outlen
= len
+ 4; /* total size including length field */
956 *out
= dupprintf("%.*s", len
, (char *)data
+ 4);
960 static char *getstring(const void *data
, int datalen
)
963 if (getstring_inner(data
, datalen
, &ret
, NULL
))
969 static int getstring_size(const void *data
, int datalen
)
972 if (getstring_inner(data
, datalen
, NULL
, &ret
))
979 * Append a message to the end of an xchannel's queue, with the length
980 * and type code filled in and the data block allocated but
983 struct share_xchannel_message
*share_xchannel_add_message
984 (struct share_xchannel
*xc
, int type
, int len
)
986 unsigned char *block
;
987 struct share_xchannel_message
*msg
;
990 * Be a little tricksy here by allocating a single memory block
991 * containing both the 'struct share_xchannel_message' and the
992 * actual data. Simplifies freeing it later.
994 block
= smalloc(sizeof(struct share_xchannel_message
) + len
);
995 msg
= (struct share_xchannel_message
*)block
;
996 msg
->data
= block
+ sizeof(struct share_xchannel_message
);
1001 * Queue it in the xchannel.
1004 xc
->msgtail
->next
= msg
;
1013 void share_dead_xchannel_respond(struct ssh_sharing_connstate
*cs
,
1014 struct share_xchannel
*xc
)
1017 * Handle queued incoming messages from the server destined for an
1018 * xchannel which is dead (i.e. downstream sent OPEN_FAILURE).
1021 while (xc
->msghead
) {
1022 struct share_xchannel_message
*msg
= xc
->msghead
;
1023 xc
->msghead
= msg
->next
;
1025 if (msg
->type
== SSH2_MSG_CHANNEL_REQUEST
&& msg
->datalen
> 4) {
1027 * A CHANNEL_REQUEST is responded to by sending
1028 * CHANNEL_FAILURE, if it has want_reply set.
1030 int wantreplypos
= getstring_size(msg
->data
, msg
->datalen
);
1031 if (wantreplypos
> 0 && wantreplypos
< msg
->datalen
&&
1032 msg
->data
[wantreplypos
] != 0) {
1033 unsigned char id
[4];
1034 PUT_32BIT(id
, xc
->server_id
);
1035 ssh_send_packet_from_downstream
1036 (cs
->parent
->ssh
, cs
->id
, SSH2_MSG_CHANNEL_FAILURE
, id
, 4,
1037 "downstream refused X channel open");
1039 } else if (msg
->type
== SSH2_MSG_CHANNEL_CLOSE
) {
1041 * On CHANNEL_CLOSE we can discard the channel completely.
1050 ssh_delete_sharing_channel(cs
->parent
->ssh
, xc
->upstream_id
);
1051 share_remove_xchannel(cs
, xc
);
1055 void share_xchannel_confirmation(struct ssh_sharing_connstate
*cs
,
1056 struct share_xchannel
*xc
,
1057 struct share_channel
*chan
,
1058 unsigned downstream_window
)
1060 unsigned char window_adjust
[8];
1063 * Send all the queued messages downstream.
1065 while (xc
->msghead
) {
1066 struct share_xchannel_message
*msg
= xc
->msghead
;
1067 xc
->msghead
= msg
->next
;
1069 if (msg
->datalen
>= 4)
1070 PUT_32BIT(msg
->data
, chan
->downstream_id
);
1071 send_packet_to_downstream(cs
, msg
->type
,
1072 msg
->data
, msg
->datalen
, chan
);
1078 * Send a WINDOW_ADJUST back upstream, to synchronise the window
1079 * size downstream thinks it's presented with the one we've
1080 * actually presented.
1082 PUT_32BIT(window_adjust
, xc
->server_id
);
1083 PUT_32BIT(window_adjust
+ 4, downstream_window
- xc
->window
);
1084 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1085 SSH2_MSG_CHANNEL_WINDOW_ADJUST
,
1086 window_adjust
, 8, "window adjustment after"
1087 " downstream accepted X channel");
1090 void share_xchannel_failure(struct ssh_sharing_connstate
*cs
,
1091 struct share_xchannel
*xc
)
1094 * If downstream refuses to open our X channel at all for some
1095 * reason, we must respond by sending an emergency CLOSE upstream.
1097 unsigned char id
[4];
1098 PUT_32BIT(id
, xc
->server_id
);
1099 ssh_send_packet_from_downstream
1100 (cs
->parent
->ssh
, cs
->id
, SSH2_MSG_CHANNEL_CLOSE
, id
, 4,
1101 "downstream refused X channel open");
1104 * Now mark the xchannel as dead, and respond to anything sent on
1105 * it until we see CLOSE for it in turn.
1108 share_dead_xchannel_respond(cs
, xc
);
1111 void share_setup_x11_channel(void *csv
, void *chanv
,
1112 unsigned upstream_id
, unsigned server_id
,
1113 unsigned server_currwin
, unsigned server_maxpkt
,
1114 unsigned client_adjusted_window
,
1115 const char *peer_addr
, int peer_port
, int endian
,
1116 int protomajor
, int protominor
,
1117 const void *initial_data
, int initial_len
)
1119 struct ssh_sharing_connstate
*cs
= (struct ssh_sharing_connstate
*)csv
;
1120 struct share_channel
*chan
= (struct share_channel
*)chanv
;
1121 struct share_xchannel
*xc
;
1122 struct share_xchannel_message
*msg
;
1129 * Create an xchannel containing data we've already received from
1130 * the X client, and preload it with a CHANNEL_DATA message
1131 * containing our own made-up authorisation greeting and any
1132 * additional data sent from the server so far.
1134 xc
= share_add_xchannel(cs
, upstream_id
, server_id
);
1135 greeting
= x11_make_greeting(endian
, protomajor
, protominor
,
1136 chan
->x11_auth_proto
,
1137 chan
->x11_auth_data
, chan
->x11_auth_datalen
,
1138 peer_addr
, peer_port
, &greeting_len
);
1139 msg
= share_xchannel_add_message(xc
, SSH2_MSG_CHANNEL_DATA
,
1140 8 + greeting_len
+ initial_len
);
1141 /* leave the channel id field unfilled - we don't know the
1142 * downstream id yet, of course */
1143 PUT_32BIT(msg
->data
+ 4, greeting_len
+ initial_len
);
1144 memcpy(msg
->data
+ 8, greeting
, greeting_len
);
1145 memcpy(msg
->data
+ 8 + greeting_len
, initial_data
, initial_len
);
1148 xc
->window
= client_adjusted_window
+ greeting_len
;
1151 * Send on a CHANNEL_OPEN to downstream.
1153 pktlen
= 27 + strlen(peer_addr
);
1154 pkt
= snewn(pktlen
, unsigned char);
1155 PUT_32BIT(pkt
, 3); /* strlen("x11") */
1156 memcpy(pkt
+4, "x11", 3);
1157 PUT_32BIT(pkt
+7, server_id
);
1158 PUT_32BIT(pkt
+11, server_currwin
);
1159 PUT_32BIT(pkt
+15, server_maxpkt
);
1160 PUT_32BIT(pkt
+19, strlen(peer_addr
));
1161 memcpy(pkt
+23, peer_addr
, strlen(peer_addr
));
1162 PUT_32BIT(pkt
+23+strlen(peer_addr
), peer_port
);
1163 send_packet_to_downstream(cs
, SSH2_MSG_CHANNEL_OPEN
, pkt
, pktlen
, NULL
);
1167 * If this was a once-only X forwarding, clean it up now.
1169 if (chan
->x11_one_shot
) {
1170 ssh_sharing_remove_x11_display(cs
->parent
->ssh
,
1171 chan
->x11_auth_upstream
);
1172 chan
->x11_auth_upstream
= NULL
;
1173 sfree(chan
->x11_auth_data
);
1174 chan
->x11_auth_proto
= -1;
1175 chan
->x11_auth_datalen
= 0;
1176 chan
->x11_one_shot
= 0;
1180 void share_got_pkt_from_server(void *csv
, int type
,
1181 unsigned char *pkt
, int pktlen
)
1183 struct ssh_sharing_connstate
*cs
= (struct ssh_sharing_connstate
*)csv
;
1184 struct share_globreq
*globreq
;
1186 unsigned upstream_id
, server_id
;
1187 struct share_channel
*chan
;
1188 struct share_xchannel
*xc
;
1191 case SSH2_MSG_REQUEST_SUCCESS
:
1192 case SSH2_MSG_REQUEST_FAILURE
:
1193 globreq
= cs
->globreq_head
;
1194 if (globreq
->type
== GLOBREQ_TCPIP_FORWARD
) {
1195 if (type
== SSH2_MSG_REQUEST_FAILURE
) {
1196 share_remove_forwarding(cs
, globreq
->fwd
);
1198 globreq
->fwd
->active
= TRUE
;
1200 } else if (globreq
->type
== GLOBREQ_CANCEL_TCPIP_FORWARD
) {
1201 if (type
== SSH2_MSG_REQUEST_SUCCESS
) {
1202 share_remove_forwarding(cs
, globreq
->fwd
);
1205 if (globreq
->want_reply
) {
1206 send_packet_to_downstream(cs
, type
, pkt
, pktlen
, NULL
);
1208 cs
->globreq_head
= globreq
->next
;
1210 if (cs
->globreq_head
== NULL
)
1211 cs
->globreq_tail
= NULL
;
1214 /* Retry cleaning up this connection, in case that reply
1215 * was the last thing we were waiting for. */
1216 share_try_cleanup(cs
);
1221 case SSH2_MSG_CHANNEL_OPEN
:
1222 id_pos
= getstring_size(pkt
, pktlen
);
1223 assert(id_pos
>= 0);
1224 server_id
= GET_32BIT(pkt
+ id_pos
);
1225 share_add_halfchannel(cs
, server_id
);
1227 send_packet_to_downstream(cs
, type
, pkt
, pktlen
, NULL
);
1230 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
:
1231 case SSH2_MSG_CHANNEL_OPEN_FAILURE
:
1232 case SSH2_MSG_CHANNEL_CLOSE
:
1233 case SSH2_MSG_CHANNEL_WINDOW_ADJUST
:
1234 case SSH2_MSG_CHANNEL_DATA
:
1235 case SSH2_MSG_CHANNEL_EXTENDED_DATA
:
1236 case SSH2_MSG_CHANNEL_EOF
:
1237 case SSH2_MSG_CHANNEL_REQUEST
:
1238 case SSH2_MSG_CHANNEL_SUCCESS
:
1239 case SSH2_MSG_CHANNEL_FAILURE
:
1241 * All these messages have the recipient channel id as the
1242 * first uint32 field in the packet. Substitute the downstream
1243 * channel id for our one and pass the packet downstream.
1245 assert(pktlen
>= 4);
1246 upstream_id
= GET_32BIT(pkt
);
1247 if ((chan
= share_find_channel_by_upstream(cs
, upstream_id
)) != NULL
) {
1249 * The normal case: this id refers to an open channel.
1251 PUT_32BIT(pkt
, chan
->downstream_id
);
1252 send_packet_to_downstream(cs
, type
, pkt
, pktlen
, chan
);
1255 * Update the channel state, for messages that need it.
1257 if (type
== SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
) {
1258 if (chan
->state
== UNACKNOWLEDGED
&& pktlen
>= 8) {
1259 share_channel_set_server_id(cs
, chan
, GET_32BIT(pkt
+4),
1262 /* Retry cleaning up this connection, so that we
1263 * can send an immediate CLOSE on this channel for
1264 * which we now know the server id. */
1265 share_try_cleanup(cs
);
1268 } else if (type
== SSH2_MSG_CHANNEL_OPEN_FAILURE
) {
1269 ssh_delete_sharing_channel(cs
->parent
->ssh
, chan
->upstream_id
);
1270 share_remove_channel(cs
, chan
);
1271 } else if (type
== SSH2_MSG_CHANNEL_CLOSE
) {
1272 if (chan
->state
== SENT_CLOSE
) {
1273 ssh_delete_sharing_channel(cs
->parent
->ssh
,
1275 share_remove_channel(cs
, chan
);
1277 /* Retry cleaning up this connection, in case this
1278 * channel closure was the last thing we were
1280 share_try_cleanup(cs
);
1283 chan
->state
= RCVD_CLOSE
;
1286 } else if ((xc
= share_find_xchannel_by_upstream(cs
, upstream_id
))
1289 * The unusual case: this id refers to an xchannel. Add it
1290 * to the xchannel's queue.
1292 struct share_xchannel_message
*msg
;
1294 msg
= share_xchannel_add_message(xc
, type
, pktlen
);
1295 memcpy(msg
->data
, pkt
, pktlen
);
1297 /* If the xchannel is dead, then also respond to it (which
1298 * may involve deleting the channel). */
1300 share_dead_xchannel_respond(cs
, xc
);
1305 assert(!"This packet type should never have come from ssh.c");
1310 static void share_got_pkt_from_downstream(struct ssh_sharing_connstate
*cs
,
1312 unsigned char *pkt
, int pktlen
)
1315 struct share_forwarding
*fwd
;
1317 unsigned old_id
, new_id
, server_id
;
1318 struct share_globreq
*globreq
;
1319 struct share_channel
*chan
;
1320 struct share_halfchannel
*hc
;
1321 struct share_xchannel
*xc
;
1325 case SSH2_MSG_DISCONNECT
:
1327 * This message stops here: if downstream is disconnecting
1328 * from us, that doesn't mean we want to disconnect from the
1329 * SSH server. Close the downstream connection and start
1332 share_begin_cleanup(cs
);
1335 case SSH2_MSG_GLOBAL_REQUEST
:
1337 * The only global requests we understand are "tcpip-forward"
1338 * and "cancel-tcpip-forward". Since those require us to
1339 * maintain state, we must assume that other global requests
1340 * will probably require that too, and so we don't forward on
1341 * any request we don't understand.
1343 request_name
= getstring(pkt
, pktlen
);
1344 if (request_name
== NULL
) {
1345 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1349 if (!strcmp(request_name
, "tcpip-forward")) {
1350 int wantreplypos
, orig_wantreply
, port
, ret
;
1353 sfree(request_name
);
1356 * Pick the packet apart to find the want_reply field and
1357 * the host/port we're going to ask to listen on.
1359 wantreplypos
= getstring_size(pkt
, pktlen
);
1360 if (wantreplypos
< 0 || wantreplypos
>= pktlen
) {
1361 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1364 orig_wantreply
= pkt
[wantreplypos
];
1365 port
= getstring_size(pkt
+ (wantreplypos
+ 1),
1366 pktlen
- (wantreplypos
+ 1));
1367 port
+= (wantreplypos
+ 1);
1368 if (port
< 0 || port
> pktlen
- 4) {
1369 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1372 host
= getstring(pkt
+ (wantreplypos
+ 1),
1373 pktlen
- (wantreplypos
+ 1));
1374 assert(host
!= NULL
);
1375 port
= GET_32BIT(pkt
+ port
);
1378 * See if we can allocate space in ssh.c's tree of remote
1379 * port forwardings. If we can't, it's because another
1380 * client sharing this connection has already allocated
1381 * the identical port forwarding, so we take it on
1382 * ourselves to manufacture a failure packet and send it
1383 * back to downstream.
1385 ret
= ssh_alloc_sharing_rportfwd(cs
->parent
->ssh
, host
, port
, cs
);
1387 if (orig_wantreply
) {
1388 send_packet_to_downstream(cs
, SSH2_MSG_REQUEST_FAILURE
,
1393 * We've managed to make space for this forwarding
1394 * locally. Pass the request on to the SSH server, but
1395 * set want_reply even if it wasn't originally set, so
1396 * that we know whether this forwarding needs to be
1397 * cleaned up if downstream goes away.
1399 int old_wantreply
= pkt
[wantreplypos
];
1400 pkt
[wantreplypos
] = 1;
1401 ssh_send_packet_from_downstream
1402 (cs
->parent
->ssh
, cs
->id
, type
, pkt
, pktlen
,
1403 old_wantreply
? NULL
: "upstream added want_reply flag");
1404 fwd
= share_add_forwarding(cs
, host
, port
);
1405 ssh_sharing_queue_global_request(cs
->parent
->ssh
, cs
);
1408 globreq
= snew(struct share_globreq
);
1409 globreq
->next
= NULL
;
1410 if (cs
->globreq_tail
)
1411 cs
->globreq_tail
->next
= globreq
;
1413 cs
->globreq_head
= globreq
;
1415 globreq
->want_reply
= orig_wantreply
;
1416 globreq
->type
= GLOBREQ_TCPIP_FORWARD
;
1421 } else if (!strcmp(request_name
, "cancel-tcpip-forward")) {
1422 int wantreplypos
, orig_wantreply
, port
;
1424 struct share_forwarding
*fwd
;
1426 sfree(request_name
);
1429 * Pick the packet apart to find the want_reply field and
1430 * the host/port we're going to ask to listen on.
1432 wantreplypos
= getstring_size(pkt
, pktlen
);
1433 if (wantreplypos
< 0 || wantreplypos
>= pktlen
) {
1434 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1437 orig_wantreply
= pkt
[wantreplypos
];
1438 port
= getstring_size(pkt
+ (wantreplypos
+ 1),
1439 pktlen
- (wantreplypos
+ 1));
1440 port
+= (wantreplypos
+ 1);
1441 if (port
< 0 || port
> pktlen
- 4) {
1442 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1445 host
= getstring(pkt
+ (wantreplypos
+ 1),
1446 pktlen
- (wantreplypos
+ 1));
1447 assert(host
!= NULL
);
1448 port
= GET_32BIT(pkt
+ port
);
1451 * Look up the existing forwarding with these details.
1453 fwd
= share_find_forwarding(cs
, host
, port
);
1455 if (orig_wantreply
) {
1456 send_packet_to_downstream(cs
, SSH2_MSG_REQUEST_FAILURE
,
1461 * Pass the cancel request on to the SSH server, but
1462 * set want_reply even if it wasn't originally set, so
1463 * that _we_ know whether the forwarding has been
1464 * deleted even if downstream doesn't want to know.
1466 int old_wantreply
= pkt
[wantreplypos
];
1467 pkt
[wantreplypos
] = 1;
1468 ssh_send_packet_from_downstream
1469 (cs
->parent
->ssh
, cs
->id
, type
, pkt
, pktlen
,
1470 old_wantreply
? NULL
: "upstream added want_reply flag");
1471 ssh_sharing_queue_global_request(cs
->parent
->ssh
, cs
);
1477 * Request we don't understand. Manufacture a failure
1478 * message if an answer was required.
1482 sfree(request_name
);
1484 wantreplypos
= getstring_size(pkt
, pktlen
);
1485 if (wantreplypos
< 0 || wantreplypos
>= pktlen
) {
1486 err
= dupprintf("Truncated GLOBAL_REQUEST packet");
1489 if (pkt
[wantreplypos
])
1490 send_packet_to_downstream(cs
, SSH2_MSG_REQUEST_FAILURE
,
1495 case SSH2_MSG_CHANNEL_OPEN
:
1496 /* Sender channel id comes after the channel type string */
1497 id_pos
= getstring_size(pkt
, pktlen
);
1498 if (id_pos
< 0 || id_pos
> pktlen
- 12) {
1499 err
= dupprintf("Truncated CHANNEL_OPEN packet");
1503 old_id
= GET_32BIT(pkt
+ id_pos
);
1504 new_id
= ssh_alloc_sharing_channel(cs
->parent
->ssh
, cs
);
1505 share_add_channel(cs
, old_id
, new_id
, 0, UNACKNOWLEDGED
,
1506 GET_32BIT(pkt
+ id_pos
+ 8));
1507 PUT_32BIT(pkt
+ id_pos
, new_id
);
1508 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1509 type
, pkt
, pktlen
, NULL
);
1512 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION
:
1514 err
= dupprintf("Truncated CHANNEL_OPEN_CONFIRMATION packet");
1518 id_pos
= 4; /* sender channel id is 2nd uint32 field in packet */
1519 old_id
= GET_32BIT(pkt
+ id_pos
);
1521 server_id
= GET_32BIT(pkt
);
1522 /* This server id may refer to either a halfchannel or an xchannel. */
1523 hc
= NULL
, xc
= NULL
; /* placate optimiser */
1524 if ((hc
= share_find_halfchannel(cs
, server_id
)) != NULL
) {
1525 new_id
= ssh_alloc_sharing_channel(cs
->parent
->ssh
, cs
);
1526 } else if ((xc
= share_find_xchannel_by_server(cs
, server_id
))
1528 new_id
= xc
->upstream_id
;
1530 err
= dupprintf("CHANNEL_OPEN_CONFIRMATION packet cited unknown channel %u", (unsigned)server_id
);
1534 PUT_32BIT(pkt
+ id_pos
, new_id
);
1536 chan
= share_add_channel(cs
, old_id
, new_id
, server_id
, OPEN
,
1537 GET_32BIT(pkt
+ 12));
1540 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1541 type
, pkt
, pktlen
, NULL
);
1542 share_remove_halfchannel(cs
, hc
);
1544 unsigned downstream_window
= GET_32BIT(pkt
+ 8);
1545 if (downstream_window
< 256) {
1546 err
= dupprintf("Initial window size for x11 channel must be at least 256 (got %u)", downstream_window
);
1549 share_xchannel_confirmation(cs
, xc
, chan
, downstream_window
);
1550 share_remove_xchannel(cs
, xc
);
1555 case SSH2_MSG_CHANNEL_OPEN_FAILURE
:
1557 err
= dupprintf("Truncated CHANNEL_OPEN_FAILURE packet");
1561 server_id
= GET_32BIT(pkt
);
1562 /* This server id may refer to either a halfchannel or an xchannel. */
1563 if ((hc
= share_find_halfchannel(cs
, server_id
)) != NULL
) {
1564 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1565 type
, pkt
, pktlen
, NULL
);
1566 share_remove_halfchannel(cs
, hc
);
1567 } else if ((xc
= share_find_xchannel_by_server(cs
, server_id
))
1569 share_xchannel_failure(cs
, xc
);
1571 err
= dupprintf("CHANNEL_OPEN_FAILURE packet cited unknown channel %u", (unsigned)server_id
);
1577 case SSH2_MSG_CHANNEL_WINDOW_ADJUST
:
1578 case SSH2_MSG_CHANNEL_DATA
:
1579 case SSH2_MSG_CHANNEL_EXTENDED_DATA
:
1580 case SSH2_MSG_CHANNEL_EOF
:
1581 case SSH2_MSG_CHANNEL_CLOSE
:
1582 case SSH2_MSG_CHANNEL_REQUEST
:
1583 case SSH2_MSG_CHANNEL_SUCCESS
:
1584 case SSH2_MSG_CHANNEL_FAILURE
:
1585 case SSH2_MSG_IGNORE
:
1586 case SSH2_MSG_DEBUG
:
1587 if (type
== SSH2_MSG_CHANNEL_REQUEST
&&
1588 (request_name
= getstring(pkt
+ 4, pktlen
- 4)) != NULL
) {
1590 * Agent forwarding requests from downstream are treated
1591 * specially. Because OpenSSHD doesn't let us enable agent
1592 * forwarding independently per session channel, and in
1593 * particular because the OpenSSH-defined agent forwarding
1594 * protocol does not mark agent-channel requests with the
1595 * id of the session channel they originate from, the only
1596 * way we can implement agent forwarding in a
1597 * connection-shared PuTTY is to forward the _upstream_
1598 * agent. Hence, we unilaterally deny agent forwarding
1599 * requests from downstreams if we aren't prepared to
1600 * forward an agent ourselves.
1602 * (If we are, then we dutifully pass agent forwarding
1603 * requests upstream. OpenSSHD has the curious behaviour
1604 * that all but the first such request will be rejected,
1605 * but all session channels opened after the first request
1606 * get agent forwarding enabled whether they ask for it or
1607 * not; but that's not our concern, since other SSH
1608 * servers supporting the same piece of protocol might in
1609 * principle at least manage to enable agent forwarding on
1610 * precisely the channels that requested it, even if the
1611 * subsequent CHANNEL_OPENs still can't be associated with
1612 * a parent session channel.)
1614 if (!strcmp(request_name
, "auth-agent-req@openssh.com") &&
1615 !ssh_agent_forwarding_permitted(cs
->parent
->ssh
)) {
1616 unsigned server_id
= GET_32BIT(pkt
);
1617 unsigned char recipient_id
[4];
1619 sfree(request_name
);
1621 chan
= share_find_channel_by_server(cs
, server_id
);
1623 PUT_32BIT(recipient_id
, chan
->downstream_id
);
1624 send_packet_to_downstream(cs
, SSH2_MSG_CHANNEL_FAILURE
,
1625 recipient_id
, 4, NULL
);
1627 char *buf
= dupprintf("Agent forwarding request for "
1628 "unrecognised channel %u", server_id
);
1629 share_disconnect(cs
, buf
);
1637 * Another thing we treat specially is X11 forwarding
1638 * requests. For these, we have to make up another set of
1639 * X11 auth data, and enter it into our SSH connection's
1640 * list of possible X11 authorisation credentials so that
1641 * when we see an X11 channel open request we can know
1642 * whether it's one to handle locally or one to pass on to
1643 * a downstream, and if the latter, which one.
1645 if (!strcmp(request_name
, "x11-req")) {
1646 unsigned server_id
= GET_32BIT(pkt
);
1647 int want_reply
, single_connection
, screen
;
1648 char *auth_proto_str
, *auth_data
;
1649 int auth_proto
, protolen
, datalen
;
1652 sfree(request_name
);
1654 chan
= share_find_channel_by_server(cs
, server_id
);
1656 char *buf
= dupprintf("X11 forwarding request for "
1657 "unrecognised channel %u", server_id
);
1658 share_disconnect(cs
, buf
);
1664 * Pick apart the whole message to find the downstream
1667 /* we have already seen: 4 bytes channel id, 4+7 request name */
1669 err
= dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1672 want_reply
= pkt
[15] != 0;
1673 single_connection
= pkt
[16] != 0;
1674 auth_proto_str
= getstring(pkt
+17, pktlen
-17);
1675 auth_proto
= x11_identify_auth_proto(auth_proto_str
);
1676 sfree(auth_proto_str
);
1677 pos
= 17 + getstring_size(pkt
+17, pktlen
-17);
1678 auth_data
= getstring(pkt
+pos
, pktlen
-pos
);
1679 pos
+= getstring_size(pkt
+pos
, pktlen
-pos
);
1681 if (pktlen
< pos
+4) {
1682 err
= dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1686 screen
= GET_32BIT(pkt
+pos
);
1688 if (auth_proto
< 0) {
1689 /* Reject due to not understanding downstream's
1690 * requested authorisation method. */
1691 unsigned char recipient_id
[4];
1692 PUT_32BIT(recipient_id
, chan
->downstream_id
);
1693 send_packet_to_downstream(cs
, SSH2_MSG_CHANNEL_FAILURE
,
1694 recipient_id
, 4, NULL
);
1699 chan
->x11_auth_proto
= auth_proto
;
1700 chan
->x11_auth_data
= x11_dehexify(auth_data
,
1701 &chan
->x11_auth_datalen
);
1703 chan
->x11_auth_upstream
=
1704 ssh_sharing_add_x11_display(cs
->parent
->ssh
, auth_proto
,
1706 chan
->x11_one_shot
= single_connection
;
1709 * Now construct a replacement X forwarding request,
1710 * containing our own auth data, and send that to the
1713 protolen
= strlen(chan
->x11_auth_upstream
->protoname
);
1714 datalen
= strlen(chan
->x11_auth_upstream
->datastring
);
1715 pktlen
= 29+protolen
+datalen
;
1716 pkt
= snewn(pktlen
, unsigned char);
1717 PUT_32BIT(pkt
, server_id
);
1718 PUT_32BIT(pkt
+4, 7); /* strlen("x11-req") */
1719 memcpy(pkt
+8, "x11-req", 7);
1720 pkt
[15] = want_reply
;
1721 pkt
[16] = single_connection
;
1722 PUT_32BIT(pkt
+17, protolen
);
1723 memcpy(pkt
+21, chan
->x11_auth_upstream
->protoname
, protolen
);
1724 PUT_32BIT(pkt
+21+protolen
, datalen
);
1725 memcpy(pkt
+25+protolen
, chan
->x11_auth_upstream
->datastring
,
1727 PUT_32BIT(pkt
+25+protolen
+datalen
, screen
);
1728 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1729 SSH2_MSG_CHANNEL_REQUEST
,
1736 sfree(request_name
);
1739 ssh_send_packet_from_downstream(cs
->parent
->ssh
, cs
->id
,
1740 type
, pkt
, pktlen
, NULL
);
1741 if (type
== SSH2_MSG_CHANNEL_CLOSE
&& pktlen
>= 4) {
1742 server_id
= GET_32BIT(pkt
);
1743 chan
= share_find_channel_by_server(cs
, server_id
);
1745 if (chan
->state
== RCVD_CLOSE
) {
1746 ssh_delete_sharing_channel(cs
->parent
->ssh
,
1748 share_remove_channel(cs
, chan
);
1750 chan
->state
= SENT_CLOSE
;
1757 err
= dupprintf("Unexpected packet type %d\n", type
);
1761 * Any other packet type is unexpected. In particular, we
1762 * never pass GLOBAL_REQUESTs downstream, so we never expect
1763 * to see SSH2_MSG_REQUEST_{SUCCESS,FAILURE}.
1766 assert(err
!= NULL
);
1767 share_disconnect(cs
, err
);
1774 * Coroutine macros similar to, but simplified from, those in ssh.c.
1776 #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
1777 #define crFinishV } *crLine = 0; return; }
1778 #define crGetChar(c) do \
1780 while (len == 0) { \
1781 *crLine =__LINE__; return; case __LINE__:; \
1784 (c) = (unsigned char)*data++; \
1787 static void share_receive(Plug plug
, int urgent
, char *data
, int len
)
1789 struct ssh_sharing_connstate
*cs
= (struct ssh_sharing_connstate
*)plug
;
1790 static const char expected_verstring_prefix
[] =
1791 "SSHCONNECTION@putty.projects.tartarus.org-2.0-";
1794 crBegin(cs
->crLine
);
1797 * First read the version string from downstream.
1804 if (cs
->recvlen
>= sizeof(cs
->recvbuf
)) {
1805 char *buf
= dupprintf("Version string far too long\n");
1806 share_disconnect(cs
, buf
);
1810 cs
->recvbuf
[cs
->recvlen
++] = c
;
1814 * Now parse the version string to make sure it's at least vaguely
1815 * sensible, and log it.
1817 if (cs
->recvlen
< sizeof(expected_verstring_prefix
)-1 ||
1818 memcmp(cs
->recvbuf
, expected_verstring_prefix
,
1819 sizeof(expected_verstring_prefix
) - 1)) {
1820 char *buf
= dupprintf("Version string did not have expected prefix\n");
1821 share_disconnect(cs
, buf
);
1825 if (cs
->recvlen
> 0 && cs
->recvbuf
[cs
->recvlen
-1] == '\015')
1826 cs
->recvlen
--; /* trim off \r before \n */
1827 ssh_sharing_logf(cs
->parent
->ssh
, cs
->id
,
1828 "Downstream version string: %.*s",
1829 cs
->recvlen
, cs
->recvbuf
);
1830 cs
->got_verstring
= TRUE
;
1833 * Loop round reading packets.
1837 while (cs
->recvlen
< 4) {
1839 cs
->recvbuf
[cs
->recvlen
++] = c
;
1841 cs
->curr_packetlen
= toint(GET_32BIT(cs
->recvbuf
) + 4);
1842 if (cs
->curr_packetlen
< 5 ||
1843 cs
->curr_packetlen
> sizeof(cs
->recvbuf
)) {
1844 char *buf
= dupprintf("Bad packet length %u\n",
1845 (unsigned)cs
->curr_packetlen
);
1846 share_disconnect(cs
, buf
);
1850 while (cs
->recvlen
< cs
->curr_packetlen
) {
1852 cs
->recvbuf
[cs
->recvlen
++] = c
;
1855 share_got_pkt_from_downstream(cs
, cs
->recvbuf
[4],
1856 cs
->recvbuf
+ 5, cs
->recvlen
- 5);
1863 static void share_sent(Plug plug
, int bufsize
)
1865 /* struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug; */
1868 * We do nothing here, because we expect that there won't be a
1869 * need to throttle and unthrottle the connection to a downstream.
1870 * It should automatically throttle itself: if the SSH server
1871 * sends huge amounts of data on all channels then it'll run out
1872 * of window until our downstream sends it back some
1877 static void share_listen_closing(Plug plug
, const char *error_msg
,
1878 int error_code
, int calling_back
)
1880 struct ssh_sharing_state
*sharestate
= (struct ssh_sharing_state
*)plug
;
1882 ssh_sharing_logf(sharestate
->ssh
, 0,
1883 "listening socket: %s", error_msg
);
1884 sk_close(sharestate
->listensock
);
1885 sharestate
->listensock
= NULL
;
1888 static void share_send_verstring(struct ssh_sharing_connstate
*cs
)
1890 char *fullstring
= dupcat("SSHCONNECTION@putty.projects.tartarus.org-2.0-",
1891 cs
->parent
->server_verstring
, "\015\012", NULL
);
1892 sk_write(cs
->sock
, fullstring
, strlen(fullstring
));
1895 cs
->sent_verstring
= TRUE
;
1898 int share_ndownstreams(void *state
)
1900 struct ssh_sharing_state
*sharestate
= (struct ssh_sharing_state
*)state
;
1901 return count234(sharestate
->connections
);
1904 void share_activate(void *state
, const char *server_verstring
)
1907 * Indication from ssh.c that we are now ready to begin serving
1908 * any downstreams that have already connected to us.
1910 struct ssh_sharing_state
*sharestate
= (struct ssh_sharing_state
*)state
;
1911 struct ssh_sharing_connstate
*cs
;
1915 * Trim the server's version string down to just the software
1916 * version component, removing "SSH-2.0-" or whatever at the
1919 for (i
= 0; i
< 2; i
++) {
1920 server_verstring
+= strcspn(server_verstring
, "-");
1921 if (*server_verstring
)
1925 sharestate
->server_verstring
= dupstr(server_verstring
);
1927 for (i
= 0; (cs
= (struct ssh_sharing_connstate
*)
1928 index234(sharestate
->connections
, i
)) != NULL
; i
++) {
1929 assert(!cs
->sent_verstring
);
1930 share_send_verstring(cs
);
1934 static int share_listen_accepting(Plug plug
,
1935 accept_fn_t constructor
, accept_ctx_t ctx
)
1937 static const struct plug_function_table connection_fn_table
= {
1938 NULL
, /* no log function, because that's for outgoing connections */
1942 NULL
/* no accepting function, because we've already done it */
1944 struct ssh_sharing_state
*sharestate
= (struct ssh_sharing_state
*)plug
;
1945 struct ssh_sharing_connstate
*cs
;
1950 * A new downstream has connected to us.
1952 cs
= snew(struct ssh_sharing_connstate
);
1953 cs
->fn
= &connection_fn_table
;
1954 cs
->parent
= sharestate
;
1956 if ((cs
->id
= share_find_unused_id(sharestate
, sharestate
->nextid
)) == 0 &&
1957 (cs
->id
= share_find_unused_id(sharestate
, 1)) == 0) {
1961 sharestate
->nextid
= cs
->id
+ 1;
1962 if (sharestate
->nextid
== 0)
1963 sharestate
->nextid
++; /* only happens in VERY long-running upstreams */
1965 cs
->sock
= constructor(ctx
, (Plug
) cs
);
1966 if ((err
= sk_socket_error(cs
->sock
)) != NULL
) {
1971 sk_set_frozen(cs
->sock
, 0);
1973 add234(cs
->parent
->connections
, cs
);
1975 cs
->sent_verstring
= FALSE
;
1976 if (sharestate
->server_verstring
)
1977 share_send_verstring(cs
);
1979 cs
->got_verstring
= FALSE
;
1982 cs
->halfchannels
= newtree234(share_halfchannel_cmp
);
1983 cs
->channels_by_us
= newtree234(share_channel_us_cmp
);
1984 cs
->channels_by_server
= newtree234(share_channel_server_cmp
);
1985 cs
->xchannels_by_us
= newtree234(share_xchannel_us_cmp
);
1986 cs
->xchannels_by_server
= newtree234(share_xchannel_server_cmp
);
1987 cs
->forwardings
= newtree234(share_forwarding_cmp
);
1988 cs
->globreq_head
= cs
->globreq_tail
= NULL
;
1990 peerinfo
= sk_peer_info(cs
->sock
);
1991 ssh_sharing_downstream_connected(sharestate
->ssh
, cs
->id
, peerinfo
);
1997 /* Per-application overrides for what roles we can take (e.g. pscp
1998 * will never be an upstream) */
1999 extern const int share_can_be_downstream
;
2000 extern const int share_can_be_upstream
;
2003 * Decide on the string used to identify the connection point between
2004 * upstream and downstream (be it a Windows named pipe or a
2005 * Unix-domain socket or whatever else).
2007 * I wondered about making this a SHA hash of all sorts of pieces of
2008 * the PuTTY configuration - essentially everything PuTTY uses to know
2009 * where and how to make a connection, including all the proxy details
2010 * (or rather, all the _relevant_ ones - only including settings that
2011 * other settings didn't prevent from having any effect), plus the
2012 * username. However, I think it's better to keep it really simple:
2013 * the connection point identifier is derived from the hostname and
2014 * port used to index the host-key cache (not necessarily where we
2015 * _physically_ connected to, in cases involving proxies or
2016 * CONF_loghost), plus the username if one is specified.
2018 * The per-platform code will quite likely hash or obfuscate this name
2019 * in turn, for privacy from other users; failing that, it might
2020 * transform it to avoid dangerous filename characters and so on. But
2021 * that doesn't matter to us: for us, the point is that two session
2022 * configurations which return the same string from this function will
2023 * be treated as potentially shareable with each other.
2025 char *ssh_share_sockname(const char *host
, int port
, Conf
*conf
)
2027 char *username
= get_remote_username(conf
);
2032 sockname
= dupprintf("%s@%s", username
, host
);
2034 sockname
= dupprintf("%s", host
);
2037 sockname
= dupprintf("%s@%s:%d", username
, host
, port
);
2039 sockname
= dupprintf("%s:%d", host
, port
);
2046 static void nullplug_socket_log(Plug plug
, int type
, SockAddr addr
, int port
,
2047 const char *error_msg
, int error_code
) {}
2048 static void nullplug_closing(Plug plug
, const char *error_msg
, int error_code
,
2049 int calling_back
) {}
2050 static void nullplug_receive(Plug plug
, int urgent
, char *data
, int len
) {}
2051 static void nullplug_sent(Plug plug
, int bufsize
) {}
2053 int ssh_share_test_for_upstream(const char *host
, int port
, Conf
*conf
)
2055 static const struct plug_function_table fn_table
= {
2056 nullplug_socket_log
,
2063 const struct plug_function_table
*fn
;
2066 char *sockname
, *logtext
, *ds_err
, *us_err
;
2072 sockname
= ssh_share_sockname(host
, port
, conf
);
2075 logtext
= ds_err
= us_err
= NULL
;
2076 result
= platform_ssh_share(sockname
, conf
, (Plug
)&np
, (Plug
)NULL
, &sock
,
2077 &logtext
, &ds_err
, &us_err
, FALSE
, TRUE
);
2084 if (result
== SHARE_NONE
) {
2085 assert(sock
== NULL
);
2088 assert(result
== SHARE_DOWNSTREAM
);
2095 * Init function for connection sharing. We either open a listening
2096 * socket and become an upstream, or connect to an existing one and
2097 * become a downstream, or do neither. We are responsible for deciding
2098 * which of these to do (including checking the Conf to see if
2099 * connection sharing is even enabled in the first place). If we
2100 * become a downstream, we return the Socket with which we connected
2101 * to the upstream; otherwise (whether or not we have established an
2102 * upstream) we return NULL.
2104 Socket
ssh_connection_sharing_init(const char *host
, int port
,
2105 Conf
*conf
, Ssh ssh
, void **state
)
2107 static const struct plug_function_table listen_fn_table
= {
2108 NULL
, /* no log function, because that's for outgoing connections */
2109 share_listen_closing
,
2110 NULL
, /* no receive function on a listening socket */
2111 NULL
, /* no sent function on a listening socket */
2112 share_listen_accepting
2115 int result
, can_upstream
, can_downstream
;
2116 char *logtext
, *ds_err
, *us_err
;
2119 struct ssh_sharing_state
*sharestate
;
2121 if (!conf_get_int(conf
, CONF_ssh_connection_sharing
))
2122 return NULL
; /* do not share anything */
2123 can_upstream
= share_can_be_upstream
&&
2124 conf_get_int(conf
, CONF_ssh_connection_sharing_upstream
);
2125 can_downstream
= share_can_be_downstream
&&
2126 conf_get_int(conf
, CONF_ssh_connection_sharing_downstream
);
2127 if (!can_upstream
&& !can_downstream
)
2130 sockname
= ssh_share_sockname(host
, port
, conf
);
2133 * Create a data structure for the listening plug if we turn out
2134 * to be an upstream.
2136 sharestate
= snew(struct ssh_sharing_state
);
2137 sharestate
->fn
= &listen_fn_table
;
2138 sharestate
->listensock
= NULL
;
2141 * Now hand off to a per-platform routine that either connects to
2142 * an existing upstream (using 'ssh' as the plug), establishes our
2143 * own upstream (using 'sharestate' as the plug), or forks off a
2144 * separate upstream and then connects to that. It will return a
2145 * code telling us which kind of socket it put in 'sock'.
2148 logtext
= ds_err
= us_err
= NULL
;
2149 result
= platform_ssh_share(sockname
, conf
, (Plug
)ssh
,
2150 (Plug
)sharestate
, &sock
, &logtext
, &ds_err
,
2151 &us_err
, can_upstream
, can_downstream
);
2152 ssh_connshare_log(ssh
, result
, logtext
, ds_err
, us_err
);
2159 * We aren't sharing our connection at all (e.g. something
2160 * went wrong setting the socket up). Free the upstream
2161 * structure and return NULL.
2163 assert(sock
== NULL
);
2169 case SHARE_DOWNSTREAM
:
2171 * We are downstream, so free sharestate which it turns out we
2172 * don't need after all, and return the downstream socket as a
2173 * replacement for an ordinary SSH connection.
2180 case SHARE_UPSTREAM
:
2182 * We are upstream. Set up sharestate properly and pass a copy
2183 * to the caller; return NULL, to tell ssh.c that it has to
2184 * make an ordinary connection after all.
2186 *state
= sharestate
;
2187 sharestate
->listensock
= sock
;
2188 sharestate
->connections
= newtree234(share_connstate_cmp
);
2189 sharestate
->ssh
= ssh
;
2190 sharestate
->server_verstring
= NULL
;
2191 sharestate
->sockname
= sockname
;
2192 sharestate
->nextid
= 1;