Fixed issue #2495: "Show Reflog" dialog shows empty action for "push" entries
[TortoiseGit.git] / src / TortoisePlink / sshshare.c
blob5bca2fcd0594b4171c0161383e45fbb98d96bf2f
1 /*
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.
4 */
6 /*
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
65 * on to.
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
84 * of the form
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
113 * Protocol.
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.)
132 #include <stdio.h>
133 #include <stdlib.h>
134 #include <assert.h>
135 #include <limits.h>
137 #include "putty.h"
138 #include "tree234.h"
139 #include "ssh.h"
141 struct ssh_sharing_state {
142 const struct plug_function_table *fn;
143 /* the above variable absolutely *must* be the first in this structure */
145 char *sockname; /* the socket name, kept for cleanup */
146 Socket listensock; /* the master listening Socket */
147 tree234 *connections; /* holds ssh_sharing_connstates */
148 unsigned nextid; /* preferred id for next connstate */
149 Ssh ssh; /* instance of the ssh backend */
150 char *server_verstring; /* server version string after "SSH-" */
153 struct share_globreq;
155 struct ssh_sharing_connstate {
156 const struct plug_function_table *fn;
157 /* the above variable absolutely *must* be the first in this structure */
159 unsigned id; /* used to identify this downstream in log messages */
161 Socket sock; /* the Socket for this connection */
162 struct ssh_sharing_state *parent;
164 int crLine; /* coroutine state for share_receive */
166 int sent_verstring, got_verstring, curr_packetlen;
168 unsigned char recvbuf[0x4010];
169 int recvlen;
172 * Assorted state we have to remember about this downstream, so
173 * that we can clean it up appropriately when the downstream goes
174 * away.
177 /* Channels which don't have a downstream id, i.e. we've passed a
178 * CHANNEL_OPEN down from the server but not had an
179 * OPEN_CONFIRMATION or OPEN_FAILURE back. If downstream goes
180 * away, we respond to all of these with OPEN_FAILURE. */
181 tree234 *halfchannels; /* stores 'struct share_halfchannel' */
183 /* Channels which do have a downstream id. We need to index these
184 * by both server id and upstream id, so we can find a channel
185 * when handling either an upward or a downward message referring
186 * to it. */
187 tree234 *channels_by_us; /* stores 'struct share_channel' */
188 tree234 *channels_by_server; /* stores 'struct share_channel' */
190 /* Another class of channel which doesn't have a downstream id.
191 * The difference between these and halfchannels is that xchannels
192 * do have an *upstream* id, because upstream has already accepted
193 * the channel request from the server. This arises in the case of
194 * X forwarding, where we have to accept the request and read the
195 * X authorisation data before we know whether the channel needs
196 * to be forwarded to a downstream. */
197 tree234 *xchannels_by_us; /* stores 'struct share_xchannel' */
198 tree234 *xchannels_by_server; /* stores 'struct share_xchannel' */
200 /* Remote port forwarding requests in force. */
201 tree234 *forwardings; /* stores 'struct share_forwarding' */
203 /* Global requests we've sent on to the server, pending replies. */
204 struct share_globreq *globreq_head, *globreq_tail;
207 struct share_halfchannel {
208 unsigned server_id;
211 /* States of a share_channel. */
212 enum {
213 OPEN,
214 SENT_CLOSE,
215 RCVD_CLOSE,
216 /* Downstream has sent CHANNEL_OPEN but server hasn't replied yet.
217 * If downstream goes away when a channel is in this state, we
218 * must wait for the server's response before starting to send
219 * CLOSE. Channels in this state are also not held in
220 * channels_by_server, because their server_id field is
221 * meaningless. */
222 UNACKNOWLEDGED
225 struct share_channel {
226 unsigned downstream_id, upstream_id, server_id;
227 int downstream_maxpkt;
228 int state;
230 * Some channels (specifically, channels on which downstream has
231 * sent "x11-req") have the additional function of storing a set
232 * of downstream X authorisation data and a handle to an upstream
233 * fake set.
235 struct X11FakeAuth *x11_auth_upstream;
236 int x11_auth_proto;
237 char *x11_auth_data;
238 int x11_auth_datalen;
239 int x11_one_shot;
242 struct share_forwarding {
243 char *host;
244 int port;
245 int active; /* has the server sent REQUEST_SUCCESS? */
248 struct share_xchannel_message {
249 struct share_xchannel_message *next;
250 int type;
251 unsigned char *data;
252 int datalen;
255 struct share_xchannel {
256 unsigned upstream_id, server_id;
259 * xchannels come in two flavours: live and dead. Live ones are
260 * waiting for an OPEN_CONFIRMATION or OPEN_FAILURE from
261 * downstream; dead ones have had an OPEN_FAILURE, so they only
262 * exist as a means of letting us conveniently respond to further
263 * channel messages from the server until such time as the server
264 * sends us CHANNEL_CLOSE.
266 int live;
269 * When we receive OPEN_CONFIRMATION, we will need to send a
270 * WINDOW_ADJUST to the server to synchronise the windows. For
271 * this purpose we need to know what window we have so far offered
272 * the server. We record this as exactly the value in the
273 * OPEN_CONFIRMATION that upstream sent us, adjusted by the amount
274 * by which the two X greetings differed in length.
276 int window;
279 * Linked list of SSH messages from the server relating to this
280 * channel, which we queue up until downstream sends us an
281 * OPEN_CONFIRMATION and we can belatedly send them all on.
283 struct share_xchannel_message *msghead, *msgtail;
286 enum {
287 GLOBREQ_TCPIP_FORWARD,
288 GLOBREQ_CANCEL_TCPIP_FORWARD
291 struct share_globreq {
292 struct share_globreq *next;
293 int type;
294 int want_reply;
295 struct share_forwarding *fwd;
298 static int share_connstate_cmp(void *av, void *bv)
300 const struct ssh_sharing_connstate *a =
301 (const struct ssh_sharing_connstate *)av;
302 const struct ssh_sharing_connstate *b =
303 (const struct ssh_sharing_connstate *)bv;
305 if (a->id < b->id)
306 return -1;
307 else if (a->id > b->id)
308 return +1;
309 else
310 return 0;
313 static unsigned share_find_unused_id
314 (struct ssh_sharing_state *sharestate, unsigned first)
316 int low_orig, low, mid, high, high_orig;
317 struct ssh_sharing_connstate *cs;
318 unsigned ret;
321 * Find the lowest unused downstream ID greater or equal to
322 * 'first'.
324 * Begin by seeing if 'first' itself is available. If it is, we'll
325 * just return it; if it's already in the tree, we'll find the
326 * tree index where it appears and use that for the next stage.
329 struct ssh_sharing_connstate dummy;
330 dummy.id = first;
331 cs = findrelpos234(sharestate->connections, &dummy, NULL,
332 REL234_GE, &low_orig);
333 if (!cs)
334 return first;
338 * Now binary-search using the counted B-tree, to find the largest
339 * ID which is in a contiguous sequence from the beginning of that
340 * range.
342 low = low_orig;
343 high = high_orig = count234(sharestate->connections);
344 while (high - low > 1) {
345 mid = (high + low) / 2;
346 cs = index234(sharestate->connections, mid);
347 if (cs->id == first + (mid - low_orig))
348 low = mid; /* this one is still in the sequence */
349 else
350 high = mid; /* this one is past the end */
354 * Now low is the tree index of the largest ID in the initial
355 * sequence. So the return value is one more than low's id, and we
356 * know low's id is given by the formula in the binary search loop
357 * above.
359 * (If an SSH connection went on for _enormously_ long, we might
360 * reach a point where all ids from 'first' to UINT_MAX were in
361 * use. In that situation the formula below would wrap round by
362 * one and return zero, which is conveniently the right way to
363 * signal 'no id available' from this function.)
365 ret = first + (low - low_orig) + 1;
367 struct ssh_sharing_connstate dummy;
368 dummy.id = ret;
369 assert(NULL == find234(sharestate->connections, &dummy, NULL));
371 return ret;
374 static int share_halfchannel_cmp(void *av, void *bv)
376 const struct share_halfchannel *a = (const struct share_halfchannel *)av;
377 const struct share_halfchannel *b = (const struct share_halfchannel *)bv;
379 if (a->server_id < b->server_id)
380 return -1;
381 else if (a->server_id > b->server_id)
382 return +1;
383 else
384 return 0;
387 static int share_channel_us_cmp(void *av, void *bv)
389 const struct share_channel *a = (const struct share_channel *)av;
390 const struct share_channel *b = (const struct share_channel *)bv;
392 if (a->upstream_id < b->upstream_id)
393 return -1;
394 else if (a->upstream_id > b->upstream_id)
395 return +1;
396 else
397 return 0;
400 static int share_channel_server_cmp(void *av, void *bv)
402 const struct share_channel *a = (const struct share_channel *)av;
403 const struct share_channel *b = (const struct share_channel *)bv;
405 if (a->server_id < b->server_id)
406 return -1;
407 else if (a->server_id > b->server_id)
408 return +1;
409 else
410 return 0;
413 static int share_xchannel_us_cmp(void *av, void *bv)
415 const struct share_xchannel *a = (const struct share_xchannel *)av;
416 const struct share_xchannel *b = (const struct share_xchannel *)bv;
418 if (a->upstream_id < b->upstream_id)
419 return -1;
420 else if (a->upstream_id > b->upstream_id)
421 return +1;
422 else
423 return 0;
426 static int share_xchannel_server_cmp(void *av, void *bv)
428 const struct share_xchannel *a = (const struct share_xchannel *)av;
429 const struct share_xchannel *b = (const struct share_xchannel *)bv;
431 if (a->server_id < b->server_id)
432 return -1;
433 else if (a->server_id > b->server_id)
434 return +1;
435 else
436 return 0;
439 static int share_forwarding_cmp(void *av, void *bv)
441 const struct share_forwarding *a = (const struct share_forwarding *)av;
442 const struct share_forwarding *b = (const struct share_forwarding *)bv;
443 int i;
445 if ((i = strcmp(a->host, b->host)) != 0)
446 return i;
447 else if (a->port < b->port)
448 return -1;
449 else if (a->port > b->port)
450 return +1;
451 else
452 return 0;
455 static void share_xchannel_free(struct share_xchannel *xc)
457 while (xc->msghead) {
458 struct share_xchannel_message *tmp = xc->msghead;
459 xc->msghead = tmp->next;
460 sfree(tmp);
462 sfree(xc);
465 static void share_connstate_free(struct ssh_sharing_connstate *cs)
467 struct share_halfchannel *hc;
468 struct share_xchannel *xc;
469 struct share_channel *chan;
470 struct share_forwarding *fwd;
472 while ((hc = (struct share_halfchannel *)
473 delpos234(cs->halfchannels, 0)) != NULL)
474 sfree(hc);
475 freetree234(cs->halfchannels);
477 /* All channels live in 'channels_by_us' but only some in
478 * 'channels_by_server', so we use the former to find the list of
479 * ones to free */
480 freetree234(cs->channels_by_server);
481 while ((chan = (struct share_channel *)
482 delpos234(cs->channels_by_us, 0)) != NULL)
483 sfree(chan);
484 freetree234(cs->channels_by_us);
486 /* But every xchannel is in both trees, so it doesn't matter which
487 * we use to free them. */
488 while ((xc = (struct share_xchannel *)
489 delpos234(cs->xchannels_by_us, 0)) != NULL)
490 share_xchannel_free(xc);
491 freetree234(cs->xchannels_by_us);
492 freetree234(cs->xchannels_by_server);
494 while ((fwd = (struct share_forwarding *)
495 delpos234(cs->forwardings, 0)) != NULL)
496 sfree(fwd);
497 freetree234(cs->forwardings);
499 while (cs->globreq_head) {
500 struct share_globreq *globreq = cs->globreq_head;
501 cs->globreq_head = cs->globreq_head->next;
502 sfree(globreq);
505 sfree(cs);
508 void sharestate_free(void *v)
510 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)v;
511 struct ssh_sharing_connstate *cs;
513 platform_ssh_share_cleanup(sharestate->sockname);
515 while ((cs = (struct ssh_sharing_connstate *)
516 delpos234(sharestate->connections, 0)) != NULL) {
517 share_connstate_free(cs);
519 freetree234(sharestate->connections);
520 if (sharestate->listensock) {
521 sk_close(sharestate->listensock);
522 sharestate->listensock = NULL;
524 sfree(sharestate->server_verstring);
525 sfree(sharestate->sockname);
526 sfree(sharestate);
529 static struct share_halfchannel *share_add_halfchannel
530 (struct ssh_sharing_connstate *cs, unsigned server_id)
532 struct share_halfchannel *hc = snew(struct share_halfchannel);
533 hc->server_id = server_id;
534 if (add234(cs->halfchannels, hc) != hc) {
535 /* Duplicate?! */
536 sfree(hc);
537 return NULL;
538 } else {
539 return hc;
543 static struct share_halfchannel *share_find_halfchannel
544 (struct ssh_sharing_connstate *cs, unsigned server_id)
546 struct share_halfchannel dummyhc;
547 dummyhc.server_id = server_id;
548 return find234(cs->halfchannels, &dummyhc, NULL);
551 static void share_remove_halfchannel(struct ssh_sharing_connstate *cs,
552 struct share_halfchannel *hc)
554 del234(cs->halfchannels, hc);
555 sfree(hc);
558 static struct share_channel *share_add_channel
559 (struct ssh_sharing_connstate *cs, unsigned downstream_id,
560 unsigned upstream_id, unsigned server_id, int state, int maxpkt)
562 struct share_channel *chan = snew(struct share_channel);
563 chan->downstream_id = downstream_id;
564 chan->upstream_id = upstream_id;
565 chan->server_id = server_id;
566 chan->state = state;
567 chan->downstream_maxpkt = maxpkt;
568 chan->x11_auth_upstream = NULL;
569 chan->x11_auth_data = NULL;
570 chan->x11_auth_proto = -1;
571 chan->x11_auth_datalen = 0;
572 chan->x11_one_shot = 0;
573 if (add234(cs->channels_by_us, chan) != chan) {
574 sfree(chan);
575 return NULL;
577 if (chan->state != UNACKNOWLEDGED) {
578 if (add234(cs->channels_by_server, chan) != chan) {
579 del234(cs->channels_by_us, chan);
580 sfree(chan);
581 return NULL;
584 return chan;
587 static void share_channel_set_server_id(struct ssh_sharing_connstate *cs,
588 struct share_channel *chan,
589 unsigned server_id, int newstate)
591 chan->server_id = server_id;
592 chan->state = newstate;
593 assert(newstate != UNACKNOWLEDGED);
594 add234(cs->channels_by_server, chan);
597 static struct share_channel *share_find_channel_by_upstream
598 (struct ssh_sharing_connstate *cs, unsigned upstream_id)
600 struct share_channel dummychan;
601 dummychan.upstream_id = upstream_id;
602 return find234(cs->channels_by_us, &dummychan, NULL);
605 static struct share_channel *share_find_channel_by_server
606 (struct ssh_sharing_connstate *cs, unsigned server_id)
608 struct share_channel dummychan;
609 dummychan.server_id = server_id;
610 return find234(cs->channels_by_server, &dummychan, NULL);
613 static void share_remove_channel(struct ssh_sharing_connstate *cs,
614 struct share_channel *chan)
616 del234(cs->channels_by_us, chan);
617 del234(cs->channels_by_server, chan);
618 if (chan->x11_auth_upstream)
619 ssh_sharing_remove_x11_display(cs->parent->ssh,
620 chan->x11_auth_upstream);
621 sfree(chan->x11_auth_data);
622 sfree(chan);
625 static struct share_xchannel *share_add_xchannel
626 (struct ssh_sharing_connstate *cs,
627 unsigned upstream_id, unsigned server_id)
629 struct share_xchannel *xc = snew(struct share_xchannel);
630 xc->upstream_id = upstream_id;
631 xc->server_id = server_id;
632 xc->live = TRUE;
633 xc->msghead = xc->msgtail = NULL;
634 if (add234(cs->xchannels_by_us, xc) != xc) {
635 sfree(xc);
636 return NULL;
638 if (add234(cs->xchannels_by_server, xc) != xc) {
639 del234(cs->xchannels_by_us, xc);
640 sfree(xc);
641 return NULL;
643 return xc;
646 static struct share_xchannel *share_find_xchannel_by_upstream
647 (struct ssh_sharing_connstate *cs, unsigned upstream_id)
649 struct share_xchannel dummyxc;
650 dummyxc.upstream_id = upstream_id;
651 return find234(cs->xchannels_by_us, &dummyxc, NULL);
654 static struct share_xchannel *share_find_xchannel_by_server
655 (struct ssh_sharing_connstate *cs, unsigned server_id)
657 struct share_xchannel dummyxc;
658 dummyxc.server_id = server_id;
659 return find234(cs->xchannels_by_server, &dummyxc, NULL);
662 static void share_remove_xchannel(struct ssh_sharing_connstate *cs,
663 struct share_xchannel *xc)
665 del234(cs->xchannels_by_us, xc);
666 del234(cs->xchannels_by_server, xc);
667 share_xchannel_free(xc);
670 static struct share_forwarding *share_add_forwarding
671 (struct ssh_sharing_connstate *cs,
672 const char *host, int port)
674 struct share_forwarding *fwd = snew(struct share_forwarding);
675 fwd->host = dupstr(host);
676 fwd->port = port;
677 fwd->active = FALSE;
678 if (add234(cs->forwardings, fwd) != fwd) {
679 /* Duplicate?! */
680 sfree(fwd);
681 return NULL;
683 return fwd;
686 static struct share_forwarding *share_find_forwarding
687 (struct ssh_sharing_connstate *cs, const char *host, int port)
689 struct share_forwarding dummyfwd, *ret;
690 dummyfwd.host = dupstr(host);
691 dummyfwd.port = port;
692 ret = find234(cs->forwardings, &dummyfwd, NULL);
693 sfree(dummyfwd.host);
694 return ret;
697 static void share_remove_forwarding(struct ssh_sharing_connstate *cs,
698 struct share_forwarding *fwd)
700 del234(cs->forwardings, fwd);
701 sfree(fwd);
704 static void send_packet_to_downstream(struct ssh_sharing_connstate *cs,
705 int type, const void *pkt, int pktlen,
706 struct share_channel *chan)
708 if (!cs->sock) /* throw away all packets destined for a dead downstream */
709 return;
711 if (type == SSH2_MSG_CHANNEL_DATA) {
713 * Special case which we take care of at a low level, so as to
714 * be sure to apply it in all cases. On rare occasions we
715 * might find that we have a channel for which the
716 * downstream's maximum packet size exceeds the max packet
717 * size we presented to the server on its behalf. (This can
718 * occur in X11 forwarding, where we have to send _our_
719 * CHANNEL_OPEN_CONFIRMATION before we discover which if any
720 * downstream the channel is destined for, so if that
721 * downstream turns out to present a smaller max packet size
722 * then we're in this situation.)
724 * If that happens, we just chop up the packet into pieces and
725 * send them as separate CHANNEL_DATA packets.
727 const char *upkt = (const char *)pkt;
728 char header[13]; /* 4 length + 1 type + 4 channel id + 4 string len */
730 int len = toint(GET_32BIT(upkt + 4));
731 upkt += 8; /* skip channel id + length field */
733 if (len < 0 || len > pktlen - 8)
734 len = pktlen - 8;
736 do {
737 int this_len = (len > chan->downstream_maxpkt ?
738 chan->downstream_maxpkt : len);
739 PUT_32BIT(header, this_len + 9);
740 header[4] = type;
741 PUT_32BIT(header + 5, chan->downstream_id);
742 PUT_32BIT(header + 9, this_len);
743 sk_write(cs->sock, header, 13);
744 sk_write(cs->sock, upkt, this_len);
745 len -= this_len;
746 upkt += this_len;
747 } while (len > 0);
748 } else {
750 * Just do the obvious thing.
752 char header[9];
754 PUT_32BIT(header, pktlen + 1);
755 header[4] = type;
756 sk_write(cs->sock, header, 5);
757 sk_write(cs->sock, pkt, pktlen);
761 static void share_try_cleanup(struct ssh_sharing_connstate *cs)
763 int i;
764 struct share_halfchannel *hc;
765 struct share_channel *chan;
766 struct share_forwarding *fwd;
769 * Any half-open channels, i.e. those for which we'd received
770 * CHANNEL_OPEN from the server but not passed back a response
771 * from downstream, should be responded to with OPEN_FAILURE.
773 while ((hc = (struct share_halfchannel *)
774 index234(cs->halfchannels, 0)) != NULL) {
775 static const char reason[] = "PuTTY downstream no longer available";
776 static const char lang[] = "en";
777 unsigned char packet[256];
778 int pos = 0;
780 PUT_32BIT(packet + pos, hc->server_id); pos += 4;
781 PUT_32BIT(packet + pos, SSH2_OPEN_CONNECT_FAILED); pos += 4;
782 PUT_32BIT(packet + pos, strlen(reason)); pos += 4;
783 memcpy(packet + pos, reason, strlen(reason)); pos += strlen(reason);
784 PUT_32BIT(packet + pos, strlen(lang)); pos += 4;
785 memcpy(packet + pos, lang, strlen(lang)); pos += strlen(lang);
786 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
787 SSH2_MSG_CHANNEL_OPEN_FAILURE,
788 packet, pos, "cleanup after"
789 " downstream went away");
791 share_remove_halfchannel(cs, hc);
795 * Any actually open channels should have a CHANNEL_CLOSE sent for
796 * them, unless we've already done so. We won't be able to
797 * actually clean them up until CHANNEL_CLOSE comes back from the
798 * server, though (unless the server happens to have sent a CLOSE
799 * already).
801 * Another annoying exception is UNACKNOWLEDGED channels, i.e.
802 * we've _sent_ a CHANNEL_OPEN to the server but not received an
803 * OPEN_CONFIRMATION or OPEN_FAILURE. We must wait for a reply
804 * before closing the channel, because until we see that reply we
805 * won't have the server's channel id to put in the close message.
807 for (i = 0; (chan = (struct share_channel *)
808 index234(cs->channels_by_us, i)) != NULL; i++) {
809 unsigned char packet[256];
810 int pos = 0;
812 if (chan->state != SENT_CLOSE && chan->state != UNACKNOWLEDGED) {
813 PUT_32BIT(packet + pos, chan->server_id); pos += 4;
814 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
815 SSH2_MSG_CHANNEL_CLOSE,
816 packet, pos, "cleanup after"
817 " downstream went away");
818 if (chan->state != RCVD_CLOSE) {
819 chan->state = SENT_CLOSE;
820 } else {
821 /* In this case, we _can_ clear up the channel now. */
822 ssh_delete_sharing_channel(cs->parent->ssh, chan->upstream_id);
823 share_remove_channel(cs, chan);
824 i--; /* don't accidentally skip one as a result */
830 * Any remote port forwardings we're managing on behalf of this
831 * downstream should be cancelled. Again, we must defer those for
832 * which we haven't yet seen REQUEST_SUCCESS/FAILURE.
834 * We take a fire-and-forget approach during cleanup, not
835 * bothering to set want_reply.
837 for (i = 0; (fwd = (struct share_forwarding *)
838 index234(cs->forwardings, i)) != NULL; i++) {
839 if (fwd->active) {
840 static const char request[] = "cancel-tcpip-forward";
841 char *packet = snewn(256 + strlen(fwd->host), char);
842 int pos = 0;
844 PUT_32BIT(packet + pos, strlen(request)); pos += 4;
845 memcpy(packet + pos, request, strlen(request));
846 pos += strlen(request);
848 packet[pos++] = 0; /* !want_reply */
850 PUT_32BIT(packet + pos, strlen(fwd->host)); pos += 4;
851 memcpy(packet + pos, fwd->host, strlen(fwd->host));
852 pos += strlen(fwd->host);
854 PUT_32BIT(packet + pos, fwd->port); pos += 4;
856 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
857 SSH2_MSG_GLOBAL_REQUEST,
858 packet, pos, "cleanup after"
859 " downstream went away");
860 sfree(packet);
862 share_remove_forwarding(cs, fwd);
863 i--; /* don't accidentally skip one as a result */
867 if (count234(cs->halfchannels) == 0 &&
868 count234(cs->channels_by_us) == 0 &&
869 count234(cs->forwardings) == 0) {
871 * Now we're _really_ done, so we can get rid of cs completely.
873 del234(cs->parent->connections, cs);
874 ssh_sharing_downstream_disconnected(cs->parent->ssh, cs->id);
875 share_connstate_free(cs);
879 static void share_begin_cleanup(struct ssh_sharing_connstate *cs)
882 sk_close(cs->sock);
883 cs->sock = NULL;
885 share_try_cleanup(cs);
888 static void share_disconnect(struct ssh_sharing_connstate *cs,
889 const char *message)
891 static const char lang[] = "en";
892 int msglen = strlen(message);
893 char *packet = snewn(msglen + 256, char);
894 int pos = 0;
896 PUT_32BIT(packet + pos, SSH2_DISCONNECT_PROTOCOL_ERROR); pos += 4;
898 PUT_32BIT(packet + pos, msglen); pos += 4;
899 memcpy(packet + pos, message, msglen);
900 pos += msglen;
902 PUT_32BIT(packet + pos, strlen(lang)); pos += 4;
903 memcpy(packet + pos, lang, strlen(lang)); pos += strlen(lang);
905 send_packet_to_downstream(cs, SSH2_MSG_DISCONNECT, packet, pos, NULL);
907 share_begin_cleanup(cs);
910 static int share_closing(Plug plug, const char *error_msg, int error_code,
911 int calling_back)
913 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
914 if (error_msg)
915 ssh_sharing_logf(cs->parent->ssh, cs->id, "%s", error_msg);
916 share_begin_cleanup(cs);
917 return 1;
920 static int getstring_inner(const void *vdata, int datalen,
921 char **out, int *outlen)
923 const unsigned char *data = (const unsigned char *)vdata;
924 int len;
926 if (datalen < 4)
927 return FALSE;
929 len = toint(GET_32BIT(data));
930 if (len < 0 || len > datalen - 4)
931 return FALSE;
933 if (outlen)
934 *outlen = len + 4; /* total size including length field */
935 if (out)
936 *out = dupprintf("%.*s", len, (char *)data + 4);
937 return TRUE;
940 static char *getstring(const void *data, int datalen)
942 char *ret;
943 if (getstring_inner(data, datalen, &ret, NULL))
944 return ret;
945 else
946 return NULL;
949 static int getstring_size(const void *data, int datalen)
951 int ret;
952 if (getstring_inner(data, datalen, NULL, &ret))
953 return ret;
954 else
955 return -1;
959 * Append a message to the end of an xchannel's queue, with the length
960 * and type code filled in and the data block allocated but
961 * uninitialised.
963 struct share_xchannel_message *share_xchannel_add_message
964 (struct share_xchannel *xc, int type, int len)
966 unsigned char *block;
967 struct share_xchannel_message *msg;
970 * Be a little tricksy here by allocating a single memory block
971 * containing both the 'struct share_xchannel_message' and the
972 * actual data. Simplifies freeing it later.
974 block = smalloc(sizeof(struct share_xchannel_message) + len);
975 msg = (struct share_xchannel_message *)block;
976 msg->data = block + sizeof(struct share_xchannel_message);
977 msg->datalen = len;
978 msg->type = type;
981 * Queue it in the xchannel.
983 if (xc->msgtail)
984 xc->msgtail->next = msg;
985 else
986 xc->msghead = msg;
987 msg->next = NULL;
988 xc->msgtail = msg;
990 return msg;
993 void share_dead_xchannel_respond(struct ssh_sharing_connstate *cs,
994 struct share_xchannel *xc)
997 * Handle queued incoming messages from the server destined for an
998 * xchannel which is dead (i.e. downstream sent OPEN_FAILURE).
1000 int delete = FALSE;
1001 while (xc->msghead) {
1002 struct share_xchannel_message *msg = xc->msghead;
1003 xc->msghead = msg->next;
1005 if (msg->type == SSH2_MSG_CHANNEL_REQUEST && msg->datalen > 4) {
1007 * A CHANNEL_REQUEST is responded to by sending
1008 * CHANNEL_FAILURE, if it has want_reply set.
1010 int wantreplypos = getstring_size(msg->data, msg->datalen);
1011 if (wantreplypos > 0 && wantreplypos < msg->datalen &&
1012 msg->data[wantreplypos] != 0) {
1013 unsigned char id[4];
1014 PUT_32BIT(id, xc->server_id);
1015 ssh_send_packet_from_downstream
1016 (cs->parent->ssh, cs->id, SSH2_MSG_CHANNEL_FAILURE, id, 4,
1017 "downstream refused X channel open");
1019 } else if (msg->type == SSH2_MSG_CHANNEL_CLOSE) {
1021 * On CHANNEL_CLOSE we can discard the channel completely.
1023 delete = TRUE;
1026 sfree(msg);
1028 xc->msgtail = NULL;
1029 if (delete) {
1030 ssh_delete_sharing_channel(cs->parent->ssh, xc->upstream_id);
1031 share_remove_xchannel(cs, xc);
1035 void share_xchannel_confirmation(struct ssh_sharing_connstate *cs,
1036 struct share_xchannel *xc,
1037 struct share_channel *chan,
1038 unsigned downstream_window)
1040 unsigned char window_adjust[8];
1043 * Send all the queued messages downstream.
1045 while (xc->msghead) {
1046 struct share_xchannel_message *msg = xc->msghead;
1047 xc->msghead = msg->next;
1049 if (msg->datalen >= 4)
1050 PUT_32BIT(msg->data, chan->downstream_id);
1051 send_packet_to_downstream(cs, msg->type,
1052 msg->data, msg->datalen, chan);
1054 sfree(msg);
1058 * Send a WINDOW_ADJUST back upstream, to synchronise the window
1059 * size downstream thinks it's presented with the one we've
1060 * actually presented.
1062 PUT_32BIT(window_adjust, xc->server_id);
1063 PUT_32BIT(window_adjust + 4, downstream_window - xc->window);
1064 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1065 SSH2_MSG_CHANNEL_WINDOW_ADJUST,
1066 window_adjust, 8, "window adjustment after"
1067 " downstream accepted X channel");
1070 void share_xchannel_failure(struct ssh_sharing_connstate *cs,
1071 struct share_xchannel *xc)
1074 * If downstream refuses to open our X channel at all for some
1075 * reason, we must respond by sending an emergency CLOSE upstream.
1077 unsigned char id[4];
1078 PUT_32BIT(id, xc->server_id);
1079 ssh_send_packet_from_downstream
1080 (cs->parent->ssh, cs->id, SSH2_MSG_CHANNEL_CLOSE, id, 4,
1081 "downstream refused X channel open");
1084 * Now mark the xchannel as dead, and respond to anything sent on
1085 * it until we see CLOSE for it in turn.
1087 xc->live = FALSE;
1088 share_dead_xchannel_respond(cs, xc);
1091 void share_setup_x11_channel(void *csv, void *chanv,
1092 unsigned upstream_id, unsigned server_id,
1093 unsigned server_currwin, unsigned server_maxpkt,
1094 unsigned client_adjusted_window,
1095 const char *peer_addr, int peer_port, int endian,
1096 int protomajor, int protominor,
1097 const void *initial_data, int initial_len)
1099 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv;
1100 struct share_channel *chan = (struct share_channel *)chanv;
1101 struct share_xchannel *xc;
1102 struct share_xchannel_message *msg;
1103 void *greeting;
1104 int greeting_len;
1105 unsigned char *pkt;
1106 int pktlen;
1109 * Create an xchannel containing data we've already received from
1110 * the X client, and preload it with a CHANNEL_DATA message
1111 * containing our own made-up authorisation greeting and any
1112 * additional data sent from the server so far.
1114 xc = share_add_xchannel(cs, upstream_id, server_id);
1115 greeting = x11_make_greeting(endian, protomajor, protominor,
1116 chan->x11_auth_proto,
1117 chan->x11_auth_data, chan->x11_auth_datalen,
1118 peer_addr, peer_port, &greeting_len);
1119 msg = share_xchannel_add_message(xc, SSH2_MSG_CHANNEL_DATA,
1120 8 + greeting_len + initial_len);
1121 /* leave the channel id field unfilled - we don't know the
1122 * downstream id yet, of course */
1123 PUT_32BIT(msg->data + 4, greeting_len + initial_len);
1124 memcpy(msg->data + 8, greeting, greeting_len);
1125 memcpy(msg->data + 8 + greeting_len, initial_data, initial_len);
1126 sfree(greeting);
1128 xc->window = client_adjusted_window + greeting_len;
1131 * Send on a CHANNEL_OPEN to downstream.
1133 pktlen = 27 + strlen(peer_addr);
1134 pkt = snewn(pktlen, unsigned char);
1135 PUT_32BIT(pkt, 3); /* strlen("x11") */
1136 memcpy(pkt+4, "x11", 3);
1137 PUT_32BIT(pkt+7, server_id);
1138 PUT_32BIT(pkt+11, server_currwin);
1139 PUT_32BIT(pkt+15, server_maxpkt);
1140 PUT_32BIT(pkt+19, strlen(peer_addr));
1141 memcpy(pkt+23, peer_addr, strlen(peer_addr));
1142 PUT_32BIT(pkt+23+strlen(peer_addr), peer_port);
1143 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_OPEN, pkt, pktlen, NULL);
1144 sfree(pkt);
1147 * If this was a once-only X forwarding, clean it up now.
1149 if (chan->x11_one_shot) {
1150 ssh_sharing_remove_x11_display(cs->parent->ssh,
1151 chan->x11_auth_upstream);
1152 chan->x11_auth_upstream = NULL;
1153 sfree(chan->x11_auth_data);
1154 chan->x11_auth_proto = -1;
1155 chan->x11_auth_datalen = 0;
1156 chan->x11_one_shot = 0;
1160 void share_got_pkt_from_server(void *csv, int type,
1161 unsigned char *pkt, int pktlen)
1163 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv;
1164 struct share_globreq *globreq;
1165 int id_pos;
1166 unsigned upstream_id, server_id;
1167 struct share_channel *chan;
1168 struct share_xchannel *xc;
1170 switch (type) {
1171 case SSH2_MSG_REQUEST_SUCCESS:
1172 case SSH2_MSG_REQUEST_FAILURE:
1173 globreq = cs->globreq_head;
1174 if (globreq->type == GLOBREQ_TCPIP_FORWARD) {
1175 if (type == SSH2_MSG_REQUEST_FAILURE) {
1176 share_remove_forwarding(cs, globreq->fwd);
1177 } else {
1178 globreq->fwd->active = TRUE;
1180 } else if (globreq->type == GLOBREQ_CANCEL_TCPIP_FORWARD) {
1181 if (type == SSH2_MSG_REQUEST_SUCCESS) {
1182 share_remove_forwarding(cs, globreq->fwd);
1185 if (globreq->want_reply) {
1186 send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1188 cs->globreq_head = globreq->next;
1189 sfree(globreq);
1190 if (cs->globreq_head == NULL)
1191 cs->globreq_tail = NULL;
1193 if (!cs->sock) {
1194 /* Retry cleaning up this connection, in case that reply
1195 * was the last thing we were waiting for. */
1196 share_try_cleanup(cs);
1199 break;
1201 case SSH2_MSG_CHANNEL_OPEN:
1202 id_pos = getstring_size(pkt, pktlen);
1203 assert(id_pos >= 0);
1204 server_id = GET_32BIT(pkt + id_pos);
1205 share_add_halfchannel(cs, server_id);
1207 send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1208 break;
1210 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
1211 case SSH2_MSG_CHANNEL_OPEN_FAILURE:
1212 case SSH2_MSG_CHANNEL_CLOSE:
1213 case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1214 case SSH2_MSG_CHANNEL_DATA:
1215 case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1216 case SSH2_MSG_CHANNEL_EOF:
1217 case SSH2_MSG_CHANNEL_REQUEST:
1218 case SSH2_MSG_CHANNEL_SUCCESS:
1219 case SSH2_MSG_CHANNEL_FAILURE:
1221 * All these messages have the recipient channel id as the
1222 * first uint32 field in the packet. Substitute the downstream
1223 * channel id for our one and pass the packet downstream.
1225 assert(pktlen >= 4);
1226 upstream_id = GET_32BIT(pkt);
1227 if ((chan = share_find_channel_by_upstream(cs, upstream_id)) != NULL) {
1229 * The normal case: this id refers to an open channel.
1231 PUT_32BIT(pkt, chan->downstream_id);
1232 send_packet_to_downstream(cs, type, pkt, pktlen, chan);
1235 * Update the channel state, for messages that need it.
1237 if (type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
1238 if (chan->state == UNACKNOWLEDGED && pktlen >= 8) {
1239 share_channel_set_server_id(cs, chan, GET_32BIT(pkt+4),
1240 OPEN);
1241 if (!cs->sock) {
1242 /* Retry cleaning up this connection, so that we
1243 * can send an immediate CLOSE on this channel for
1244 * which we now know the server id. */
1245 share_try_cleanup(cs);
1248 } else if (type == SSH2_MSG_CHANNEL_OPEN_FAILURE) {
1249 ssh_delete_sharing_channel(cs->parent->ssh, chan->upstream_id);
1250 share_remove_channel(cs, chan);
1251 } else if (type == SSH2_MSG_CHANNEL_CLOSE) {
1252 if (chan->state == SENT_CLOSE) {
1253 ssh_delete_sharing_channel(cs->parent->ssh,
1254 chan->upstream_id);
1255 share_remove_channel(cs, chan);
1256 if (!cs->sock) {
1257 /* Retry cleaning up this connection, in case this
1258 * channel closure was the last thing we were
1259 * waiting for. */
1260 share_try_cleanup(cs);
1262 } else {
1263 chan->state = RCVD_CLOSE;
1266 } else if ((xc = share_find_xchannel_by_upstream(cs, upstream_id))
1267 != NULL) {
1269 * The unusual case: this id refers to an xchannel. Add it
1270 * to the xchannel's queue.
1272 struct share_xchannel_message *msg;
1274 msg = share_xchannel_add_message(xc, type, pktlen);
1275 memcpy(msg->data, pkt, pktlen);
1277 /* If the xchannel is dead, then also respond to it (which
1278 * may involve deleting the channel). */
1279 if (!xc->live)
1280 share_dead_xchannel_respond(cs, xc);
1282 break;
1284 default:
1285 assert(!"This packet type should never have come from ssh.c");
1286 break;
1290 static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
1291 int type,
1292 unsigned char *pkt, int pktlen)
1294 char *request_name;
1295 struct share_forwarding *fwd;
1296 int id_pos;
1297 unsigned old_id, new_id, server_id;
1298 struct share_globreq *globreq;
1299 struct share_channel *chan;
1300 struct share_halfchannel *hc;
1301 struct share_xchannel *xc;
1302 char *err = NULL;
1304 switch (type) {
1305 case SSH2_MSG_DISCONNECT:
1307 * This message stops here: if downstream is disconnecting
1308 * from us, that doesn't mean we want to disconnect from the
1309 * SSH server. Close the downstream connection and start
1310 * cleanup.
1312 share_begin_cleanup(cs);
1313 break;
1315 case SSH2_MSG_GLOBAL_REQUEST:
1317 * The only global requests we understand are "tcpip-forward"
1318 * and "cancel-tcpip-forward". Since those require us to
1319 * maintain state, we must assume that other global requests
1320 * will probably require that too, and so we don't forward on
1321 * any request we don't understand.
1323 request_name = getstring(pkt, pktlen);
1324 if (request_name == NULL) {
1325 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1326 goto confused;
1329 if (!strcmp(request_name, "tcpip-forward")) {
1330 int wantreplypos, orig_wantreply, port, ret;
1331 char *host;
1333 sfree(request_name);
1336 * Pick the packet apart to find the want_reply field and
1337 * the host/port we're going to ask to listen on.
1339 wantreplypos = getstring_size(pkt, pktlen);
1340 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1341 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1342 goto confused;
1344 orig_wantreply = pkt[wantreplypos];
1345 port = getstring_size(pkt + (wantreplypos + 1),
1346 pktlen - (wantreplypos + 1));
1347 port += (wantreplypos + 1);
1348 if (port < 0 || port > pktlen - 4) {
1349 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1350 goto confused;
1352 host = getstring(pkt + (wantreplypos + 1),
1353 pktlen - (wantreplypos + 1));
1354 assert(host != NULL);
1355 port = GET_32BIT(pkt + port);
1358 * See if we can allocate space in ssh.c's tree of remote
1359 * port forwardings. If we can't, it's because another
1360 * client sharing this connection has already allocated
1361 * the identical port forwarding, so we take it on
1362 * ourselves to manufacture a failure packet and send it
1363 * back to downstream.
1365 ret = ssh_alloc_sharing_rportfwd(cs->parent->ssh, host, port, cs);
1366 if (!ret) {
1367 if (orig_wantreply) {
1368 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1369 "", 0, NULL);
1371 } else {
1373 * We've managed to make space for this forwarding
1374 * locally. Pass the request on to the SSH server, but
1375 * set want_reply even if it wasn't originally set, so
1376 * that we know whether this forwarding needs to be
1377 * cleaned up if downstream goes away.
1379 int old_wantreply = pkt[wantreplypos];
1380 pkt[wantreplypos] = 1;
1381 ssh_send_packet_from_downstream
1382 (cs->parent->ssh, cs->id, type, pkt, pktlen,
1383 old_wantreply ? NULL : "upstream added want_reply flag");
1384 fwd = share_add_forwarding(cs, host, port);
1385 ssh_sharing_queue_global_request(cs->parent->ssh, cs);
1387 if (fwd) {
1388 globreq = snew(struct share_globreq);
1389 globreq->next = NULL;
1390 if (cs->globreq_tail)
1391 cs->globreq_tail->next = globreq;
1392 else
1393 cs->globreq_head = globreq;
1394 globreq->fwd = fwd;
1395 globreq->want_reply = orig_wantreply;
1396 globreq->type = GLOBREQ_TCPIP_FORWARD;
1400 sfree(host);
1401 } else if (!strcmp(request_name, "cancel-tcpip-forward")) {
1402 int wantreplypos, orig_wantreply, port;
1403 char *host;
1404 struct share_forwarding *fwd;
1406 sfree(request_name);
1409 * Pick the packet apart to find the want_reply field and
1410 * the host/port we're going to ask to listen on.
1412 wantreplypos = getstring_size(pkt, pktlen);
1413 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1414 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1415 goto confused;
1417 orig_wantreply = pkt[wantreplypos];
1418 port = getstring_size(pkt + (wantreplypos + 1),
1419 pktlen - (wantreplypos + 1));
1420 port += (wantreplypos + 1);
1421 if (port < 0 || port > pktlen - 4) {
1422 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1423 goto confused;
1425 host = getstring(pkt + (wantreplypos + 1),
1426 pktlen - (wantreplypos + 1));
1427 assert(host != NULL);
1428 port = GET_32BIT(pkt + port);
1431 * Look up the existing forwarding with these details.
1433 fwd = share_find_forwarding(cs, host, port);
1434 if (!fwd) {
1435 if (orig_wantreply) {
1436 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1437 "", 0, NULL);
1439 } else {
1441 * Pass the cancel request on to the SSH server, but
1442 * set want_reply even if it wasn't originally set, so
1443 * that _we_ know whether the forwarding has been
1444 * deleted even if downstream doesn't want to know.
1446 int old_wantreply = pkt[wantreplypos];
1447 pkt[wantreplypos] = 1;
1448 ssh_send_packet_from_downstream
1449 (cs->parent->ssh, cs->id, type, pkt, pktlen,
1450 old_wantreply ? NULL : "upstream added want_reply flag");
1451 ssh_sharing_queue_global_request(cs->parent->ssh, cs);
1454 sfree(host);
1455 } else {
1457 * Request we don't understand. Manufacture a failure
1458 * message if an answer was required.
1460 int wantreplypos;
1462 sfree(request_name);
1464 wantreplypos = getstring_size(pkt, pktlen);
1465 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1466 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1467 goto confused;
1469 if (pkt[wantreplypos])
1470 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1471 "", 0, NULL);
1473 break;
1475 case SSH2_MSG_CHANNEL_OPEN:
1476 /* Sender channel id comes after the channel type string */
1477 id_pos = getstring_size(pkt, pktlen);
1478 if (id_pos < 0 || id_pos > pktlen - 12) {
1479 err = dupprintf("Truncated CHANNEL_OPEN packet");
1480 goto confused;
1483 old_id = GET_32BIT(pkt + id_pos);
1484 new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
1485 share_add_channel(cs, old_id, new_id, 0, UNACKNOWLEDGED,
1486 GET_32BIT(pkt + id_pos + 8));
1487 PUT_32BIT(pkt + id_pos, new_id);
1488 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1489 type, pkt, pktlen, NULL);
1490 break;
1492 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
1493 if (pktlen < 16) {
1494 err = dupprintf("Truncated CHANNEL_OPEN_CONFIRMATION packet");
1495 goto confused;
1498 id_pos = 4; /* sender channel id is 2nd uint32 field in packet */
1499 old_id = GET_32BIT(pkt + id_pos);
1501 server_id = GET_32BIT(pkt);
1502 /* This server id may refer to either a halfchannel or an xchannel. */
1503 hc = NULL, xc = NULL; /* placate optimiser */
1504 if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
1505 new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
1506 } else if ((xc = share_find_xchannel_by_server(cs, server_id))
1507 != NULL) {
1508 new_id = xc->upstream_id;
1509 } else {
1510 err = dupprintf("CHANNEL_OPEN_CONFIRMATION packet cited unknown channel %u", (unsigned)server_id);
1511 goto confused;
1514 PUT_32BIT(pkt + id_pos, new_id);
1516 chan = share_add_channel(cs, old_id, new_id, server_id, OPEN,
1517 GET_32BIT(pkt + 12));
1519 if (hc) {
1520 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1521 type, pkt, pktlen, NULL);
1522 share_remove_halfchannel(cs, hc);
1523 } else if (xc) {
1524 unsigned downstream_window = GET_32BIT(pkt + 8);
1525 if (downstream_window < 256) {
1526 err = dupprintf("Initial window size for x11 channel must be at least 256 (got %u)", downstream_window);
1527 goto confused;
1529 share_xchannel_confirmation(cs, xc, chan, downstream_window);
1530 share_remove_xchannel(cs, xc);
1533 break;
1535 case SSH2_MSG_CHANNEL_OPEN_FAILURE:
1536 if (pktlen < 4) {
1537 err = dupprintf("Truncated CHANNEL_OPEN_FAILURE packet");
1538 goto confused;
1541 server_id = GET_32BIT(pkt);
1542 /* This server id may refer to either a halfchannel or an xchannel. */
1543 if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
1544 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1545 type, pkt, pktlen, NULL);
1546 share_remove_halfchannel(cs, hc);
1547 } else if ((xc = share_find_xchannel_by_server(cs, server_id))
1548 != NULL) {
1549 share_xchannel_failure(cs, xc);
1550 } else {
1551 err = dupprintf("CHANNEL_OPEN_FAILURE packet cited unknown channel %u", (unsigned)server_id);
1552 goto confused;
1555 break;
1557 case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1558 case SSH2_MSG_CHANNEL_DATA:
1559 case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1560 case SSH2_MSG_CHANNEL_EOF:
1561 case SSH2_MSG_CHANNEL_CLOSE:
1562 case SSH2_MSG_CHANNEL_REQUEST:
1563 case SSH2_MSG_CHANNEL_SUCCESS:
1564 case SSH2_MSG_CHANNEL_FAILURE:
1565 case SSH2_MSG_IGNORE:
1566 case SSH2_MSG_DEBUG:
1567 if (type == SSH2_MSG_CHANNEL_REQUEST &&
1568 (request_name = getstring(pkt + 4, pktlen - 4)) != NULL) {
1570 * Agent forwarding requests from downstream are treated
1571 * specially. Because OpenSSHD doesn't let us enable agent
1572 * forwarding independently per session channel, and in
1573 * particular because the OpenSSH-defined agent forwarding
1574 * protocol does not mark agent-channel requests with the
1575 * id of the session channel they originate from, the only
1576 * way we can implement agent forwarding in a
1577 * connection-shared PuTTY is to forward the _upstream_
1578 * agent. Hence, we unilaterally deny agent forwarding
1579 * requests from downstreams if we aren't prepared to
1580 * forward an agent ourselves.
1582 * (If we are, then we dutifully pass agent forwarding
1583 * requests upstream. OpenSSHD has the curious behaviour
1584 * that all but the first such request will be rejected,
1585 * but all session channels opened after the first request
1586 * get agent forwarding enabled whether they ask for it or
1587 * not; but that's not our concern, since other SSH
1588 * servers supporting the same piece of protocol might in
1589 * principle at least manage to enable agent forwarding on
1590 * precisely the channels that requested it, even if the
1591 * subsequent CHANNEL_OPENs still can't be associated with
1592 * a parent session channel.)
1594 if (!strcmp(request_name, "auth-agent-req@openssh.com") &&
1595 !ssh_agent_forwarding_permitted(cs->parent->ssh)) {
1596 unsigned server_id = GET_32BIT(pkt);
1597 unsigned char recipient_id[4];
1599 sfree(request_name);
1601 chan = share_find_channel_by_server(cs, server_id);
1602 if (chan) {
1603 PUT_32BIT(recipient_id, chan->downstream_id);
1604 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_FAILURE,
1605 recipient_id, 4, NULL);
1606 } else {
1607 char *buf = dupprintf("Agent forwarding request for "
1608 "unrecognised channel %u", server_id);
1609 share_disconnect(cs, buf);
1610 sfree(buf);
1611 return;
1613 break;
1617 * Another thing we treat specially is X11 forwarding
1618 * requests. For these, we have to make up another set of
1619 * X11 auth data, and enter it into our SSH connection's
1620 * list of possible X11 authorisation credentials so that
1621 * when we see an X11 channel open request we can know
1622 * whether it's one to handle locally or one to pass on to
1623 * a downstream, and if the latter, which one.
1625 if (!strcmp(request_name, "x11-req")) {
1626 unsigned server_id = GET_32BIT(pkt);
1627 int want_reply, single_connection, screen;
1628 char *auth_proto_str, *auth_data;
1629 int auth_proto, protolen, datalen;
1630 int pos;
1632 sfree(request_name);
1634 chan = share_find_channel_by_server(cs, server_id);
1635 if (!chan) {
1636 char *buf = dupprintf("X11 forwarding request for "
1637 "unrecognised channel %u", server_id);
1638 share_disconnect(cs, buf);
1639 sfree(buf);
1640 return;
1644 * Pick apart the whole message to find the downstream
1645 * auth details.
1647 /* we have already seen: 4 bytes channel id, 4+7 request name */
1648 if (pktlen < 17) {
1649 err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1650 goto confused;
1652 want_reply = pkt[15] != 0;
1653 single_connection = pkt[16] != 0;
1654 auth_proto_str = getstring(pkt+17, pktlen-17);
1655 auth_proto = x11_identify_auth_proto(auth_proto_str);
1656 sfree(auth_proto_str);
1657 pos = 17 + getstring_size(pkt+17, pktlen-17);
1658 auth_data = getstring(pkt+pos, pktlen-pos);
1659 pos += getstring_size(pkt+pos, pktlen-pos);
1661 if (pktlen < pos+4) {
1662 err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1663 sfree(auth_data);
1664 goto confused;
1666 screen = GET_32BIT(pkt+pos);
1668 if (auth_proto < 0) {
1669 /* Reject due to not understanding downstream's
1670 * requested authorisation method. */
1671 unsigned char recipient_id[4];
1672 PUT_32BIT(recipient_id, chan->downstream_id);
1673 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_FAILURE,
1674 recipient_id, 4, NULL);
1675 sfree(auth_data);
1676 break;
1679 chan->x11_auth_proto = auth_proto;
1680 chan->x11_auth_data = x11_dehexify(auth_data,
1681 &chan->x11_auth_datalen);
1682 sfree(auth_data);
1683 chan->x11_auth_upstream =
1684 ssh_sharing_add_x11_display(cs->parent->ssh, auth_proto,
1685 cs, chan);
1686 chan->x11_one_shot = single_connection;
1689 * Now construct a replacement X forwarding request,
1690 * containing our own auth data, and send that to the
1691 * server.
1693 protolen = strlen(chan->x11_auth_upstream->protoname);
1694 datalen = strlen(chan->x11_auth_upstream->datastring);
1695 pktlen = 29+protolen+datalen;
1696 pkt = snewn(pktlen, unsigned char);
1697 PUT_32BIT(pkt, server_id);
1698 PUT_32BIT(pkt+4, 7); /* strlen("x11-req") */
1699 memcpy(pkt+8, "x11-req", 7);
1700 pkt[15] = want_reply;
1701 pkt[16] = single_connection;
1702 PUT_32BIT(pkt+17, protolen);
1703 memcpy(pkt+21, chan->x11_auth_upstream->protoname, protolen);
1704 PUT_32BIT(pkt+21+protolen, datalen);
1705 memcpy(pkt+25+protolen, chan->x11_auth_upstream->datastring,
1706 datalen);
1707 PUT_32BIT(pkt+25+protolen+datalen, screen);
1708 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1709 SSH2_MSG_CHANNEL_REQUEST,
1710 pkt, pktlen, NULL);
1711 sfree(pkt);
1713 break;
1716 sfree(request_name);
1719 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1720 type, pkt, pktlen, NULL);
1721 if (type == SSH2_MSG_CHANNEL_CLOSE && pktlen >= 4) {
1722 server_id = GET_32BIT(pkt);
1723 chan = share_find_channel_by_server(cs, server_id);
1724 if (chan) {
1725 if (chan->state == RCVD_CLOSE) {
1726 ssh_delete_sharing_channel(cs->parent->ssh,
1727 chan->upstream_id);
1728 share_remove_channel(cs, chan);
1729 } else {
1730 chan->state = SENT_CLOSE;
1734 break;
1736 default:
1737 err = dupprintf("Unexpected packet type %d\n", type);
1738 goto confused;
1741 * Any other packet type is unexpected. In particular, we
1742 * never pass GLOBAL_REQUESTs downstream, so we never expect
1743 * to see SSH2_MSG_REQUEST_{SUCCESS,FAILURE}.
1745 confused:
1746 assert(err != NULL);
1747 share_disconnect(cs, err);
1748 sfree(err);
1749 break;
1754 * Coroutine macros similar to, but simplified from, those in ssh.c.
1756 #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
1757 #define crFinish(z) } *crLine = 0; return (z); }
1758 #define crGetChar(c) do \
1760 while (len == 0) { \
1761 *crLine =__LINE__; return 1; case __LINE__:; \
1763 len--; \
1764 (c) = (unsigned char)*data++; \
1765 } while (0)
1767 static int share_receive(Plug plug, int urgent, char *data, int len)
1769 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
1770 static const char expected_verstring_prefix[] =
1771 "SSHCONNECTION@putty.projects.tartarus.org-2.0-";
1772 unsigned char c;
1774 crBegin(cs->crLine);
1777 * First read the version string from downstream.
1779 cs->recvlen = 0;
1780 while (1) {
1781 crGetChar(c);
1782 if (c == '\012')
1783 break;
1784 if (cs->recvlen >= sizeof(cs->recvbuf)) {
1785 char *buf = dupprintf("Version string far too long\n");
1786 share_disconnect(cs, buf);
1787 sfree(buf);
1788 goto dead;
1790 cs->recvbuf[cs->recvlen++] = c;
1794 * Now parse the version string to make sure it's at least vaguely
1795 * sensible, and log it.
1797 if (cs->recvlen < sizeof(expected_verstring_prefix)-1 ||
1798 memcmp(cs->recvbuf, expected_verstring_prefix,
1799 sizeof(expected_verstring_prefix) - 1)) {
1800 char *buf = dupprintf("Version string did not have expected prefix\n");
1801 share_disconnect(cs, buf);
1802 sfree(buf);
1803 goto dead;
1805 if (cs->recvlen > 0 && cs->recvbuf[cs->recvlen-1] == '\015')
1806 cs->recvlen--; /* trim off \r before \n */
1807 ssh_sharing_logf(cs->parent->ssh, cs->id,
1808 "Downstream version string: %.*s",
1809 cs->recvlen, cs->recvbuf);
1812 * Loop round reading packets.
1814 while (1) {
1815 cs->recvlen = 0;
1816 while (cs->recvlen < 4) {
1817 crGetChar(c);
1818 cs->recvbuf[cs->recvlen++] = c;
1820 cs->curr_packetlen = toint(GET_32BIT(cs->recvbuf) + 4);
1821 if (cs->curr_packetlen < 5 ||
1822 cs->curr_packetlen > sizeof(cs->recvbuf)) {
1823 char *buf = dupprintf("Bad packet length %u\n",
1824 (unsigned)cs->curr_packetlen);
1825 share_disconnect(cs, buf);
1826 sfree(buf);
1827 goto dead;
1829 while (cs->recvlen < cs->curr_packetlen) {
1830 crGetChar(c);
1831 cs->recvbuf[cs->recvlen++] = c;
1834 share_got_pkt_from_downstream(cs, cs->recvbuf[4],
1835 cs->recvbuf + 5, cs->recvlen - 5);
1838 dead:;
1839 crFinish(1);
1842 static void share_sent(Plug plug, int bufsize)
1844 /* struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug; */
1847 * We do nothing here, because we expect that there won't be a
1848 * need to throttle and unthrottle the connection to a downstream.
1849 * It should automatically throttle itself: if the SSH server
1850 * sends huge amounts of data on all channels then it'll run out
1851 * of window until our downstream sends it back some
1852 * WINDOW_ADJUSTs.
1856 static int share_listen_closing(Plug plug, const char *error_msg,
1857 int error_code, int calling_back)
1859 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
1860 if (error_msg)
1861 ssh_sharing_logf(sharestate->ssh, 0,
1862 "listening socket: %s", error_msg);
1863 sk_close(sharestate->listensock);
1864 sharestate->listensock = NULL;
1865 return 1;
1868 static void share_send_verstring(struct ssh_sharing_connstate *cs)
1870 char *fullstring = dupcat("SSHCONNECTION@putty.projects.tartarus.org-2.0-",
1871 cs->parent->server_verstring, "\015\012", NULL);
1872 sk_write(cs->sock, fullstring, strlen(fullstring));
1873 sfree(fullstring);
1875 cs->sent_verstring = TRUE;
1878 int share_ndownstreams(void *state)
1880 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1881 return count234(sharestate->connections);
1884 void share_activate(void *state, const char *server_verstring)
1887 * Indication from ssh.c that we are now ready to begin serving
1888 * any downstreams that have already connected to us.
1890 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1891 struct ssh_sharing_connstate *cs;
1892 int i;
1895 * Trim the server's version string down to just the software
1896 * version component, removing "SSH-2.0-" or whatever at the
1897 * front.
1899 for (i = 0; i < 2; i++) {
1900 server_verstring += strcspn(server_verstring, "-");
1901 if (*server_verstring)
1902 server_verstring++;
1905 sharestate->server_verstring = dupstr(server_verstring);
1907 for (i = 0; (cs = (struct ssh_sharing_connstate *)
1908 index234(sharestate->connections, i)) != NULL; i++) {
1909 assert(!cs->sent_verstring);
1910 share_send_verstring(cs);
1914 static int share_listen_accepting(Plug plug,
1915 accept_fn_t constructor, accept_ctx_t ctx)
1917 static const struct plug_function_table connection_fn_table = {
1918 NULL, /* no log function, because that's for outgoing connections */
1919 share_closing,
1920 share_receive,
1921 share_sent,
1922 NULL /* no accepting function, because we've already done it */
1924 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
1925 struct ssh_sharing_connstate *cs;
1926 const char *err;
1929 * A new downstream has connected to us.
1931 cs = snew(struct ssh_sharing_connstate);
1932 cs->fn = &connection_fn_table;
1933 cs->parent = sharestate;
1935 if ((cs->id = share_find_unused_id(sharestate, sharestate->nextid)) == 0 &&
1936 (cs->id = share_find_unused_id(sharestate, 1)) == 0) {
1937 sfree(cs);
1938 return 1;
1940 sharestate->nextid = cs->id + 1;
1941 if (sharestate->nextid == 0)
1942 sharestate->nextid++; /* only happens in VERY long-running upstreams */
1944 cs->sock = constructor(ctx, (Plug) cs);
1945 if ((err = sk_socket_error(cs->sock)) != NULL) {
1946 sfree(cs);
1947 return err != NULL;
1950 sk_set_frozen(cs->sock, 0);
1952 add234(cs->parent->connections, cs);
1954 cs->sent_verstring = FALSE;
1955 if (sharestate->server_verstring)
1956 share_send_verstring(cs);
1958 cs->got_verstring = FALSE;
1959 cs->recvlen = 0;
1960 cs->crLine = 0;
1961 cs->halfchannels = newtree234(share_halfchannel_cmp);
1962 cs->channels_by_us = newtree234(share_channel_us_cmp);
1963 cs->channels_by_server = newtree234(share_channel_server_cmp);
1964 cs->xchannels_by_us = newtree234(share_xchannel_us_cmp);
1965 cs->xchannels_by_server = newtree234(share_xchannel_server_cmp);
1966 cs->forwardings = newtree234(share_forwarding_cmp);
1967 cs->globreq_head = cs->globreq_tail = NULL;
1969 ssh_sharing_downstream_connected(sharestate->ssh, cs->id);
1971 return 0;
1974 /* Per-application overrides for what roles we can take (e.g. pscp
1975 * will never be an upstream) */
1976 extern const int share_can_be_downstream;
1977 extern const int share_can_be_upstream;
1980 * Init function for connection sharing. We either open a listening
1981 * socket and become an upstream, or connect to an existing one and
1982 * become a downstream, or do neither. We are responsible for deciding
1983 * which of these to do (including checking the Conf to see if
1984 * connection sharing is even enabled in the first place). If we
1985 * become a downstream, we return the Socket with which we connected
1986 * to the upstream; otherwise (whether or not we have established an
1987 * upstream) we return NULL.
1989 Socket ssh_connection_sharing_init(const char *host, int port,
1990 Conf *conf, Ssh ssh, void **state)
1992 static const struct plug_function_table listen_fn_table = {
1993 NULL, /* no log function, because that's for outgoing connections */
1994 share_listen_closing,
1995 NULL, /* no receive function on a listening socket */
1996 NULL, /* no sent function on a listening socket */
1997 share_listen_accepting
2000 int result, can_upstream, can_downstream;
2001 char *logtext, *ds_err, *us_err;
2002 char *sockname;
2003 Socket sock;
2004 struct ssh_sharing_state *sharestate;
2006 if (!conf_get_int(conf, CONF_ssh_connection_sharing))
2007 return NULL; /* do not share anything */
2008 can_upstream = share_can_be_upstream &&
2009 conf_get_int(conf, CONF_ssh_connection_sharing_upstream);
2010 can_downstream = share_can_be_downstream &&
2011 conf_get_int(conf, CONF_ssh_connection_sharing_downstream);
2012 if (!can_upstream && !can_downstream)
2013 return NULL;
2016 * Decide on the string used to identify the connection point
2017 * between upstream and downstream (be it a Windows named pipe or
2018 * a Unix-domain socket or whatever else).
2020 * I wondered about making this a SHA hash of all sorts of pieces
2021 * of the PuTTY configuration - essentially everything PuTTY uses
2022 * to know where and how to make a connection, including all the
2023 * proxy details (or rather, all the _relevant_ ones - only
2024 * including settings that other settings didn't prevent from
2025 * having any effect), plus the username. However, I think it's
2026 * better to keep it really simple: the connection point
2027 * identifier is derived from the hostname and port used to index
2028 * the host-key cache (not necessarily where we _physically_
2029 * connected to, in cases involving proxies or CONF_loghost), plus
2030 * the username if one is specified.
2033 char *username = get_remote_username(conf);
2035 if (port == 22) {
2036 if (username)
2037 sockname = dupprintf("%s@%s", username, host);
2038 else
2039 sockname = dupprintf("%s", host);
2040 } else {
2041 if (username)
2042 sockname = dupprintf("%s@%s:%d", username, host, port);
2043 else
2044 sockname = dupprintf("%s:%d", host, port);
2047 sfree(username);
2050 * The platform-specific code may transform this further in
2051 * order to conform to local namespace conventions (e.g. not
2052 * using slashes in filenames), but that's its job and not
2053 * ours.
2058 * Create a data structure for the listening plug if we turn out
2059 * to be an upstream.
2061 sharestate = snew(struct ssh_sharing_state);
2062 sharestate->fn = &listen_fn_table;
2063 sharestate->listensock = NULL;
2066 * Now hand off to a per-platform routine that either connects to
2067 * an existing upstream (using 'ssh' as the plug), establishes our
2068 * own upstream (using 'sharestate' as the plug), or forks off a
2069 * separate upstream and then connects to that. It will return a
2070 * code telling us which kind of socket it put in 'sock'.
2072 sock = NULL;
2073 logtext = ds_err = us_err = NULL;
2074 result = platform_ssh_share(sockname, conf, (Plug)ssh,
2075 (Plug)sharestate, &sock, &logtext, &ds_err,
2076 &us_err, can_upstream, can_downstream);
2077 ssh_connshare_log(ssh, result, logtext, ds_err, us_err);
2078 sfree(logtext);
2079 sfree(ds_err);
2080 sfree(us_err);
2081 switch (result) {
2082 case SHARE_NONE:
2084 * We aren't sharing our connection at all (e.g. something
2085 * went wrong setting the socket up). Free the upstream
2086 * structure and return NULL.
2088 assert(sock == NULL);
2089 *state = NULL;
2090 sfree(sharestate);
2091 sfree(sockname);
2092 return NULL;
2094 case SHARE_DOWNSTREAM:
2096 * We are downstream, so free sharestate which it turns out we
2097 * don't need after all, and return the downstream socket as a
2098 * replacement for an ordinary SSH connection.
2100 *state = NULL;
2101 sfree(sharestate);
2102 sfree(sockname);
2103 return sock;
2105 case SHARE_UPSTREAM:
2107 * We are upstream. Set up sharestate properly and pass a copy
2108 * to the caller; return NULL, to tell ssh.c that it has to
2109 * make an ordinary connection after all.
2111 *state = sharestate;
2112 sharestate->listensock = sock;
2113 sharestate->connections = newtree234(share_connstate_cmp);
2114 sharestate->ssh = ssh;
2115 sharestate->server_verstring = NULL;
2116 sharestate->sockname = sockname;
2117 sharestate->nextid = 1;
2118 return NULL;
2121 return NULL;