AddDlg: Might show wrong files (i.e., modified ones instead of unversioned files)
[TortoiseGit.git] / src / TortoisePlink / sshshare.c
blobdac0824c9cbae20ea59a2bf8ae78f2b178415085
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>
136 #include <errno.h>
138 #include "putty.h"
139 #include "tree234.h"
140 #include "ssh.h"
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];
170 int recvlen;
173 * Assorted state we have to remember about this downstream, so
174 * that we can clean it up appropriately when the downstream goes
175 * away.
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
187 * to it. */
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 {
209 unsigned server_id;
212 /* States of a share_channel. */
213 enum {
214 OPEN,
215 SENT_CLOSE,
216 RCVD_CLOSE,
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
222 * meaningless. */
223 UNACKNOWLEDGED
226 struct share_channel {
227 unsigned downstream_id, upstream_id, server_id;
228 int downstream_maxpkt;
229 int state;
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
234 * fake set.
236 struct X11FakeAuth *x11_auth_upstream;
237 int x11_auth_proto;
238 char *x11_auth_data;
239 int x11_auth_datalen;
240 int x11_one_shot;
243 struct share_forwarding {
244 char *host;
245 int port;
246 int active; /* has the server sent REQUEST_SUCCESS? */
249 struct share_xchannel_message {
250 struct share_xchannel_message *next;
251 int type;
252 unsigned char *data;
253 int datalen;
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.
267 int live;
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.
277 int window;
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;
287 enum {
288 GLOBREQ_TCPIP_FORWARD,
289 GLOBREQ_CANCEL_TCPIP_FORWARD
292 struct share_globreq {
293 struct share_globreq *next;
294 int type;
295 int want_reply;
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;
306 if (a->id < b->id)
307 return -1;
308 else if (a->id > b->id)
309 return +1;
310 else
311 return 0;
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;
319 unsigned ret;
322 * Find the lowest unused downstream ID greater or equal to
323 * 'first'.
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;
331 dummy.id = first;
332 cs = findrelpos234(sharestate->connections, &dummy, NULL,
333 REL234_GE, &low_orig);
334 if (!cs)
335 return first;
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
341 * range.
343 low = low_orig;
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 */
350 else
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
358 * above.
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;
369 dummy.id = ret;
370 assert(NULL == find234(sharestate->connections, &dummy, NULL));
372 return ret;
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)
381 return -1;
382 else if (a->server_id > b->server_id)
383 return +1;
384 else
385 return 0;
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)
394 return -1;
395 else if (a->upstream_id > b->upstream_id)
396 return +1;
397 else
398 return 0;
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)
407 return -1;
408 else if (a->server_id > b->server_id)
409 return +1;
410 else
411 return 0;
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)
420 return -1;
421 else if (a->upstream_id > b->upstream_id)
422 return +1;
423 else
424 return 0;
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)
433 return -1;
434 else if (a->server_id > b->server_id)
435 return +1;
436 else
437 return 0;
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;
444 int i;
446 if ((i = strcmp(a->host, b->host)) != 0)
447 return i;
448 else if (a->port < b->port)
449 return -1;
450 else if (a->port > b->port)
451 return +1;
452 else
453 return 0;
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;
461 sfree(tmp);
463 sfree(xc);
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)
475 sfree(hc);
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
480 * ones to free */
481 freetree234(cs->channels_by_server);
482 while ((chan = (struct share_channel *)
483 delpos234(cs->channels_by_us, 0)) != NULL)
484 sfree(chan);
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)
497 sfree(fwd);
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;
503 sfree(globreq);
506 if (cs->sock)
507 sk_close(cs->sock);
509 sfree(cs);
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);
530 sfree(sharestate);
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) {
539 /* Duplicate?! */
540 sfree(hc);
541 return NULL;
542 } else {
543 return 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);
559 sfree(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;
570 chan->state = state;
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) {
578 sfree(chan);
579 return NULL;
581 if (chan->state != UNACKNOWLEDGED) {
582 if (add234(cs->channels_by_server, chan) != chan) {
583 del234(cs->channels_by_us, chan);
584 sfree(chan);
585 return NULL;
588 return 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);
626 sfree(chan);
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;
636 xc->live = TRUE;
637 xc->msghead = xc->msgtail = NULL;
638 if (add234(cs->xchannels_by_us, xc) != xc) {
639 sfree(xc);
640 return NULL;
642 if (add234(cs->xchannels_by_server, xc) != xc) {
643 del234(cs->xchannels_by_us, xc);
644 sfree(xc);
645 return NULL;
647 return 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);
680 fwd->port = port;
681 fwd->active = FALSE;
682 if (add234(cs->forwardings, fwd) != fwd) {
683 /* Duplicate?! */
684 sfree(fwd);
685 return NULL;
687 return 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);
698 return ret;
701 static void share_remove_forwarding(struct ssh_sharing_connstate *cs,
702 struct share_forwarding *fwd)
704 del234(cs->forwardings, fwd);
705 sfree(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 */
713 return;
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)
738 len = pktlen - 8;
740 do {
741 int this_len = (len > chan->downstream_maxpkt ?
742 chan->downstream_maxpkt : len);
743 PUT_32BIT(header, this_len + 9);
744 header[4] = type;
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);
749 len -= this_len;
750 upkt += this_len;
751 } while (len > 0);
752 } else {
754 * Just do the obvious thing.
756 char header[9];
758 PUT_32BIT(header, pktlen + 1);
759 header[4] = type;
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)
767 int i;
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];
782 int pos = 0;
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
803 * already).
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];
814 int pos = 0;
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;
824 } else {
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++) {
843 if (fwd->active) {
844 static const char request[] = "cancel-tcpip-forward";
845 char *packet = snewn(256 + strlen(fwd->host), char);
846 int pos = 0;
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");
864 sfree(packet);
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)
886 sk_close(cs->sock);
887 cs->sock = NULL;
889 share_try_cleanup(cs);
892 static void share_disconnect(struct ssh_sharing_connstate *cs,
893 const char *message)
895 static const char lang[] = "en";
896 int msglen = strlen(message);
897 char *packet = snewn(msglen + 256, char);
898 int pos = 0;
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);
904 pos += 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 int share_closing(Plug plug, const char *error_msg, int error_code,
915 int calling_back)
917 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
919 if (error_msg) {
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)
931 /* do nothing */;
932 else
933 #endif
934 ssh_sharing_logf(cs->parent->ssh, cs->id,
935 "Socket error: %s", error_msg);
937 share_begin_cleanup(cs);
938 return 1;
941 static int getstring_inner(const void *vdata, int datalen,
942 char **out, int *outlen)
944 const unsigned char *data = (const unsigned char *)vdata;
945 int len;
947 if (datalen < 4)
948 return FALSE;
950 len = toint(GET_32BIT(data));
951 if (len < 0 || len > datalen - 4)
952 return FALSE;
954 if (outlen)
955 *outlen = len + 4; /* total size including length field */
956 if (out)
957 *out = dupprintf("%.*s", len, (char *)data + 4);
958 return TRUE;
961 static char *getstring(const void *data, int datalen)
963 char *ret;
964 if (getstring_inner(data, datalen, &ret, NULL))
965 return ret;
966 else
967 return NULL;
970 static int getstring_size(const void *data, int datalen)
972 int ret;
973 if (getstring_inner(data, datalen, NULL, &ret))
974 return ret;
975 else
976 return -1;
980 * Append a message to the end of an xchannel's queue, with the length
981 * and type code filled in and the data block allocated but
982 * uninitialised.
984 struct share_xchannel_message *share_xchannel_add_message
985 (struct share_xchannel *xc, int type, int len)
987 unsigned char *block;
988 struct share_xchannel_message *msg;
991 * Be a little tricksy here by allocating a single memory block
992 * containing both the 'struct share_xchannel_message' and the
993 * actual data. Simplifies freeing it later.
995 block = smalloc(sizeof(struct share_xchannel_message) + len);
996 msg = (struct share_xchannel_message *)block;
997 msg->data = block + sizeof(struct share_xchannel_message);
998 msg->datalen = len;
999 msg->type = type;
1002 * Queue it in the xchannel.
1004 if (xc->msgtail)
1005 xc->msgtail->next = msg;
1006 else
1007 xc->msghead = msg;
1008 msg->next = NULL;
1009 xc->msgtail = msg;
1011 return msg;
1014 void share_dead_xchannel_respond(struct ssh_sharing_connstate *cs,
1015 struct share_xchannel *xc)
1018 * Handle queued incoming messages from the server destined for an
1019 * xchannel which is dead (i.e. downstream sent OPEN_FAILURE).
1021 int delete = FALSE;
1022 while (xc->msghead) {
1023 struct share_xchannel_message *msg = xc->msghead;
1024 xc->msghead = msg->next;
1026 if (msg->type == SSH2_MSG_CHANNEL_REQUEST && msg->datalen > 4) {
1028 * A CHANNEL_REQUEST is responded to by sending
1029 * CHANNEL_FAILURE, if it has want_reply set.
1031 int wantreplypos = getstring_size(msg->data, msg->datalen);
1032 if (wantreplypos > 0 && wantreplypos < msg->datalen &&
1033 msg->data[wantreplypos] != 0) {
1034 unsigned char id[4];
1035 PUT_32BIT(id, xc->server_id);
1036 ssh_send_packet_from_downstream
1037 (cs->parent->ssh, cs->id, SSH2_MSG_CHANNEL_FAILURE, id, 4,
1038 "downstream refused X channel open");
1040 } else if (msg->type == SSH2_MSG_CHANNEL_CLOSE) {
1042 * On CHANNEL_CLOSE we can discard the channel completely.
1044 delete = TRUE;
1047 sfree(msg);
1049 xc->msgtail = NULL;
1050 if (delete) {
1051 ssh_delete_sharing_channel(cs->parent->ssh, xc->upstream_id);
1052 share_remove_xchannel(cs, xc);
1056 void share_xchannel_confirmation(struct ssh_sharing_connstate *cs,
1057 struct share_xchannel *xc,
1058 struct share_channel *chan,
1059 unsigned downstream_window)
1061 unsigned char window_adjust[8];
1064 * Send all the queued messages downstream.
1066 while (xc->msghead) {
1067 struct share_xchannel_message *msg = xc->msghead;
1068 xc->msghead = msg->next;
1070 if (msg->datalen >= 4)
1071 PUT_32BIT(msg->data, chan->downstream_id);
1072 send_packet_to_downstream(cs, msg->type,
1073 msg->data, msg->datalen, chan);
1075 sfree(msg);
1079 * Send a WINDOW_ADJUST back upstream, to synchronise the window
1080 * size downstream thinks it's presented with the one we've
1081 * actually presented.
1083 PUT_32BIT(window_adjust, xc->server_id);
1084 PUT_32BIT(window_adjust + 4, downstream_window - xc->window);
1085 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1086 SSH2_MSG_CHANNEL_WINDOW_ADJUST,
1087 window_adjust, 8, "window adjustment after"
1088 " downstream accepted X channel");
1091 void share_xchannel_failure(struct ssh_sharing_connstate *cs,
1092 struct share_xchannel *xc)
1095 * If downstream refuses to open our X channel at all for some
1096 * reason, we must respond by sending an emergency CLOSE upstream.
1098 unsigned char id[4];
1099 PUT_32BIT(id, xc->server_id);
1100 ssh_send_packet_from_downstream
1101 (cs->parent->ssh, cs->id, SSH2_MSG_CHANNEL_CLOSE, id, 4,
1102 "downstream refused X channel open");
1105 * Now mark the xchannel as dead, and respond to anything sent on
1106 * it until we see CLOSE for it in turn.
1108 xc->live = FALSE;
1109 share_dead_xchannel_respond(cs, xc);
1112 void share_setup_x11_channel(void *csv, void *chanv,
1113 unsigned upstream_id, unsigned server_id,
1114 unsigned server_currwin, unsigned server_maxpkt,
1115 unsigned client_adjusted_window,
1116 const char *peer_addr, int peer_port, int endian,
1117 int protomajor, int protominor,
1118 const void *initial_data, int initial_len)
1120 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv;
1121 struct share_channel *chan = (struct share_channel *)chanv;
1122 struct share_xchannel *xc;
1123 struct share_xchannel_message *msg;
1124 void *greeting;
1125 int greeting_len;
1126 unsigned char *pkt;
1127 int pktlen;
1130 * Create an xchannel containing data we've already received from
1131 * the X client, and preload it with a CHANNEL_DATA message
1132 * containing our own made-up authorisation greeting and any
1133 * additional data sent from the server so far.
1135 xc = share_add_xchannel(cs, upstream_id, server_id);
1136 greeting = x11_make_greeting(endian, protomajor, protominor,
1137 chan->x11_auth_proto,
1138 chan->x11_auth_data, chan->x11_auth_datalen,
1139 peer_addr, peer_port, &greeting_len);
1140 msg = share_xchannel_add_message(xc, SSH2_MSG_CHANNEL_DATA,
1141 8 + greeting_len + initial_len);
1142 /* leave the channel id field unfilled - we don't know the
1143 * downstream id yet, of course */
1144 PUT_32BIT(msg->data + 4, greeting_len + initial_len);
1145 memcpy(msg->data + 8, greeting, greeting_len);
1146 memcpy(msg->data + 8 + greeting_len, initial_data, initial_len);
1147 sfree(greeting);
1149 xc->window = client_adjusted_window + greeting_len;
1152 * Send on a CHANNEL_OPEN to downstream.
1154 pktlen = 27 + strlen(peer_addr);
1155 pkt = snewn(pktlen, unsigned char);
1156 PUT_32BIT(pkt, 3); /* strlen("x11") */
1157 memcpy(pkt+4, "x11", 3);
1158 PUT_32BIT(pkt+7, server_id);
1159 PUT_32BIT(pkt+11, server_currwin);
1160 PUT_32BIT(pkt+15, server_maxpkt);
1161 PUT_32BIT(pkt+19, strlen(peer_addr));
1162 memcpy(pkt+23, peer_addr, strlen(peer_addr));
1163 PUT_32BIT(pkt+23+strlen(peer_addr), peer_port);
1164 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_OPEN, pkt, pktlen, NULL);
1165 sfree(pkt);
1168 * If this was a once-only X forwarding, clean it up now.
1170 if (chan->x11_one_shot) {
1171 ssh_sharing_remove_x11_display(cs->parent->ssh,
1172 chan->x11_auth_upstream);
1173 chan->x11_auth_upstream = NULL;
1174 sfree(chan->x11_auth_data);
1175 chan->x11_auth_proto = -1;
1176 chan->x11_auth_datalen = 0;
1177 chan->x11_one_shot = 0;
1181 void share_got_pkt_from_server(void *csv, int type,
1182 unsigned char *pkt, int pktlen)
1184 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)csv;
1185 struct share_globreq *globreq;
1186 int id_pos;
1187 unsigned upstream_id, server_id;
1188 struct share_channel *chan;
1189 struct share_xchannel *xc;
1191 switch (type) {
1192 case SSH2_MSG_REQUEST_SUCCESS:
1193 case SSH2_MSG_REQUEST_FAILURE:
1194 globreq = cs->globreq_head;
1195 if (globreq->type == GLOBREQ_TCPIP_FORWARD) {
1196 if (type == SSH2_MSG_REQUEST_FAILURE) {
1197 share_remove_forwarding(cs, globreq->fwd);
1198 } else {
1199 globreq->fwd->active = TRUE;
1201 } else if (globreq->type == GLOBREQ_CANCEL_TCPIP_FORWARD) {
1202 if (type == SSH2_MSG_REQUEST_SUCCESS) {
1203 share_remove_forwarding(cs, globreq->fwd);
1206 if (globreq->want_reply) {
1207 send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1209 cs->globreq_head = globreq->next;
1210 sfree(globreq);
1211 if (cs->globreq_head == NULL)
1212 cs->globreq_tail = NULL;
1214 if (!cs->sock) {
1215 /* Retry cleaning up this connection, in case that reply
1216 * was the last thing we were waiting for. */
1217 share_try_cleanup(cs);
1220 break;
1222 case SSH2_MSG_CHANNEL_OPEN:
1223 id_pos = getstring_size(pkt, pktlen);
1224 assert(id_pos >= 0);
1225 server_id = GET_32BIT(pkt + id_pos);
1226 share_add_halfchannel(cs, server_id);
1228 send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1229 break;
1231 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
1232 case SSH2_MSG_CHANNEL_OPEN_FAILURE:
1233 case SSH2_MSG_CHANNEL_CLOSE:
1234 case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1235 case SSH2_MSG_CHANNEL_DATA:
1236 case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1237 case SSH2_MSG_CHANNEL_EOF:
1238 case SSH2_MSG_CHANNEL_REQUEST:
1239 case SSH2_MSG_CHANNEL_SUCCESS:
1240 case SSH2_MSG_CHANNEL_FAILURE:
1242 * All these messages have the recipient channel id as the
1243 * first uint32 field in the packet. Substitute the downstream
1244 * channel id for our one and pass the packet downstream.
1246 assert(pktlen >= 4);
1247 upstream_id = GET_32BIT(pkt);
1248 if ((chan = share_find_channel_by_upstream(cs, upstream_id)) != NULL) {
1250 * The normal case: this id refers to an open channel.
1252 PUT_32BIT(pkt, chan->downstream_id);
1253 send_packet_to_downstream(cs, type, pkt, pktlen, chan);
1256 * Update the channel state, for messages that need it.
1258 if (type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
1259 if (chan->state == UNACKNOWLEDGED && pktlen >= 8) {
1260 share_channel_set_server_id(cs, chan, GET_32BIT(pkt+4),
1261 OPEN);
1262 if (!cs->sock) {
1263 /* Retry cleaning up this connection, so that we
1264 * can send an immediate CLOSE on this channel for
1265 * which we now know the server id. */
1266 share_try_cleanup(cs);
1269 } else if (type == SSH2_MSG_CHANNEL_OPEN_FAILURE) {
1270 ssh_delete_sharing_channel(cs->parent->ssh, chan->upstream_id);
1271 share_remove_channel(cs, chan);
1272 } else if (type == SSH2_MSG_CHANNEL_CLOSE) {
1273 if (chan->state == SENT_CLOSE) {
1274 ssh_delete_sharing_channel(cs->parent->ssh,
1275 chan->upstream_id);
1276 share_remove_channel(cs, chan);
1277 if (!cs->sock) {
1278 /* Retry cleaning up this connection, in case this
1279 * channel closure was the last thing we were
1280 * waiting for. */
1281 share_try_cleanup(cs);
1283 } else {
1284 chan->state = RCVD_CLOSE;
1287 } else if ((xc = share_find_xchannel_by_upstream(cs, upstream_id))
1288 != NULL) {
1290 * The unusual case: this id refers to an xchannel. Add it
1291 * to the xchannel's queue.
1293 struct share_xchannel_message *msg;
1295 msg = share_xchannel_add_message(xc, type, pktlen);
1296 memcpy(msg->data, pkt, pktlen);
1298 /* If the xchannel is dead, then also respond to it (which
1299 * may involve deleting the channel). */
1300 if (!xc->live)
1301 share_dead_xchannel_respond(cs, xc);
1303 break;
1305 default:
1306 assert(!"This packet type should never have come from ssh.c");
1307 break;
1311 static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
1312 int type,
1313 unsigned char *pkt, int pktlen)
1315 char *request_name;
1316 struct share_forwarding *fwd;
1317 int id_pos;
1318 unsigned old_id, new_id, server_id;
1319 struct share_globreq *globreq;
1320 struct share_channel *chan;
1321 struct share_halfchannel *hc;
1322 struct share_xchannel *xc;
1323 char *err = NULL;
1325 switch (type) {
1326 case SSH2_MSG_DISCONNECT:
1328 * This message stops here: if downstream is disconnecting
1329 * from us, that doesn't mean we want to disconnect from the
1330 * SSH server. Close the downstream connection and start
1331 * cleanup.
1333 share_begin_cleanup(cs);
1334 break;
1336 case SSH2_MSG_GLOBAL_REQUEST:
1338 * The only global requests we understand are "tcpip-forward"
1339 * and "cancel-tcpip-forward". Since those require us to
1340 * maintain state, we must assume that other global requests
1341 * will probably require that too, and so we don't forward on
1342 * any request we don't understand.
1344 request_name = getstring(pkt, pktlen);
1345 if (request_name == NULL) {
1346 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1347 goto confused;
1350 if (!strcmp(request_name, "tcpip-forward")) {
1351 int wantreplypos, orig_wantreply, port, ret;
1352 char *host;
1354 sfree(request_name);
1357 * Pick the packet apart to find the want_reply field and
1358 * the host/port we're going to ask to listen on.
1360 wantreplypos = getstring_size(pkt, pktlen);
1361 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1362 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1363 goto confused;
1365 orig_wantreply = pkt[wantreplypos];
1366 port = getstring_size(pkt + (wantreplypos + 1),
1367 pktlen - (wantreplypos + 1));
1368 port += (wantreplypos + 1);
1369 if (port < 0 || port > pktlen - 4) {
1370 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1371 goto confused;
1373 host = getstring(pkt + (wantreplypos + 1),
1374 pktlen - (wantreplypos + 1));
1375 assert(host != NULL);
1376 port = GET_32BIT(pkt + port);
1379 * See if we can allocate space in ssh.c's tree of remote
1380 * port forwardings. If we can't, it's because another
1381 * client sharing this connection has already allocated
1382 * the identical port forwarding, so we take it on
1383 * ourselves to manufacture a failure packet and send it
1384 * back to downstream.
1386 ret = ssh_alloc_sharing_rportfwd(cs->parent->ssh, host, port, cs);
1387 if (!ret) {
1388 if (orig_wantreply) {
1389 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1390 "", 0, NULL);
1392 } else {
1394 * We've managed to make space for this forwarding
1395 * locally. Pass the request on to the SSH server, but
1396 * set want_reply even if it wasn't originally set, so
1397 * that we know whether this forwarding needs to be
1398 * cleaned up if downstream goes away.
1400 int old_wantreply = pkt[wantreplypos];
1401 pkt[wantreplypos] = 1;
1402 ssh_send_packet_from_downstream
1403 (cs->parent->ssh, cs->id, type, pkt, pktlen,
1404 old_wantreply ? NULL : "upstream added want_reply flag");
1405 fwd = share_add_forwarding(cs, host, port);
1406 ssh_sharing_queue_global_request(cs->parent->ssh, cs);
1408 if (fwd) {
1409 globreq = snew(struct share_globreq);
1410 globreq->next = NULL;
1411 if (cs->globreq_tail)
1412 cs->globreq_tail->next = globreq;
1413 else
1414 cs->globreq_head = globreq;
1415 globreq->fwd = fwd;
1416 globreq->want_reply = orig_wantreply;
1417 globreq->type = GLOBREQ_TCPIP_FORWARD;
1421 sfree(host);
1422 } else if (!strcmp(request_name, "cancel-tcpip-forward")) {
1423 int wantreplypos, orig_wantreply, port;
1424 char *host;
1425 struct share_forwarding *fwd;
1427 sfree(request_name);
1430 * Pick the packet apart to find the want_reply field and
1431 * the host/port we're going to ask to listen on.
1433 wantreplypos = getstring_size(pkt, pktlen);
1434 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1435 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1436 goto confused;
1438 orig_wantreply = pkt[wantreplypos];
1439 port = getstring_size(pkt + (wantreplypos + 1),
1440 pktlen - (wantreplypos + 1));
1441 port += (wantreplypos + 1);
1442 if (port < 0 || port > pktlen - 4) {
1443 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1444 goto confused;
1446 host = getstring(pkt + (wantreplypos + 1),
1447 pktlen - (wantreplypos + 1));
1448 assert(host != NULL);
1449 port = GET_32BIT(pkt + port);
1452 * Look up the existing forwarding with these details.
1454 fwd = share_find_forwarding(cs, host, port);
1455 if (!fwd) {
1456 if (orig_wantreply) {
1457 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1458 "", 0, NULL);
1460 } else {
1462 * Pass the cancel request on to the SSH server, but
1463 * set want_reply even if it wasn't originally set, so
1464 * that _we_ know whether the forwarding has been
1465 * deleted even if downstream doesn't want to know.
1467 int old_wantreply = pkt[wantreplypos];
1468 pkt[wantreplypos] = 1;
1469 ssh_send_packet_from_downstream
1470 (cs->parent->ssh, cs->id, type, pkt, pktlen,
1471 old_wantreply ? NULL : "upstream added want_reply flag");
1472 ssh_sharing_queue_global_request(cs->parent->ssh, cs);
1475 sfree(host);
1476 } else {
1478 * Request we don't understand. Manufacture a failure
1479 * message if an answer was required.
1481 int wantreplypos;
1483 sfree(request_name);
1485 wantreplypos = getstring_size(pkt, pktlen);
1486 if (wantreplypos < 0 || wantreplypos >= pktlen) {
1487 err = dupprintf("Truncated GLOBAL_REQUEST packet");
1488 goto confused;
1490 if (pkt[wantreplypos])
1491 send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1492 "", 0, NULL);
1494 break;
1496 case SSH2_MSG_CHANNEL_OPEN:
1497 /* Sender channel id comes after the channel type string */
1498 id_pos = getstring_size(pkt, pktlen);
1499 if (id_pos < 0 || id_pos > pktlen - 12) {
1500 err = dupprintf("Truncated CHANNEL_OPEN packet");
1501 goto confused;
1504 old_id = GET_32BIT(pkt + id_pos);
1505 new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
1506 share_add_channel(cs, old_id, new_id, 0, UNACKNOWLEDGED,
1507 GET_32BIT(pkt + id_pos + 8));
1508 PUT_32BIT(pkt + id_pos, new_id);
1509 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1510 type, pkt, pktlen, NULL);
1511 break;
1513 case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
1514 if (pktlen < 16) {
1515 err = dupprintf("Truncated CHANNEL_OPEN_CONFIRMATION packet");
1516 goto confused;
1519 id_pos = 4; /* sender channel id is 2nd uint32 field in packet */
1520 old_id = GET_32BIT(pkt + id_pos);
1522 server_id = GET_32BIT(pkt);
1523 /* This server id may refer to either a halfchannel or an xchannel. */
1524 hc = NULL, xc = NULL; /* placate optimiser */
1525 if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
1526 new_id = ssh_alloc_sharing_channel(cs->parent->ssh, cs);
1527 } else if ((xc = share_find_xchannel_by_server(cs, server_id))
1528 != NULL) {
1529 new_id = xc->upstream_id;
1530 } else {
1531 err = dupprintf("CHANNEL_OPEN_CONFIRMATION packet cited unknown channel %u", (unsigned)server_id);
1532 goto confused;
1535 PUT_32BIT(pkt + id_pos, new_id);
1537 chan = share_add_channel(cs, old_id, new_id, server_id, OPEN,
1538 GET_32BIT(pkt + 12));
1540 if (hc) {
1541 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1542 type, pkt, pktlen, NULL);
1543 share_remove_halfchannel(cs, hc);
1544 } else if (xc) {
1545 unsigned downstream_window = GET_32BIT(pkt + 8);
1546 if (downstream_window < 256) {
1547 err = dupprintf("Initial window size for x11 channel must be at least 256 (got %u)", downstream_window);
1548 goto confused;
1550 share_xchannel_confirmation(cs, xc, chan, downstream_window);
1551 share_remove_xchannel(cs, xc);
1554 break;
1556 case SSH2_MSG_CHANNEL_OPEN_FAILURE:
1557 if (pktlen < 4) {
1558 err = dupprintf("Truncated CHANNEL_OPEN_FAILURE packet");
1559 goto confused;
1562 server_id = GET_32BIT(pkt);
1563 /* This server id may refer to either a halfchannel or an xchannel. */
1564 if ((hc = share_find_halfchannel(cs, server_id)) != NULL) {
1565 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1566 type, pkt, pktlen, NULL);
1567 share_remove_halfchannel(cs, hc);
1568 } else if ((xc = share_find_xchannel_by_server(cs, server_id))
1569 != NULL) {
1570 share_xchannel_failure(cs, xc);
1571 } else {
1572 err = dupprintf("CHANNEL_OPEN_FAILURE packet cited unknown channel %u", (unsigned)server_id);
1573 goto confused;
1576 break;
1578 case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
1579 case SSH2_MSG_CHANNEL_DATA:
1580 case SSH2_MSG_CHANNEL_EXTENDED_DATA:
1581 case SSH2_MSG_CHANNEL_EOF:
1582 case SSH2_MSG_CHANNEL_CLOSE:
1583 case SSH2_MSG_CHANNEL_REQUEST:
1584 case SSH2_MSG_CHANNEL_SUCCESS:
1585 case SSH2_MSG_CHANNEL_FAILURE:
1586 case SSH2_MSG_IGNORE:
1587 case SSH2_MSG_DEBUG:
1588 if (type == SSH2_MSG_CHANNEL_REQUEST &&
1589 (request_name = getstring(pkt + 4, pktlen - 4)) != NULL) {
1591 * Agent forwarding requests from downstream are treated
1592 * specially. Because OpenSSHD doesn't let us enable agent
1593 * forwarding independently per session channel, and in
1594 * particular because the OpenSSH-defined agent forwarding
1595 * protocol does not mark agent-channel requests with the
1596 * id of the session channel they originate from, the only
1597 * way we can implement agent forwarding in a
1598 * connection-shared PuTTY is to forward the _upstream_
1599 * agent. Hence, we unilaterally deny agent forwarding
1600 * requests from downstreams if we aren't prepared to
1601 * forward an agent ourselves.
1603 * (If we are, then we dutifully pass agent forwarding
1604 * requests upstream. OpenSSHD has the curious behaviour
1605 * that all but the first such request will be rejected,
1606 * but all session channels opened after the first request
1607 * get agent forwarding enabled whether they ask for it or
1608 * not; but that's not our concern, since other SSH
1609 * servers supporting the same piece of protocol might in
1610 * principle at least manage to enable agent forwarding on
1611 * precisely the channels that requested it, even if the
1612 * subsequent CHANNEL_OPENs still can't be associated with
1613 * a parent session channel.)
1615 if (!strcmp(request_name, "auth-agent-req@openssh.com") &&
1616 !ssh_agent_forwarding_permitted(cs->parent->ssh)) {
1617 unsigned server_id = GET_32BIT(pkt);
1618 unsigned char recipient_id[4];
1620 sfree(request_name);
1622 chan = share_find_channel_by_server(cs, server_id);
1623 if (chan) {
1624 PUT_32BIT(recipient_id, chan->downstream_id);
1625 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_FAILURE,
1626 recipient_id, 4, NULL);
1627 } else {
1628 char *buf = dupprintf("Agent forwarding request for "
1629 "unrecognised channel %u", server_id);
1630 share_disconnect(cs, buf);
1631 sfree(buf);
1632 return;
1634 break;
1638 * Another thing we treat specially is X11 forwarding
1639 * requests. For these, we have to make up another set of
1640 * X11 auth data, and enter it into our SSH connection's
1641 * list of possible X11 authorisation credentials so that
1642 * when we see an X11 channel open request we can know
1643 * whether it's one to handle locally or one to pass on to
1644 * a downstream, and if the latter, which one.
1646 if (!strcmp(request_name, "x11-req")) {
1647 unsigned server_id = GET_32BIT(pkt);
1648 int want_reply, single_connection, screen;
1649 char *auth_proto_str, *auth_data;
1650 int auth_proto, protolen, datalen;
1651 int pos;
1653 sfree(request_name);
1655 chan = share_find_channel_by_server(cs, server_id);
1656 if (!chan) {
1657 char *buf = dupprintf("X11 forwarding request for "
1658 "unrecognised channel %u", server_id);
1659 share_disconnect(cs, buf);
1660 sfree(buf);
1661 return;
1665 * Pick apart the whole message to find the downstream
1666 * auth details.
1668 /* we have already seen: 4 bytes channel id, 4+7 request name */
1669 if (pktlen < 17) {
1670 err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1671 goto confused;
1673 want_reply = pkt[15] != 0;
1674 single_connection = pkt[16] != 0;
1675 auth_proto_str = getstring(pkt+17, pktlen-17);
1676 auth_proto = x11_identify_auth_proto(auth_proto_str);
1677 sfree(auth_proto_str);
1678 pos = 17 + getstring_size(pkt+17, pktlen-17);
1679 auth_data = getstring(pkt+pos, pktlen-pos);
1680 pos += getstring_size(pkt+pos, pktlen-pos);
1682 if (pktlen < pos+4) {
1683 err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1684 sfree(auth_data);
1685 goto confused;
1687 screen = GET_32BIT(pkt+pos);
1689 if (auth_proto < 0) {
1690 /* Reject due to not understanding downstream's
1691 * requested authorisation method. */
1692 unsigned char recipient_id[4];
1693 PUT_32BIT(recipient_id, chan->downstream_id);
1694 send_packet_to_downstream(cs, SSH2_MSG_CHANNEL_FAILURE,
1695 recipient_id, 4, NULL);
1696 sfree(auth_data);
1697 break;
1700 chan->x11_auth_proto = auth_proto;
1701 chan->x11_auth_data = x11_dehexify(auth_data,
1702 &chan->x11_auth_datalen);
1703 sfree(auth_data);
1704 chan->x11_auth_upstream =
1705 ssh_sharing_add_x11_display(cs->parent->ssh, auth_proto,
1706 cs, chan);
1707 chan->x11_one_shot = single_connection;
1710 * Now construct a replacement X forwarding request,
1711 * containing our own auth data, and send that to the
1712 * server.
1714 protolen = strlen(chan->x11_auth_upstream->protoname);
1715 datalen = strlen(chan->x11_auth_upstream->datastring);
1716 pktlen = 29+protolen+datalen;
1717 pkt = snewn(pktlen, unsigned char);
1718 PUT_32BIT(pkt, server_id);
1719 PUT_32BIT(pkt+4, 7); /* strlen("x11-req") */
1720 memcpy(pkt+8, "x11-req", 7);
1721 pkt[15] = want_reply;
1722 pkt[16] = single_connection;
1723 PUT_32BIT(pkt+17, protolen);
1724 memcpy(pkt+21, chan->x11_auth_upstream->protoname, protolen);
1725 PUT_32BIT(pkt+21+protolen, datalen);
1726 memcpy(pkt+25+protolen, chan->x11_auth_upstream->datastring,
1727 datalen);
1728 PUT_32BIT(pkt+25+protolen+datalen, screen);
1729 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1730 SSH2_MSG_CHANNEL_REQUEST,
1731 pkt, pktlen, NULL);
1732 sfree(pkt);
1734 break;
1737 sfree(request_name);
1740 ssh_send_packet_from_downstream(cs->parent->ssh, cs->id,
1741 type, pkt, pktlen, NULL);
1742 if (type == SSH2_MSG_CHANNEL_CLOSE && pktlen >= 4) {
1743 server_id = GET_32BIT(pkt);
1744 chan = share_find_channel_by_server(cs, server_id);
1745 if (chan) {
1746 if (chan->state == RCVD_CLOSE) {
1747 ssh_delete_sharing_channel(cs->parent->ssh,
1748 chan->upstream_id);
1749 share_remove_channel(cs, chan);
1750 } else {
1751 chan->state = SENT_CLOSE;
1755 break;
1757 default:
1758 err = dupprintf("Unexpected packet type %d\n", type);
1759 goto confused;
1762 * Any other packet type is unexpected. In particular, we
1763 * never pass GLOBAL_REQUESTs downstream, so we never expect
1764 * to see SSH2_MSG_REQUEST_{SUCCESS,FAILURE}.
1766 confused:
1767 assert(err != NULL);
1768 share_disconnect(cs, err);
1769 sfree(err);
1770 break;
1775 * Coroutine macros similar to, but simplified from, those in ssh.c.
1777 #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
1778 #define crFinish(z) } *crLine = 0; return (z); }
1779 #define crGetChar(c) do \
1781 while (len == 0) { \
1782 *crLine =__LINE__; return 1; case __LINE__:; \
1784 len--; \
1785 (c) = (unsigned char)*data++; \
1786 } while (0)
1788 static int share_receive(Plug plug, int urgent, char *data, int len)
1790 struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
1791 static const char expected_verstring_prefix[] =
1792 "SSHCONNECTION@putty.projects.tartarus.org-2.0-";
1793 unsigned char c;
1795 crBegin(cs->crLine);
1798 * First read the version string from downstream.
1800 cs->recvlen = 0;
1801 while (1) {
1802 crGetChar(c);
1803 if (c == '\012')
1804 break;
1805 if (cs->recvlen >= sizeof(cs->recvbuf)) {
1806 char *buf = dupprintf("Version string far too long\n");
1807 share_disconnect(cs, buf);
1808 sfree(buf);
1809 goto dead;
1811 cs->recvbuf[cs->recvlen++] = c;
1815 * Now parse the version string to make sure it's at least vaguely
1816 * sensible, and log it.
1818 if (cs->recvlen < sizeof(expected_verstring_prefix)-1 ||
1819 memcmp(cs->recvbuf, expected_verstring_prefix,
1820 sizeof(expected_verstring_prefix) - 1)) {
1821 char *buf = dupprintf("Version string did not have expected prefix\n");
1822 share_disconnect(cs, buf);
1823 sfree(buf);
1824 goto dead;
1826 if (cs->recvlen > 0 && cs->recvbuf[cs->recvlen-1] == '\015')
1827 cs->recvlen--; /* trim off \r before \n */
1828 ssh_sharing_logf(cs->parent->ssh, cs->id,
1829 "Downstream version string: %.*s",
1830 cs->recvlen, cs->recvbuf);
1831 cs->got_verstring = TRUE;
1834 * Loop round reading packets.
1836 while (1) {
1837 cs->recvlen = 0;
1838 while (cs->recvlen < 4) {
1839 crGetChar(c);
1840 cs->recvbuf[cs->recvlen++] = c;
1842 cs->curr_packetlen = toint(GET_32BIT(cs->recvbuf) + 4);
1843 if (cs->curr_packetlen < 5 ||
1844 cs->curr_packetlen > sizeof(cs->recvbuf)) {
1845 char *buf = dupprintf("Bad packet length %u\n",
1846 (unsigned)cs->curr_packetlen);
1847 share_disconnect(cs, buf);
1848 sfree(buf);
1849 goto dead;
1851 while (cs->recvlen < cs->curr_packetlen) {
1852 crGetChar(c);
1853 cs->recvbuf[cs->recvlen++] = c;
1856 share_got_pkt_from_downstream(cs, cs->recvbuf[4],
1857 cs->recvbuf + 5, cs->recvlen - 5);
1860 dead:;
1861 crFinish(1);
1864 static void share_sent(Plug plug, int bufsize)
1866 /* struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug; */
1869 * We do nothing here, because we expect that there won't be a
1870 * need to throttle and unthrottle the connection to a downstream.
1871 * It should automatically throttle itself: if the SSH server
1872 * sends huge amounts of data on all channels then it'll run out
1873 * of window until our downstream sends it back some
1874 * WINDOW_ADJUSTs.
1878 static int share_listen_closing(Plug plug, const char *error_msg,
1879 int error_code, int calling_back)
1881 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
1882 if (error_msg)
1883 ssh_sharing_logf(sharestate->ssh, 0,
1884 "listening socket: %s", error_msg);
1885 sk_close(sharestate->listensock);
1886 sharestate->listensock = NULL;
1887 return 1;
1890 static void share_send_verstring(struct ssh_sharing_connstate *cs)
1892 char *fullstring = dupcat("SSHCONNECTION@putty.projects.tartarus.org-2.0-",
1893 cs->parent->server_verstring, "\015\012", NULL);
1894 sk_write(cs->sock, fullstring, strlen(fullstring));
1895 sfree(fullstring);
1897 cs->sent_verstring = TRUE;
1900 int share_ndownstreams(void *state)
1902 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1903 return count234(sharestate->connections);
1906 void share_activate(void *state, const char *server_verstring)
1909 * Indication from ssh.c that we are now ready to begin serving
1910 * any downstreams that have already connected to us.
1912 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1913 struct ssh_sharing_connstate *cs;
1914 int i;
1917 * Trim the server's version string down to just the software
1918 * version component, removing "SSH-2.0-" or whatever at the
1919 * front.
1921 for (i = 0; i < 2; i++) {
1922 server_verstring += strcspn(server_verstring, "-");
1923 if (*server_verstring)
1924 server_verstring++;
1927 sharestate->server_verstring = dupstr(server_verstring);
1929 for (i = 0; (cs = (struct ssh_sharing_connstate *)
1930 index234(sharestate->connections, i)) != NULL; i++) {
1931 assert(!cs->sent_verstring);
1932 share_send_verstring(cs);
1936 static int share_listen_accepting(Plug plug,
1937 accept_fn_t constructor, accept_ctx_t ctx)
1939 static const struct plug_function_table connection_fn_table = {
1940 NULL, /* no log function, because that's for outgoing connections */
1941 share_closing,
1942 share_receive,
1943 share_sent,
1944 NULL /* no accepting function, because we've already done it */
1946 struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
1947 struct ssh_sharing_connstate *cs;
1948 const char *err;
1949 char *peerinfo;
1952 * A new downstream has connected to us.
1954 cs = snew(struct ssh_sharing_connstate);
1955 cs->fn = &connection_fn_table;
1956 cs->parent = sharestate;
1958 if ((cs->id = share_find_unused_id(sharestate, sharestate->nextid)) == 0 &&
1959 (cs->id = share_find_unused_id(sharestate, 1)) == 0) {
1960 sfree(cs);
1961 return 1;
1963 sharestate->nextid = cs->id + 1;
1964 if (sharestate->nextid == 0)
1965 sharestate->nextid++; /* only happens in VERY long-running upstreams */
1967 cs->sock = constructor(ctx, (Plug) cs);
1968 if ((err = sk_socket_error(cs->sock)) != NULL) {
1969 sfree(cs);
1970 return err != NULL;
1973 sk_set_frozen(cs->sock, 0);
1975 add234(cs->parent->connections, cs);
1977 cs->sent_verstring = FALSE;
1978 if (sharestate->server_verstring)
1979 share_send_verstring(cs);
1981 cs->got_verstring = FALSE;
1982 cs->recvlen = 0;
1983 cs->crLine = 0;
1984 cs->halfchannels = newtree234(share_halfchannel_cmp);
1985 cs->channels_by_us = newtree234(share_channel_us_cmp);
1986 cs->channels_by_server = newtree234(share_channel_server_cmp);
1987 cs->xchannels_by_us = newtree234(share_xchannel_us_cmp);
1988 cs->xchannels_by_server = newtree234(share_xchannel_server_cmp);
1989 cs->forwardings = newtree234(share_forwarding_cmp);
1990 cs->globreq_head = cs->globreq_tail = NULL;
1992 peerinfo = sk_peer_info(cs->sock);
1993 ssh_sharing_downstream_connected(sharestate->ssh, cs->id, peerinfo);
1994 sfree(peerinfo);
1996 return 0;
1999 /* Per-application overrides for what roles we can take (e.g. pscp
2000 * will never be an upstream) */
2001 extern const int share_can_be_downstream;
2002 extern const int share_can_be_upstream;
2005 * Decide on the string used to identify the connection point between
2006 * upstream and downstream (be it a Windows named pipe or a
2007 * Unix-domain socket or whatever else).
2009 * I wondered about making this a SHA hash of all sorts of pieces of
2010 * the PuTTY configuration - essentially everything PuTTY uses to know
2011 * where and how to make a connection, including all the proxy details
2012 * (or rather, all the _relevant_ ones - only including settings that
2013 * other settings didn't prevent from having any effect), plus the
2014 * username. However, I think it's better to keep it really simple:
2015 * the connection point identifier is derived from the hostname and
2016 * port used to index the host-key cache (not necessarily where we
2017 * _physically_ connected to, in cases involving proxies or
2018 * CONF_loghost), plus the username if one is specified.
2020 * The per-platform code will quite likely hash or obfuscate this name
2021 * in turn, for privacy from other users; failing that, it might
2022 * transform it to avoid dangerous filename characters and so on. But
2023 * that doesn't matter to us: for us, the point is that two session
2024 * configurations which return the same string from this function will
2025 * be treated as potentially shareable with each other.
2027 char *ssh_share_sockname(const char *host, int port, Conf *conf)
2029 char *username = get_remote_username(conf);
2030 char *sockname;
2032 if (port == 22) {
2033 if (username)
2034 sockname = dupprintf("%s@%s", username, host);
2035 else
2036 sockname = dupprintf("%s", host);
2037 } else {
2038 if (username)
2039 sockname = dupprintf("%s@%s:%d", username, host, port);
2040 else
2041 sockname = dupprintf("%s:%d", host, port);
2044 sfree(username);
2045 return sockname;
2048 static void nullplug_socket_log(Plug plug, int type, SockAddr addr, int port,
2049 const char *error_msg, int error_code) {}
2050 static int nullplug_closing(Plug plug, const char *error_msg, int error_code,
2051 int calling_back) { return 0; }
2052 static int nullplug_receive(Plug plug, int urgent, char *data,
2053 int len) { return 0; }
2054 static void nullplug_sent(Plug plug, int bufsize) {}
2056 int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
2058 static const struct plug_function_table fn_table = {
2059 nullplug_socket_log,
2060 nullplug_closing,
2061 nullplug_receive,
2062 nullplug_sent,
2063 NULL
2065 struct nullplug {
2066 const struct plug_function_table *fn;
2067 } np;
2069 char *sockname, *logtext, *ds_err, *us_err;
2070 int result;
2071 Socket sock;
2073 np.fn = &fn_table;
2075 sockname = ssh_share_sockname(host, port, conf);
2077 sock = NULL;
2078 logtext = ds_err = us_err = NULL;
2079 result = platform_ssh_share(sockname, conf, (Plug)&np, (Plug)NULL, &sock,
2080 &logtext, &ds_err, &us_err, FALSE, TRUE);
2082 sfree(logtext);
2083 sfree(ds_err);
2084 sfree(us_err);
2085 sfree(sockname);
2087 if (result == SHARE_NONE) {
2088 assert(sock == NULL);
2089 return FALSE;
2090 } else {
2091 assert(result == SHARE_DOWNSTREAM);
2092 sk_close(sock);
2093 return TRUE;
2098 * Init function for connection sharing. We either open a listening
2099 * socket and become an upstream, or connect to an existing one and
2100 * become a downstream, or do neither. We are responsible for deciding
2101 * which of these to do (including checking the Conf to see if
2102 * connection sharing is even enabled in the first place). If we
2103 * become a downstream, we return the Socket with which we connected
2104 * to the upstream; otherwise (whether or not we have established an
2105 * upstream) we return NULL.
2107 Socket ssh_connection_sharing_init(const char *host, int port,
2108 Conf *conf, Ssh ssh, void **state)
2110 static const struct plug_function_table listen_fn_table = {
2111 NULL, /* no log function, because that's for outgoing connections */
2112 share_listen_closing,
2113 NULL, /* no receive function on a listening socket */
2114 NULL, /* no sent function on a listening socket */
2115 share_listen_accepting
2118 int result, can_upstream, can_downstream;
2119 char *logtext, *ds_err, *us_err;
2120 char *sockname;
2121 Socket sock;
2122 struct ssh_sharing_state *sharestate;
2124 if (!conf_get_int(conf, CONF_ssh_connection_sharing))
2125 return NULL; /* do not share anything */
2126 can_upstream = share_can_be_upstream &&
2127 conf_get_int(conf, CONF_ssh_connection_sharing_upstream);
2128 can_downstream = share_can_be_downstream &&
2129 conf_get_int(conf, CONF_ssh_connection_sharing_downstream);
2130 if (!can_upstream && !can_downstream)
2131 return NULL;
2133 sockname = ssh_share_sockname(host, port, conf);
2136 * Create a data structure for the listening plug if we turn out
2137 * to be an upstream.
2139 sharestate = snew(struct ssh_sharing_state);
2140 sharestate->fn = &listen_fn_table;
2141 sharestate->listensock = NULL;
2144 * Now hand off to a per-platform routine that either connects to
2145 * an existing upstream (using 'ssh' as the plug), establishes our
2146 * own upstream (using 'sharestate' as the plug), or forks off a
2147 * separate upstream and then connects to that. It will return a
2148 * code telling us which kind of socket it put in 'sock'.
2150 sock = NULL;
2151 logtext = ds_err = us_err = NULL;
2152 result = platform_ssh_share(sockname, conf, (Plug)ssh,
2153 (Plug)sharestate, &sock, &logtext, &ds_err,
2154 &us_err, can_upstream, can_downstream);
2155 ssh_connshare_log(ssh, result, logtext, ds_err, us_err);
2156 sfree(logtext);
2157 sfree(ds_err);
2158 sfree(us_err);
2159 switch (result) {
2160 case SHARE_NONE:
2162 * We aren't sharing our connection at all (e.g. something
2163 * went wrong setting the socket up). Free the upstream
2164 * structure and return NULL.
2166 assert(sock == NULL);
2167 *state = NULL;
2168 sfree(sharestate);
2169 sfree(sockname);
2170 return NULL;
2172 case SHARE_DOWNSTREAM:
2174 * We are downstream, so free sharestate which it turns out we
2175 * don't need after all, and return the downstream socket as a
2176 * replacement for an ordinary SSH connection.
2178 *state = NULL;
2179 sfree(sharestate);
2180 sfree(sockname);
2181 return sock;
2183 case SHARE_UPSTREAM:
2185 * We are upstream. Set up sharestate properly and pass a copy
2186 * to the caller; return NULL, to tell ssh.c that it has to
2187 * make an ordinary connection after all.
2189 *state = sharestate;
2190 sharestate->listensock = sock;
2191 sharestate->connections = newtree234(share_connstate_cmp);
2192 sharestate->ssh = ssh;
2193 sharestate->server_verstring = NULL;
2194 sharestate->sockname = sockname;
2195 sharestate->nextid = 1;
2196 return NULL;
2199 return NULL;