source: filezilla/trunk/fuentes/src/putty/sshshare.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 78.5 KB
Line 
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 */
5
6/*
7 * Discussion and technical documentation
8 * ======================================
9 *
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).
16 *
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.)
27 *
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).
41 *
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).
49 *
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.
58 *
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.
66 *
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.
74 *
75 * Downstream-to-upstream protocol
76 * -------------------------------
77 *
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.
81 *
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
85 *
86 *   <protocol>-<version>-<softwareversion> [comments] \r\n
87 *
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".
91 *
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 :-)
98 *
99 * Thereafter, all data exchanged consists of a sequence of binary
100 * packets concatenated end-to-end, each of which is of the form
101 *
102 *     uint32     length of packet, N
103 *     byte[N]    N bytes of packet data
104 *
105 * and, since these are SSH-2 messages, the first data byte is taken
106 * to be the packet type code.
107 *
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.
114 *
115 * This protocol imposes a few additional requirements, over and above
116 * those of the standard SSH Connection Protocol:
117 *
118 * Message sizes are not permitted to exceed 0x4010 (16400) bytes,
119 * including their length header.
120 *
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.)
130 */
131
132#include <stdio.h>
133#include <stdlib.h>
134#include <assert.h>
135#include <limits.h>
136#include <errno.h>
137
138#include "putty.h"
139#include "tree234.h"
140#include "ssh.h"
141
142struct ssh_sharing_state {
143    const struct plug_function_table *fn;
144    /* the above variable absolutely *must* be the first in this structure */
145
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-" */
152};
153
154struct share_globreq;
155
156struct ssh_sharing_connstate {
157    const struct plug_function_table *fn;
158    /* the above variable absolutely *must* be the first in this structure */
159
160    unsigned id;    /* used to identify this downstream in log messages */
161
162    Socket sock;                     /* the Socket for this connection */
163    struct ssh_sharing_state *parent;
164
165    int crLine;                        /* coroutine state for share_receive */
166
167    int sent_verstring, got_verstring, curr_packetlen;
168
169    unsigned char recvbuf[0x4010];
170    int recvlen;
171
172    /*
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.
176     */
177
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' */
183
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' */
190
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' */
200
201    /* Remote port forwarding requests in force. */
202    tree234 *forwardings;          /* stores 'struct share_forwarding' */
203
204    /* Global requests we've sent on to the server, pending replies. */
205    struct share_globreq *globreq_head, *globreq_tail;
206};
207
208struct share_halfchannel {
209    unsigned server_id;
210};
211
212/* States of a share_channel. */
213enum {
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
224};
225
226struct share_channel {
227    unsigned downstream_id, upstream_id, server_id;
228    int downstream_maxpkt;
229    int state;
230    /*
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.
235     */
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;
241};
242
243struct share_forwarding {
244    char *host;
245    int port;
246    int active;             /* has the server sent REQUEST_SUCCESS? */
247};
248
249struct share_xchannel_message {
250    struct share_xchannel_message *next;
251    int type;
252    unsigned char *data;
253    int datalen;
254};
255
256struct share_xchannel {
257    unsigned upstream_id, server_id;
258
259    /*
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.
266     */
267    int live;
268
269    /*
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.
276     */
277    int window;
278
279    /*
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.
283     */
284    struct share_xchannel_message *msghead, *msgtail;
285};
286
287enum {
288    GLOBREQ_TCPIP_FORWARD,
289    GLOBREQ_CANCEL_TCPIP_FORWARD
290};
291
292struct share_globreq {
293    struct share_globreq *next;
294    int type;
295    int want_reply;
296    struct share_forwarding *fwd;
297};
298
299static int share_connstate_cmp(void *av, void *bv)
300{
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;
305
306    if (a->id < b->id)
307        return -1;
308    else if (a->id > b->id)
309        return +1;
310    else
311        return 0;
312}
313
314static unsigned share_find_unused_id
315(struct ssh_sharing_state *sharestate, unsigned first)
316{
317    int low_orig, low, mid, high, high_orig;
318    struct ssh_sharing_connstate *cs;
319    unsigned ret;
320
321    /*
322     * Find the lowest unused downstream ID greater or equal to
323     * 'first'.
324     *
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.
328     */
329    {
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;
336    }
337
338    /*
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.
342     */
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 */
352    }
353
354    /*
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.
359     *
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.)
365     */
366    ret = first + (low - low_orig) + 1;
367    {
368        struct ssh_sharing_connstate dummy;
369        dummy.id = ret;
370        assert(NULL == find234(sharestate->connections, &dummy, NULL));
371    }
372    return ret;
373}
374
375static int share_halfchannel_cmp(void *av, void *bv)
376{
377    const struct share_halfchannel *a = (const struct share_halfchannel *)av;
378    const struct share_halfchannel *b = (const struct share_halfchannel *)bv;
379
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;
386}
387
388static int share_channel_us_cmp(void *av, void *bv)
389{
390    const struct share_channel *a = (const struct share_channel *)av;
391    const struct share_channel *b = (const struct share_channel *)bv;
392
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;
399}
400
401static int share_channel_server_cmp(void *av, void *bv)
402{
403    const struct share_channel *a = (const struct share_channel *)av;
404    const struct share_channel *b = (const struct share_channel *)bv;
405
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;
412}
413
414static int share_xchannel_us_cmp(void *av, void *bv)
415{
416    const struct share_xchannel *a = (const struct share_xchannel *)av;
417    const struct share_xchannel *b = (const struct share_xchannel *)bv;
418
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;
425}
426
427static int share_xchannel_server_cmp(void *av, void *bv)
428{
429    const struct share_xchannel *a = (const struct share_xchannel *)av;
430    const struct share_xchannel *b = (const struct share_xchannel *)bv;
431
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;
438}
439
440static int share_forwarding_cmp(void *av, void *bv)
441{
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;
445
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;
454}
455
456static void share_xchannel_free(struct share_xchannel *xc)
457{
458    while (xc->msghead) {
459        struct share_xchannel_message *tmp = xc->msghead;
460        xc->msghead = tmp->next;
461        sfree(tmp);
462    }
463    sfree(xc);
464}
465
466static void share_connstate_free(struct ssh_sharing_connstate *cs)
467{
468    struct share_halfchannel *hc;
469    struct share_xchannel *xc;
470    struct share_channel *chan;
471    struct share_forwarding *fwd;
472
473    while ((hc = (struct share_halfchannel *)
474            delpos234(cs->halfchannels, 0)) != NULL)
475        sfree(hc);
476    freetree234(cs->halfchannels);
477
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);
486
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);
494
495    while ((fwd = (struct share_forwarding *)
496            delpos234(cs->forwardings, 0)) != NULL)
497        sfree(fwd);
498    freetree234(cs->forwardings);
499
500    while (cs->globreq_head) {
501        struct share_globreq *globreq = cs->globreq_head;
502        cs->globreq_head = cs->globreq_head->next;
503        sfree(globreq);
504    }
505
506    if (cs->sock)
507        sk_close(cs->sock);
508
509    sfree(cs);
510}
511
512void sharestate_free(void *v)
513{
514    struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)v;
515    struct ssh_sharing_connstate *cs;
516
517    platform_ssh_share_cleanup(sharestate->sockname);
518
519    while ((cs = (struct ssh_sharing_connstate *)
520            delpos234(sharestate->connections, 0)) != NULL) {
521        share_connstate_free(cs);
522    }
523    freetree234(sharestate->connections);
524    if (sharestate->listensock) {
525        sk_close(sharestate->listensock);
526        sharestate->listensock = NULL;
527    }
528    sfree(sharestate->server_verstring);
529    sfree(sharestate->sockname);
530    sfree(sharestate);
531}
532
533static struct share_halfchannel *share_add_halfchannel
534    (struct ssh_sharing_connstate *cs, unsigned server_id)
535{
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;
544    }
545}
546
547static struct share_halfchannel *share_find_halfchannel
548    (struct ssh_sharing_connstate *cs, unsigned server_id)
549{
550    struct share_halfchannel dummyhc;
551    dummyhc.server_id = server_id;
552    return find234(cs->halfchannels, &dummyhc, NULL);
553}
554
555static void share_remove_halfchannel(struct ssh_sharing_connstate *cs,
556                                     struct share_halfchannel *hc)
557{
558    del234(cs->halfchannels, hc);
559    sfree(hc);
560}
561
562static 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)
565{
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;
580    }
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;
586        }
587    }
588    return chan;
589}
590
591static void share_channel_set_server_id(struct ssh_sharing_connstate *cs,
592                                        struct share_channel *chan,
593                                        unsigned server_id, int newstate)
594{
595    chan->server_id = server_id;
596    chan->state = newstate;
597    assert(newstate != UNACKNOWLEDGED);
598    add234(cs->channels_by_server, chan);
599}
600
601static struct share_channel *share_find_channel_by_upstream
602    (struct ssh_sharing_connstate *cs, unsigned upstream_id)
603{
604    struct share_channel dummychan;
605    dummychan.upstream_id = upstream_id;
606    return find234(cs->channels_by_us, &dummychan, NULL);
607}
608
609static struct share_channel *share_find_channel_by_server
610    (struct ssh_sharing_connstate *cs, unsigned server_id)
611{
612    struct share_channel dummychan;
613    dummychan.server_id = server_id;
614    return find234(cs->channels_by_server, &dummychan, NULL);
615}
616
617static void share_remove_channel(struct ssh_sharing_connstate *cs,
618                                 struct share_channel *chan)
619{
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);
627}
628
629static struct share_xchannel *share_add_xchannel
630    (struct ssh_sharing_connstate *cs,
631     unsigned upstream_id, unsigned server_id)
632{
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;
641    }
642    if (add234(cs->xchannels_by_server, xc) != xc) {
643        del234(cs->xchannels_by_us, xc);
644        sfree(xc);
645        return NULL;
646    }
647    return xc;
648}
649
650static struct share_xchannel *share_find_xchannel_by_upstream
651    (struct ssh_sharing_connstate *cs, unsigned upstream_id)
652{
653    struct share_xchannel dummyxc;
654    dummyxc.upstream_id = upstream_id;
655    return find234(cs->xchannels_by_us, &dummyxc, NULL);
656}
657
658static struct share_xchannel *share_find_xchannel_by_server
659    (struct ssh_sharing_connstate *cs, unsigned server_id)
660{
661    struct share_xchannel dummyxc;
662    dummyxc.server_id = server_id;
663    return find234(cs->xchannels_by_server, &dummyxc, NULL);
664}
665
666static void share_remove_xchannel(struct ssh_sharing_connstate *cs,
667                                 struct share_xchannel *xc)
668{
669    del234(cs->xchannels_by_us, xc);
670    del234(cs->xchannels_by_server, xc);
671    share_xchannel_free(xc);
672}
673
674static struct share_forwarding *share_add_forwarding
675    (struct ssh_sharing_connstate *cs,
676     const char *host, int port)
677{
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;
686    }
687    return fwd;
688}
689
690static struct share_forwarding *share_find_forwarding
691    (struct ssh_sharing_connstate *cs, const char *host, int port)
692{
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;
699}
700
701static void share_remove_forwarding(struct ssh_sharing_connstate *cs,
702                                    struct share_forwarding *fwd)
703{
704    del234(cs->forwardings, fwd);
705    sfree(fwd);
706}
707
708static void send_packet_to_downstream(struct ssh_sharing_connstate *cs,
709                                      int type, const void *pkt, int pktlen,
710                                      struct share_channel *chan)
711{
712    if (!cs->sock) /* throw away all packets destined for a dead downstream */
713        return;
714
715    if (type == SSH2_MSG_CHANNEL_DATA) {
716        /*
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.)
727         *
728         * If that happens, we just chop up the packet into pieces and
729         * send them as separate CHANNEL_DATA packets.
730         */
731        const char *upkt = (const char *)pkt;
732        char header[13]; /* 4 length + 1 type + 4 channel id + 4 string len */
733
734        int len = toint(GET_32BIT(upkt + 4));
735        upkt += 8;                /* skip channel id + length field */
736
737        if (len < 0 || len > pktlen - 8)
738            len = pktlen - 8;
739
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 {
753        /*
754         * Just do the obvious thing.
755         */
756        char header[9];
757
758        PUT_32BIT(header, pktlen + 1);
759        header[4] = type;
760        sk_write(cs->sock, header, 5);
761        sk_write(cs->sock, pkt, pktlen);
762    }
763}
764
765static void share_try_cleanup(struct ssh_sharing_connstate *cs)
766{
767    int i;
768    struct share_halfchannel *hc;
769    struct share_channel *chan;
770    struct share_forwarding *fwd;
771
772    /*
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.
776     */
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;
783
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");
794
795        share_remove_halfchannel(cs, hc);
796    }
797
798    /*
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).
804     *
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.
810     */
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;
815
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 */
829            }
830        }
831    }
832
833    /*
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.
837     *
838     * We take a fire-and-forget approach during cleanup, not
839     * bothering to set want_reply.
840     */
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;
847
848            PUT_32BIT(packet + pos, strlen(request)); pos += 4;
849            memcpy(packet + pos, request, strlen(request));
850            pos += strlen(request);
851
852            packet[pos++] = 0;         /* !want_reply */
853
854            PUT_32BIT(packet + pos, strlen(fwd->host)); pos += 4;
855            memcpy(packet + pos, fwd->host, strlen(fwd->host));
856            pos += strlen(fwd->host);
857
858            PUT_32BIT(packet + pos, fwd->port); pos += 4;
859
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);
865
866            share_remove_forwarding(cs, fwd);
867            i--;    /* don't accidentally skip one as a result */
868        }
869    }
870
871    if (count234(cs->halfchannels) == 0 &&
872        count234(cs->channels_by_us) == 0 &&
873        count234(cs->forwardings) == 0) {
874        /*
875         * Now we're _really_ done, so we can get rid of cs completely.
876         */
877        del234(cs->parent->connections, cs);
878        ssh_sharing_downstream_disconnected(cs->parent->ssh, cs->id);
879        share_connstate_free(cs);
880    }
881}
882
883static void share_begin_cleanup(struct ssh_sharing_connstate *cs)
884{
885
886    sk_close(cs->sock);
887    cs->sock = NULL;
888
889    share_try_cleanup(cs);
890}
891
892static void share_disconnect(struct ssh_sharing_connstate *cs,
893                             const char *message)
894{
895    static const char lang[] = "en";
896    int msglen = strlen(message);
897    char *packet = snewn(msglen + 256, char);
898    int pos = 0;
899
900    PUT_32BIT(packet + pos, SSH2_DISCONNECT_PROTOCOL_ERROR); pos += 4;
901
902    PUT_32BIT(packet + pos, msglen); pos += 4;
903    memcpy(packet + pos, message, msglen);
904    pos += msglen;
905
906    PUT_32BIT(packet + pos, strlen(lang)); pos += 4;
907    memcpy(packet + pos, lang, strlen(lang)); pos += strlen(lang);
908
909    send_packet_to_downstream(cs, SSH2_MSG_DISCONNECT, packet, pos, NULL);
910
911    share_begin_cleanup(cs);
912}
913
914static int share_closing(Plug plug, const char *error_msg, int error_code,
915                         int calling_back)
916{
917    struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
918
919    if (error_msg) {
920#ifdef BROKEN_PIPE_ERROR_CODE
921        /*
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.
929         */
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);
936    }
937    share_begin_cleanup(cs);
938    return 1;
939}
940
941static int getstring_inner(const void *vdata, int datalen,
942                           char **out, int *outlen)
943{
944    const unsigned char *data = (const unsigned char *)vdata;
945    int len;
946
947    if (datalen < 4)
948        return FALSE;
949
950    len = toint(GET_32BIT(data));
951    if (len < 0 || len > datalen - 4)
952        return FALSE;
953
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;
959}
960
961static char *getstring(const void *data, int datalen)
962{
963    char *ret;
964    if (getstring_inner(data, datalen, &ret, NULL))
965        return ret;
966    else
967        return NULL;
968}
969
970static int getstring_size(const void *data, int datalen)
971{
972    int ret;
973    if (getstring_inner(data, datalen, NULL, &ret))
974        return ret;
975    else
976        return -1;
977}
978
979/*
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.
983 */
984struct share_xchannel_message *share_xchannel_add_message
985(struct share_xchannel *xc, int type, int len)
986{
987    unsigned char *block;
988    struct share_xchannel_message *msg;
989
990    /*
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.
994     */
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;
1000
1001    /*
1002     * Queue it in the xchannel.
1003     */
1004    if (xc->msgtail)
1005        xc->msgtail->next = msg;
1006    else
1007        xc->msghead = msg;
1008    msg->next = NULL;
1009    xc->msgtail = msg;
1010
1011    return msg;
1012}
1013
1014void share_dead_xchannel_respond(struct ssh_sharing_connstate *cs,
1015                                 struct share_xchannel *xc)
1016{
1017    /*
1018     * Handle queued incoming messages from the server destined for an
1019     * xchannel which is dead (i.e. downstream sent OPEN_FAILURE).
1020     */
1021    int delete = FALSE;
1022    while (xc->msghead) {
1023        struct share_xchannel_message *msg = xc->msghead;
1024        xc->msghead = msg->next;
1025
1026        if (msg->type == SSH2_MSG_CHANNEL_REQUEST && msg->datalen > 4) {
1027            /*
1028             * A CHANNEL_REQUEST is responded to by sending
1029             * CHANNEL_FAILURE, if it has want_reply set.
1030             */
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");
1039            }
1040        } else if (msg->type == SSH2_MSG_CHANNEL_CLOSE) {
1041            /*
1042             * On CHANNEL_CLOSE we can discard the channel completely.
1043             */
1044            delete = TRUE;
1045        }
1046
1047        sfree(msg);
1048    }
1049    xc->msgtail = NULL;
1050    if (delete) {
1051        ssh_delete_sharing_channel(cs->parent->ssh, xc->upstream_id);
1052        share_remove_xchannel(cs, xc);
1053    }
1054}
1055
1056void share_xchannel_confirmation(struct ssh_sharing_connstate *cs,
1057                                 struct share_xchannel *xc,
1058                                 struct share_channel *chan,
1059                                 unsigned downstream_window)
1060{
1061    unsigned char window_adjust[8];
1062
1063    /*
1064     * Send all the queued messages downstream.
1065     */
1066    while (xc->msghead) {
1067        struct share_xchannel_message *msg = xc->msghead;
1068        xc->msghead = msg->next;
1069
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);
1074
1075        sfree(msg);
1076    }
1077
1078    /*
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.
1082     */
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");
1089}
1090
1091void share_xchannel_failure(struct ssh_sharing_connstate *cs,
1092                            struct share_xchannel *xc)
1093{
1094    /*
1095     * If downstream refuses to open our X channel at all for some
1096     * reason, we must respond by sending an emergency CLOSE upstream.
1097     */
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");
1103
1104    /*
1105     * Now mark the xchannel as dead, and respond to anything sent on
1106     * it until we see CLOSE for it in turn.
1107     */
1108    xc->live = FALSE;
1109    share_dead_xchannel_respond(cs, xc);
1110}
1111
1112void 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)
1119{
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;
1128
1129    /*
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.
1134     */
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);
1148
1149    xc->window = client_adjusted_window + greeting_len;
1150
1151    /*
1152     * Send on a CHANNEL_OPEN to downstream.
1153     */
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);
1166
1167    /*
1168     * If this was a once-only X forwarding, clean it up now.
1169     */
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;
1178    }
1179}
1180
1181void share_got_pkt_from_server(void *csv, int type,
1182                               unsigned char *pkt, int pktlen)
1183{
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;
1190
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;
1200            }
1201        } else if (globreq->type == GLOBREQ_CANCEL_TCPIP_FORWARD) {
1202            if (type == SSH2_MSG_REQUEST_SUCCESS) {
1203                share_remove_forwarding(cs, globreq->fwd);
1204            }
1205        }
1206        if (globreq->want_reply) {
1207            send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1208        }
1209        cs->globreq_head = globreq->next;
1210        sfree(globreq);
1211        if (cs->globreq_head == NULL)
1212            cs->globreq_tail = NULL;
1213
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);
1218        }
1219
1220        break;
1221
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);
1227
1228        send_packet_to_downstream(cs, type, pkt, pktlen, NULL);
1229        break;
1230
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:
1241        /*
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.
1245         */
1246        assert(pktlen >= 4);
1247        upstream_id = GET_32BIT(pkt);
1248        if ((chan = share_find_channel_by_upstream(cs, upstream_id)) != NULL) {
1249            /*
1250             * The normal case: this id refers to an open channel.
1251             */
1252            PUT_32BIT(pkt, chan->downstream_id);
1253            send_packet_to_downstream(cs, type, pkt, pktlen, chan);
1254
1255            /*
1256             * Update the channel state, for messages that need it.
1257             */
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);
1267                    }
1268                }
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);
1282                    }
1283                } else {
1284                    chan->state = RCVD_CLOSE;
1285                }
1286            }
1287        } else if ((xc = share_find_xchannel_by_upstream(cs, upstream_id))
1288                   != NULL) {
1289            /*
1290             * The unusual case: this id refers to an xchannel. Add it
1291             * to the xchannel's queue.
1292             */
1293            struct share_xchannel_message *msg;
1294
1295            msg = share_xchannel_add_message(xc, type, pktlen);
1296            memcpy(msg->data, pkt, pktlen);
1297
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);
1302        }
1303        break;
1304
1305      default:
1306        assert(!"This packet type should never have come from ssh.c");
1307        break;
1308    }
1309}
1310
1311static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
1312                                          int type,
1313                                          unsigned char *pkt, int pktlen)
1314{
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;
1324
1325    switch (type) {
1326      case SSH2_MSG_DISCONNECT:
1327        /*
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.
1332         */
1333        share_begin_cleanup(cs);
1334        break;
1335
1336      case SSH2_MSG_GLOBAL_REQUEST:
1337        /*
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.
1343         */
1344        request_name = getstring(pkt, pktlen);
1345        if (request_name == NULL) {
1346            err = dupprintf("Truncated GLOBAL_REQUEST packet");
1347            goto confused;
1348        }
1349
1350        if (!strcmp(request_name, "tcpip-forward")) {
1351            int wantreplypos, orig_wantreply, port, ret;
1352            char *host;
1353
1354            sfree(request_name);
1355
1356            /*
1357             * Pick the packet apart to find the want_reply field and
1358             * the host/port we're going to ask to listen on.
1359             */
1360            wantreplypos = getstring_size(pkt, pktlen);
1361            if (wantreplypos < 0 || wantreplypos >= pktlen) {
1362                err = dupprintf("Truncated GLOBAL_REQUEST packet");
1363                goto confused;
1364            }
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;
1372            }
1373            host = getstring(pkt + (wantreplypos + 1),
1374                             pktlen - (wantreplypos + 1));
1375            assert(host != NULL);
1376            port = GET_32BIT(pkt + port);
1377
1378            /*
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.
1385             */
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);
1391                }
1392            } else {
1393                /*
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.
1399                 */
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);
1407
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;
1418                }
1419            }
1420
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;
1426
1427            sfree(request_name);
1428
1429            /*
1430             * Pick the packet apart to find the want_reply field and
1431             * the host/port we're going to ask to listen on.
1432             */
1433            wantreplypos = getstring_size(pkt, pktlen);
1434            if (wantreplypos < 0 || wantreplypos >= pktlen) {
1435                err = dupprintf("Truncated GLOBAL_REQUEST packet");
1436                goto confused;
1437            }
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;
1445            }
1446            host = getstring(pkt + (wantreplypos + 1),
1447                             pktlen - (wantreplypos + 1));
1448            assert(host != NULL);
1449            port = GET_32BIT(pkt + port);
1450
1451            /*
1452             * Look up the existing forwarding with these details.
1453             */
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);
1459                }
1460            } else {
1461                /*
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.
1466                 */
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);
1473            }
1474
1475            sfree(host);
1476        } else {
1477            /*
1478             * Request we don't understand. Manufacture a failure
1479             * message if an answer was required.
1480             */
1481            int wantreplypos;
1482
1483            sfree(request_name);
1484
1485            wantreplypos = getstring_size(pkt, pktlen);
1486            if (wantreplypos < 0 || wantreplypos >= pktlen) {
1487                err = dupprintf("Truncated GLOBAL_REQUEST packet");
1488                goto confused;
1489            }
1490            if (pkt[wantreplypos])
1491                send_packet_to_downstream(cs, SSH2_MSG_REQUEST_FAILURE,
1492                                          "", 0, NULL);
1493        }
1494        break;
1495
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;
1502        }
1503
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;
1512
1513      case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
1514        if (pktlen < 16) {
1515            err = dupprintf("Truncated CHANNEL_OPEN_CONFIRMATION packet");
1516            goto confused;
1517        }
1518
1519        id_pos = 4;  /* sender channel id is 2nd uint32 field in packet */
1520        old_id = GET_32BIT(pkt + id_pos);
1521
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;
1533        }
1534           
1535        PUT_32BIT(pkt + id_pos, new_id);
1536
1537        chan = share_add_channel(cs, old_id, new_id, server_id, OPEN,
1538                                 GET_32BIT(pkt + 12));
1539
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;
1549            }
1550            share_xchannel_confirmation(cs, xc, chan, downstream_window);
1551            share_remove_xchannel(cs, xc);
1552        }
1553
1554        break;
1555
1556      case SSH2_MSG_CHANNEL_OPEN_FAILURE:
1557        if (pktlen < 4) {
1558            err = dupprintf("Truncated CHANNEL_OPEN_FAILURE packet");
1559            goto confused;
1560        }
1561
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;
1574        }
1575
1576        break;
1577
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) {
1590            /*
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.
1602             *
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.)
1614             */
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];
1619
1620                sfree(request_name);
1621
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;
1633                }
1634                break;
1635            }
1636
1637            /*
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.
1645             */
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;
1652
1653                sfree(request_name);
1654
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;
1662                }
1663
1664                /*
1665                 * Pick apart the whole message to find the downstream
1666                 * auth details.
1667                 */
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;
1672                }
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);
1681
1682                if (pktlen < pos+4) {
1683                    err = dupprintf("Truncated CHANNEL_REQUEST(\"x11\") packet");
1684                    sfree(auth_data);
1685                    goto confused;
1686                }
1687                screen = GET_32BIT(pkt+pos);
1688
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;
1698                }
1699
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;
1708
1709                /*
1710                 * Now construct a replacement X forwarding request,
1711                 * containing our own auth data, and send that to the
1712                 * server.
1713                 */
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);
1733
1734                break;
1735            }
1736
1737            sfree(request_name);
1738        }
1739
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;
1752                }
1753            }
1754        }
1755        break;
1756
1757      default:
1758        err = dupprintf("Unexpected packet type %d\n", type);
1759        goto confused;
1760
1761        /*
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}.
1765         */
1766      confused:
1767        assert(err != NULL);
1768        share_disconnect(cs, err);
1769        sfree(err);
1770        break;
1771    }
1772}
1773
1774/*
1775 * Coroutine macros similar to, but simplified from, those in ssh.c.
1776 */
1777#define crBegin(v)      { int *crLine = &v; switch(v) { case 0:;
1778#define crFinish(z)     } *crLine = 0; return (z); }
1779#define crGetChar(c) do                                         \
1780    {                                                           \
1781        while (len == 0) {                                      \
1782            *crLine =__LINE__; return 1; case __LINE__:;        \
1783        }                                                       \
1784        len--;                                                  \
1785        (c) = (unsigned char)*data++;                           \
1786    } while (0)
1787
1788static int share_receive(Plug plug, int urgent, char *data, int len)
1789{
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;
1794
1795    crBegin(cs->crLine);
1796
1797    /*
1798     * First read the version string from downstream.
1799     */
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;
1810        }
1811        cs->recvbuf[cs->recvlen++] = c;
1812    }
1813
1814    /*
1815     * Now parse the version string to make sure it's at least vaguely
1816     * sensible, and log it.
1817     */
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;
1825    }
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;
1832
1833    /*
1834     * Loop round reading packets.
1835     */
1836    while (1) {
1837        cs->recvlen = 0;
1838        while (cs->recvlen < 4) {
1839            crGetChar(c);
1840            cs->recvbuf[cs->recvlen++] = c;
1841        }
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;
1850        }
1851        while (cs->recvlen < cs->curr_packetlen) {
1852            crGetChar(c);
1853            cs->recvbuf[cs->recvlen++] = c;
1854        }
1855
1856        share_got_pkt_from_downstream(cs, cs->recvbuf[4],
1857                                      cs->recvbuf + 5, cs->recvlen - 5);
1858    }
1859
1860  dead:;
1861    crFinish(1);
1862}
1863
1864static void share_sent(Plug plug, int bufsize)
1865{
1866    /* struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug; */
1867
1868    /*
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.
1875     */
1876}
1877
1878static int share_listen_closing(Plug plug, const char *error_msg,
1879                                int error_code, int calling_back)
1880{
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;
1888}
1889
1890static void share_send_verstring(struct ssh_sharing_connstate *cs)
1891{
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);
1896
1897    cs->sent_verstring = TRUE;
1898}
1899
1900int share_ndownstreams(void *state)
1901{
1902    struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1903    return count234(sharestate->connections);
1904}
1905
1906void share_activate(void *state, const char *server_verstring)
1907{
1908    /*
1909     * Indication from ssh.c that we are now ready to begin serving
1910     * any downstreams that have already connected to us.
1911     */
1912    struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)state;
1913    struct ssh_sharing_connstate *cs;
1914    int i;
1915
1916    /*
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.
1920     */
1921    for (i = 0; i < 2; i++) {
1922        server_verstring += strcspn(server_verstring, "-");
1923        if (*server_verstring)
1924            server_verstring++;
1925    }
1926
1927    sharestate->server_verstring = dupstr(server_verstring);
1928
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);
1933    }
1934}
1935
1936static int share_listen_accepting(Plug plug,
1937                                  accept_fn_t constructor, accept_ctx_t ctx)
1938{
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 */
1945    };
1946    struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
1947    struct ssh_sharing_connstate *cs;
1948    const char *err;
1949    char *peerinfo;
1950
1951    /*
1952     * A new downstream has connected to us.
1953     */
1954    cs = snew(struct ssh_sharing_connstate);
1955    cs->fn = &connection_fn_table;
1956    cs->parent = sharestate;
1957
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;
1962    }
1963    sharestate->nextid = cs->id + 1;
1964    if (sharestate->nextid == 0)
1965        sharestate->nextid++; /* only happens in VERY long-running upstreams */
1966
1967    cs->sock = constructor(ctx, (Plug) cs);
1968    if ((err = sk_socket_error(cs->sock)) != NULL) {
1969        sfree(cs);
1970        return err != NULL;
1971    }
1972
1973    sk_set_frozen(cs->sock, 0);
1974
1975    add234(cs->parent->connections, cs);
1976
1977    cs->sent_verstring = FALSE;
1978    if (sharestate->server_verstring)
1979        share_send_verstring(cs);
1980
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;
1991
1992    peerinfo = sk_peer_info(cs->sock);
1993    ssh_sharing_downstream_connected(sharestate->ssh, cs->id, peerinfo);
1994    sfree(peerinfo);
1995
1996    return 0;
1997}
1998
1999/* Per-application overrides for what roles we can take (e.g. pscp
2000 * will never be an upstream) */
2001extern const int share_can_be_downstream;
2002extern const int share_can_be_upstream;
2003
2004/*
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).
2008 *
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.
2019 *
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.
2026 */
2027char *ssh_share_sockname(const char *host, int port, Conf *conf)
2028{
2029    char *username = get_remote_username(conf);
2030    char *sockname;
2031
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);
2042    }
2043
2044    sfree(username);
2045    return sockname;
2046}
2047
2048static void nullplug_socket_log(Plug plug, int type, SockAddr addr, int port,
2049                                const char *error_msg, int error_code) {}
2050static int nullplug_closing(Plug plug, const char *error_msg, int error_code,
2051                            int calling_back) { return 0; }
2052static int nullplug_receive(Plug plug, int urgent, char *data,
2053                            int len) { return 0; }
2054static void nullplug_sent(Plug plug, int bufsize) {}
2055
2056int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
2057{
2058    static const struct plug_function_table fn_table = {
2059        nullplug_socket_log,
2060        nullplug_closing,
2061        nullplug_receive,
2062        nullplug_sent,
2063        NULL
2064    };
2065    struct nullplug {
2066        const struct plug_function_table *fn;
2067    } np;
2068
2069    char *sockname, *logtext, *ds_err, *us_err;
2070    int result;
2071    Socket sock;
2072
2073    np.fn = &fn_table;
2074
2075    sockname = ssh_share_sockname(host, port, conf);
2076
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);
2081
2082    sfree(logtext);
2083    sfree(ds_err);
2084    sfree(us_err);
2085    sfree(sockname);
2086
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;
2094    }
2095}
2096
2097/*
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.
2106 */
2107Socket ssh_connection_sharing_init(const char *host, int port,
2108                                   Conf *conf, Ssh ssh, void **state)
2109{
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
2116    };
2117
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;
2123
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;
2132
2133    sockname = ssh_share_sockname(host, port, conf);
2134
2135    /*
2136     * Create a data structure for the listening plug if we turn out
2137     * to be an upstream.
2138     */
2139    sharestate = snew(struct ssh_sharing_state);
2140    sharestate->fn = &listen_fn_table;
2141    sharestate->listensock = NULL;
2142
2143    /*
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'.
2149     */
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:
2161        /*
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.
2165         */
2166        assert(sock == NULL);
2167        *state = NULL;
2168        sfree(sharestate);
2169        sfree(sockname);
2170        return NULL;
2171
2172      case SHARE_DOWNSTREAM:
2173        /*
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.
2177         */
2178        *state = NULL;
2179        sfree(sharestate);
2180        sfree(sockname);
2181        return sock;
2182
2183      case SHARE_UPSTREAM:
2184        /*
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.
2188         */
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;
2197    }
2198
2199    return NULL;
2200}
Note: See TracBrowser for help on using the repository browser.