libssh2

Форк
0
/
channel.c 
3075 строк · 103.9 Кб
1
/* Copyright (C) Sara Golemon <sarag@libssh2.org>
2
 * Copyright (C) Mikhail Gusarov <dottedmag@dottedmag.net>
3
 * Copyright (C) Daniel Stenberg
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms,
7
 * with or without modification, are permitted provided
8
 * that the following conditions are met:
9
 *
10
 *   Redistributions of source code must retain the above
11
 *   copyright notice, this list of conditions and the
12
 *   following disclaimer.
13
 *
14
 *   Redistributions in binary form must reproduce the above
15
 *   copyright notice, this list of conditions and the following
16
 *   disclaimer in the documentation and/or other materials
17
 *   provided with the distribution.
18
 *
19
 *   Neither the name of the copyright holder nor the names
20
 *   of any other contributors may be used to endorse or
21
 *   promote products derived from this software without
22
 *   specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
37
 * OF SUCH DAMAGE.
38
 *
39
 * SPDX-License-Identifier: BSD-3-Clause
40
 */
41

42
#include "libssh2_priv.h"
43

44
#ifdef HAVE_UNISTD_H
45
#include <unistd.h>
46
#endif
47
#ifdef HAVE_INTTYPES_H
48
#include <inttypes.h>
49
#endif
50

51
#include <assert.h>
52

53
#include "channel.h"
54
#include "transport.h"
55
#include "packet.h"
56
#include "session.h"
57

58
/*
59
 *  _libssh2_channel_nextid
60
 *
61
 * Determine the next channel ID we can use at our end
62
 */
63
uint32_t
64
_libssh2_channel_nextid(LIBSSH2_SESSION * session)
65
{
66
    uint32_t id = session->next_channel;
67
    LIBSSH2_CHANNEL *channel;
68

69
    channel = _libssh2_list_first(&session->channels);
70

71
    while(channel) {
72
        if(channel->local.id > id) {
73
            id = channel->local.id;
74
        }
75
        channel = _libssh2_list_next(&channel->node);
76
    }
77

78
    /* This is a shortcut to avoid waiting for close packets on channels we've
79
     * forgotten about, This *could* be a problem if we request and close 4
80
     * billion or so channels in too rapid succession for the remote end to
81
     * respond, but the worst case scenario is that some data meant for
82
     * another channel Gets picked up by the new one.... Pretty unlikely all
83
     * told...
84
     */
85
    session->next_channel = id + 1;
86
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
87
                   "Allocated new channel ID#%u", id));
88
    return id;
89
}
90

91
/*
92
 * _libssh2_channel_locate
93
 *
94
 * Locate a channel pointer by number
95
 */
96
LIBSSH2_CHANNEL *
97
_libssh2_channel_locate(LIBSSH2_SESSION *session, uint32_t channel_id)
98
{
99
    LIBSSH2_CHANNEL *channel;
100
    LIBSSH2_LISTENER *l;
101

102
    for(channel = _libssh2_list_first(&session->channels);
103
        channel;
104
        channel = _libssh2_list_next(&channel->node)) {
105
        if(channel->local.id == channel_id)
106
            return channel;
107
    }
108

109
    /* We didn't find the channel in the session, let's then check its
110
       listeners since each listener may have its own set of pending channels
111
    */
112
    for(l = _libssh2_list_first(&session->listeners); l;
113
        l = _libssh2_list_next(&l->node)) {
114
        for(channel = _libssh2_list_first(&l->queue);
115
            channel;
116
            channel = _libssh2_list_next(&channel->node)) {
117
            if(channel->local.id == channel_id)
118
                return channel;
119
        }
120
    }
121

122
    return NULL;
123
}
124

125
/*
126
 * _libssh2_channel_open
127
 *
128
 * Establish a generic session channel
129
 */
130
LIBSSH2_CHANNEL *
131
_libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type,
132
                      uint32_t channel_type_len,
133
                      uint32_t window_size,
134
                      uint32_t packet_size,
135
                      const unsigned char *message,
136
                      size_t message_len)
137
{
138
    static const unsigned char reply_codes[3] = {
139
        SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
140
        SSH_MSG_CHANNEL_OPEN_FAILURE,
141
        0
142
    };
143
    unsigned char *s;
144
    int rc;
145

146
    if(session->open_state == libssh2_NB_state_idle) {
147
        session->open_channel = NULL;
148
        session->open_packet = NULL;
149
        session->open_data = NULL;
150
        /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
151
         * window_size(4) + packet_size(4) */
152
        session->open_packet_len = channel_type_len + 17;
153
        session->open_local_channel = _libssh2_channel_nextid(session);
154

155
        /* Zero the whole thing out */
156
        memset(&session->open_packet_requirev_state, 0,
157
               sizeof(session->open_packet_requirev_state));
158

159
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
160
                       "Opening Channel - win %d pack %d", window_size,
161
                       packet_size));
162
        session->open_channel =
163
            LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
164
        if(!session->open_channel) {
165
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
166
                           "Unable to allocate space for channel data");
167
            return NULL;
168
        }
169
        session->open_channel->channel_type_len = channel_type_len;
170
        session->open_channel->channel_type =
171
            LIBSSH2_ALLOC(session, channel_type_len);
172
        if(!session->open_channel->channel_type) {
173
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
174
                           "Failed allocating memory for channel type name");
175
            LIBSSH2_FREE(session, session->open_channel);
176
            session->open_channel = NULL;
177
            return NULL;
178
        }
179
        memcpy(session->open_channel->channel_type, channel_type,
180
               channel_type_len);
181

182
        /* REMEMBER: local as in locally sourced */
183
        session->open_channel->local.id = session->open_local_channel;
184
        session->open_channel->remote.window_size = window_size;
185
        session->open_channel->remote.window_size_initial = window_size;
186
        session->open_channel->remote.packet_size = packet_size;
187
        session->open_channel->session = session;
188

189
        _libssh2_list_add(&session->channels,
190
                          &session->open_channel->node);
191

192
        s = session->open_packet =
193
            LIBSSH2_ALLOC(session, session->open_packet_len);
194
        if(!session->open_packet) {
195
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
196
                           "Unable to allocate temporary space for packet");
197
            goto channel_error;
198
        }
199
        *(s++) = SSH_MSG_CHANNEL_OPEN;
200
        _libssh2_store_str(&s, channel_type, channel_type_len);
201
        _libssh2_store_u32(&s, session->open_local_channel);
202
        _libssh2_store_u32(&s, window_size);
203
        _libssh2_store_u32(&s, packet_size);
204

205
        /* Do not copy the message */
206

207
        session->open_state = libssh2_NB_state_created;
208
    }
209

210
    if(session->open_state == libssh2_NB_state_created) {
211
        rc = _libssh2_transport_send(session,
212
                                     session->open_packet,
213
                                     session->open_packet_len,
214
                                     message, message_len);
215
        if(rc == LIBSSH2_ERROR_EAGAIN) {
216
            _libssh2_error(session, rc,
217
                           "Would block sending channel-open request");
218
            return NULL;
219
        }
220
        else if(rc) {
221
            _libssh2_error(session, rc,
222
                           "Unable to send channel-open request");
223
            goto channel_error;
224
        }
225

226
        session->open_state = libssh2_NB_state_sent;
227
    }
228

229
    if(session->open_state == libssh2_NB_state_sent) {
230
        rc = _libssh2_packet_requirev(session, reply_codes,
231
                                      &session->open_data,
232
                                      &session->open_data_len, 1,
233
                                      session->open_packet + 5 +
234
                                      channel_type_len, 4,
235
                                      &session->open_packet_requirev_state);
236
        if(rc == LIBSSH2_ERROR_EAGAIN) {
237
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
238
            return NULL;
239
        }
240
        else if(rc) {
241
            _libssh2_error(session, rc, "Unexpected error");
242
            goto channel_error;
243
        }
244

245
        if(session->open_data_len < 1) {
246
            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
247
                           "Unexpected packet size");
248
            goto channel_error;
249
        }
250

251
        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
252

253
            if(session->open_data_len < 17) {
254
                _libssh2_error(session, LIBSSH2_ERROR_PROTO,
255
                               "Unexpected packet size");
256
                goto channel_error;
257
            }
258

259
            session->open_channel->remote.id =
260
                _libssh2_ntohu32(session->open_data + 5);
261
            session->open_channel->local.window_size =
262
                _libssh2_ntohu32(session->open_data + 9);
263
            session->open_channel->local.window_size_initial =
264
                _libssh2_ntohu32(session->open_data + 9);
265
            session->open_channel->local.packet_size =
266
                _libssh2_ntohu32(session->open_data + 13);
267
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
268
                           "Connection Established - ID: %u/%u win: %u/%u"
269
                           " pack: %u/%u",
270
                           session->open_channel->local.id,
271
                           session->open_channel->remote.id,
272
                           session->open_channel->local.window_size,
273
                           session->open_channel->remote.window_size,
274
                           session->open_channel->local.packet_size,
275
                           session->open_channel->remote.packet_size));
276
            LIBSSH2_FREE(session, session->open_packet);
277
            session->open_packet = NULL;
278
            LIBSSH2_FREE(session, session->open_data);
279
            session->open_data = NULL;
280

281
            session->open_state = libssh2_NB_state_idle;
282
            return session->open_channel;
283
        }
284

285
        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
286
            unsigned int reason_code =
287
                _libssh2_ntohu32(session->open_data + 5);
288
            switch(reason_code) {
289
            case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED:
290
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
291
                               "Channel open failure "
292
                               "(administratively prohibited)");
293
                break;
294
            case SSH_OPEN_CONNECT_FAILED:
295
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
296
                               "Channel open failure (connect failed)");
297
                break;
298
            case SSH_OPEN_UNKNOWN_CHANNELTYPE:
299
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
300
                               "Channel open failure (unknown channel type)");
301
                break;
302
            case SSH_OPEN_RESOURCE_SHORTAGE:
303
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
304
                               "Channel open failure (resource shortage)");
305
                break;
306
            default:
307
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
308
                               "Channel open failure");
309
            }
310
        }
311
    }
312

313
channel_error:
314

315
    if(session->open_data) {
316
        LIBSSH2_FREE(session, session->open_data);
317
        session->open_data = NULL;
318
    }
319
    if(session->open_packet) {
320
        LIBSSH2_FREE(session, session->open_packet);
321
        session->open_packet = NULL;
322
    }
323
    if(session->open_channel) {
324
        unsigned char channel_id[4];
325
        LIBSSH2_FREE(session, session->open_channel->channel_type);
326

327
        _libssh2_list_remove(&session->open_channel->node);
328

329
        /* Clear out packets meant for this channel */
330
        _libssh2_htonu32(channel_id, session->open_channel->local.id);
331
        while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
332
                                   &session->open_data,
333
                                   &session->open_data_len, 1,
334
                                   channel_id, 4) >= 0)
335
              ||
336
              (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA,
337
                                   &session->open_data,
338
                                   &session->open_data_len, 1,
339
                                   channel_id, 4) >= 0)) {
340
            LIBSSH2_FREE(session, session->open_data);
341
            session->open_data = NULL;
342
        }
343

344
        LIBSSH2_FREE(session, session->open_channel);
345
        session->open_channel = NULL;
346
    }
347

348
    session->open_state = libssh2_NB_state_idle;
349
    return NULL;
350
}
351

352
/*
353
 * libssh2_channel_open_ex
354
 *
355
 * Establish a generic session channel
356
 */
357
LIBSSH2_API LIBSSH2_CHANNEL *
358
libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type,
359
                        unsigned int type_len,
360
                        unsigned int window_size, unsigned int packet_size,
361
                        const char *msg, unsigned int msg_len)
362
{
363
    LIBSSH2_CHANNEL *ptr;
364

365
    if(!session)
366
        return NULL;
367

368
    BLOCK_ADJUST_ERRNO(ptr, session,
369
                       _libssh2_channel_open(session, type, type_len,
370
                                             window_size, packet_size,
371
                                             (unsigned char *)msg,
372
                                             msg_len));
373
    return ptr;
374
}
375

376
/*
377
 * libssh2_channel_direct_tcpip_ex
378
 *
379
 * Tunnel TCP/IP connect through the SSH session to direct host/port
380
 */
381
static LIBSSH2_CHANNEL *
382
channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host,
383
                     int port, const char *shost, int sport)
384
{
385
    LIBSSH2_CHANNEL *channel;
386
    unsigned char *s;
387

388
    if(session->direct_state == libssh2_NB_state_idle) {
389
        session->direct_host_len = strlen(host);
390
        session->direct_shost_len = strlen(shost);
391
        /* host_len(4) + port(4) + shost_len(4) + sport(4) */
392
        session->direct_message_len =
393
            session->direct_host_len + session->direct_shost_len + 16;
394

395
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
396
                       "Requesting direct-tcpip session from %s:%d to %s:%d",
397
                       shost, sport, host, port));
398

399
        s = session->direct_message =
400
            LIBSSH2_ALLOC(session, session->direct_message_len);
401
        if(!session->direct_message) {
402
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
403
                           "Unable to allocate memory for "
404
                           "direct-tcpip connection");
405
            return NULL;
406
        }
407
        _libssh2_store_str(&s, host, session->direct_host_len);
408
        _libssh2_store_u32(&s, port);
409
        _libssh2_store_str(&s, shost, session->direct_shost_len);
410
        _libssh2_store_u32(&s, sport);
411
    }
412

413
    channel =
414
        _libssh2_channel_open(session, "direct-tcpip",
415
                              sizeof("direct-tcpip") - 1,
416
                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
417
                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
418
                              session->direct_message,
419
                              session->direct_message_len);
420

421
    if(!channel &&
422
        libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
423
        /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
424
           to created to avoid re-creating the package on next invoke */
425
        session->direct_state = libssh2_NB_state_created;
426
        return NULL;
427
    }
428
    /* by default we set (keep?) idle state... */
429
    session->direct_state = libssh2_NB_state_idle;
430

431
    LIBSSH2_FREE(session, session->direct_message);
432
    session->direct_message = NULL;
433

434
    return channel;
435
}
436

437
/*
438
 * libssh2_channel_direct_tcpip_ex
439
 *
440
 * Tunnel TCP/IP connect through the SSH session to direct host/port
441
 */
442
LIBSSH2_API LIBSSH2_CHANNEL *
443
libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *session, const char *host,
444
                                int port, const char *shost, int sport)
445
{
446
    LIBSSH2_CHANNEL *ptr;
447

448
    if(!session)
449
        return NULL;
450

451
    BLOCK_ADJUST_ERRNO(ptr, session,
452
                       channel_direct_tcpip(session, host, port,
453
                                            shost, sport));
454
    return ptr;
455
}
456

457
/*
458
 * libssh2_channel_direct_streamlocal_ex
459
 *
460
 * Tunnel TCP/IP connect through the SSH session to direct UNIX socket
461
 */
462
static LIBSSH2_CHANNEL *
463
channel_direct_streamlocal(LIBSSH2_SESSION * session, const char *socket_path,
464
                           const char *shost, int sport)
465
{
466
    LIBSSH2_CHANNEL *channel;
467
    unsigned char *s;
468

469
    if(session->direct_state == libssh2_NB_state_idle) {
470
        session->direct_host_len = strlen(socket_path);
471
        session->direct_shost_len = strlen(shost);
472
        session->direct_message_len =
473
            session->direct_host_len + session->direct_shost_len + 12;
474

475
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
476
                       "Requesting direct-streamlocal session to %s",
477
                       socket_path));
478

479
        s = session->direct_message =
480
            LIBSSH2_ALLOC(session, session->direct_message_len);
481
        if(!session->direct_message) {
482
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
483
                "Unable to allocate memory for direct-streamlocal connection");
484
            return NULL;
485
        }
486
        _libssh2_store_str(&s, socket_path, session->direct_host_len);
487
        _libssh2_store_str(&s, shost, session->direct_shost_len);
488
        _libssh2_store_u32(&s, sport);
489
    }
490

491
    channel =
492
        _libssh2_channel_open(session, "direct-streamlocal@openssh.com",
493
                              sizeof("direct-streamlocal@openssh.com") - 1,
494
                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
495
                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
496
                              session->direct_message,
497
                              session->direct_message_len);
498

499
    if(!channel &&
500
        libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN) {
501
        /* The error code is still set to LIBSSH2_ERROR_EAGAIN, set our state
502
           to created to avoid re-creating the package on next invoke */
503
        session->direct_state = libssh2_NB_state_created;
504
        return NULL;
505
    }
506
    /* by default we set (keep?) idle state... */
507
    session->direct_state = libssh2_NB_state_idle;
508

509
    LIBSSH2_FREE(session, session->direct_message);
510
    session->direct_message = NULL;
511

512
    return channel;
513
}
514

515
/*
516
 * libssh2_channel_direct_streamlocal_ex
517
 *
518
 * Tunnel TCP/IP connect through the SSH session to direct UNIX socket
519
 */
520
LIBSSH2_API LIBSSH2_CHANNEL *
521
libssh2_channel_direct_streamlocal_ex(LIBSSH2_SESSION * session,
522
                                      const char *socket_path,
523
                                      const char *shost, int sport)
524
{
525
    LIBSSH2_CHANNEL *ptr;
526

527
    if(!session)
528
        return NULL;
529

530
    BLOCK_ADJUST_ERRNO(ptr, session,
531
                       channel_direct_streamlocal(session,
532
                       socket_path, shost, sport));
533
    return ptr;
534
}
535

536
/*
537
 * channel_forward_listen
538
 *
539
 * Bind a port on the remote host and listen for connections
540
 */
541
static LIBSSH2_LISTENER *
542
channel_forward_listen(LIBSSH2_SESSION * session, const char *host,
543
                       int port, int *bound_port, int queue_maxsize)
544
{
545
    unsigned char *s;
546
    static const unsigned char reply_codes[3] =
547
        { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
548
    int rc;
549

550
    if(!host)
551
        host = "0.0.0.0";
552

553
    if(session->fwdLstn_state == libssh2_NB_state_idle) {
554
        session->fwdLstn_host_len = (uint32_t)strlen(host);
555
        /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4)
556
           + port(4) */
557
        session->fwdLstn_packet_len =
558
            session->fwdLstn_host_len +
559
            (uint32_t)(sizeof("tcpip-forward") - 1) + 14;
560

561
        /* Zero the whole thing out */
562
        memset(&session->fwdLstn_packet_requirev_state, 0,
563
               sizeof(session->fwdLstn_packet_requirev_state));
564

565
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
566
                       "Requesting tcpip-forward session for %s:%d", host,
567
                       port));
568

569
        s = session->fwdLstn_packet =
570
            LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
571
        if(!session->fwdLstn_packet) {
572
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
573
                           "Unable to allocate memory for setenv packet");
574
            return NULL;
575
        }
576

577
        *(s++) = SSH_MSG_GLOBAL_REQUEST;
578
        _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1);
579
        *(s++) = 0x01;          /* want_reply */
580

581
        _libssh2_store_str(&s, host, session->fwdLstn_host_len);
582
        _libssh2_store_u32(&s, port);
583

584
        session->fwdLstn_state = libssh2_NB_state_created;
585
    }
586

587
    if(session->fwdLstn_state == libssh2_NB_state_created) {
588
        rc = _libssh2_transport_send(session,
589
                                     session->fwdLstn_packet,
590
                                     session->fwdLstn_packet_len,
591
                                     NULL, 0);
592
        if(rc == LIBSSH2_ERROR_EAGAIN) {
593
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
594
                           "Would block sending global-request packet for "
595
                           "forward listen request");
596
            return NULL;
597
        }
598
        else if(rc) {
599
            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
600
                           "Unable to send global-request packet for forward "
601
                           "listen request");
602
            LIBSSH2_FREE(session, session->fwdLstn_packet);
603
            session->fwdLstn_packet = NULL;
604
            session->fwdLstn_state = libssh2_NB_state_idle;
605
            return NULL;
606
        }
607
        LIBSSH2_FREE(session, session->fwdLstn_packet);
608
        session->fwdLstn_packet = NULL;
609

610
        session->fwdLstn_state = libssh2_NB_state_sent;
611
    }
612

613
    if(session->fwdLstn_state == libssh2_NB_state_sent) {
614
        unsigned char *data;
615
        size_t data_len;
616
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
617
                                      0, NULL, 0,
618
                                      &session->fwdLstn_packet_requirev_state);
619
        if(rc == LIBSSH2_ERROR_EAGAIN) {
620
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
621
            return NULL;
622
        }
623
        else if(rc || (data_len < 1)) {
624
            _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
625
            session->fwdLstn_state = libssh2_NB_state_idle;
626
            return NULL;
627
        }
628

629
        if(data[0] == SSH_MSG_REQUEST_SUCCESS) {
630
            LIBSSH2_LISTENER *listener;
631

632
            listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER));
633
            if(!listener)
634
                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
635
                               "Unable to allocate memory for listener queue");
636
            else {
637
                listener->host =
638
                    LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1);
639
                if(!listener->host) {
640
                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
641
                                   "Unable to allocate memory "
642
                                   "for listener queue");
643
                    LIBSSH2_FREE(session, listener);
644
                    listener = NULL;
645
                }
646
                else {
647
                    listener->session = session;
648
                    memcpy(listener->host, host, session->fwdLstn_host_len);
649
                    listener->host[session->fwdLstn_host_len] = 0;
650
                    if(data_len >= 5 && !port) {
651
                        listener->port = _libssh2_ntohu32(data + 1);
652
                        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
653
                                       "Dynamic tcpip-forward port "
654
                                       "allocated: %d",
655
                                       listener->port));
656
                    }
657
                    else
658
                        listener->port = port;
659

660
                    listener->queue_size = 0;
661
                    listener->queue_maxsize = queue_maxsize;
662

663
                    /* append this to the parent's list of listeners */
664
                    _libssh2_list_add(&session->listeners, &listener->node);
665

666
                    if(bound_port) {
667
                        *bound_port = listener->port;
668
                    }
669
                }
670
            }
671

672
            LIBSSH2_FREE(session, data);
673
            session->fwdLstn_state = libssh2_NB_state_idle;
674
            return listener;
675
        }
676
        else if(data[0] == SSH_MSG_REQUEST_FAILURE) {
677
            LIBSSH2_FREE(session, data);
678
            _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
679
                           "Unable to complete request for forward-listen");
680
            session->fwdLstn_state = libssh2_NB_state_idle;
681
            return NULL;
682
        }
683
    }
684

685
    session->fwdLstn_state = libssh2_NB_state_idle;
686

687
    return NULL;
688
}
689

690
/*
691
 * libssh2_channel_forward_listen_ex
692
 *
693
 * Bind a port on the remote host and listen for connections
694
 */
695
LIBSSH2_API LIBSSH2_LISTENER *
696
libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, const char *host,
697
                                  int port, int *bound_port, int queue_maxsize)
698
{
699
    LIBSSH2_LISTENER *ptr;
700

701
    if(!session)
702
        return NULL;
703

704
    BLOCK_ADJUST_ERRNO(ptr, session,
705
                       channel_forward_listen(session, host, port, bound_port,
706
                                              queue_maxsize));
707
    return ptr;
708
}
709

710
/*
711
 * _libssh2_channel_forward_cancel
712
 *
713
 * Stop listening on a remote port and free the listener
714
 * Toss out any pending (un-accept()ed) connections
715
 *
716
 * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
717
 */
718
int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
719
{
720
    LIBSSH2_SESSION *session = listener->session;
721
    LIBSSH2_CHANNEL *queued;
722
    unsigned char *packet, *s;
723
    size_t host_len = strlen(listener->host);
724
    /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) +
725
       port(4) */
726
    size_t packet_len =
727
        host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
728
    int rc;
729
    int retcode = 0;
730

731
    if(listener->chanFwdCncl_state == libssh2_NB_state_idle) {
732
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
733
                       "Cancelling tcpip-forward session for %s:%d",
734
                       listener->host, listener->port));
735

736
        s = packet = LIBSSH2_ALLOC(session, packet_len);
737
        if(!packet) {
738
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
739
                           "Unable to allocate memory for setenv packet");
740
            return LIBSSH2_ERROR_ALLOC;
741
        }
742

743
        *(s++) = SSH_MSG_GLOBAL_REQUEST;
744
        _libssh2_store_str(&s, "cancel-tcpip-forward",
745
                           sizeof("cancel-tcpip-forward") - 1);
746
        *(s++) = 0x00;          /* want_reply */
747

748
        _libssh2_store_str(&s, listener->host, host_len);
749
        _libssh2_store_u32(&s, listener->port);
750

751
        listener->chanFwdCncl_state = libssh2_NB_state_created;
752
    }
753
    else {
754
        packet = listener->chanFwdCncl_data;
755
    }
756

757
    if(listener->chanFwdCncl_state == libssh2_NB_state_created) {
758
        rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
759
        if(rc == LIBSSH2_ERROR_EAGAIN) {
760
            _libssh2_error(session, rc,
761
                           "Would block sending forward request");
762
            listener->chanFwdCncl_data = packet;
763
            return rc;
764
        }
765
        else if(rc) {
766
            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
767
                           "Unable to send global-request packet for forward "
768
                           "listen request");
769
            /* set the state to something we don't check for, for the
770
               unfortunate situation where we get an EAGAIN further down
771
               when trying to bail out due to errors! */
772
            listener->chanFwdCncl_state = libssh2_NB_state_sent;
773
            retcode = LIBSSH2_ERROR_SOCKET_SEND;
774
        }
775
        LIBSSH2_FREE(session, packet);
776

777
        listener->chanFwdCncl_state = libssh2_NB_state_sent;
778
    }
779

780
    queued = _libssh2_list_first(&listener->queue);
781
    while(queued) {
782
        LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
783

784
        rc = _libssh2_channel_free(queued);
785
        if(rc == LIBSSH2_ERROR_EAGAIN) {
786
            return rc;
787
        }
788
        queued = next;
789
    }
790
    LIBSSH2_FREE(session, listener->host);
791

792
    /* remove this entry from the parent's list of listeners */
793
    _libssh2_list_remove(&listener->node);
794

795
    LIBSSH2_FREE(session, listener);
796

797
    return retcode;
798
}
799

800
/*
801
 * libssh2_channel_forward_cancel
802
 *
803
 * Stop listening on a remote port and free the listener
804
 * Toss out any pending (un-accept()ed) connections
805
 *
806
 * Return 0 on success, LIBSSH2_ERROR_EAGAIN if would block, -1 on error
807
 */
808
LIBSSH2_API int
809
libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener)
810
{
811
    int rc;
812

813
    if(!listener)
814
        return LIBSSH2_ERROR_BAD_USE;
815

816
    BLOCK_ADJUST(rc, listener->session,
817
                 _libssh2_channel_forward_cancel(listener));
818
    return rc;
819
}
820

821
/*
822
 * channel_forward_accept
823
 *
824
 * Accept a connection
825
 */
826
static LIBSSH2_CHANNEL *
827
channel_forward_accept(LIBSSH2_LISTENER *listener)
828
{
829
    int rc;
830

831
    do {
832
        rc = _libssh2_transport_read(listener->session);
833
    } while(rc > 0);
834

835
    if(_libssh2_list_first(&listener->queue)) {
836
        LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
837

838
        /* detach channel from listener's queue */
839
        _libssh2_list_remove(&channel->node);
840

841
        listener->queue_size--;
842

843
        /* add channel to session's channel list */
844
        _libssh2_list_add(&channel->session->channels, &channel->node);
845

846
        return channel;
847
    }
848

849
    if(rc == LIBSSH2_ERROR_EAGAIN) {
850
        _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
851
                       "Would block waiting for packet");
852
    }
853
    else
854
        _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
855
                       "Channel not found");
856
    return NULL;
857
}
858

859
/*
860
 * libssh2_channel_forward_accept
861
 *
862
 * Accept a connection
863
 */
864
LIBSSH2_API LIBSSH2_CHANNEL *
865
libssh2_channel_forward_accept(LIBSSH2_LISTENER *listener)
866
{
867
    LIBSSH2_CHANNEL *ptr;
868

869
    if(!listener)
870
        return NULL;
871

872
    BLOCK_ADJUST_ERRNO(ptr, listener->session,
873
                       channel_forward_accept(listener));
874
    return ptr;
875

876
}
877

878
/*
879
 * channel_setenv
880
 *
881
 * Set an environment variable prior to requesting a shell/program/subsystem
882
 */
883
static int channel_setenv(LIBSSH2_CHANNEL *channel,
884
                          const char *varname, unsigned int varname_len,
885
                          const char *value, unsigned int value_len)
886
{
887
    LIBSSH2_SESSION *session = channel->session;
888
    unsigned char *s, *data;
889
    static const unsigned char reply_codes[3] =
890
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
891
    size_t data_len;
892
    int rc;
893

894
    if(channel->setenv_state == libssh2_NB_state_idle) {
895
        /* 21 = packet_type(1) + channel_id(4) + request_len(4) +
896
         * request(3)"env" + want_reply(1) + varname_len(4) + value_len(4) */
897
        channel->setenv_packet_len = varname_len + value_len + 21;
898

899
        /* Zero the whole thing out */
900
        memset(&channel->setenv_packet_requirev_state, 0,
901
               sizeof(channel->setenv_packet_requirev_state));
902

903
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
904
                       "Setting remote environment variable: %s=%s on "
905
                       "channel %u/%u",
906
                       varname, value, channel->local.id, channel->remote.id));
907

908
        s = channel->setenv_packet =
909
            LIBSSH2_ALLOC(session, channel->setenv_packet_len);
910
        if(!channel->setenv_packet) {
911
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
912
                                  "Unable to allocate memory "
913
                                  "for setenv packet");
914
        }
915

916
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
917
        _libssh2_store_u32(&s, channel->remote.id);
918
        _libssh2_store_str(&s, "env", sizeof("env") - 1);
919
        *(s++) = 0x01;
920
        _libssh2_store_str(&s, varname, varname_len);
921
        _libssh2_store_str(&s, value, value_len);
922

923
        channel->setenv_state = libssh2_NB_state_created;
924
    }
925

926
    if(channel->setenv_state == libssh2_NB_state_created) {
927
        rc = _libssh2_transport_send(session,
928
                                     channel->setenv_packet,
929
                                     channel->setenv_packet_len,
930
                                     NULL, 0);
931
        if(rc == LIBSSH2_ERROR_EAGAIN) {
932
            _libssh2_error(session, rc,
933
                           "Would block sending setenv request");
934
            return rc;
935
        }
936
        else if(rc) {
937
            LIBSSH2_FREE(session, channel->setenv_packet);
938
            channel->setenv_packet = NULL;
939
            channel->setenv_state = libssh2_NB_state_idle;
940
            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
941
                                  "Unable to send channel-request packet for "
942
                                  "setenv request");
943
        }
944
        LIBSSH2_FREE(session, channel->setenv_packet);
945
        channel->setenv_packet = NULL;
946

947
        _libssh2_htonu32(channel->setenv_local_channel, channel->local.id);
948

949
        channel->setenv_state = libssh2_NB_state_sent;
950
    }
951

952
    if(channel->setenv_state == libssh2_NB_state_sent) {
953
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
954
                                      1, channel->setenv_local_channel, 4,
955
                                      &channel->
956
                                      setenv_packet_requirev_state);
957
        if(rc == LIBSSH2_ERROR_EAGAIN) {
958
            return rc;
959
        }
960
        if(rc) {
961
            channel->setenv_state = libssh2_NB_state_idle;
962
            return _libssh2_error(session, rc,
963
                                  "Failed getting response for "
964
                                  "channel-setenv");
965
        }
966
        else if(data_len < 1) {
967
            channel->setenv_state = libssh2_NB_state_idle;
968
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
969
                                  "Unexpected packet size");
970
        }
971

972
        if(data[0] == SSH_MSG_CHANNEL_SUCCESS) {
973
            LIBSSH2_FREE(session, data);
974
            channel->setenv_state = libssh2_NB_state_idle;
975
            return 0;
976
        }
977

978
        LIBSSH2_FREE(session, data);
979
    }
980

981
    channel->setenv_state = libssh2_NB_state_idle;
982
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
983
                          "Unable to complete request for channel-setenv");
984
}
985

986
/*
987
 * libssh2_channel_setenv_ex
988
 *
989
 * Set an environment variable prior to requesting a shell/program/subsystem
990
 */
991
LIBSSH2_API int
992
libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel,
993
                          const char *varname, unsigned int varname_len,
994
                          const char *value, unsigned int value_len)
995
{
996
    int rc;
997

998
    if(!channel)
999
        return LIBSSH2_ERROR_BAD_USE;
1000

1001
    BLOCK_ADJUST(rc, channel->session,
1002
                 channel_setenv(channel, varname, varname_len,
1003
                                value, value_len));
1004
    return rc;
1005
}
1006

1007
/*
1008
 * channel_request_pty
1009
 * Duh... Request a PTY
1010
 */
1011
static int channel_request_pty(LIBSSH2_CHANNEL *channel,
1012
                               const char *term, unsigned int term_len,
1013
                               const char *modes, unsigned int modes_len,
1014
                               int width, int height,
1015
                               int width_px, int height_px)
1016
{
1017
    LIBSSH2_SESSION *session = channel->session;
1018
    unsigned char *s;
1019
    static const unsigned char reply_codes[3] =
1020
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1021
    int rc;
1022

1023
    if(channel->reqPTY_state == libssh2_NB_state_idle) {
1024
        /* 41 = packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) +
1025
         * want_reply(1) + term_len(4) + width(4) + height(4) + width_px(4) +
1026
         * height_px(4) + modes_len(4) */
1027
        if(term_len + modes_len > 256) {
1028
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1029
                                  "term + mode lengths too large");
1030
        }
1031

1032
        channel->reqPTY_packet_len = term_len + modes_len + 41;
1033

1034
        /* Zero the whole thing out */
1035
        memset(&channel->reqPTY_packet_requirev_state, 0,
1036
               sizeof(channel->reqPTY_packet_requirev_state));
1037

1038
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1039
                       "Allocating tty on channel %u/%u", channel->local.id,
1040
                       channel->remote.id));
1041

1042
        s = channel->reqPTY_packet;
1043

1044
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1045
        _libssh2_store_u32(&s, channel->remote.id);
1046
        _libssh2_store_str(&s, (char *)"pty-req", sizeof("pty-req") - 1);
1047

1048
        *(s++) = 0x01;
1049

1050
        _libssh2_store_str(&s, term, term_len);
1051
        _libssh2_store_u32(&s, width);
1052
        _libssh2_store_u32(&s, height);
1053
        _libssh2_store_u32(&s, width_px);
1054
        _libssh2_store_u32(&s, height_px);
1055
        _libssh2_store_str(&s, modes, modes_len);
1056

1057
        channel->reqPTY_state = libssh2_NB_state_created;
1058
    }
1059

1060
    if(channel->reqPTY_state == libssh2_NB_state_created) {
1061
        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1062
                                     channel->reqPTY_packet_len,
1063
                                     NULL, 0);
1064
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1065
            _libssh2_error(session, rc,
1066
                           "Would block sending pty request");
1067
            return rc;
1068
        }
1069
        else if(rc) {
1070
            channel->reqPTY_state = libssh2_NB_state_idle;
1071
            return _libssh2_error(session, rc,
1072
                                  "Unable to send pty-request packet");
1073
        }
1074
        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1075

1076
        channel->reqPTY_state = libssh2_NB_state_sent;
1077
    }
1078

1079
    if(channel->reqPTY_state == libssh2_NB_state_sent) {
1080
        unsigned char *data;
1081
        size_t data_len;
1082
        unsigned char code;
1083
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1084
                                      1, channel->reqPTY_local_channel, 4,
1085
                                      &channel->reqPTY_packet_requirev_state);
1086
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1087
            return rc;
1088
        }
1089
        else if(rc || data_len < 1) {
1090
            channel->reqPTY_state = libssh2_NB_state_idle;
1091
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1092
                                  "Failed to require the PTY package");
1093
        }
1094

1095
        code = data[0];
1096

1097
        LIBSSH2_FREE(session, data);
1098
        channel->reqPTY_state = libssh2_NB_state_idle;
1099

1100
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1101
            return 0;
1102
    }
1103

1104
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1105
                          "Unable to complete request for "
1106
                          "channel request-pty");
1107
}
1108

1109
/**
1110
 * channel_request_auth_agent
1111
 * The actual re-entrant method which requests an auth agent.
1112
 * */
1113
static int channel_request_auth_agent(LIBSSH2_CHANNEL *channel,
1114
                                      const char *request_str,
1115
                                      int request_str_len)
1116
{
1117
    LIBSSH2_SESSION *session = channel->session;
1118
    unsigned char *s;
1119
    static const unsigned char reply_codes[3] =
1120
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1121
    int rc;
1122

1123
    if(channel->req_auth_agent_state == libssh2_NB_state_idle) {
1124
        /* Only valid options are "auth-agent-req" and
1125
         * "auth-agent-req_at_openssh.com" so we make sure it is not
1126
         * actually longer than the longest possible. */
1127
        if(request_str_len > 26) {
1128
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1129
                                  "request_str length too large");
1130
        }
1131

1132
        /*
1133
         *  Length: 24 or 36 = packet_type(1) + channel(4) + req_len(4) +
1134
         *    request_str (variable) + want_reply (1) */
1135
        channel->req_auth_agent_packet_len = 10 + request_str_len;
1136

1137
        /* Zero out the requireev state to reset */
1138
        memset(&channel->req_auth_agent_requirev_state, 0,
1139
               sizeof(channel->req_auth_agent_requirev_state));
1140

1141
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1142
                       "Requesting auth agent on channel %u/%u",
1143
                       channel->local.id, channel->remote.id));
1144

1145
        /*
1146
         *  byte      SSH_MSG_CHANNEL_REQUEST
1147
         *  uint32    recipient channel
1148
         *  string    "auth-agent-req"
1149
         *  boolean   want reply
1150
         * */
1151
        s = channel->req_auth_agent_packet;
1152
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1153
        _libssh2_store_u32(&s, channel->remote.id);
1154
        _libssh2_store_str(&s, (char *)request_str, request_str_len);
1155
        *(s++) = 0x01;
1156

1157
        channel->req_auth_agent_state = libssh2_NB_state_created;
1158
    }
1159

1160
    if(channel->req_auth_agent_state == libssh2_NB_state_created) {
1161
        /* Send the packet, we can use sizeof() on the packet because it
1162
         * is always completely filled; there are no variable length fields. */
1163
        rc = _libssh2_transport_send(session, channel->req_auth_agent_packet,
1164
                                     channel->req_auth_agent_packet_len,
1165
                                     NULL, 0);
1166

1167
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1168
            _libssh2_error(session, rc,
1169
                           "Would block sending auth-agent request");
1170
            return rc;
1171
        }
1172
        else if(rc) {
1173
            channel->req_auth_agent_state = libssh2_NB_state_idle;
1174
            return _libssh2_error(session, rc,
1175
                                  "Unable to send auth-agent request");
1176
        }
1177
        _libssh2_htonu32(channel->req_auth_agent_local_channel,
1178
                         channel->local.id);
1179
        channel->req_auth_agent_state = libssh2_NB_state_sent;
1180
    }
1181

1182
    if(channel->req_auth_agent_state == libssh2_NB_state_sent) {
1183
        unsigned char *data;
1184
        size_t data_len;
1185
        unsigned char code;
1186

1187
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1188
                                      1, channel->req_auth_agent_local_channel,
1189
                                      4,
1190
                                      &channel->req_auth_agent_requirev_state);
1191
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1192
            return rc;
1193
        }
1194
        else if(rc) {
1195
            channel->req_auth_agent_state = libssh2_NB_state_idle;
1196
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1197
                                  "Failed to request auth-agent");
1198
        }
1199

1200
        code = data[0];
1201

1202
        LIBSSH2_FREE(session, data);
1203
        channel->req_auth_agent_state = libssh2_NB_state_idle;
1204

1205
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1206
            return 0;
1207
    }
1208

1209
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1210
                          "Unable to complete request for auth-agent");
1211
}
1212

1213
/*
1214
 * libssh2_channel_request_auth_agent
1215
 *
1216
 * Requests that agent forwarding be enabled for the session. The
1217
 * request must be sent over a specific channel, which starts the agent
1218
 * listener on the remote side. Once the channel is closed, the agent
1219
 * listener continues to exist.
1220
 */
1221
LIBSSH2_API int
1222
libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
1223
{
1224
    int rc;
1225

1226
    if(!channel)
1227
        return LIBSSH2_ERROR_BAD_USE;
1228

1229
    rc = LIBSSH2_ERROR_CHANNEL_UNKNOWN;
1230

1231
    /* The current RFC draft for agent forwarding says you're supposed to
1232
     * send "auth-agent-req," but most SSH servers out there right now
1233
     * actually expect "auth-agent-req@openssh.com", so we try that
1234
     * first. */
1235
    if(channel->req_auth_agent_try_state == libssh2_NB_state_idle) {
1236
        BLOCK_ADJUST(rc, channel->session,
1237
                     channel_request_auth_agent(channel,
1238
                                                "auth-agent-req@openssh.com",
1239
                                                26));
1240

1241
        /* If we failed (but not with EAGAIN), then we move onto
1242
         * the next step to try another request type. */
1243
        if(rc != LIBSSH2_ERROR_NONE &&
1244
           rc != LIBSSH2_ERROR_EAGAIN)
1245
            channel->req_auth_agent_try_state = libssh2_NB_state_sent;
1246
    }
1247

1248
    if(channel->req_auth_agent_try_state == libssh2_NB_state_sent) {
1249
        BLOCK_ADJUST(rc, channel->session,
1250
                     channel_request_auth_agent(channel,
1251
                                                "auth-agent-req", 14));
1252

1253
        /* If we failed without an EAGAIN, then move on with this
1254
         * state machine. */
1255
        if(rc != LIBSSH2_ERROR_NONE &&
1256
           rc != LIBSSH2_ERROR_EAGAIN)
1257
            channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
1258
    }
1259

1260
    /* If things are good, reset the try state. */
1261
    if(rc == LIBSSH2_ERROR_NONE)
1262
        channel->req_auth_agent_try_state = libssh2_NB_state_idle;
1263

1264
    return rc;
1265
}
1266

1267
/*
1268
 * libssh2_channel_request_pty_ex
1269
 * Duh... Request a PTY
1270
 */
1271
LIBSSH2_API int
1272
libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, const char *term,
1273
                               unsigned int term_len, const char *modes,
1274
                               unsigned int modes_len, int width, int height,
1275
                               int width_px, int height_px)
1276
{
1277
    int rc;
1278

1279
    if(!channel)
1280
        return LIBSSH2_ERROR_BAD_USE;
1281

1282
    BLOCK_ADJUST(rc, channel->session,
1283
                 channel_request_pty(channel, term, term_len, modes,
1284
                                     modes_len, width, height,
1285
                                     width_px, height_px));
1286
    return rc;
1287
}
1288

1289
static int
1290
channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
1291
                         int height, int width_px, int height_px)
1292
{
1293
    LIBSSH2_SESSION *session = channel->session;
1294
    unsigned char *s;
1295
    int rc;
1296
    int retcode = LIBSSH2_ERROR_PROTO;
1297

1298
    if(channel->reqPTY_state == libssh2_NB_state_idle) {
1299
        channel->reqPTY_packet_len = 39;
1300

1301
        /* Zero the whole thing out */
1302
        memset(&channel->reqPTY_packet_requirev_state, 0,
1303
               sizeof(channel->reqPTY_packet_requirev_state));
1304

1305
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1306
                       "changing tty size on channel %u/%u",
1307
                       channel->local.id,
1308
                       channel->remote.id));
1309

1310
        s = channel->reqPTY_packet;
1311

1312
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1313
        _libssh2_store_u32(&s, channel->remote.id);
1314
        _libssh2_store_str(&s, (char *)"window-change",
1315
                           sizeof("window-change") - 1);
1316
        *(s++) = 0x00; /* Don't reply */
1317
        _libssh2_store_u32(&s, width);
1318
        _libssh2_store_u32(&s, height);
1319
        _libssh2_store_u32(&s, width_px);
1320
        _libssh2_store_u32(&s, height_px);
1321

1322
        channel->reqPTY_state = libssh2_NB_state_created;
1323
    }
1324

1325
    if(channel->reqPTY_state == libssh2_NB_state_created) {
1326
        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1327
                                     channel->reqPTY_packet_len,
1328
                                     NULL, 0);
1329
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1330
            _libssh2_error(session, rc,
1331
                           "Would block sending window-change request");
1332
            return rc;
1333
        }
1334
        else if(rc) {
1335
            channel->reqPTY_state = libssh2_NB_state_idle;
1336
            return _libssh2_error(session, rc,
1337
                                  "Unable to send window-change packet");
1338
        }
1339
        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1340
        retcode = LIBSSH2_ERROR_NONE;
1341
    }
1342

1343
    channel->reqPTY_state = libssh2_NB_state_idle;
1344
    return retcode;
1345
}
1346

1347
LIBSSH2_API int
1348
libssh2_channel_request_pty_size_ex(LIBSSH2_CHANNEL *channel, int width,
1349
                                    int height, int width_px, int height_px)
1350
{
1351
    int rc;
1352

1353
    if(!channel)
1354
        return LIBSSH2_ERROR_BAD_USE;
1355

1356
    BLOCK_ADJUST(rc, channel->session,
1357
                 channel_request_pty_size(channel, width, height, width_px,
1358
                                          height_px));
1359
    return rc;
1360
}
1361

1362
/* Keep this an even number */
1363
#define LIBSSH2_X11_RANDOM_COOKIE_LEN       32
1364

1365
/*
1366
 * channel_x11_req
1367
 * Request X11 forwarding
1368
 */
1369
static int
1370
channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
1371
                const char *auth_proto, const char *auth_cookie,
1372
                int screen_number)
1373
{
1374
    LIBSSH2_SESSION *session = channel->session;
1375
    unsigned char *s;
1376
    static const unsigned char reply_codes[3] =
1377
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1378
    size_t proto_len =
1379
        auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
1380
    size_t cookie_len =
1381
        auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
1382
    int rc;
1383

1384
    if(channel->reqX11_state == libssh2_NB_state_idle) {
1385
        /* 30 = packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) +
1386
         * want_reply(1) + single_cnx(1) + proto_len(4) + cookie_len(4) +
1387
         * screen_num(4) */
1388
        channel->reqX11_packet_len = proto_len + cookie_len + 30;
1389

1390
        /* Zero the whole thing out */
1391
        memset(&channel->reqX11_packet_requirev_state, 0,
1392
               sizeof(channel->reqX11_packet_requirev_state));
1393

1394
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1395
                       "Requesting x11-req for channel %u/%u: single=%d "
1396
                       "proto=%s cookie=%s screen=%d",
1397
                       channel->local.id, channel->remote.id,
1398
                       single_connection,
1399
                       auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1400
                       auth_cookie ? auth_cookie : "<random>", screen_number));
1401

1402
        s = channel->reqX11_packet =
1403
            LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
1404
        if(!channel->reqX11_packet) {
1405
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1406
                                  "Unable to allocate memory for pty-request");
1407
        }
1408

1409
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1410
        _libssh2_store_u32(&s, channel->remote.id);
1411
        _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1);
1412

1413
        *(s++) = 0x01;          /* want_reply */
1414
        *(s++) = single_connection ? 0x01 : 0x00;
1415

1416
        _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1417
                           proto_len);
1418

1419
        _libssh2_store_u32(&s, (uint32_t)cookie_len);
1420
        if(auth_cookie) {
1421
            memcpy(s, auth_cookie, cookie_len);
1422
        }
1423
        else {
1424
            int i;
1425
            /* note: the extra +1 below is necessary since the sprintf()
1426
               loop will always write 3 bytes so the last one will write
1427
               the trailing zero at the LIBSSH2_X11_RANDOM_COOKIE_LEN/2
1428
               border */
1429
            unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
1430

1431
            if(_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2)) {
1432
                return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
1433
                                      "Unable to get random bytes "
1434
                                      "for x11-req cookie");
1435
            }
1436
            for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
1437
                snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
1438
            }
1439
        }
1440
        s += cookie_len;
1441

1442
        _libssh2_store_u32(&s, screen_number);
1443
        channel->reqX11_state = libssh2_NB_state_created;
1444
    }
1445

1446
    if(channel->reqX11_state == libssh2_NB_state_created) {
1447
        rc = _libssh2_transport_send(session, channel->reqX11_packet,
1448
                                     channel->reqX11_packet_len,
1449
                                     NULL, 0);
1450
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1451
            _libssh2_error(session, rc,
1452
                           "Would block sending X11-req packet");
1453
            return rc;
1454
        }
1455
        if(rc) {
1456
            LIBSSH2_FREE(session, channel->reqX11_packet);
1457
            channel->reqX11_packet = NULL;
1458
            channel->reqX11_state = libssh2_NB_state_idle;
1459
            return _libssh2_error(session, rc,
1460
                                  "Unable to send x11-req packet");
1461
        }
1462
        LIBSSH2_FREE(session, channel->reqX11_packet);
1463
        channel->reqX11_packet = NULL;
1464

1465
        _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
1466

1467
        channel->reqX11_state = libssh2_NB_state_sent;
1468
    }
1469

1470
    if(channel->reqX11_state == libssh2_NB_state_sent) {
1471
        size_t data_len;
1472
        unsigned char *data;
1473
        unsigned char code;
1474

1475
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1476
                                      1, channel->reqX11_local_channel, 4,
1477
                                      &channel->reqX11_packet_requirev_state);
1478
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1479
            return rc;
1480
        }
1481
        else if(rc || data_len < 1) {
1482
            channel->reqX11_state = libssh2_NB_state_idle;
1483
            return _libssh2_error(session, rc,
1484
                                  "waiting for x11-req response packet");
1485
        }
1486

1487
        code = data[0];
1488
        LIBSSH2_FREE(session, data);
1489
        channel->reqX11_state = libssh2_NB_state_idle;
1490

1491
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1492
            return 0;
1493
    }
1494

1495
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1496
                          "Unable to complete request for channel x11-req");
1497
}
1498

1499
/*
1500
 * libssh2_channel_x11_req_ex
1501
 * Request X11 forwarding
1502
 */
1503
LIBSSH2_API int
1504
libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection,
1505
                           const char *auth_proto, const char *auth_cookie,
1506
                           int screen_number)
1507
{
1508
    int rc;
1509

1510
    if(!channel)
1511
        return LIBSSH2_ERROR_BAD_USE;
1512

1513
    BLOCK_ADJUST(rc, channel->session,
1514
                 channel_x11_req(channel, single_connection, auth_proto,
1515
                                 auth_cookie, screen_number));
1516
    return rc;
1517
}
1518

1519

1520
/*
1521
 * _libssh2_channel_process_startup
1522
 *
1523
 * Primitive for libssh2_channel_(shell|exec|subsystem)
1524
 */
1525
int
1526
_libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1527
                                 const char *request, size_t request_len,
1528
                                 const char *message, size_t message_len)
1529
{
1530
    LIBSSH2_SESSION *session = channel->session;
1531
    unsigned char *s;
1532
    static const unsigned char reply_codes[3] =
1533
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1534
    int rc;
1535

1536
    if(channel->process_state == libssh2_NB_state_end) {
1537
        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
1538
                              "Channel can not be reused");
1539
    }
1540

1541
    if(channel->process_state == libssh2_NB_state_idle) {
1542
        /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
1543
        channel->process_packet_len = request_len + 10;
1544

1545
        /* Zero the whole thing out */
1546
        memset(&channel->process_packet_requirev_state, 0,
1547
               sizeof(channel->process_packet_requirev_state));
1548

1549
        if(message)
1550
            channel->process_packet_len += + 4;
1551

1552
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1553
                       "starting request(%s) on channel %u/%u, message=%s",
1554
                       request, channel->local.id, channel->remote.id,
1555
                       message ? message : "<null>"));
1556
        s = channel->process_packet =
1557
            LIBSSH2_ALLOC(session, channel->process_packet_len);
1558
        if(!channel->process_packet)
1559
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1560
                                  "Unable to allocate memory "
1561
                                  "for channel-process request");
1562

1563
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1564
        _libssh2_store_u32(&s, channel->remote.id);
1565
        _libssh2_store_str(&s, request, request_len);
1566
        *(s++) = 0x01;
1567

1568
        if(message)
1569
            _libssh2_store_u32(&s, (uint32_t)message_len);
1570

1571
        channel->process_state = libssh2_NB_state_created;
1572
    }
1573

1574
    if(channel->process_state == libssh2_NB_state_created) {
1575
        rc = _libssh2_transport_send(session,
1576
                                     channel->process_packet,
1577
                                     channel->process_packet_len,
1578
                                     (unsigned char *)message, message_len);
1579
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1580
            _libssh2_error(session, rc,
1581
                           "Would block sending channel request");
1582
            return rc;
1583
        }
1584
        else if(rc) {
1585
            LIBSSH2_FREE(session, channel->process_packet);
1586
            channel->process_packet = NULL;
1587
            channel->process_state = libssh2_NB_state_end;
1588
            return _libssh2_error(session, rc,
1589
                                  "Unable to send channel request");
1590
        }
1591
        LIBSSH2_FREE(session, channel->process_packet);
1592
        channel->process_packet = NULL;
1593

1594
        _libssh2_htonu32(channel->process_local_channel, channel->local.id);
1595

1596
        channel->process_state = libssh2_NB_state_sent;
1597
    }
1598

1599
    if(channel->process_state == libssh2_NB_state_sent) {
1600
        unsigned char *data;
1601
        size_t data_len;
1602
        unsigned char code;
1603
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1604
                                      1, channel->process_local_channel, 4,
1605
                                      &channel->process_packet_requirev_state);
1606
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1607
            return rc;
1608
        }
1609
        else if(rc || data_len < 1) {
1610
            channel->process_state = libssh2_NB_state_end;
1611
            return _libssh2_error(session, rc,
1612
                                  "Failed waiting for channel success");
1613
        }
1614

1615
        code = data[0];
1616
        LIBSSH2_FREE(session, data);
1617
        channel->process_state = libssh2_NB_state_end;
1618

1619
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1620
            return 0;
1621
    }
1622

1623
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1624
                          "Unable to complete request for "
1625
                          "channel-process-startup");
1626
}
1627

1628
/*
1629
 * libssh2_channel_process_startup
1630
 *
1631
 * Primitive for libssh2_channel_(shell|exec|subsystem)
1632
 */
1633
LIBSSH2_API int
1634
libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1635
                                const char *req, unsigned int req_len,
1636
                                const char *msg, unsigned int msg_len)
1637
{
1638
    int rc;
1639

1640
    if(!channel)
1641
        return LIBSSH2_ERROR_BAD_USE;
1642

1643
    BLOCK_ADJUST(rc, channel->session,
1644
                 _libssh2_channel_process_startup(channel, req, req_len,
1645
                                                  msg, msg_len));
1646
    return rc;
1647
}
1648

1649

1650
/*
1651
 * libssh2_channel_set_blocking
1652
 *
1653
 * Set a channel's BEHAVIOR blocking on or off. The socket will remain non-
1654
 * blocking.
1655
 */
1656
LIBSSH2_API void
1657
libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
1658
{
1659
    if(channel)
1660
        (void)_libssh2_session_set_blocking(channel->session, blocking);
1661
}
1662

1663
/*
1664
 * _libssh2_channel_flush
1665
 *
1666
 * Flush data from one (or all) stream
1667
 * Returns number of bytes flushed, or negative on failure
1668
 */
1669
int
1670
_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
1671
{
1672
    if(channel->flush_state == libssh2_NB_state_idle) {
1673
        LIBSSH2_PACKET *packet =
1674
            _libssh2_list_first(&channel->session->packets);
1675
        channel->flush_refund_bytes = 0;
1676
        channel->flush_flush_bytes = 0;
1677

1678
        while(packet) {
1679
            unsigned char packet_type;
1680
            LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
1681

1682
            if(packet->data_len < 1) {
1683
                packet = next;
1684
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
1685
                               "Unexpected packet length"));
1686
                continue;
1687
            }
1688

1689
            packet_type = packet->data[0];
1690

1691
            if(((packet_type == SSH_MSG_CHANNEL_DATA)
1692
                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
1693
               && ((packet->data_len >= 5)
1694
                   && (_libssh2_ntohu32(packet->data + 1)
1695
                       == channel->local.id))) {
1696
                /* It's our channel at least */
1697
                int packet_stream_id;
1698

1699
                if(packet_type == SSH_MSG_CHANNEL_DATA) {
1700
                    packet_stream_id = 0;
1701
                }
1702
                else if(packet->data_len >= 9) {
1703
                    packet_stream_id = _libssh2_ntohu32(packet->data + 5);
1704
                }
1705
                else {
1706
                    channel->flush_state = libssh2_NB_state_idle;
1707
                    return _libssh2_error(channel->session,
1708
                                          LIBSSH2_ERROR_PROTO,
1709
                                          "Unexpected packet length");
1710
                }
1711

1712
                if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
1713
                    || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
1714
                        && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
1715
                            || (streamid == packet_stream_id)))
1716
                    || ((packet_type == SSH_MSG_CHANNEL_DATA)
1717
                        && (streamid == 0))) {
1718
                    size_t bytes_to_flush = packet->data_len -
1719
                        packet->data_head;
1720

1721
                    _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1722
                                   "Flushing %ld bytes of data from stream "
1723
                                   "%d on channel %u/%u",
1724
                                   (long)bytes_to_flush, packet_stream_id,
1725
                                   channel->local.id, channel->remote.id));
1726

1727
                    /* It's one of the streams we wanted to flush */
1728
                    channel->flush_refund_bytes += packet->data_len - 13;
1729
                    channel->flush_flush_bytes += bytes_to_flush;
1730

1731
                    LIBSSH2_FREE(channel->session, packet->data);
1732

1733
                    /* remove this packet from the parent's list */
1734
                    _libssh2_list_remove(&packet->node);
1735
                    LIBSSH2_FREE(channel->session, packet);
1736
                }
1737
            }
1738
            packet = next;
1739
        }
1740

1741
        channel->flush_state = libssh2_NB_state_created;
1742
    }
1743

1744
    channel->read_avail -= channel->flush_flush_bytes;
1745
    channel->remote.window_size -= (uint32_t)channel->flush_flush_bytes;
1746

1747
    if(channel->flush_refund_bytes) {
1748
        int rc =
1749
            _libssh2_channel_receive_window_adjust(channel,
1750
                                         (uint32_t)channel->flush_refund_bytes,
1751
                                         1, NULL);
1752
        if(rc == LIBSSH2_ERROR_EAGAIN)
1753
            return rc;
1754
    }
1755

1756
    channel->flush_state = libssh2_NB_state_idle;
1757

1758
    return (int)channel->flush_flush_bytes;
1759
}
1760

1761
/*
1762
 * libssh2_channel_flush_ex
1763
 *
1764
 * Flush data from one (or all) stream
1765
 * Returns number of bytes flushed, or negative on failure
1766
 */
1767
LIBSSH2_API int
1768
libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream)
1769
{
1770
    int rc;
1771

1772
    if(!channel)
1773
        return LIBSSH2_ERROR_BAD_USE;
1774

1775
    BLOCK_ADJUST(rc, channel->session,
1776
                 _libssh2_channel_flush(channel, stream));
1777
    return rc;
1778
}
1779

1780
/*
1781
 * libssh2_channel_get_exit_status
1782
 *
1783
 * Return the channel's program exit status. Note that the actual protocol
1784
 * provides the full 32bit this function returns.  We cannot abuse it to
1785
 * return error values in case of errors so we return a zero if channel is
1786
 * NULL.
1787
 */
1788
LIBSSH2_API int
1789
libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
1790
{
1791
    if(!channel)
1792
        return 0;
1793

1794
    return channel->exit_status;
1795
}
1796

1797
/*
1798
 * libssh2_channel_get_exit_signal
1799
 *
1800
 * Get exit signal (without leading "SIG"), error message, and language
1801
 * tag into newly allocated buffers of indicated length.  Caller can
1802
 * use NULL pointers to indicate that the value should not be set.  The
1803
 * *_len variables are set if they are non-NULL even if the
1804
 * corresponding string parameter is NULL.  Returns LIBSSH2_ERROR_NONE
1805
 * on success, or an API error code.
1806
 */
1807
LIBSSH2_API int
1808
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
1809
                                char **exitsignal,
1810
                                size_t *exitsignal_len,
1811
                                char **errmsg,
1812
                                size_t *errmsg_len,
1813
                                char **langtag,
1814
                                size_t *langtag_len)
1815
{
1816
    size_t namelen = 0;
1817

1818
    if(channel) {
1819
        LIBSSH2_SESSION *session = channel->session;
1820

1821
        if(channel->exit_signal) {
1822
            namelen = strlen(channel->exit_signal);
1823
            if(exitsignal) {
1824
                *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
1825
                if(!*exitsignal) {
1826
                    return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1827
                                  "Unable to allocate memory for signal name");
1828
                }
1829
                memcpy(*exitsignal, channel->exit_signal, namelen);
1830
                (*exitsignal)[namelen] = '\0';
1831
            }
1832
            if(exitsignal_len)
1833
                *exitsignal_len = namelen;
1834
        }
1835
        else {
1836
            if(exitsignal)
1837
                *exitsignal = NULL;
1838
            if(exitsignal_len)
1839
                *exitsignal_len = 0;
1840
        }
1841

1842
        /* TODO: set error message and language tag */
1843

1844
        if(errmsg)
1845
            *errmsg = NULL;
1846

1847
        if(errmsg_len)
1848
            *errmsg_len = 0;
1849

1850
        if(langtag)
1851
            *langtag = NULL;
1852

1853
        if(langtag_len)
1854
            *langtag_len = 0;
1855
    }
1856

1857
    return LIBSSH2_ERROR_NONE;
1858
}
1859

1860
/*
1861
 * _libssh2_channel_receive_window_adjust
1862
 *
1863
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1864
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1865
 * adjustment amount will be queued for a later packet.
1866
 *
1867
 * Calls _libssh2_error() !
1868
 */
1869
int
1870
_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
1871
                                       uint32_t adjustment,
1872
                                       unsigned char force,
1873
                                       unsigned int *store)
1874
{
1875
    int rc;
1876

1877
    if(store)
1878
        *store = channel->remote.window_size;
1879

1880
    if(channel->adjust_state == libssh2_NB_state_idle) {
1881
        if(!force
1882
            && (adjustment + channel->adjust_queue <
1883
                LIBSSH2_CHANNEL_MINADJUST)) {
1884
            _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1885
                           "Queueing %u bytes for receive window adjustment "
1886
                           "for channel %u/%u",
1887
                           adjustment, channel->local.id, channel->remote.id));
1888
            channel->adjust_queue += adjustment;
1889
            return 0;
1890
        }
1891

1892
        if(!adjustment && !channel->adjust_queue) {
1893
            return 0;
1894
        }
1895

1896
        adjustment += channel->adjust_queue;
1897
        channel->adjust_queue = 0;
1898

1899
        /* Adjust the window based on the block we just freed */
1900
        channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
1901
        _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
1902
        _libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
1903
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1904
                       "Adjusting window %u bytes for data on "
1905
                       "channel %u/%u",
1906
                       adjustment, channel->local.id, channel->remote.id));
1907

1908
        channel->adjust_state = libssh2_NB_state_created;
1909
    }
1910

1911
    rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
1912
                                 NULL, 0);
1913
    if(rc == LIBSSH2_ERROR_EAGAIN) {
1914
        _libssh2_error(channel->session, rc,
1915
                       "Would block sending window adjust");
1916
        return rc;
1917
    }
1918
    else if(rc) {
1919
        channel->adjust_queue = adjustment;
1920
        return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
1921
                              "Unable to send transfer-window adjustment "
1922
                              "packet, deferring");
1923
    }
1924
    else {
1925
        channel->remote.window_size += adjustment;
1926
    }
1927

1928
    channel->adjust_state = libssh2_NB_state_idle;
1929

1930
    return 0;
1931
}
1932

1933
#ifndef LIBSSH2_NO_DEPRECATED
1934
/*
1935
 * libssh2_channel_receive_window_adjust (DEPRECATED, DO NOT USE!)
1936
 *
1937
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1938
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1939
 * adjustment amount will be queued for a later packet.
1940
 *
1941
 * Returns the new size of the receive window (as understood by remote end).
1942
 * Note that it might return EAGAIN too which is highly stupid.
1943
 *
1944
 */
1945
LIBSSH2_API unsigned long
1946
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
1947
                                      unsigned long adj,
1948
                                      unsigned char force)
1949
{
1950
    unsigned int window;
1951
    int rc;
1952

1953
    if(!channel)
1954
        return (unsigned long)LIBSSH2_ERROR_BAD_USE;
1955

1956
    BLOCK_ADJUST(rc, channel->session,
1957
                 _libssh2_channel_receive_window_adjust(channel,
1958
                                                        (uint32_t)adj,
1959
                                                        force, &window));
1960

1961
    /* stupid - but this is how it was made to work before and this is just
1962
       kept for backwards compatibility */
1963
    return rc ? (unsigned long)rc : window;
1964
}
1965
#endif
1966

1967
/*
1968
 * libssh2_channel_receive_window_adjust2
1969
 *
1970
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1971
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1972
 * adjustment amount will be queued for a later packet.
1973
 *
1974
 * Stores the new size of the receive window in the data 'window' points to.
1975
 *
1976
 * Returns the "normal" error code: 0 for success, negative for failure.
1977
 */
1978
LIBSSH2_API int
1979
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
1980
                                       unsigned long adj,
1981
                                       unsigned char force,
1982
                                       unsigned int *window)
1983
{
1984
    int rc;
1985

1986
    if(!channel)
1987
        return LIBSSH2_ERROR_BAD_USE;
1988

1989
    BLOCK_ADJUST(rc, channel->session,
1990
                 _libssh2_channel_receive_window_adjust(channel,
1991
                                                        (uint32_t)adj,
1992
                                                        force, window));
1993
    return rc;
1994
}
1995

1996
int
1997
_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
1998
{
1999
    if(channel->extData2_state == libssh2_NB_state_idle) {
2000
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
2001
                       "Setting channel %u/%u handle_extended_data"
2002
                       " mode to %d",
2003
                       channel->local.id, channel->remote.id, ignore_mode));
2004
        channel->remote.extended_data_ignore_mode = (char)ignore_mode;
2005

2006
        channel->extData2_state = libssh2_NB_state_created;
2007
    }
2008

2009
    if(channel->extData2_state == libssh2_NB_state_idle) {
2010
        if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
2011
            int rc =
2012
                _libssh2_channel_flush(channel,
2013
                                       LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
2014
            if(LIBSSH2_ERROR_EAGAIN == rc)
2015
                return rc;
2016
        }
2017
    }
2018

2019
    channel->extData2_state = libssh2_NB_state_idle;
2020
    return 0;
2021
}
2022

2023
/*
2024
 * libssh2_channel_handle_extended_data2
2025
 *
2026
 */
2027
LIBSSH2_API int
2028
libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
2029
                                      int mode)
2030
{
2031
    int rc;
2032

2033
    if(!channel)
2034
        return LIBSSH2_ERROR_BAD_USE;
2035

2036
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel,
2037
                                                                      mode));
2038
    return rc;
2039
}
2040

2041
#ifndef LIBSSH2_NO_DEPRECATED
2042
/*
2043
 * libssh2_channel_handle_extended_data (DEPRECATED, DO NOT USE!)
2044
 *
2045
 * How should extended data look to the calling app?  Keep it in separate
2046
 * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
2047
 * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
2048
 * out packets as they come in]? (IGNORE)
2049
 */
2050
LIBSSH2_API void
2051
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
2052
                                     int ignore_mode)
2053
{
2054
    (void)libssh2_channel_handle_extended_data2(channel, ignore_mode);
2055
}
2056
#endif
2057

2058

2059
/*
2060
 * _libssh2_channel_read
2061
 *
2062
 * Read data from a channel
2063
 *
2064
 * It is important to not return 0 until the currently read channel is
2065
 * complete. If we read stuff from the wire but it was no payload data to fill
2066
 * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
2067
 *
2068
 * The receive window must be maintained (enlarged) by the user of this
2069
 * function.
2070
 */
2071
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
2072
                              char *buf, size_t buflen)
2073
{
2074
    LIBSSH2_SESSION *session = channel->session;
2075
    int rc;
2076
    size_t bytes_read = 0;
2077
    size_t bytes_want;
2078
    int unlink_packet;
2079
    LIBSSH2_PACKET *read_packet;
2080
    LIBSSH2_PACKET *read_next;
2081

2082
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2083
                   "channel_read() wants %ld bytes from channel %u/%u "
2084
                   "stream #%d",
2085
                   (long)buflen, channel->local.id, channel->remote.id,
2086
                   stream_id));
2087

2088
    /* expand the receiving window first if it has become too narrow */
2089
    if((channel->read_state == libssh2_NB_state_jump1) ||
2090
       (channel->remote.window_size <
2091
        channel->remote.window_size_initial / 4 * 3 + buflen)) {
2092

2093
        uint32_t adjustment = (uint32_t)(channel->remote.window_size_initial +
2094
            buflen - channel->remote.window_size);
2095
        if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
2096
            adjustment = LIBSSH2_CHANNEL_MINADJUST;
2097

2098
        /* the actual window adjusting may not finish so we need to deal with
2099
           this special state here */
2100
        channel->read_state = libssh2_NB_state_jump1;
2101
        rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
2102
                                                    0, NULL);
2103
        if(rc)
2104
            return rc;
2105

2106
        channel->read_state = libssh2_NB_state_idle;
2107
    }
2108

2109
    /* Process all pending incoming packets. Tests prove that this way
2110
       produces faster transfers. */
2111
    do {
2112
        rc = _libssh2_transport_read(session);
2113
    } while(rc > 0);
2114

2115
    if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
2116
        return _libssh2_error(session, rc, "transport read");
2117

2118
    read_packet = _libssh2_list_first(&session->packets);
2119
    while(read_packet && (bytes_read < buflen)) {
2120
        /* previously this loop condition also checked for
2121
           !channel->remote.close but we cannot let it do this:
2122

2123
           We may have a series of packets to read that are still pending even
2124
           if a close has been received. Acknowledging the close too early
2125
           makes us flush buffers prematurely and loose data.
2126
        */
2127

2128
        LIBSSH2_PACKET *readpkt = read_packet;
2129

2130
        /* In case packet gets destroyed during this iteration */
2131
        read_next = _libssh2_list_next(&readpkt->node);
2132

2133
        if(readpkt->data_len < 5) {
2134
            read_packet = read_next;
2135

2136
            if(readpkt->data_len != 1 ||
2137
                readpkt->data[0] != SSH_MSG_REQUEST_FAILURE) {
2138
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2139
                               "Unexpected packet length"));
2140
            }
2141

2142
            continue;
2143
        }
2144

2145
        channel->read_local_id =
2146
            _libssh2_ntohu32(readpkt->data + 1);
2147

2148
        /*
2149
         * Either we asked for a specific extended data stream
2150
         * (and data was available),
2151
         * or the standard stream (and data was available),
2152
         * or the standard stream with extended_data_merge
2153
         * enabled and data was available
2154
         */
2155
        if((stream_id
2156
             && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2157
             && (channel->local.id == channel->read_local_id)
2158
             && (readpkt->data_len >= 9)
2159
             && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
2160
            || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
2161
                && (channel->local.id == channel->read_local_id))
2162
            || (!stream_id
2163
                && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2164
                && (channel->local.id == channel->read_local_id)
2165
                && (channel->remote.extended_data_ignore_mode ==
2166
                    LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2167

2168
            /* figure out much more data we want to read */
2169
            bytes_want = buflen - bytes_read;
2170
            unlink_packet = FALSE;
2171

2172
            if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
2173
                /* we want more than this node keeps, so adjust the number and
2174
                   delete this node after the copy */
2175
                bytes_want = readpkt->data_len - readpkt->data_head;
2176
                unlink_packet = TRUE;
2177
            }
2178

2179
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2180
                           "channel_read() got %ld of data from %u/%u/%d%s",
2181
                           (long)bytes_want, channel->local.id,
2182
                           channel->remote.id, stream_id,
2183
                           unlink_packet?" [ul]":""));
2184

2185
            /* copy data from this struct to the target buffer */
2186
            memcpy(&buf[bytes_read],
2187
                   &readpkt->data[readpkt->data_head], bytes_want);
2188

2189
            /* advance pointer and counter */
2190
            readpkt->data_head += bytes_want;
2191
            bytes_read += bytes_want;
2192

2193
            /* if drained, remove from list */
2194
            if(unlink_packet) {
2195
                /* detach readpkt from session->packets list */
2196
                _libssh2_list_remove(&readpkt->node);
2197

2198
                LIBSSH2_FREE(session, readpkt->data);
2199
                LIBSSH2_FREE(session, readpkt);
2200
            }
2201
        }
2202

2203
        /* check the next struct in the chain */
2204
        read_packet = read_next;
2205
    }
2206

2207
    if(!bytes_read) {
2208
        /* If the channel is already at EOF or even closed, we need to signal
2209
           that back. We may have gotten that info while draining the incoming
2210
           transport layer until EAGAIN so we must not be fooled by that
2211
           return code. */
2212
        if(channel->remote.eof || channel->remote.close)
2213
            return 0;
2214
        else if(rc != LIBSSH2_ERROR_EAGAIN)
2215
            return 0;
2216

2217
        /* if the transport layer said EAGAIN then we say so as well */
2218
        return _libssh2_error(session, rc, "would block");
2219
    }
2220

2221
    channel->read_avail -= bytes_read;
2222
    channel->remote.window_size -= (uint32_t)bytes_read;
2223

2224
    return bytes_read;
2225
}
2226

2227
/*
2228
 * libssh2_channel_read_ex
2229
 *
2230
 * Read data from a channel (blocking or non-blocking depending on set state)
2231
 *
2232
 * When this is done non-blocking, it is important to not return 0 until the
2233
 * currently read channel is complete. If we read stuff from the wire but it
2234
 * was no payload data to fill in the buffer with, we MUST make sure to return
2235
 * LIBSSH2_ERROR_EAGAIN.
2236
 *
2237
 * This function will first make sure there's a receive window enough to
2238
 * receive a full buffer's wort of contents. An application may choose to
2239
 * adjust the receive window more to increase transfer performance.
2240
 */
2241
LIBSSH2_API ssize_t
2242
libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
2243
                        size_t buflen)
2244
{
2245
    ssize_t rc;
2246
    unsigned long recv_window;
2247

2248
    if(!channel)
2249
        return LIBSSH2_ERROR_BAD_USE;
2250

2251
    recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
2252

2253
    if(buflen > recv_window) {
2254
        BLOCK_ADJUST(rc, channel->session,
2255
                     _libssh2_channel_receive_window_adjust(channel,
2256
                                                   (uint32_t)buflen, 1, NULL));
2257
    }
2258

2259
    BLOCK_ADJUST(rc, channel->session,
2260
                 _libssh2_channel_read(channel, stream_id, buf, buflen));
2261
    return rc;
2262
}
2263

2264
/*
2265
 * _libssh2_channel_packet_data_len
2266
 *
2267
 * Return the size of the data block of the current packet, or 0 if there
2268
 * isn't a packet.
2269
 */
2270
size_t
2271
_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
2272
{
2273
    LIBSSH2_SESSION *session = channel->session;
2274
    LIBSSH2_PACKET *read_packet;
2275
    LIBSSH2_PACKET *next_packet;
2276
    uint32_t read_local_id;
2277

2278
    read_packet = _libssh2_list_first(&session->packets);
2279
    if(!read_packet)
2280
        return 0;
2281

2282
    while(read_packet) {
2283

2284
        next_packet = _libssh2_list_next(&read_packet->node);
2285

2286
        if(read_packet->data_len < 5) {
2287
            read_packet = next_packet;
2288
            _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2289
                           "Unexpected packet length"));
2290
            continue;
2291
        }
2292

2293
        read_local_id = _libssh2_ntohu32(read_packet->data + 1);
2294

2295
        /*
2296
         * Either we asked for a specific extended data stream
2297
         * (and data was available),
2298
         * or the standard stream (and data was available),
2299
         * or the standard stream with extended_data_merge
2300
         * enabled and data was available
2301
         */
2302
        if((stream_id
2303
             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2304
             && (channel->local.id == read_local_id)
2305
             && (read_packet->data_len >= 9)
2306
             && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
2307
            ||
2308
            (!stream_id
2309
             && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
2310
             && (channel->local.id == read_local_id))
2311
            ||
2312
            (!stream_id
2313
             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2314
             && (channel->local.id == read_local_id)
2315
             && (channel->remote.extended_data_ignore_mode
2316
                 == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2317
            return read_packet->data_len - read_packet->data_head;
2318
        }
2319

2320
        read_packet = next_packet;
2321
    }
2322

2323
    return 0;
2324
}
2325

2326
/*
2327
 * _libssh2_channel_write
2328
 *
2329
 * Send data to a channel. Note that if this returns EAGAIN, the caller must
2330
 * call this function again with the SAME input arguments.
2331
 *
2332
 * Returns: number of bytes sent, or if it returns a negative number, that is
2333
 * the error code!
2334
 */
2335
ssize_t
2336
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
2337
                       const unsigned char *buf, size_t buflen)
2338
{
2339
    int rc = 0;
2340
    LIBSSH2_SESSION *session = channel->session;
2341
    ssize_t wrote = 0; /* counter for this specific this call */
2342

2343
    /* In theory we could split larger buffers into several smaller packets
2344
     * but it turns out to be really hard and nasty to do while still offering
2345
     * the API/prototype.
2346
     *
2347
     * Instead we only deal with the first 32K in this call and for the parent
2348
     * function to call it again with the remainder! 32K is a conservative
2349
     * limit based on the text in RFC4253 section 6.1.
2350
     */
2351
    if(buflen > 32700)
2352
        buflen = 32700;
2353

2354
    if(channel->write_state == libssh2_NB_state_idle) {
2355
        unsigned char *s = channel->write_packet;
2356

2357
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
2358
                       "Writing %ld bytes on channel %u/%u, stream #%d",
2359
                       (long)buflen, channel->local.id, channel->remote.id,
2360
                       stream_id));
2361

2362
        if(channel->local.close)
2363
            return _libssh2_error(channel->session,
2364
                                  LIBSSH2_ERROR_CHANNEL_CLOSED,
2365
                                  "We have already closed this channel");
2366
        else if(channel->local.eof)
2367
            return _libssh2_error(channel->session,
2368
                                  LIBSSH2_ERROR_CHANNEL_EOF_SENT,
2369
                                  "EOF has already been received, "
2370
                                  "data might be ignored");
2371

2372
        /* drain the incoming flow first, mostly to make sure we get all
2373
         * pending window adjust packets */
2374
        do
2375
            rc = _libssh2_transport_read(session);
2376
        while(rc > 0);
2377

2378
        if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
2379
            return _libssh2_error(channel->session, rc,
2380
                                  "Failure while draining incoming flow");
2381
        }
2382

2383
        if(channel->local.window_size <= 0) {
2384
            /* there's no room for data so we stop */
2385

2386
            /* Waiting on the socket to be writable would be wrong because we
2387
             * would be back here immediately, but a readable socket might
2388
             * herald an incoming window adjustment.
2389
             */
2390
            session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
2391

2392
            return rc == LIBSSH2_ERROR_EAGAIN ? rc : 0;
2393
        }
2394

2395
        channel->write_bufwrite = buflen;
2396

2397
        *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
2398
            SSH_MSG_CHANNEL_DATA;
2399
        _libssh2_store_u32(&s, channel->remote.id);
2400
        if(stream_id)
2401
            _libssh2_store_u32(&s, stream_id);
2402

2403
        /* Don't exceed the remote end's limits */
2404
        /* REMEMBER local means local as the SOURCE of the data */
2405
        if(channel->write_bufwrite > channel->local.window_size) {
2406
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2407
                           "Splitting write block due to %u byte "
2408
                           "window_size on %u/%u/%d",
2409
                           channel->local.window_size, channel->local.id,
2410
                           channel->remote.id, stream_id));
2411
            channel->write_bufwrite = channel->local.window_size;
2412
        }
2413
        if(channel->write_bufwrite > channel->local.packet_size) {
2414
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2415
                           "Splitting write block due to %u byte "
2416
                           "packet_size on %u/%u/%d",
2417
                           channel->local.packet_size, channel->local.id,
2418
                           channel->remote.id, stream_id));
2419
            channel->write_bufwrite = channel->local.packet_size;
2420
        }
2421
        /* store the size here only, the buffer is passed in as-is to
2422
           _libssh2_transport_send() */
2423
        _libssh2_store_u32(&s, (uint32_t)channel->write_bufwrite);
2424
        channel->write_packet_len = s - channel->write_packet;
2425

2426
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2427
                       "Sending %ld bytes on channel %u/%u, stream_id=%d",
2428
                       (long)channel->write_bufwrite, channel->local.id,
2429
                       channel->remote.id, stream_id));
2430

2431
        channel->write_state = libssh2_NB_state_created;
2432
    }
2433

2434
    if(channel->write_state == libssh2_NB_state_created) {
2435
        rc = _libssh2_transport_send(session, channel->write_packet,
2436
                                     channel->write_packet_len,
2437
                                     buf, channel->write_bufwrite);
2438
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2439
            return _libssh2_error(session, rc,
2440
                                  "Unable to send channel data");
2441
        }
2442
        else if(rc) {
2443
            channel->write_state = libssh2_NB_state_idle;
2444
            return _libssh2_error(session, rc,
2445
                                  "Unable to send channel data");
2446
        }
2447
        /* Shrink local window size */
2448
        channel->local.window_size -= (uint32_t)channel->write_bufwrite;
2449

2450
        wrote += channel->write_bufwrite;
2451

2452
        /* Since _libssh2_transport_write() succeeded, we must return
2453
           now to allow the caller to provide the next chunk of data.
2454

2455
           We cannot move on to send the next piece of data that may
2456
           already have been provided in this same function call, as we
2457
           risk getting EAGAIN for that and we can't return information
2458
           both about sent data as well as EAGAIN. So, by returning short
2459
           now, the caller will call this function again with new data to
2460
           send */
2461

2462
        channel->write_state = libssh2_NB_state_idle;
2463

2464
        return wrote;
2465
    }
2466

2467
    return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
2468
}
2469

2470
/*
2471
 * libssh2_channel_write_ex
2472
 *
2473
 * Send data to a channel
2474
 */
2475
LIBSSH2_API ssize_t
2476
libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
2477
                         const char *buf, size_t buflen)
2478
{
2479
    ssize_t rc;
2480

2481
    if(!channel)
2482
        return LIBSSH2_ERROR_BAD_USE;
2483

2484
    BLOCK_ADJUST(rc, channel->session,
2485
                 _libssh2_channel_write(channel, stream_id,
2486
                                        (unsigned char *)buf, buflen));
2487
    return rc;
2488
}
2489

2490
/*
2491
 * channel_send_eof
2492
 *
2493
 * Send EOF on channel
2494
 */
2495
static int channel_send_eof(LIBSSH2_CHANNEL *channel)
2496
{
2497
    LIBSSH2_SESSION *session = channel->session;
2498
    unsigned char packet[5];    /* packet_type(1) + channelno(4) */
2499
    int rc;
2500

2501
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2502
                   "Sending EOF on channel %u/%u",
2503
                   channel->local.id, channel->remote.id));
2504
    packet[0] = SSH_MSG_CHANNEL_EOF;
2505
    _libssh2_htonu32(packet + 1, channel->remote.id);
2506
    rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
2507
    if(rc == LIBSSH2_ERROR_EAGAIN) {
2508
        _libssh2_error(session, rc,
2509
                       "Would block sending EOF");
2510
        return rc;
2511
    }
2512
    else if(rc) {
2513
        return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2514
                              "Unable to send EOF on channel");
2515
    }
2516
    channel->local.eof = 1;
2517

2518
    return 0;
2519
}
2520

2521
/*
2522
 * libssh2_channel_send_eof
2523
 *
2524
 * Send EOF on channel
2525
 */
2526
LIBSSH2_API int
2527
libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel)
2528
{
2529
    int rc;
2530

2531
    if(!channel)
2532
        return LIBSSH2_ERROR_BAD_USE;
2533

2534
    BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel));
2535
    return rc;
2536
}
2537

2538
/*
2539
 * libssh2_channel_eof
2540
 *
2541
 * Read channel's eof status
2542
 */
2543
LIBSSH2_API int
2544
libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
2545
{
2546
    LIBSSH2_SESSION *session;
2547
    LIBSSH2_PACKET *packet;
2548
    LIBSSH2_PACKET *next_packet;
2549

2550
    if(!channel)
2551
        return LIBSSH2_ERROR_BAD_USE;
2552

2553
    session = channel->session;
2554
    packet = _libssh2_list_first(&session->packets);
2555

2556
    while(packet) {
2557

2558
        next_packet = _libssh2_list_next(&packet->node);
2559

2560
        if(packet->data_len < 1) {
2561
            packet = next_packet;
2562
            _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2563
                           "Unexpected packet length"));
2564
            continue;
2565
        }
2566

2567
        if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
2568
            || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
2569
            && ((packet->data_len >= 5)
2570
            && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
2571
            /* There's data waiting to be read yet, mask the EOF status */
2572
            return 0;
2573
        }
2574
        packet = next_packet;
2575
    }
2576

2577
    return channel->remote.eof;
2578
}
2579

2580
/*
2581
 * channel_wait_eof
2582
 *
2583
 * Awaiting channel EOF
2584
 */
2585
static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
2586
{
2587
    LIBSSH2_SESSION *session = channel->session;
2588
    int rc;
2589

2590
    if(channel->wait_eof_state == libssh2_NB_state_idle) {
2591
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2592
                       "Awaiting EOF for channel %u/%u", channel->local.id,
2593
                       channel->remote.id));
2594

2595
        channel->wait_eof_state = libssh2_NB_state_created;
2596
    }
2597

2598
    /*
2599
     * While channel is not eof, read more packets from the network.
2600
     * Either the EOF will be set or network timeout will occur.
2601
     */
2602
    do {
2603
        if(channel->remote.eof) {
2604
            break;
2605
        }
2606

2607
        if((channel->remote.window_size == channel->read_avail) &&
2608
            session->api_block_mode)
2609
            return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
2610
                                  "Receiving channel window "
2611
                                  "has been exhausted");
2612

2613
        rc = _libssh2_transport_read(session);
2614
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2615
            return rc;
2616
        }
2617
        else if(rc < 0) {
2618
            channel->wait_eof_state = libssh2_NB_state_idle;
2619
            return _libssh2_error(session, rc,
2620
                                  "_libssh2_transport_read() bailed out");
2621
        }
2622
    } while(1);
2623

2624
    channel->wait_eof_state = libssh2_NB_state_idle;
2625

2626
    return 0;
2627
}
2628

2629
/*
2630
 * libssh2_channel_wait_eof
2631
 *
2632
 * Awaiting channel EOF
2633
 */
2634
LIBSSH2_API int
2635
libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel)
2636
{
2637
    int rc;
2638

2639
    if(!channel)
2640
        return LIBSSH2_ERROR_BAD_USE;
2641

2642
    BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel));
2643
    return rc;
2644
}
2645

2646
int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
2647
{
2648
    LIBSSH2_SESSION *session = channel->session;
2649
    int rc = 0;
2650

2651
    if(channel->local.close) {
2652
        /* Already closed, act like we sent another close,
2653
         * even though we didn't... shhhhhh */
2654
        channel->close_state = libssh2_NB_state_idle;
2655
        return 0;
2656
    }
2657

2658
    if(!channel->local.eof) {
2659
        rc = channel_send_eof(channel);
2660
        if(rc) {
2661
            if(rc == LIBSSH2_ERROR_EAGAIN) {
2662
                return rc;
2663
            }
2664
            _libssh2_error(session, rc,
2665
                           "Unable to send EOF, but closing channel anyway");
2666
        }
2667
    }
2668

2669
    /* ignore if we have received a remote eof or not, as it is now too
2670
       late for us to wait for it. Continue closing! */
2671

2672
    if(channel->close_state == libssh2_NB_state_idle) {
2673
        _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Closing channel %u/%u",
2674
                       channel->local.id, channel->remote.id));
2675

2676
        channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
2677
        _libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
2678

2679
        channel->close_state = libssh2_NB_state_created;
2680
    }
2681

2682
    if(channel->close_state == libssh2_NB_state_created) {
2683
        rc = _libssh2_transport_send(session, channel->close_packet, 5,
2684
                                     NULL, 0);
2685
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2686
            _libssh2_error(session, rc,
2687
                           "Would block sending close-channel");
2688
            return rc;
2689

2690
        }
2691
        else if(rc) {
2692
            _libssh2_error(session, rc,
2693
                           "Unable to send close-channel request, "
2694
                           "but closing anyway");
2695
            /* skip waiting for the response and fall through to
2696
               LIBSSH2_CHANNEL_CLOSE below */
2697

2698
        }
2699
        else
2700
            channel->close_state = libssh2_NB_state_sent;
2701
    }
2702

2703
    if(channel->close_state == libssh2_NB_state_sent) {
2704
        /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
2705

2706
        while(!channel->remote.close && !rc &&
2707
               (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
2708
            rc = _libssh2_transport_read(session);
2709
    }
2710

2711
    if(rc != LIBSSH2_ERROR_EAGAIN) {
2712
        /* set the local close state first when we're perfectly confirmed to
2713
           not do any more EAGAINs */
2714
        channel->local.close = 1;
2715

2716
        /* We call the callback last in this function to make it keep the local
2717
           data as long as EAGAIN is returned. */
2718
        if(channel->close_cb) {
2719
            LIBSSH2_CHANNEL_CLOSE(session, channel);
2720
        }
2721

2722
        channel->close_state = libssh2_NB_state_idle;
2723
    }
2724

2725
    /* return 0 or an error */
2726
    return rc >= 0 ? 0 : rc;
2727
}
2728

2729
/*
2730
 * libssh2_channel_close
2731
 *
2732
 * Close a channel
2733
 */
2734
LIBSSH2_API int
2735
libssh2_channel_close(LIBSSH2_CHANNEL *channel)
2736
{
2737
    int rc;
2738

2739
    if(!channel)
2740
        return LIBSSH2_ERROR_BAD_USE;
2741

2742
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel));
2743
    return rc;
2744
}
2745

2746
/*
2747
 * channel_wait_closed
2748
 *
2749
 * Awaiting channel close after EOF
2750
 */
2751
static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
2752
{
2753
    LIBSSH2_SESSION *session = channel->session;
2754
    int rc;
2755

2756
    if(!channel->remote.eof) {
2757
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
2758
                              "libssh2_channel_wait_closed() invoked when "
2759
                              "channel is not in EOF state");
2760
    }
2761

2762
    if(channel->wait_closed_state == libssh2_NB_state_idle) {
2763
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2764
                       "Awaiting close of channel %u/%u", channel->local.id,
2765
                       channel->remote.id));
2766

2767
        channel->wait_closed_state = libssh2_NB_state_created;
2768
    }
2769

2770
    /*
2771
     * While channel is not closed, read more packets from the network.
2772
     * Either the channel will be closed or network timeout will occur.
2773
     */
2774
    if(!channel->remote.close) {
2775
        do {
2776
            rc = _libssh2_transport_read(session);
2777
            if(channel->remote.close)
2778
                /* it is now closed, move on! */
2779
                break;
2780
        } while(rc > 0);
2781
        if(rc < 0)
2782
            return rc;
2783
    }
2784

2785
    channel->wait_closed_state = libssh2_NB_state_idle;
2786

2787
    return 0;
2788
}
2789

2790
/*
2791
 * libssh2_channel_wait_closed
2792
 *
2793
 * Awaiting channel close after EOF
2794
 */
2795
LIBSSH2_API int
2796
libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel)
2797
{
2798
    int rc;
2799

2800
    if(!channel)
2801
        return LIBSSH2_ERROR_BAD_USE;
2802

2803
    BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel));
2804
    return rc;
2805
}
2806

2807
/*
2808
 * _libssh2_channel_free
2809
 *
2810
 * Make sure a channel is closed, then remove the channel from the session
2811
 * and free its resource(s)
2812
 *
2813
 * Returns 0 on success, negative on failure
2814
 */
2815
int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2816
{
2817
    LIBSSH2_SESSION *session = channel->session;
2818
    unsigned char channel_id[4];
2819
    unsigned char *data;
2820
    size_t data_len;
2821
    int rc;
2822

2823
    assert(session);
2824

2825
    if(channel->free_state == libssh2_NB_state_idle) {
2826
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2827
                       "Freeing channel %u/%u resources", channel->local.id,
2828
                       channel->remote.id));
2829

2830
        channel->free_state = libssh2_NB_state_created;
2831
    }
2832

2833
    /* Allow channel freeing even when the socket has lost its connection */
2834
    if(!channel->local.close
2835
        && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
2836
        rc = _libssh2_channel_close(channel);
2837

2838
        if(rc == LIBSSH2_ERROR_EAGAIN)
2839
            return rc;
2840

2841
        /* ignore all other errors as they otherwise risk blocking the channel
2842
           free from happening */
2843
    }
2844

2845
    channel->free_state = libssh2_NB_state_idle;
2846

2847
    if(channel->exit_signal) {
2848
        LIBSSH2_FREE(session, channel->exit_signal);
2849
    }
2850

2851
    /*
2852
     * channel->remote.close *might* not be set yet, Well...
2853
     * We've sent the close packet, what more do you want?
2854
     * Just let packet_add ignore it when it finally arrives
2855
     */
2856

2857
    /* Clear out packets meant for this channel */
2858
    _libssh2_htonu32(channel_id, channel->local.id);
2859
    while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
2860
                               &data_len, 1, channel_id, 4) >= 0)
2861
          ||
2862
          (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
2863
                               &data_len, 1, channel_id, 4) >= 0)) {
2864
        LIBSSH2_FREE(session, data);
2865
    }
2866

2867
    /* free "channel_type" */
2868
    if(channel->channel_type) {
2869
        LIBSSH2_FREE(session, channel->channel_type);
2870
    }
2871

2872
    /* Unlink from channel list */
2873
    _libssh2_list_remove(&channel->node);
2874

2875
    /*
2876
     * Make sure all memory used in the state variables are free
2877
     */
2878
    if(channel->setenv_packet) {
2879
        LIBSSH2_FREE(session, channel->setenv_packet);
2880
    }
2881
    if(channel->reqX11_packet) {
2882
        LIBSSH2_FREE(session, channel->reqX11_packet);
2883
    }
2884
    if(channel->process_packet) {
2885
        LIBSSH2_FREE(session, channel->process_packet);
2886
    }
2887

2888
    LIBSSH2_FREE(session, channel);
2889

2890
    return 0;
2891
}
2892

2893
/*
2894
 * libssh2_channel_free
2895
 *
2896
 * Make sure a channel is closed, then remove the channel from the session
2897
 * and free its resource(s)
2898
 *
2899
 * Returns 0 on success, negative on failure
2900
 */
2901
LIBSSH2_API int
2902
libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2903
{
2904
    int rc;
2905

2906
    if(!channel)
2907
        return LIBSSH2_ERROR_BAD_USE;
2908

2909
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel));
2910
    return rc;
2911
}
2912
/*
2913
 * libssh2_channel_window_read_ex
2914
 *
2915
 * Check the status of the read window. Returns the number of bytes which the
2916
 * remote end may send without overflowing the window limit read_avail (if
2917
 * passed) will be populated with the number of bytes actually available to be
2918
 * read window_size_initial (if passed) will be populated with the
2919
 * window_size_initial as defined by the channel_open request
2920
 */
2921
LIBSSH2_API unsigned long
2922
libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
2923
        /* FIXME: -> size_t */ unsigned long *read_avail,
2924
                               unsigned long *window_size_initial)
2925
{
2926
    if(!channel)
2927
        return 0; /* no channel, no window! */
2928

2929
    if(window_size_initial) {
2930
        *window_size_initial = channel->remote.window_size_initial;
2931
    }
2932

2933
    if(read_avail) {
2934
        size_t bytes_queued = 0;
2935
        LIBSSH2_PACKET *next_packet;
2936
        LIBSSH2_PACKET *packet =
2937
            _libssh2_list_first(&channel->session->packets);
2938

2939
        while(packet) {
2940
            unsigned char packet_type;
2941
               next_packet = _libssh2_list_next(&packet->node);
2942

2943
            if(packet->data_len < 1) {
2944
                packet = next_packet;
2945
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2946
                               "Unexpected packet length"));
2947
                continue;
2948
            }
2949

2950
            packet_type = packet->data[0];
2951

2952
            if(((packet_type == SSH_MSG_CHANNEL_DATA)
2953
                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
2954
               && ((packet->data_len >= 5)
2955
                   && (_libssh2_ntohu32(packet->data + 1) ==
2956
                       channel->local.id))) {
2957
                bytes_queued += packet->data_len - packet->data_head;
2958
            }
2959

2960
            packet = next_packet;
2961
        }
2962

2963
        *read_avail = (unsigned long)bytes_queued;
2964
    }
2965

2966
    return channel->remote.window_size;
2967
}
2968

2969
/*
2970
 * libssh2_channel_window_write_ex
2971
 *
2972
 * Check the status of the write window Returns the number of bytes which may
2973
 * be safely written on the channel without blocking window_size_initial (if
2974
 * passed) will be populated with the size of the initial window as defined by
2975
 * the channel_open request
2976
 */
2977
LIBSSH2_API unsigned long
2978
libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
2979
                                unsigned long *window_size_initial)
2980
{
2981
    if(!channel)
2982
        return 0; /* no channel, no window! */
2983

2984
    if(window_size_initial) {
2985
        /* For locally initiated channels this is very often 0, so it's not
2986
         * *that* useful as information goes */
2987
        *window_size_initial = channel->local.window_size_initial;
2988
    }
2989

2990
    return channel->local.window_size;
2991
}
2992

2993
/* A signal can be delivered to the remote process/service using the
2994
   following message.  Some systems may not implement signals, in which
2995
   case they SHOULD ignore this message.
2996

2997
      byte      SSH_MSG_CHANNEL_REQUEST
2998
      uint32    recipient channel
2999
      string    "signal"
3000
      boolean   FALSE
3001
      string    signal name (without the "SIG" prefix)
3002

3003
   'signal name' values will be encoded as discussed in the passage
3004
   describing SSH_MSG_CHANNEL_REQUEST messages using "exit-signal" in
3005
   this section.
3006
 */
3007
static int channel_signal(LIBSSH2_CHANNEL *channel,
3008
                          const char *signame,
3009
                          size_t signame_len)
3010
{
3011
    LIBSSH2_SESSION *session = channel->session;
3012
    int retcode = LIBSSH2_ERROR_PROTO;
3013

3014
    if(channel->sendsignal_state == libssh2_NB_state_idle) {
3015
        unsigned char *s;
3016

3017
        /* 20 = packet_type(1) + channel(4) +
3018
                signal_len + sizeof(signal) - 1 + want_reply(1) +
3019
                signame_len_len(4) */
3020
        channel->sendsignal_packet_len = 20 + signame_len;
3021

3022
        s = channel->sendsignal_packet =
3023
            LIBSSH2_ALLOC(session, channel->sendsignal_packet_len);
3024
        if(!channel->sendsignal_packet)
3025
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3026
                                  "Unable to allocate memory for "
3027
                                  "signal request");
3028

3029
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
3030
        _libssh2_store_u32(&s, channel->remote.id);
3031
        _libssh2_store_str(&s, "signal", sizeof("signal") - 1);
3032
        *(s++) = 0x00;  /* Don't reply */
3033
        _libssh2_store_str(&s, signame, signame_len);
3034

3035
        channel->sendsignal_state = libssh2_NB_state_created;
3036
    }
3037

3038
    if(channel->sendsignal_state == libssh2_NB_state_created) {
3039
        int rc;
3040

3041
        rc = _libssh2_transport_send(session, channel->sendsignal_packet,
3042
                                     channel->sendsignal_packet_len,
3043
                                     NULL, 0);
3044
        if(rc == LIBSSH2_ERROR_EAGAIN) {
3045
            _libssh2_error(session, rc, "Would block sending signal request");
3046
            return rc;
3047
        }
3048
        else if(rc) {
3049
            LIBSSH2_FREE(session, channel->sendsignal_packet);
3050
            channel->sendsignal_state = libssh2_NB_state_idle;
3051
            return _libssh2_error(session, rc, "Unable to send signal packet");
3052
        }
3053
        LIBSSH2_FREE(session, channel->sendsignal_packet);
3054
        retcode = LIBSSH2_ERROR_NONE;
3055
    }
3056

3057
    channel->sendsignal_state = libssh2_NB_state_idle;
3058

3059
    return retcode;
3060
}
3061

3062
LIBSSH2_API int
3063
libssh2_channel_signal_ex(LIBSSH2_CHANNEL *channel,
3064
                          const char *signame,
3065
                          size_t signame_len)
3066
{
3067
    int rc;
3068

3069
    if(!channel)
3070
        return LIBSSH2_ERROR_BAD_USE;
3071

3072
    BLOCK_ADJUST(rc, channel->session,
3073
                 channel_signal(channel, signame, signame_len));
3074
    return rc;
3075
}
3076

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.