Diff

Differences From Artifact [db88364e0c]:

To Artifact [4d033a5f47]:


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57



































58
59
60


61
62
63
64
65
66
67
68
69








70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100






























101
102
103
104
105
106






107
108
109
110
111
112
113
16
17
18
19
20
21
22



































23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58


59
60
61








62
63
64
65
66
67
68
69
70






























71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101





102
103
104
105
106
107
108
109
110
111
112
113
114







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
+
+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-
-
+
+
+
+
+
+







#define TRUE 1
#endif

#define logevent(s) { logevent(s); \
                      if (!(flags & FLAG_CONNECTION) && (flags & FLAG_VERBOSE)) \
                      fprintf(stderr, "%s\n", s); }

#define SSH1_MSG_DISCONNECT	1
#define SSH1_SMSG_PUBLIC_KEY	2
#define SSH1_CMSG_SESSION_KEY	3
#define SSH1_CMSG_USER		4
#define SSH1_CMSG_AUTH_RSA      6
#define SSH1_SMSG_AUTH_RSA_CHALLENGE 7
#define SSH1_CMSG_AUTH_RSA_RESPONSE 8
#define SSH1_CMSG_AUTH_PASSWORD	9
#define SSH1_CMSG_REQUEST_PTY	10
#define SSH1_CMSG_WINDOW_SIZE	11
#define SSH1_CMSG_EXEC_SHELL	12
#define SSH1_CMSG_EXEC_CMD	13
#define SSH1_SMSG_SUCCESS	14
#define SSH1_SMSG_FAILURE	15
#define SSH1_CMSG_STDIN_DATA	16
#define SSH1_SMSG_STDOUT_DATA	17
#define SSH1_SMSG_STDERR_DATA	18
#define SSH1_CMSG_EOF		19
#define SSH1_SMSG_EXIT_STATUS	20
#define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION  21
#define SSH1_MSG_CHANNEL_OPEN_FAILURE   22
#define SSH1_MSG_CHANNEL_DATA   23
#define SSH1_MSG_CHANNEL_CLOSE  24
#define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION 25
#define SSH1_CMSG_AGENT_REQUEST_FORWARDING  30
#define SSH1_SMSG_AGENT_OPEN    31
#define SSH1_CMSG_EXIT_CONFIRMATION	33
#define SSH1_MSG_IGNORE		32
#define SSH1_MSG_DEBUG		36
#define SSH1_CMSG_AUTH_TIS	39
#define SSH1_SMSG_AUTH_TIS_CHALLENGE	40
#define SSH1_CMSG_AUTH_TIS_RESPONSE	41
#define SSH1_CMSG_AUTH_CCARD	70
#define SSH1_SMSG_AUTH_CCARD_CHALLENGE	71
#define SSH1_CMSG_AUTH_CCARD_RESPONSE	72
#define SSH1_MSG_DISCONNECT                       1    /* 0x1 */
#define SSH1_SMSG_PUBLIC_KEY                      2    /* 0x2 */
#define SSH1_CMSG_SESSION_KEY                     3    /* 0x3 */
#define SSH1_CMSG_USER                            4    /* 0x4 */
#define SSH1_CMSG_AUTH_RSA                        6    /* 0x6 */
#define SSH1_SMSG_AUTH_RSA_CHALLENGE              7    /* 0x7 */
#define SSH1_CMSG_AUTH_RSA_RESPONSE               8    /* 0x8 */
#define SSH1_CMSG_AUTH_PASSWORD                   9    /* 0x9 */
#define SSH1_CMSG_REQUEST_PTY                     10   /* 0xa */
#define SSH1_CMSG_WINDOW_SIZE                     11   /* 0xb */
#define SSH1_CMSG_EXEC_SHELL                      12   /* 0xc */
#define SSH1_CMSG_EXEC_CMD                        13   /* 0xd */
#define SSH1_SMSG_SUCCESS                         14   /* 0xe */
#define SSH1_SMSG_FAILURE                         15   /* 0xf */
#define SSH1_CMSG_STDIN_DATA                      16   /* 0x10 */
#define SSH1_SMSG_STDOUT_DATA                     17   /* 0x11 */
#define SSH1_SMSG_STDERR_DATA                     18   /* 0x12 */
#define SSH1_CMSG_EOF                             19   /* 0x13 */
#define SSH1_SMSG_EXIT_STATUS                     20   /* 0x14 */
#define SSH1_MSG_CHANNEL_OPEN_CONFIRMATION        21   /* 0x15 */
#define SSH1_MSG_CHANNEL_OPEN_FAILURE             22   /* 0x16 */
#define SSH1_MSG_CHANNEL_DATA                     23   /* 0x17 */
#define SSH1_MSG_CHANNEL_CLOSE                    24   /* 0x18 */
#define SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION       25   /* 0x19 */
#define SSH1_CMSG_AGENT_REQUEST_FORWARDING        30   /* 0x1e */
#define SSH1_SMSG_AGENT_OPEN                      31   /* 0x1f */
#define SSH1_CMSG_EXIT_CONFIRMATION               33   /* 0x21 */
#define SSH1_MSG_IGNORE                           32   /* 0x20 */
#define SSH1_MSG_DEBUG                            36   /* 0x24 */
#define SSH1_CMSG_AUTH_TIS                        39   /* 0x27 */
#define SSH1_SMSG_AUTH_TIS_CHALLENGE              40   /* 0x28 */
#define SSH1_CMSG_AUTH_TIS_RESPONSE               41   /* 0x29 */
#define SSH1_CMSG_AUTH_CCARD                      70   /* 0x46 */
#define SSH1_SMSG_AUTH_CCARD_CHALLENGE            71   /* 0x47 */
#define SSH1_CMSG_AUTH_CCARD_RESPONSE             72   /* 0x48 */

#define SSH1_AUTH_TIS		5
#define SSH1_AUTH_CCARD		16
#define SSH1_AUTH_TIS                             5    /* 0x5 */
#define SSH1_AUTH_CCARD                           16   /* 0x10 */

#define SSH_AGENTC_REQUEST_RSA_IDENTITIES    1
#define SSH_AGENT_RSA_IDENTITIES_ANSWER      2
#define SSH_AGENTC_RSA_CHALLENGE             3
#define SSH_AGENT_RSA_RESPONSE               4
#define SSH_AGENT_FAILURE                    5
#define SSH_AGENT_SUCCESS                    6
#define SSH_AGENTC_ADD_RSA_IDENTITY          7
#define SSH_AGENTC_REMOVE_RSA_IDENTITY       8
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES         1    /* 0x1 */
#define SSH_AGENT_RSA_IDENTITIES_ANSWER           2    /* 0x2 */
#define SSH_AGENTC_RSA_CHALLENGE                  3    /* 0x3 */
#define SSH_AGENT_RSA_RESPONSE                    4    /* 0x4 */
#define SSH_AGENT_FAILURE                         5    /* 0x5 */
#define SSH_AGENT_SUCCESS                         6    /* 0x6 */
#define SSH_AGENTC_ADD_RSA_IDENTITY               7    /* 0x7 */
#define SSH_AGENTC_REMOVE_RSA_IDENTITY            8    /* 0x8 */

#define SSH2_MSG_DISCONNECT             1
#define SSH2_MSG_IGNORE                 2
#define SSH2_MSG_UNIMPLEMENTED          3
#define SSH2_MSG_DEBUG                  4
#define SSH2_MSG_SERVICE_REQUEST        5
#define SSH2_MSG_SERVICE_ACCEPT         6
#define SSH2_MSG_KEXINIT                20
#define SSH2_MSG_NEWKEYS                21
#define SSH2_MSG_KEXDH_INIT             30
#define SSH2_MSG_KEXDH_REPLY            31
#define SSH2_MSG_USERAUTH_REQUEST            50
#define SSH2_MSG_USERAUTH_FAILURE            51
#define SSH2_MSG_USERAUTH_SUCCESS            52
#define SSH2_MSG_USERAUTH_BANNER             53
#define SSH2_MSG_USERAUTH_PK_OK              60
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ   60
#define SSH2_MSG_GLOBAL_REQUEST                  80
#define SSH2_MSG_REQUEST_SUCCESS                 81
#define SSH2_MSG_REQUEST_FAILURE                 82
#define SSH2_MSG_CHANNEL_OPEN                    90
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION       91
#define SSH2_MSG_CHANNEL_OPEN_FAILURE            92
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST           93
#define SSH2_MSG_CHANNEL_DATA                    94
#define SSH2_MSG_CHANNEL_EXTENDED_DATA           95
#define SSH2_MSG_CHANNEL_EOF                     96
#define SSH2_MSG_CHANNEL_CLOSE                   97
#define SSH2_MSG_CHANNEL_REQUEST                 98
#define SSH2_MSG_CHANNEL_SUCCESS                 99
#define SSH2_MSG_CHANNEL_FAILURE                 100
#define SSH2_MSG_DISCONNECT                       1    /* 0x1 */
#define SSH2_MSG_IGNORE                           2    /* 0x2 */
#define SSH2_MSG_UNIMPLEMENTED                    3    /* 0x3 */
#define SSH2_MSG_DEBUG                            4    /* 0x4 */
#define SSH2_MSG_SERVICE_REQUEST                  5    /* 0x5 */
#define SSH2_MSG_SERVICE_ACCEPT                   6    /* 0x6 */
#define SSH2_MSG_KEXINIT                          20   /* 0x14 */
#define SSH2_MSG_NEWKEYS                          21   /* 0x15 */
#define SSH2_MSG_KEXDH_INIT                       30   /* 0x1e */
#define SSH2_MSG_KEXDH_REPLY                      31   /* 0x1f */
#define SSH2_MSG_USERAUTH_REQUEST                 50   /* 0x32 */
#define SSH2_MSG_USERAUTH_FAILURE                 51   /* 0x33 */
#define SSH2_MSG_USERAUTH_SUCCESS                 52   /* 0x34 */
#define SSH2_MSG_USERAUTH_BANNER                  53   /* 0x35 */
#define SSH2_MSG_USERAUTH_PK_OK                   60   /* 0x3c */
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ        60   /* 0x3c */
#define SSH2_MSG_GLOBAL_REQUEST                   80   /* 0x50 */
#define SSH2_MSG_REQUEST_SUCCESS                  81   /* 0x51 */
#define SSH2_MSG_REQUEST_FAILURE                  82   /* 0x52 */
#define SSH2_MSG_CHANNEL_OPEN                     90   /* 0x5a */
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION        91   /* 0x5b */
#define SSH2_MSG_CHANNEL_OPEN_FAILURE             92   /* 0x5c */
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST            93   /* 0x5d */
#define SSH2_MSG_CHANNEL_DATA                     94   /* 0x5e */
#define SSH2_MSG_CHANNEL_EXTENDED_DATA            95   /* 0x5f */
#define SSH2_MSG_CHANNEL_EOF                      96   /* 0x60 */
#define SSH2_MSG_CHANNEL_CLOSE                    97   /* 0x61 */
#define SSH2_MSG_CHANNEL_REQUEST                  98   /* 0x62 */
#define SSH2_MSG_CHANNEL_SUCCESS                  99   /* 0x63 */
#define SSH2_MSG_CHANNEL_FAILURE                  100  /* 0x64 */

#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED    1
#define SSH2_OPEN_CONNECT_FAILED                 2
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE           3
#define SSH2_OPEN_RESOURCE_SHORTAGE              4
#define SSH2_EXTENDED_DATA_STDERR                1
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED     1    /* 0x1 */
#define SSH2_OPEN_CONNECT_FAILED                  2    /* 0x2 */
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE            3    /* 0x3 */
#define SSH2_OPEN_RESOURCE_SHORTAGE               4    /* 0x4 */

#define SSH2_EXTENDED_DATA_STDERR                 1    /* 0x1 */

#define GET_32BIT(cp) \
    (((unsigned long)(unsigned char)(cp)[0] << 24) | \
    ((unsigned long)(unsigned char)(cp)[1] << 16) | \
    ((unsigned long)(unsigned char)(cp)[2] << 8) | \
    ((unsigned long)(unsigned char)(cp)[3]))

186
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201





202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218


219
220
221
222
223
224
225
187
188
189
190
191
192
193

194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231
232
233







-
+








+
+
+
+
+











-
+





+
+







static char *savedhost;
static int ssh_send_ok;

/*
 * 2-3-4 tree storing channels.
 */
struct ssh_channel {
    int remoteid, localid;
    unsigned remoteid, localid;
    int type;
    int closes;
    union {
        struct ssh_agent_channel {
            unsigned char *message;
            unsigned char msglen[4];
            int lensofar, totallen;
        } a;
        struct ssh2_data_channel {
            unsigned char *outbuffer;
            unsigned outbuflen, outbufsize;
            unsigned remwindow, remmaxpkt;
        } v2;
    } u;
};
static tree234 *ssh_channels;           /* indexed by local id */
static int ssh_channelcmp(void *av, void *bv) {
    struct ssh_channel *a = (struct ssh_channel *)av;
    struct ssh_channel *b = (struct ssh_channel *)bv;
    if (a->localid < b->localid) return -1;
    if (a->localid > b->localid) return +1;
    return 0;
}
static int ssh_channelfind(void *av, void *bv) {
    int *a = (int *)av;
    unsigned *a = (unsigned *)av;
    struct ssh_channel *b = (struct ssh_channel *)bv;
    if (*a < b->localid) return -1;
    if (*a > b->localid) return +1;
    return 0;
}

static struct ssh_channel *mainchan;   /* primary session channel */

static enum {
    SSH_STATE_BEFORE_SIZE,
    SSH_STATE_INTERMED,
    SSH_STATE_SESSION,
    SSH_STATE_CLOSED
} ssh_state = SSH_STATE_BEFORE_SIZE;
1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621

1622
1623
1624
1625
1626
1627
1628
1602
1603
1604
1605
1606
1607
1608

1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628

1629
1630
1631
1632
1633
1634
1635
1636







-
+



















-
+







		c_write(pktin.body+4, len);
	    } else if (pktin.type == SSH1_MSG_DISCONNECT) {
                ssh_state = SSH_STATE_CLOSED;
		logevent("Received disconnect request");
            } else if (pktin.type == SSH1_SMSG_AGENT_OPEN) {
                /* Remote side is trying to open a channel to talk to our
                 * agent. Give them back a local channel number. */
                int i = 1;
                unsigned i = 1;
                struct ssh_channel *c;
                enum234 e;
                for (c = first234(ssh_channels, &e); c; c = next234(&e)) {
                    if (c->localid > i)
                        break;         /* found a free number */
                    i = c->localid + 1;
                }
                c = malloc(sizeof(struct ssh_channel));
                c->remoteid = GET_32BIT(pktin.body);
                c->localid = i;
                c->closes = 0;
                c->type = SSH1_SMSG_AGENT_OPEN;   /* identify channel type */
                add234(ssh_channels, c);
                send_packet(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
                            PKT_INT, c->remoteid, PKT_INT, c->localid,
                            PKT_END);
            } else if (pktin.type == SSH1_MSG_CHANNEL_CLOSE ||
                       pktin.type == SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION) {
                /* Remote side closes a channel. */
                int i = GET_32BIT(pktin.body);
                unsigned i = GET_32BIT(pktin.body);
                struct ssh_channel *c;
                c = find234(ssh_channels, &i, ssh_channelfind);
                if (c) {
                    int closetype;
                    closetype = (pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
                    send_packet(pktin.type, PKT_INT, c->remoteid, PKT_END);
                    c->closes |= closetype;
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2016
2017
2018
2019
2020
2021
2022





2023
2024
2025
2026
2027
2028
2029







-
-
-
-
-







        crReturn(1);
    } while (!(ispkt && pktin.type == SSH2_MSG_KEXINIT));
    goto begin_key_exchange;

    crFinish(1);
}

/*
 * SSH2: remote identifier for the main session channel.
 */
static unsigned long ssh_remote_channel;

/*
 * Handle the SSH2 userauth and connection layers.
 */
static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
{
    static unsigned long remote_winsize;
    static unsigned long remote_maxpkt;
2164
2165
2166
2167
2168
2169
2170


2171
2172
2173
2174
2175



2176
2177
2178
2179
2180
2181
2182

2183
2184
2185
2186
2187





2188
2189
2190
2191
2192
2193
2194

2195
2196
2197
2198
2199
2200
2201
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177



2178
2179
2180
2181
2182
2183
2184
2185
2186

2187
2188
2189



2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200

2201
2202
2203
2204
2205
2206
2207
2208







+
+


-
-
-
+
+
+






-
+


-
-
-
+
+
+
+
+






-
+







     * connection protocol will automatically have started at this
     * point; there's no need to send SERVICE_REQUEST.
     */

    /*
     * So now create a channel with a session in it.
     */
    mainchan = malloc(sizeof(struct ssh_channel));
    mainchan->localid = 100;           /* as good as any */
    ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
    ssh2_pkt_addstring("session");
    ssh2_pkt_adduint32(100);           /* as good as any */
    ssh2_pkt_adduint32(0x7FFFFFFFUL);  /* very big window which we ignore */
    ssh2_pkt_adduint32(0x7FFFFFFFUL);  /* very big max pkt size */
    ssh2_pkt_adduint32(mainchan->localid);
    ssh2_pkt_adduint32(0x7FFFFFFFUL);  /* our window size */
    ssh2_pkt_adduint32(0x4000UL);  /* our max pkt size */
    ssh2_pkt_send();
    crWaitUntilV(ispkt);
    if (pktin.type != SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
        fatalbox("Server refused to open a session");
        /* FIXME: error data comes back in FAILURE packet */
    }
    if (ssh2_pkt_getuint32() != 100) {
    if (ssh2_pkt_getuint32() != mainchan->localid) {
        fatalbox("Server's channel confirmation cited wrong channel");
    }
    ssh_remote_channel = ssh2_pkt_getuint32();
    remote_winsize = ssh2_pkt_getuint32();
    remote_maxpkt = ssh2_pkt_getuint32();
    mainchan->remoteid = ssh2_pkt_getuint32();
    mainchan->u.v2.remwindow = ssh2_pkt_getuint32();
    mainchan->u.v2.remmaxpkt = ssh2_pkt_getuint32();
    mainchan->u.v2.outbuffer = NULL;
    mainchan->u.v2.outbuflen = mainchan->u.v2.outbufsize = 0;
    logevent("Opened channel for session");

    /*
     * Now allocate a pty for the session.
     */
    ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
    ssh2_pkt_adduint32(ssh_remote_channel); /* recipient channel */
    ssh2_pkt_adduint32(mainchan->remoteid); /* recipient channel */
    ssh2_pkt_addstring("pty-req");
    ssh2_pkt_addbool(1);               /* want reply */
    ssh2_pkt_addstring(cfg.termtype);
    ssh2_pkt_adduint32(cols);
    ssh2_pkt_adduint32(rows);
    ssh2_pkt_adduint32(0);             /* pixel width */
    ssh2_pkt_adduint32(0);             /* pixel height */
2216
2217
2218
2219
2220
2221
2222
2223

2224
2225
2226
2227

2228






2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243

2244

2245
2246
2247
2248
2249

2250

2251
2252
2253
2254
2255
2256

2257










2258
2259
2260

2261
2262
















2263


2264



2265
2266
2267
2268





2269
2270
2271
2272
2273
2274
2275

































2276
2277
2278
2279
2280
2281
2282
2223
2224
2225
2226
2227
2228
2229

2230
2231
2232
2233

2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271

2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285

2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307

2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319







2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359







-
+



-
+

+
+
+
+
+
+















+

+





+
-
+





-
+

+
+
+
+
+
+
+
+
+
+


-
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
-
+
+
+




+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







        logevent("Allocated pty");
    }

    /*
     * Start a shell.
     */
    ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
    ssh2_pkt_adduint32(ssh_remote_channel); /* recipient channel */
    ssh2_pkt_adduint32(mainchan->remoteid); /* recipient channel */
    ssh2_pkt_addstring("shell");
    ssh2_pkt_addbool(1);               /* want reply */
    ssh2_pkt_send();
    do {                               /* FIXME: pay attention to these */
    do {
        crWaitUntilV(ispkt);
        if (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
            /* FIXME: be able to handle other channels here */
            if (ssh2_pkt_getuint32() != mainchan->localid)
                continue;          /* wrong channel */
            mainchan->u.v2.remwindow += ssh2_pkt_getuint32();
        }
    } while (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
    if (pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
        if (pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
            fatalbox("Server got confused by shell request");
        }
        fatalbox("Server refused to start a shell");
    } else {
        logevent("Started a shell");
    }

    /*
     * Transfer data!
     */
    ssh_send_ok = 1;
    while (1) {
        static int try_send;
	crReturnV;
        try_send = FALSE;
	if (ispkt) {
	    if (pktin.type == SSH2_MSG_CHANNEL_DATA ||
                pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
                char *data;
                int length;
                /* FIXME: be able to handle other channels here */
                if (ssh2_pkt_getuint32() != 100)
                if (ssh2_pkt_getuint32() != mainchan->localid)
                    continue;          /* wrong channel */
                if (pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA &&
                    ssh2_pkt_getuint32() != SSH2_EXTENDED_DATA_STDERR)
                    continue;          /* extended but not stderr */
                ssh2_pkt_getstring(&data, &length);
                if (data)
                if (data) {
                    c_write(data, length);
                    /*
                     * Enlarge the window again at the remote side,
                     * just in case it ever runs down and they fail
                     * to send us any more data.
                     */
                    ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
                    ssh2_pkt_adduint32(mainchan->remoteid);
                    ssh2_pkt_adduint32(length);
                    ssh2_pkt_send();
                }
	    } else if (pktin.type == SSH2_MSG_DISCONNECT) {
                ssh_state = SSH_STATE_CLOSED;
		logevent("Received disconnect request");
		logevent("Received disconnect message");
	    } else if (pktin.type == SSH2_MSG_CHANNEL_REQUEST) {
                continue;              /* exit status et al; ignore (FIXME?) */
	    } else if (pktin.type == SSH2_MSG_CHANNEL_EOF) {
                continue;              /* remote sends EOF; ignore */
	    } else if (pktin.type == SSH2_MSG_CHANNEL_CLOSE) {
                /* FIXME: be able to handle other channels here */
                if (ssh2_pkt_getuint32() != mainchan->localid)
                    continue;          /* wrong channel */
                ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE);
                ssh2_pkt_adduint32(mainchan->remoteid);
                ssh2_pkt_send();
                /* FIXME: mark the channel as closed */
                if (1 /* FIXME: "all channels are closed" */) {
                    logevent("All channels closed. Disconnecting");
                    ssh2_pkt_init(SSH2_MSG_DISCONNECT);
                    ssh2_pkt_send();
                }
                continue;              /* remote sends close; ignore (FIXME) */
	    } else if (pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
                /* FIXME: be able to handle other channels here */
                if (ssh2_pkt_getuint32() != mainchan->localid)
                continue;              /* ignore for now (FIXME!) */
                    continue;          /* wrong channel */
                mainchan->u.v2.remwindow += ssh2_pkt_getuint32();
                try_send = TRUE;
	    } else {
		fatalbox("Strange packet received: type %d", pktin.type);
	    }
	} else {
            /*
             * We have spare data. Add it to the channel buffer.
             */
            if (mainchan->u.v2.outbufsize <
                mainchan->u.v2.outbuflen + inlen) {
            /* FIXME: for now, ignore window size */
            ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
            ssh2_pkt_adduint32(ssh_remote_channel);
            ssh2_pkt_addstring_start();
            ssh2_pkt_addstring_data(in, inlen);
            ssh2_pkt_send();
	}
                mainchan->u.v2.outbufsize =
                    mainchan->u.v2.outbuflen + inlen + 1024;
                mainchan->u.v2.outbuffer = srealloc(mainchan->u.v2.outbuffer,
                                                    mainchan->u.v2.outbufsize);
            }
            memcpy(mainchan->u.v2.outbuffer + mainchan->u.v2.outbuflen,
                   in, inlen);
            mainchan->u.v2.outbuflen += inlen;
            try_send = TRUE;
	}
        if (try_send) {
            /*
             * Try to send data on the channel if we can. (FIXME:
             * on _all_ channels.)
             */
            while (mainchan->u.v2.remwindow > 0 &&
                   mainchan->u.v2.outbuflen > 0) {
                unsigned len = mainchan->u.v2.remwindow;
                if (len > mainchan->u.v2.outbuflen)
                    len = mainchan->u.v2.outbuflen;
                if (len > mainchan->u.v2.remmaxpkt)
                    len = mainchan->u.v2.remmaxpkt;
                ssh2_pkt_init(SSH2_MSG_CHANNEL_DATA);
                ssh2_pkt_adduint32(mainchan->remoteid);
                ssh2_pkt_addstring_start();
                ssh2_pkt_addstring_data(mainchan->u.v2.outbuffer, len);
                ssh2_pkt_send();
                mainchan->u.v2.outbuflen -= len;
                memmove(mainchan->u.v2.outbuffer, mainchan->u.v2.outbuffer+len,
                        mainchan->u.v2.outbuflen);
                mainchan->u.v2.remwindow -= len;
            }
        }
    }

    crFinishV;
}

/*
 * Handle the top-level SSH2 protocol.
2400
2401
2402
2403
2404
2405
2406
2407

2408
2409
2410
2411
2412
2413
2414
2477
2478
2479
2480
2481
2482
2483

2484
2485
2486
2487
2488
2489
2490
2491







-
+







 */
static void ssh_special (Telnet_Special code) {
    if (code == TS_EOF) {
        if (ssh_version = 1) {
            send_packet(SSH1_CMSG_EOF, PKT_END);
        } else {
            ssh2_pkt_init(SSH2_MSG_CHANNEL_EOF);
            ssh2_pkt_adduint32(ssh_remote_channel);
            ssh2_pkt_adduint32(mainchan->remoteid);
            ssh2_pkt_send();
        }
    } else {
        /* do nothing */
    }
}