Coverage Report

Created: 2025-02-15 07:01

/src/libssh2/src/channel.c
Line
Count
Source (jump to first uncovered line)
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
0
{
66
0
    uint32_t id = session->next_channel;
67
0
    LIBSSH2_CHANNEL *channel;
68
69
0
    channel = _libssh2_list_first(&session->channels);
70
71
0
    while(channel) {
72
0
        if(channel->local.id > id) {
73
0
            id = channel->local.id;
74
0
        }
75
0
        channel = _libssh2_list_next(&channel->node);
76
0
    }
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
0
    session->next_channel = id + 1;
86
0
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
87
0
                   "Allocated new channel ID#%u", id));
88
0
    return id;
89
0
}
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
15.8k
{
99
15.8k
    LIBSSH2_CHANNEL *channel;
100
15.8k
    LIBSSH2_LISTENER *l;
101
102
15.8k
    for(channel = _libssh2_list_first(&session->channels);
103
15.8k
        channel;
104
15.8k
        channel = _libssh2_list_next(&channel->node)) {
105
0
        if(channel->local.id == channel_id)
106
0
            return channel;
107
0
    }
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
15.8k
    for(l = _libssh2_list_first(&session->listeners); l;
113
15.8k
        l = _libssh2_list_next(&l->node)) {
114
0
        for(channel = _libssh2_list_first(&l->queue);
115
0
            channel;
116
0
            channel = _libssh2_list_next(&channel->node)) {
117
0
            if(channel->local.id == channel_id)
118
0
                return channel;
119
0
        }
120
0
    }
121
122
15.8k
    return NULL;
123
15.8k
}
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
0
{
138
0
    static const unsigned char reply_codes[3] = {
139
0
        SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
140
0
        SSH_MSG_CHANNEL_OPEN_FAILURE,
141
0
        0
142
0
    };
143
0
    unsigned char *s;
144
0
    int rc;
145
146
0
    if(session->open_state == libssh2_NB_state_idle) {
147
0
        session->open_channel = NULL;
148
0
        session->open_packet = NULL;
149
0
        session->open_data = NULL;
150
        /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) +
151
         * window_size(4) + packet_size(4) */
152
0
        session->open_packet_len = channel_type_len + 17;
153
0
        session->open_local_channel = _libssh2_channel_nextid(session);
154
155
        /* Zero the whole thing out */
156
0
        memset(&session->open_packet_requirev_state, 0,
157
0
               sizeof(session->open_packet_requirev_state));
158
159
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
160
0
                       "Opening Channel - win %d pack %d", window_size,
161
0
                       packet_size));
162
0
        session->open_channel =
163
0
            LIBSSH2_CALLOC(session, sizeof(LIBSSH2_CHANNEL));
164
0
        if(!session->open_channel) {
165
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
166
0
                           "Unable to allocate space for channel data");
167
0
            return NULL;
168
0
        }
169
0
        session->open_channel->channel_type_len = channel_type_len;
170
0
        session->open_channel->channel_type =
171
0
            LIBSSH2_ALLOC(session, channel_type_len);
172
0
        if(!session->open_channel->channel_type) {
173
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
174
0
                           "Failed allocating memory for channel type name");
175
0
            LIBSSH2_FREE(session, session->open_channel);
176
0
            session->open_channel = NULL;
177
0
            return NULL;
178
0
        }
179
0
        memcpy(session->open_channel->channel_type, channel_type,
180
0
               channel_type_len);
181
182
        /* REMEMBER: local as in locally sourced */
183
0
        session->open_channel->local.id = session->open_local_channel;
184
0
        session->open_channel->remote.window_size = window_size;
185
0
        session->open_channel->remote.window_size_initial = window_size;
186
0
        session->open_channel->remote.packet_size = packet_size;
187
0
        session->open_channel->session = session;
188
189
0
        _libssh2_list_add(&session->channels,
190
0
                          &session->open_channel->node);
191
192
0
        s = session->open_packet =
193
0
            LIBSSH2_ALLOC(session, session->open_packet_len);
194
0
        if(!session->open_packet) {
195
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
196
0
                           "Unable to allocate temporary space for packet");
197
0
            goto channel_error;
198
0
        }
199
0
        *(s++) = SSH_MSG_CHANNEL_OPEN;
200
0
        _libssh2_store_str(&s, channel_type, channel_type_len);
201
0
        _libssh2_store_u32(&s, session->open_local_channel);
202
0
        _libssh2_store_u32(&s, window_size);
203
0
        _libssh2_store_u32(&s, packet_size);
204
205
        /* Do not copy the message */
206
207
0
        session->open_state = libssh2_NB_state_created;
208
0
    }
209
210
0
    if(session->open_state == libssh2_NB_state_created) {
211
0
        rc = _libssh2_transport_send(session,
212
0
                                     session->open_packet,
213
0
                                     session->open_packet_len,
214
0
                                     message, message_len);
215
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
216
0
            _libssh2_error(session, rc,
217
0
                           "Would block sending channel-open request");
218
0
            return NULL;
219
0
        }
220
0
        else if(rc) {
221
0
            _libssh2_error(session, rc,
222
0
                           "Unable to send channel-open request");
223
0
            goto channel_error;
224
0
        }
225
226
0
        session->open_state = libssh2_NB_state_sent;
227
0
    }
228
229
0
    if(session->open_state == libssh2_NB_state_sent) {
230
0
        rc = _libssh2_packet_requirev(session, reply_codes,
231
0
                                      &session->open_data,
232
0
                                      &session->open_data_len, 1,
233
0
                                      session->open_packet + 5 +
234
0
                                      channel_type_len, 4,
235
0
                                      &session->open_packet_requirev_state);
236
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
237
0
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
238
0
            return NULL;
239
0
        }
240
0
        else if(rc) {
241
0
            _libssh2_error(session, rc, "Unexpected error");
242
0
            goto channel_error;
243
0
        }
244
245
0
        if(session->open_data_len < 1) {
246
0
            _libssh2_error(session, LIBSSH2_ERROR_PROTO,
247
0
                           "Unexpected packet size");
248
0
            goto channel_error;
249
0
        }
250
251
0
        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
252
253
0
            if(session->open_data_len < 17) {
254
0
                _libssh2_error(session, LIBSSH2_ERROR_PROTO,
255
0
                               "Unexpected packet size");
256
0
                goto channel_error;
257
0
            }
258
259
0
            session->open_channel->remote.id =
260
0
                _libssh2_ntohu32(session->open_data + 5);
261
0
            session->open_channel->local.window_size =
262
0
                _libssh2_ntohu32(session->open_data + 9);
263
0
            session->open_channel->local.window_size_initial =
264
0
                _libssh2_ntohu32(session->open_data + 9);
265
0
            session->open_channel->local.packet_size =
266
0
                _libssh2_ntohu32(session->open_data + 13);
267
0
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
268
0
                           "Connection Established - ID: %u/%u win: %u/%u"
269
0
                           " pack: %u/%u",
270
0
                           session->open_channel->local.id,
271
0
                           session->open_channel->remote.id,
272
0
                           session->open_channel->local.window_size,
273
0
                           session->open_channel->remote.window_size,
274
0
                           session->open_channel->local.packet_size,
275
0
                           session->open_channel->remote.packet_size));
276
0
            LIBSSH2_FREE(session, session->open_packet);
277
0
            session->open_packet = NULL;
278
0
            LIBSSH2_FREE(session, session->open_data);
279
0
            session->open_data = NULL;
280
281
0
            session->open_state = libssh2_NB_state_idle;
282
0
            return session->open_channel;
283
0
        }
284
285
0
        if(session->open_data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
286
0
            unsigned int reason_code =
287
0
                _libssh2_ntohu32(session->open_data + 5);
288
0
            switch(reason_code) {
289
0
            case SSH_OPEN_ADMINISTRATIVELY_PROHIBITED:
290
0
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
291
0
                               "Channel open failure "
292
0
                               "(administratively prohibited)");
293
0
                break;
294
0
            case SSH_OPEN_CONNECT_FAILED:
295
0
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
296
0
                               "Channel open failure (connect failed)");
297
0
                break;
298
0
            case SSH_OPEN_UNKNOWN_CHANNELTYPE:
299
0
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
300
0
                               "Channel open failure (unknown channel type)");
301
0
                break;
302
0
            case SSH_OPEN_RESOURCE_SHORTAGE:
303
0
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
304
0
                               "Channel open failure (resource shortage)");
305
0
                break;
306
0
            default:
307
0
                _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE,
308
0
                               "Channel open failure");
309
0
            }
310
0
        }
311
0
    }
312
313
0
channel_error:
314
315
0
    if(session->open_data) {
316
0
        LIBSSH2_FREE(session, session->open_data);
317
0
        session->open_data = NULL;
318
0
    }
319
0
    if(session->open_packet) {
320
0
        LIBSSH2_FREE(session, session->open_packet);
321
0
        session->open_packet = NULL;
322
0
    }
323
0
    if(session->open_channel) {
324
0
        unsigned char channel_id[4];
325
0
        LIBSSH2_FREE(session, session->open_channel->channel_type);
326
327
0
        _libssh2_list_remove(&session->open_channel->node);
328
329
        /* Clear out packets meant for this channel */
330
0
        _libssh2_htonu32(channel_id, session->open_channel->local.id);
331
0
        while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA,
332
0
                                   &session->open_data,
333
0
                                   &session->open_data_len, 1,
334
0
                                   channel_id, 4) >= 0)
335
0
              ||
336
0
              (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA,
337
0
                                   &session->open_data,
338
0
                                   &session->open_data_len, 1,
339
0
                                   channel_id, 4) >= 0)) {
340
0
            LIBSSH2_FREE(session, session->open_data);
341
0
            session->open_data = NULL;
342
0
        }
343
344
0
        LIBSSH2_FREE(session, session->open_channel);
345
0
        session->open_channel = NULL;
346
0
    }
347
348
0
    session->open_state = libssh2_NB_state_idle;
349
0
    return NULL;
350
0
}
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
0
{
363
0
    LIBSSH2_CHANNEL *ptr;
364
365
0
    if(!session)
366
0
        return NULL;
367
368
0
    BLOCK_ADJUST_ERRNO(ptr, session,
369
0
                       _libssh2_channel_open(session, type, type_len,
370
0
                                             window_size, packet_size,
371
0
                                             (const unsigned char *)msg,
372
0
                                             msg_len));
373
0
    return ptr;
374
0
}
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
0
{
385
0
    LIBSSH2_CHANNEL *channel;
386
0
    unsigned char *s;
387
388
0
    if(session->direct_state == libssh2_NB_state_idle) {
389
0
        session->direct_host_len = strlen(host);
390
0
        session->direct_shost_len = strlen(shost);
391
        /* host_len(4) + port(4) + shost_len(4) + sport(4) */
392
0
        session->direct_message_len =
393
0
            session->direct_host_len + session->direct_shost_len + 16;
394
395
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
396
0
                       "Requesting direct-tcpip session from %s:%d to %s:%d",
397
0
                       shost, sport, host, port));
398
399
0
        s = session->direct_message =
400
0
            LIBSSH2_ALLOC(session, session->direct_message_len);
401
0
        if(!session->direct_message) {
402
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
403
0
                           "Unable to allocate memory for "
404
0
                           "direct-tcpip connection");
405
0
            return NULL;
406
0
        }
407
0
        _libssh2_store_str(&s, host, session->direct_host_len);
408
0
        _libssh2_store_u32(&s, port);
409
0
        _libssh2_store_str(&s, shost, session->direct_shost_len);
410
0
        _libssh2_store_u32(&s, sport);
411
0
    }
412
413
0
    channel =
414
0
        _libssh2_channel_open(session, "direct-tcpip",
415
0
                              sizeof("direct-tcpip") - 1,
416
0
                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
417
0
                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
418
0
                              session->direct_message,
419
0
                              session->direct_message_len);
420
421
0
    if(!channel &&
422
0
        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
0
        session->direct_state = libssh2_NB_state_created;
426
0
        return NULL;
427
0
    }
428
    /* by default we set (keep?) idle state... */
429
0
    session->direct_state = libssh2_NB_state_idle;
430
431
0
    LIBSSH2_FREE(session, session->direct_message);
432
0
    session->direct_message = NULL;
433
434
0
    return channel;
435
0
}
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
0
{
446
0
    LIBSSH2_CHANNEL *ptr;
447
448
0
    if(!session)
449
0
        return NULL;
450
451
0
    BLOCK_ADJUST_ERRNO(ptr, session,
452
0
                       channel_direct_tcpip(session, host, port,
453
0
                                            shost, sport));
454
0
    return ptr;
455
0
}
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
0
{
466
0
    LIBSSH2_CHANNEL *channel;
467
0
    unsigned char *s;
468
469
0
    if(session->direct_state == libssh2_NB_state_idle) {
470
0
        session->direct_host_len = strlen(socket_path);
471
0
        session->direct_shost_len = strlen(shost);
472
0
        session->direct_message_len =
473
0
            session->direct_host_len + session->direct_shost_len + 12;
474
475
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
476
0
                       "Requesting direct-streamlocal session to %s",
477
0
                       socket_path));
478
479
0
        s = session->direct_message =
480
0
            LIBSSH2_ALLOC(session, session->direct_message_len);
481
0
        if(!session->direct_message) {
482
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
483
0
                "Unable to allocate memory for direct-streamlocal connection");
484
0
            return NULL;
485
0
        }
486
0
        _libssh2_store_str(&s, socket_path, session->direct_host_len);
487
0
        _libssh2_store_str(&s, shost, session->direct_shost_len);
488
0
        _libssh2_store_u32(&s, sport);
489
0
    }
490
491
0
    channel =
492
0
        _libssh2_channel_open(session, "direct-streamlocal@openssh.com",
493
0
                              sizeof("direct-streamlocal@openssh.com") - 1,
494
0
                              LIBSSH2_CHANNEL_WINDOW_DEFAULT,
495
0
                              LIBSSH2_CHANNEL_PACKET_DEFAULT,
496
0
                              session->direct_message,
497
0
                              session->direct_message_len);
498
499
0
    if(!channel &&
500
0
        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
0
        session->direct_state = libssh2_NB_state_created;
504
0
        return NULL;
505
0
    }
506
    /* by default we set (keep?) idle state... */
507
0
    session->direct_state = libssh2_NB_state_idle;
508
509
0
    LIBSSH2_FREE(session, session->direct_message);
510
0
    session->direct_message = NULL;
511
512
0
    return channel;
513
0
}
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
0
{
525
0
    LIBSSH2_CHANNEL *ptr;
526
527
0
    if(!session)
528
0
        return NULL;
529
530
0
    BLOCK_ADJUST_ERRNO(ptr, session,
531
0
                       channel_direct_streamlocal(session,
532
0
                       socket_path, shost, sport));
533
0
    return ptr;
534
0
}
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
0
{
545
0
    unsigned char *s;
546
0
    static const unsigned char reply_codes[3] =
547
0
        { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
548
0
    int rc;
549
550
0
    if(!host)
551
0
        host = "0.0.0.0";
552
553
0
    if(session->fwdLstn_state == libssh2_NB_state_idle) {
554
0
        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
0
        session->fwdLstn_packet_len =
558
0
            session->fwdLstn_host_len +
559
0
            (uint32_t)(sizeof("tcpip-forward") - 1) + 14;
560
561
        /* Zero the whole thing out */
562
0
        memset(&session->fwdLstn_packet_requirev_state, 0,
563
0
               sizeof(session->fwdLstn_packet_requirev_state));
564
565
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
566
0
                       "Requesting tcpip-forward session for %s:%d", host,
567
0
                       port));
568
569
0
        s = session->fwdLstn_packet =
570
0
            LIBSSH2_ALLOC(session, session->fwdLstn_packet_len);
571
0
        if(!session->fwdLstn_packet) {
572
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
573
0
                           "Unable to allocate memory for setenv packet");
574
0
            return NULL;
575
0
        }
576
577
0
        *(s++) = SSH_MSG_GLOBAL_REQUEST;
578
0
        _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1);
579
0
        *(s++) = 0x01;          /* want_reply */
580
581
0
        _libssh2_store_str(&s, host, session->fwdLstn_host_len);
582
0
        _libssh2_store_u32(&s, port);
583
584
0
        session->fwdLstn_state = libssh2_NB_state_created;
585
0
    }
586
587
0
    if(session->fwdLstn_state == libssh2_NB_state_created) {
588
0
        rc = _libssh2_transport_send(session,
589
0
                                     session->fwdLstn_packet,
590
0
                                     session->fwdLstn_packet_len,
591
0
                                     NULL, 0);
592
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
593
0
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
594
0
                           "Would block sending global-request packet for "
595
0
                           "forward listen request");
596
0
            return NULL;
597
0
        }
598
0
        else if(rc) {
599
0
            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
600
0
                           "Unable to send global-request packet for forward "
601
0
                           "listen request");
602
0
            LIBSSH2_FREE(session, session->fwdLstn_packet);
603
0
            session->fwdLstn_packet = NULL;
604
0
            session->fwdLstn_state = libssh2_NB_state_idle;
605
0
            return NULL;
606
0
        }
607
0
        LIBSSH2_FREE(session, session->fwdLstn_packet);
608
0
        session->fwdLstn_packet = NULL;
609
610
0
        session->fwdLstn_state = libssh2_NB_state_sent;
611
0
    }
612
613
0
    if(session->fwdLstn_state == libssh2_NB_state_sent) {
614
0
        unsigned char *data;
615
0
        size_t data_len;
616
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
617
0
                                      0, NULL, 0,
618
0
                                      &session->fwdLstn_packet_requirev_state);
619
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
620
0
            _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");
621
0
            return NULL;
622
0
        }
623
0
        else if(rc || (data_len < 1)) {
624
0
            _libssh2_error(session, LIBSSH2_ERROR_PROTO, "Unknown");
625
0
            session->fwdLstn_state = libssh2_NB_state_idle;
626
0
            return NULL;
627
0
        }
628
629
0
        if(data[0] == SSH_MSG_REQUEST_SUCCESS) {
630
0
            LIBSSH2_LISTENER *listener;
631
632
0
            listener = LIBSSH2_CALLOC(session, sizeof(LIBSSH2_LISTENER));
633
0
            if(!listener)
634
0
                _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
635
0
                               "Unable to allocate memory for listener queue");
636
0
            else {
637
0
                listener->host =
638
0
                    LIBSSH2_ALLOC(session, session->fwdLstn_host_len + 1);
639
0
                if(!listener->host) {
640
0
                    _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
641
0
                                   "Unable to allocate memory "
642
0
                                   "for listener queue");
643
0
                    LIBSSH2_FREE(session, listener);
644
0
                    listener = NULL;
645
0
                }
646
0
                else {
647
0
                    listener->session = session;
648
0
                    memcpy(listener->host, host, session->fwdLstn_host_len);
649
0
                    listener->host[session->fwdLstn_host_len] = 0;
650
0
                    if(data_len >= 5 && !port) {
651
0
                        listener->port = _libssh2_ntohu32(data + 1);
652
0
                        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
653
0
                                       "Dynamic tcpip-forward port "
654
0
                                       "allocated: %d",
655
0
                                       listener->port));
656
0
                    }
657
0
                    else
658
0
                        listener->port = port;
659
660
0
                    listener->queue_size = 0;
661
0
                    listener->queue_maxsize = queue_maxsize;
662
663
                    /* append this to the parent's list of listeners */
664
0
                    _libssh2_list_add(&session->listeners, &listener->node);
665
666
0
                    if(bound_port) {
667
0
                        *bound_port = listener->port;
668
0
                    }
669
0
                }
670
0
            }
671
672
0
            LIBSSH2_FREE(session, data);
673
0
            session->fwdLstn_state = libssh2_NB_state_idle;
674
0
            return listener;
675
0
        }
676
0
        else if(data[0] == SSH_MSG_REQUEST_FAILURE) {
677
0
            LIBSSH2_FREE(session, data);
678
0
            _libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED,
679
0
                           "Unable to complete request for forward-listen");
680
0
            session->fwdLstn_state = libssh2_NB_state_idle;
681
0
            return NULL;
682
0
        }
683
0
    }
684
685
0
    session->fwdLstn_state = libssh2_NB_state_idle;
686
687
0
    return NULL;
688
0
}
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
0
{
699
0
    LIBSSH2_LISTENER *ptr;
700
701
0
    if(!session)
702
0
        return NULL;
703
704
0
    BLOCK_ADJUST_ERRNO(ptr, session,
705
0
                       channel_forward_listen(session, host, port, bound_port,
706
0
                                              queue_maxsize));
707
0
    return ptr;
708
0
}
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
0
{
720
0
    LIBSSH2_SESSION *session = listener->session;
721
0
    LIBSSH2_CHANNEL *queued;
722
0
    unsigned char *packet, *s;
723
0
    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
0
    size_t packet_len =
727
0
        host_len + 14 + sizeof("cancel-tcpip-forward") - 1;
728
0
    int rc;
729
0
    int retcode = 0;
730
731
0
    if(listener->chanFwdCncl_state == libssh2_NB_state_idle) {
732
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
733
0
                       "Cancelling tcpip-forward session for %s:%d",
734
0
                       listener->host, listener->port));
735
736
0
        s = packet = LIBSSH2_ALLOC(session, packet_len);
737
0
        if(!packet) {
738
0
            _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
739
0
                           "Unable to allocate memory for setenv packet");
740
0
            return LIBSSH2_ERROR_ALLOC;
741
0
        }
742
743
0
        *(s++) = SSH_MSG_GLOBAL_REQUEST;
744
0
        _libssh2_store_str(&s, "cancel-tcpip-forward",
745
0
                           sizeof("cancel-tcpip-forward") - 1);
746
0
        *(s++) = 0x00;          /* want_reply */
747
748
0
        _libssh2_store_str(&s, listener->host, host_len);
749
0
        _libssh2_store_u32(&s, listener->port);
750
751
0
        listener->chanFwdCncl_state = libssh2_NB_state_created;
752
0
    }
753
0
    else {
754
0
        packet = listener->chanFwdCncl_data;
755
0
    }
756
757
0
    if(listener->chanFwdCncl_state == libssh2_NB_state_created) {
758
0
        rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0);
759
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
760
0
            _libssh2_error(session, rc,
761
0
                           "Would block sending forward request");
762
0
            listener->chanFwdCncl_data = packet;
763
0
            return rc;
764
0
        }
765
0
        else if(rc) {
766
0
            _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
767
0
                           "Unable to send global-request packet for forward "
768
0
                           "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
0
            listener->chanFwdCncl_state = libssh2_NB_state_sent;
773
0
            retcode = LIBSSH2_ERROR_SOCKET_SEND;
774
0
        }
775
0
        LIBSSH2_FREE(session, packet);
776
777
0
        listener->chanFwdCncl_state = libssh2_NB_state_sent;
778
0
    }
779
780
0
    queued = _libssh2_list_first(&listener->queue);
781
0
    while(queued) {
782
0
        LIBSSH2_CHANNEL *next = _libssh2_list_next(&queued->node);
783
784
0
        rc = _libssh2_channel_free(queued);
785
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
786
0
            return rc;
787
0
        }
788
0
        queued = next;
789
0
    }
790
0
    LIBSSH2_FREE(session, listener->host);
791
792
    /* remove this entry from the parent's list of listeners */
793
0
    _libssh2_list_remove(&listener->node);
794
795
0
    LIBSSH2_FREE(session, listener);
796
797
0
    return retcode;
798
0
}
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
0
{
811
0
    int rc;
812
813
0
    if(!listener)
814
0
        return LIBSSH2_ERROR_BAD_USE;
815
816
0
    BLOCK_ADJUST(rc, listener->session,
817
0
                 _libssh2_channel_forward_cancel(listener));
818
0
    return rc;
819
0
}
820
821
/*
822
 * channel_forward_accept
823
 *
824
 * Accept a connection
825
 */
826
static LIBSSH2_CHANNEL *
827
channel_forward_accept(LIBSSH2_LISTENER *listener)
828
0
{
829
0
    int rc;
830
831
0
    do {
832
0
        rc = _libssh2_transport_read(listener->session);
833
0
    } while(rc > 0);
834
835
0
    if(_libssh2_list_first(&listener->queue)) {
836
0
        LIBSSH2_CHANNEL *channel = _libssh2_list_first(&listener->queue);
837
838
        /* detach channel from listener's queue */
839
0
        _libssh2_list_remove(&channel->node);
840
841
0
        listener->queue_size--;
842
843
        /* add channel to session's channel list */
844
0
        _libssh2_list_add(&channel->session->channels, &channel->node);
845
846
0
        return channel;
847
0
    }
848
849
0
    if(rc == LIBSSH2_ERROR_EAGAIN) {
850
0
        _libssh2_error(listener->session, LIBSSH2_ERROR_EAGAIN,
851
0
                       "Would block waiting for packet");
852
0
    }
853
0
    else
854
0
        _libssh2_error(listener->session, LIBSSH2_ERROR_CHANNEL_UNKNOWN,
855
0
                       "Channel not found");
856
0
    return NULL;
857
0
}
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
0
{
867
0
    LIBSSH2_CHANNEL *ptr;
868
869
0
    if(!listener)
870
0
        return NULL;
871
872
0
    BLOCK_ADJUST_ERRNO(ptr, listener->session,
873
0
                       channel_forward_accept(listener));
874
0
    return ptr;
875
876
0
}
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
0
{
887
0
    LIBSSH2_SESSION *session = channel->session;
888
0
    unsigned char *s, *data;
889
0
    static const unsigned char reply_codes[3] =
890
0
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
891
0
    size_t data_len;
892
0
    int rc;
893
894
0
    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
0
        channel->setenv_packet_len = varname_len + value_len + 21;
898
899
        /* Zero the whole thing out */
900
0
        memset(&channel->setenv_packet_requirev_state, 0,
901
0
               sizeof(channel->setenv_packet_requirev_state));
902
903
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
904
0
                       "Setting remote environment variable: %s=%s on "
905
0
                       "channel %u/%u",
906
0
                       varname, value, channel->local.id, channel->remote.id));
907
908
0
        s = channel->setenv_packet =
909
0
            LIBSSH2_ALLOC(session, channel->setenv_packet_len);
910
0
        if(!channel->setenv_packet) {
911
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
912
0
                                  "Unable to allocate memory "
913
0
                                  "for setenv packet");
914
0
        }
915
916
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
917
0
        _libssh2_store_u32(&s, channel->remote.id);
918
0
        _libssh2_store_str(&s, "env", sizeof("env") - 1);
919
0
        *(s++) = 0x01;
920
0
        _libssh2_store_str(&s, varname, varname_len);
921
0
        _libssh2_store_str(&s, value, value_len);
922
923
0
        channel->setenv_state = libssh2_NB_state_created;
924
0
    }
925
926
0
    if(channel->setenv_state == libssh2_NB_state_created) {
927
0
        rc = _libssh2_transport_send(session,
928
0
                                     channel->setenv_packet,
929
0
                                     channel->setenv_packet_len,
930
0
                                     NULL, 0);
931
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
932
0
            _libssh2_error(session, rc,
933
0
                           "Would block sending setenv request");
934
0
            return rc;
935
0
        }
936
0
        else if(rc) {
937
0
            LIBSSH2_FREE(session, channel->setenv_packet);
938
0
            channel->setenv_packet = NULL;
939
0
            channel->setenv_state = libssh2_NB_state_idle;
940
0
            return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
941
0
                                  "Unable to send channel-request packet for "
942
0
                                  "setenv request");
943
0
        }
944
0
        LIBSSH2_FREE(session, channel->setenv_packet);
945
0
        channel->setenv_packet = NULL;
946
947
0
        _libssh2_htonu32(channel->setenv_local_channel, channel->local.id);
948
949
0
        channel->setenv_state = libssh2_NB_state_sent;
950
0
    }
951
952
0
    if(channel->setenv_state == libssh2_NB_state_sent) {
953
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
954
0
                                      1, channel->setenv_local_channel, 4,
955
0
                                      &channel->
956
0
                                      setenv_packet_requirev_state);
957
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
958
0
            return rc;
959
0
        }
960
0
        if(rc) {
961
0
            channel->setenv_state = libssh2_NB_state_idle;
962
0
            return _libssh2_error(session, rc,
963
0
                                  "Failed getting response for "
964
0
                                  "channel-setenv");
965
0
        }
966
0
        else if(data_len < 1) {
967
0
            channel->setenv_state = libssh2_NB_state_idle;
968
0
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
969
0
                                  "Unexpected packet size");
970
0
        }
971
972
0
        if(data[0] == SSH_MSG_CHANNEL_SUCCESS) {
973
0
            LIBSSH2_FREE(session, data);
974
0
            channel->setenv_state = libssh2_NB_state_idle;
975
0
            return 0;
976
0
        }
977
978
0
        LIBSSH2_FREE(session, data);
979
0
    }
980
981
0
    channel->setenv_state = libssh2_NB_state_idle;
982
0
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
983
0
                          "Unable to complete request for channel-setenv");
984
0
}
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
0
{
996
0
    int rc;
997
998
0
    if(!channel)
999
0
        return LIBSSH2_ERROR_BAD_USE;
1000
1001
0
    BLOCK_ADJUST(rc, channel->session,
1002
0
                 channel_setenv(channel, varname, varname_len,
1003
0
                                value, value_len));
1004
0
    return rc;
1005
0
}
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
0
{
1017
0
    LIBSSH2_SESSION *session = channel->session;
1018
0
    unsigned char *s;
1019
0
    static const unsigned char reply_codes[3] =
1020
0
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1021
0
    int rc;
1022
1023
0
    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
0
        if(term_len + modes_len > 256) {
1028
0
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1029
0
                                  "term + mode lengths too large");
1030
0
        }
1031
1032
0
        channel->reqPTY_packet_len = term_len + modes_len + 41;
1033
1034
        /* Zero the whole thing out */
1035
0
        memset(&channel->reqPTY_packet_requirev_state, 0,
1036
0
               sizeof(channel->reqPTY_packet_requirev_state));
1037
1038
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1039
0
                       "Allocating tty on channel %u/%u", channel->local.id,
1040
0
                       channel->remote.id));
1041
1042
0
        s = channel->reqPTY_packet;
1043
1044
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1045
0
        _libssh2_store_u32(&s, channel->remote.id);
1046
0
        _libssh2_store_str(&s, (const char *)"pty-req", sizeof("pty-req") - 1);
1047
1048
0
        *(s++) = 0x01;
1049
1050
0
        _libssh2_store_str(&s, term, term_len);
1051
0
        _libssh2_store_u32(&s, width);
1052
0
        _libssh2_store_u32(&s, height);
1053
0
        _libssh2_store_u32(&s, width_px);
1054
0
        _libssh2_store_u32(&s, height_px);
1055
0
        _libssh2_store_str(&s, modes, modes_len);
1056
1057
0
        channel->reqPTY_state = libssh2_NB_state_created;
1058
0
    }
1059
1060
0
    if(channel->reqPTY_state == libssh2_NB_state_created) {
1061
0
        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1062
0
                                     channel->reqPTY_packet_len,
1063
0
                                     NULL, 0);
1064
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1065
0
            _libssh2_error(session, rc,
1066
0
                           "Would block sending pty request");
1067
0
            return rc;
1068
0
        }
1069
0
        else if(rc) {
1070
0
            channel->reqPTY_state = libssh2_NB_state_idle;
1071
0
            return _libssh2_error(session, rc,
1072
0
                                  "Unable to send pty-request packet");
1073
0
        }
1074
0
        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1075
1076
0
        channel->reqPTY_state = libssh2_NB_state_sent;
1077
0
    }
1078
1079
0
    if(channel->reqPTY_state == libssh2_NB_state_sent) {
1080
0
        unsigned char *data;
1081
0
        size_t data_len;
1082
0
        unsigned char code;
1083
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1084
0
                                      1, channel->reqPTY_local_channel, 4,
1085
0
                                      &channel->reqPTY_packet_requirev_state);
1086
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1087
0
            return rc;
1088
0
        }
1089
0
        else if(rc || data_len < 1) {
1090
0
            channel->reqPTY_state = libssh2_NB_state_idle;
1091
0
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1092
0
                                  "Failed to require the PTY package");
1093
0
        }
1094
1095
0
        code = data[0];
1096
1097
0
        LIBSSH2_FREE(session, data);
1098
0
        channel->reqPTY_state = libssh2_NB_state_idle;
1099
1100
0
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1101
0
            return 0;
1102
0
    }
1103
1104
0
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1105
0
                          "Unable to complete request for "
1106
0
                          "channel request-pty");
1107
0
}
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
0
{
1117
0
    LIBSSH2_SESSION *session = channel->session;
1118
0
    unsigned char *s;
1119
0
    static const unsigned char reply_codes[3] =
1120
0
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1121
0
    int rc;
1122
1123
0
    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
0
        if(request_str_len > 26) {
1128
0
            return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
1129
0
                                  "request_str length too large");
1130
0
        }
1131
1132
        /*
1133
         *  Length: 24 or 36 = packet_type(1) + channel(4) + req_len(4) +
1134
         *    request_str (variable) + want_reply (1) */
1135
0
        channel->req_auth_agent_packet_len = 10 + request_str_len;
1136
1137
        /* Zero out the requireev state to reset */
1138
0
        memset(&channel->req_auth_agent_requirev_state, 0,
1139
0
               sizeof(channel->req_auth_agent_requirev_state));
1140
1141
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1142
0
                       "Requesting auth agent on channel %u/%u",
1143
0
                       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
0
        s = channel->req_auth_agent_packet;
1152
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1153
0
        _libssh2_store_u32(&s, channel->remote.id);
1154
0
        _libssh2_store_str(&s, (const char *)request_str, request_str_len);
1155
0
        *(s++) = 0x01;
1156
1157
0
        channel->req_auth_agent_state = libssh2_NB_state_created;
1158
0
    }
1159
1160
0
    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
0
        rc = _libssh2_transport_send(session, channel->req_auth_agent_packet,
1164
0
                                     channel->req_auth_agent_packet_len,
1165
0
                                     NULL, 0);
1166
1167
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1168
0
            _libssh2_error(session, rc,
1169
0
                           "Would block sending auth-agent request");
1170
0
            return rc;
1171
0
        }
1172
0
        else if(rc) {
1173
0
            channel->req_auth_agent_state = libssh2_NB_state_idle;
1174
0
            return _libssh2_error(session, rc,
1175
0
                                  "Unable to send auth-agent request");
1176
0
        }
1177
0
        _libssh2_htonu32(channel->req_auth_agent_local_channel,
1178
0
                         channel->local.id);
1179
0
        channel->req_auth_agent_state = libssh2_NB_state_sent;
1180
0
    }
1181
1182
0
    if(channel->req_auth_agent_state == libssh2_NB_state_sent) {
1183
0
        unsigned char *data;
1184
0
        size_t data_len;
1185
0
        unsigned char code;
1186
1187
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1188
0
                                      1, channel->req_auth_agent_local_channel,
1189
0
                                      4,
1190
0
                                      &channel->req_auth_agent_requirev_state);
1191
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1192
0
            return rc;
1193
0
        }
1194
0
        else if(rc) {
1195
0
            channel->req_auth_agent_state = libssh2_NB_state_idle;
1196
0
            return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
1197
0
                                  "Failed to request auth-agent");
1198
0
        }
1199
1200
0
        code = data[0];
1201
1202
0
        LIBSSH2_FREE(session, data);
1203
0
        channel->req_auth_agent_state = libssh2_NB_state_idle;
1204
1205
0
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1206
0
            return 0;
1207
0
    }
1208
1209
0
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1210
0
                          "Unable to complete request for auth-agent");
1211
0
}
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
0
{
1224
0
    int rc;
1225
1226
0
    if(!channel)
1227
0
        return LIBSSH2_ERROR_BAD_USE;
1228
1229
0
    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
0
    if(channel->req_auth_agent_try_state == libssh2_NB_state_idle) {
1236
0
        BLOCK_ADJUST(rc, channel->session,
1237
0
                     channel_request_auth_agent(channel,
1238
0
                                                "auth-agent-req@openssh.com",
1239
0
                                                26));
1240
1241
        /* If we failed (but not with EAGAIN), then we move onto
1242
         * the next step to try another request type. */
1243
0
        if(rc != LIBSSH2_ERROR_NONE &&
1244
0
           rc != LIBSSH2_ERROR_EAGAIN)
1245
0
            channel->req_auth_agent_try_state = libssh2_NB_state_sent;
1246
0
    }
1247
1248
0
    if(channel->req_auth_agent_try_state == libssh2_NB_state_sent) {
1249
0
        BLOCK_ADJUST(rc, channel->session,
1250
0
                     channel_request_auth_agent(channel,
1251
0
                                                "auth-agent-req", 14));
1252
1253
        /* If we failed without an EAGAIN, then move on with this
1254
         * state machine. */
1255
0
        if(rc != LIBSSH2_ERROR_NONE &&
1256
0
           rc != LIBSSH2_ERROR_EAGAIN)
1257
0
            channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
1258
0
    }
1259
1260
    /* If things are good, reset the try state. */
1261
0
    if(rc == LIBSSH2_ERROR_NONE)
1262
0
        channel->req_auth_agent_try_state = libssh2_NB_state_idle;
1263
1264
0
    return rc;
1265
0
}
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
0
{
1277
0
    int rc;
1278
1279
0
    if(!channel)
1280
0
        return LIBSSH2_ERROR_BAD_USE;
1281
1282
0
    BLOCK_ADJUST(rc, channel->session,
1283
0
                 channel_request_pty(channel, term, term_len, modes,
1284
0
                                     modes_len, width, height,
1285
0
                                     width_px, height_px));
1286
0
    return rc;
1287
0
}
1288
1289
static int
1290
channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width,
1291
                         int height, int width_px, int height_px)
1292
0
{
1293
0
    LIBSSH2_SESSION *session = channel->session;
1294
0
    unsigned char *s;
1295
0
    int rc;
1296
0
    int retcode = LIBSSH2_ERROR_PROTO;
1297
1298
0
    if(channel->reqPTY_state == libssh2_NB_state_idle) {
1299
0
        channel->reqPTY_packet_len = 39;
1300
1301
        /* Zero the whole thing out */
1302
0
        memset(&channel->reqPTY_packet_requirev_state, 0,
1303
0
               sizeof(channel->reqPTY_packet_requirev_state));
1304
1305
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1306
0
                       "changing tty size on channel %u/%u",
1307
0
                       channel->local.id,
1308
0
                       channel->remote.id));
1309
1310
0
        s = channel->reqPTY_packet;
1311
1312
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1313
0
        _libssh2_store_u32(&s, channel->remote.id);
1314
0
        _libssh2_store_str(&s, (const char *)"window-change",
1315
0
                           sizeof("window-change") - 1);
1316
0
        *(s++) = 0x00; /* Don't reply */
1317
0
        _libssh2_store_u32(&s, width);
1318
0
        _libssh2_store_u32(&s, height);
1319
0
        _libssh2_store_u32(&s, width_px);
1320
0
        _libssh2_store_u32(&s, height_px);
1321
1322
0
        channel->reqPTY_state = libssh2_NB_state_created;
1323
0
    }
1324
1325
0
    if(channel->reqPTY_state == libssh2_NB_state_created) {
1326
0
        rc = _libssh2_transport_send(session, channel->reqPTY_packet,
1327
0
                                     channel->reqPTY_packet_len,
1328
0
                                     NULL, 0);
1329
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1330
0
            _libssh2_error(session, rc,
1331
0
                           "Would block sending window-change request");
1332
0
            return rc;
1333
0
        }
1334
0
        else if(rc) {
1335
0
            channel->reqPTY_state = libssh2_NB_state_idle;
1336
0
            return _libssh2_error(session, rc,
1337
0
                                  "Unable to send window-change packet");
1338
0
        }
1339
0
        _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id);
1340
0
        retcode = LIBSSH2_ERROR_NONE;
1341
0
    }
1342
1343
0
    channel->reqPTY_state = libssh2_NB_state_idle;
1344
0
    return retcode;
1345
0
}
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
0
{
1351
0
    int rc;
1352
1353
0
    if(!channel)
1354
0
        return LIBSSH2_ERROR_BAD_USE;
1355
1356
0
    BLOCK_ADJUST(rc, channel->session,
1357
0
                 channel_request_pty_size(channel, width, height, width_px,
1358
0
                                          height_px));
1359
0
    return rc;
1360
0
}
1361
1362
/* Keep this an even number */
1363
0
#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
0
{
1374
0
    LIBSSH2_SESSION *session = channel->session;
1375
0
    unsigned char *s;
1376
0
    static const unsigned char reply_codes[3] =
1377
0
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1378
0
    size_t proto_len =
1379
0
        auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
1380
0
    size_t cookie_len =
1381
0
        auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
1382
0
    int rc;
1383
1384
0
    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
0
        channel->reqX11_packet_len = proto_len + cookie_len + 30;
1389
1390
        /* Zero the whole thing out */
1391
0
        memset(&channel->reqX11_packet_requirev_state, 0,
1392
0
               sizeof(channel->reqX11_packet_requirev_state));
1393
1394
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1395
0
                       "Requesting x11-req for channel %u/%u: single=%d "
1396
0
                       "proto=%s cookie=%s screen=%d",
1397
0
                       channel->local.id, channel->remote.id,
1398
0
                       single_connection,
1399
0
                       auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1400
0
                       auth_cookie ? auth_cookie : "<random>", screen_number));
1401
1402
0
        s = channel->reqX11_packet =
1403
0
            LIBSSH2_ALLOC(session, channel->reqX11_packet_len);
1404
0
        if(!channel->reqX11_packet) {
1405
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1406
0
                                  "Unable to allocate memory for pty-request");
1407
0
        }
1408
1409
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1410
0
        _libssh2_store_u32(&s, channel->remote.id);
1411
0
        _libssh2_store_str(&s, "x11-req", sizeof("x11-req") - 1);
1412
1413
0
        *(s++) = 0x01;          /* want_reply */
1414
0
        *(s++) = single_connection ? 0x01 : 0x00;
1415
1416
0
        _libssh2_store_str(&s, auth_proto ? auth_proto : "MIT-MAGIC-COOKIE-1",
1417
0
                           proto_len);
1418
1419
0
        _libssh2_store_u32(&s, (uint32_t)cookie_len);
1420
0
        if(auth_cookie) {
1421
0
            memcpy(s, auth_cookie, cookie_len);
1422
0
        }
1423
0
        else {
1424
0
            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
0
            unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
1430
1431
0
            if(_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2)) {
1432
0
                return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
1433
0
                                      "Unable to get random bytes "
1434
0
                                      "for x11-req cookie");
1435
0
            }
1436
0
            for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
1437
0
                snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
1438
0
            }
1439
0
        }
1440
0
        s += cookie_len;
1441
1442
0
        _libssh2_store_u32(&s, screen_number);
1443
0
        channel->reqX11_state = libssh2_NB_state_created;
1444
0
    }
1445
1446
0
    if(channel->reqX11_state == libssh2_NB_state_created) {
1447
0
        rc = _libssh2_transport_send(session, channel->reqX11_packet,
1448
0
                                     channel->reqX11_packet_len,
1449
0
                                     NULL, 0);
1450
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1451
0
            _libssh2_error(session, rc,
1452
0
                           "Would block sending X11-req packet");
1453
0
            return rc;
1454
0
        }
1455
0
        if(rc) {
1456
0
            LIBSSH2_FREE(session, channel->reqX11_packet);
1457
0
            channel->reqX11_packet = NULL;
1458
0
            channel->reqX11_state = libssh2_NB_state_idle;
1459
0
            return _libssh2_error(session, rc,
1460
0
                                  "Unable to send x11-req packet");
1461
0
        }
1462
0
        LIBSSH2_FREE(session, channel->reqX11_packet);
1463
0
        channel->reqX11_packet = NULL;
1464
1465
0
        _libssh2_htonu32(channel->reqX11_local_channel, channel->local.id);
1466
1467
0
        channel->reqX11_state = libssh2_NB_state_sent;
1468
0
    }
1469
1470
0
    if(channel->reqX11_state == libssh2_NB_state_sent) {
1471
0
        size_t data_len;
1472
0
        unsigned char *data;
1473
0
        unsigned char code;
1474
1475
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1476
0
                                      1, channel->reqX11_local_channel, 4,
1477
0
                                      &channel->reqX11_packet_requirev_state);
1478
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1479
0
            return rc;
1480
0
        }
1481
0
        else if(rc || data_len < 1) {
1482
0
            channel->reqX11_state = libssh2_NB_state_idle;
1483
0
            return _libssh2_error(session, rc,
1484
0
                                  "waiting for x11-req response packet");
1485
0
        }
1486
1487
0
        code = data[0];
1488
0
        LIBSSH2_FREE(session, data);
1489
0
        channel->reqX11_state = libssh2_NB_state_idle;
1490
1491
0
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1492
0
            return 0;
1493
0
    }
1494
1495
0
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1496
0
                          "Unable to complete request for channel x11-req");
1497
0
}
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
0
{
1508
0
    int rc;
1509
1510
0
    if(!channel)
1511
0
        return LIBSSH2_ERROR_BAD_USE;
1512
1513
0
    BLOCK_ADJUST(rc, channel->session,
1514
0
                 channel_x11_req(channel, single_connection, auth_proto,
1515
0
                                 auth_cookie, screen_number));
1516
0
    return rc;
1517
0
}
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
0
{
1530
0
    LIBSSH2_SESSION *session = channel->session;
1531
0
    unsigned char *s;
1532
0
    static const unsigned char reply_codes[3] =
1533
0
        { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 };
1534
0
    int rc;
1535
1536
0
    if(channel->process_state == libssh2_NB_state_end) {
1537
0
        return _libssh2_error(session, LIBSSH2_ERROR_BAD_USE,
1538
0
                              "Channel can not be reused");
1539
0
    }
1540
1541
0
    if(channel->process_state == libssh2_NB_state_idle) {
1542
        /* 10 = packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
1543
0
        channel->process_packet_len = request_len + 10;
1544
1545
        /* Zero the whole thing out */
1546
0
        memset(&channel->process_packet_requirev_state, 0,
1547
0
               sizeof(channel->process_packet_requirev_state));
1548
1549
0
        if(message)
1550
0
            channel->process_packet_len += + 4;
1551
1552
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
1553
0
                       "starting request(%s) on channel %u/%u, message=%s",
1554
0
                       request, channel->local.id, channel->remote.id,
1555
0
                       message ? message : "<null>"));
1556
0
        s = channel->process_packet =
1557
0
            LIBSSH2_ALLOC(session, channel->process_packet_len);
1558
0
        if(!channel->process_packet)
1559
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1560
0
                                  "Unable to allocate memory "
1561
0
                                  "for channel-process request");
1562
1563
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
1564
0
        _libssh2_store_u32(&s, channel->remote.id);
1565
0
        _libssh2_store_str(&s, request, request_len);
1566
0
        *(s++) = 0x01;
1567
1568
0
        if(message)
1569
0
            _libssh2_store_u32(&s, (uint32_t)message_len);
1570
1571
0
        channel->process_state = libssh2_NB_state_created;
1572
0
    }
1573
1574
0
    if(channel->process_state == libssh2_NB_state_created) {
1575
0
        rc = _libssh2_transport_send(session,
1576
0
                                     channel->process_packet,
1577
0
                                     channel->process_packet_len,
1578
0
                                     (const unsigned char *)message,
1579
0
                                     message_len);
1580
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1581
0
            _libssh2_error(session, rc,
1582
0
                           "Would block sending channel request");
1583
0
            return rc;
1584
0
        }
1585
0
        else if(rc) {
1586
0
            LIBSSH2_FREE(session, channel->process_packet);
1587
0
            channel->process_packet = NULL;
1588
0
            channel->process_state = libssh2_NB_state_end;
1589
0
            return _libssh2_error(session, rc,
1590
0
                                  "Unable to send channel request");
1591
0
        }
1592
0
        LIBSSH2_FREE(session, channel->process_packet);
1593
0
        channel->process_packet = NULL;
1594
1595
0
        _libssh2_htonu32(channel->process_local_channel, channel->local.id);
1596
1597
0
        channel->process_state = libssh2_NB_state_sent;
1598
0
    }
1599
1600
0
    if(channel->process_state == libssh2_NB_state_sent) {
1601
0
        unsigned char *data;
1602
0
        size_t data_len;
1603
0
        unsigned char code;
1604
0
        rc = _libssh2_packet_requirev(session, reply_codes, &data, &data_len,
1605
0
                                      1, channel->process_local_channel, 4,
1606
0
                                      &channel->process_packet_requirev_state);
1607
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
1608
0
            return rc;
1609
0
        }
1610
0
        else if(rc || data_len < 1) {
1611
0
            channel->process_state = libssh2_NB_state_end;
1612
0
            return _libssh2_error(session, rc,
1613
0
                                  "Failed waiting for channel success");
1614
0
        }
1615
1616
0
        code = data[0];
1617
0
        LIBSSH2_FREE(session, data);
1618
0
        channel->process_state = libssh2_NB_state_end;
1619
1620
0
        if(code == SSH_MSG_CHANNEL_SUCCESS)
1621
0
            return 0;
1622
0
    }
1623
1624
0
    return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED,
1625
0
                          "Unable to complete request for "
1626
0
                          "channel-process-startup");
1627
0
}
1628
1629
/*
1630
 * libssh2_channel_process_startup
1631
 *
1632
 * Primitive for libssh2_channel_(shell|exec|subsystem)
1633
 */
1634
LIBSSH2_API int
1635
libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel,
1636
                                const char *req, unsigned int req_len,
1637
                                const char *msg, unsigned int msg_len)
1638
0
{
1639
0
    int rc;
1640
1641
0
    if(!channel)
1642
0
        return LIBSSH2_ERROR_BAD_USE;
1643
1644
0
    BLOCK_ADJUST(rc, channel->session,
1645
0
                 _libssh2_channel_process_startup(channel, req, req_len,
1646
0
                                                  msg, msg_len));
1647
0
    return rc;
1648
0
}
1649
1650
1651
/*
1652
 * libssh2_channel_set_blocking
1653
 *
1654
 * Set a channel's BEHAVIOR blocking on or off. The socket will remain non-
1655
 * blocking.
1656
 */
1657
LIBSSH2_API void
1658
libssh2_channel_set_blocking(LIBSSH2_CHANNEL * channel, int blocking)
1659
0
{
1660
0
    if(channel)
1661
0
        (void)_libssh2_session_set_blocking(channel->session, blocking);
1662
0
}
1663
1664
/*
1665
 * _libssh2_channel_flush
1666
 *
1667
 * Flush data from one (or all) stream
1668
 * Returns number of bytes flushed, or negative on failure
1669
 */
1670
int
1671
_libssh2_channel_flush(LIBSSH2_CHANNEL *channel, int streamid)
1672
0
{
1673
0
    if(channel->flush_state == libssh2_NB_state_idle) {
1674
0
        LIBSSH2_PACKET *packet =
1675
0
            _libssh2_list_first(&channel->session->packets);
1676
0
        channel->flush_refund_bytes = 0;
1677
0
        channel->flush_flush_bytes = 0;
1678
1679
0
        while(packet) {
1680
0
            unsigned char packet_type;
1681
0
            LIBSSH2_PACKET *next = _libssh2_list_next(&packet->node);
1682
1683
0
            if(packet->data_len < 1) {
1684
0
                packet = next;
1685
0
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
1686
0
                               "Unexpected packet length"));
1687
0
                continue;
1688
0
            }
1689
1690
0
            packet_type = packet->data[0];
1691
1692
0
            if(((packet_type == SSH_MSG_CHANNEL_DATA)
1693
0
                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
1694
0
               && ((packet->data_len >= 5)
1695
0
                   && (_libssh2_ntohu32(packet->data + 1)
1696
0
                       == channel->local.id))) {
1697
                /* It's our channel at least */
1698
0
                int packet_stream_id;
1699
1700
0
                if(packet_type == SSH_MSG_CHANNEL_DATA) {
1701
0
                    packet_stream_id = 0;
1702
0
                }
1703
0
                else if(packet->data_len >= 9) {
1704
0
                    packet_stream_id = _libssh2_ntohu32(packet->data + 5);
1705
0
                }
1706
0
                else {
1707
0
                    channel->flush_state = libssh2_NB_state_idle;
1708
0
                    return _libssh2_error(channel->session,
1709
0
                                          LIBSSH2_ERROR_PROTO,
1710
0
                                          "Unexpected packet length");
1711
0
                }
1712
1713
0
                if((streamid == LIBSSH2_CHANNEL_FLUSH_ALL)
1714
0
                    || ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)
1715
0
                        && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA)
1716
0
                            || (streamid == packet_stream_id)))
1717
0
                    || ((packet_type == SSH_MSG_CHANNEL_DATA)
1718
0
                        && (streamid == 0))) {
1719
0
                    size_t bytes_to_flush = packet->data_len -
1720
0
                        packet->data_head;
1721
1722
0
                    _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1723
0
                                   "Flushing %ld bytes of data from stream "
1724
0
                                   "%d on channel %u/%u",
1725
0
                                   (long)bytes_to_flush, packet_stream_id,
1726
0
                                   channel->local.id, channel->remote.id));
1727
1728
                    /* It's one of the streams we wanted to flush */
1729
0
                    channel->flush_refund_bytes += packet->data_len - 13;
1730
0
                    channel->flush_flush_bytes += bytes_to_flush;
1731
1732
0
                    LIBSSH2_FREE(channel->session, packet->data);
1733
1734
                    /* remove this packet from the parent's list */
1735
0
                    _libssh2_list_remove(&packet->node);
1736
0
                    LIBSSH2_FREE(channel->session, packet);
1737
0
                }
1738
0
            }
1739
0
            packet = next;
1740
0
        }
1741
1742
0
        channel->flush_state = libssh2_NB_state_created;
1743
0
    }
1744
1745
0
    channel->read_avail -= channel->flush_flush_bytes;
1746
0
    channel->remote.window_size -= (uint32_t)channel->flush_flush_bytes;
1747
1748
0
    if(channel->flush_refund_bytes) {
1749
0
        int rc =
1750
0
            _libssh2_channel_receive_window_adjust(channel,
1751
0
                                         (uint32_t)channel->flush_refund_bytes,
1752
0
                                         1, NULL);
1753
0
        if(rc == LIBSSH2_ERROR_EAGAIN)
1754
0
            return rc;
1755
0
    }
1756
1757
0
    channel->flush_state = libssh2_NB_state_idle;
1758
1759
0
    return (int)channel->flush_flush_bytes;
1760
0
}
1761
1762
/*
1763
 * libssh2_channel_flush_ex
1764
 *
1765
 * Flush data from one (or all) stream
1766
 * Returns number of bytes flushed, or negative on failure
1767
 */
1768
LIBSSH2_API int
1769
libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int stream)
1770
0
{
1771
0
    int rc;
1772
1773
0
    if(!channel)
1774
0
        return LIBSSH2_ERROR_BAD_USE;
1775
1776
0
    BLOCK_ADJUST(rc, channel->session,
1777
0
                 _libssh2_channel_flush(channel, stream));
1778
0
    return rc;
1779
0
}
1780
1781
/*
1782
 * libssh2_channel_get_exit_status
1783
 *
1784
 * Return the channel's program exit status. Note that the actual protocol
1785
 * provides the full 32bit this function returns.  We cannot abuse it to
1786
 * return error values in case of errors so we return a zero if channel is
1787
 * NULL.
1788
 */
1789
LIBSSH2_API int
1790
libssh2_channel_get_exit_status(LIBSSH2_CHANNEL *channel)
1791
0
{
1792
0
    if(!channel)
1793
0
        return 0;
1794
1795
0
    return channel->exit_status;
1796
0
}
1797
1798
/*
1799
 * libssh2_channel_get_exit_signal
1800
 *
1801
 * Get exit signal (without leading "SIG"), error message, and language
1802
 * tag into newly allocated buffers of indicated length.  Caller can
1803
 * use NULL pointers to indicate that the value should not be set.  The
1804
 * *_len variables are set if they are non-NULL even if the
1805
 * corresponding string parameter is NULL.  Returns LIBSSH2_ERROR_NONE
1806
 * on success, or an API error code.
1807
 */
1808
LIBSSH2_API int
1809
libssh2_channel_get_exit_signal(LIBSSH2_CHANNEL *channel,
1810
                                char **exitsignal,
1811
                                size_t *exitsignal_len,
1812
                                char **errmsg,
1813
                                size_t *errmsg_len,
1814
                                char **langtag,
1815
                                size_t *langtag_len)
1816
0
{
1817
0
    size_t namelen = 0;
1818
1819
0
    if(channel) {
1820
0
        LIBSSH2_SESSION *session = channel->session;
1821
1822
0
        if(channel->exit_signal) {
1823
0
            namelen = strlen(channel->exit_signal);
1824
0
            if(exitsignal) {
1825
0
                *exitsignal = LIBSSH2_ALLOC(session, namelen + 1);
1826
0
                if(!*exitsignal) {
1827
0
                    return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
1828
0
                                  "Unable to allocate memory for signal name");
1829
0
                }
1830
0
                memcpy(*exitsignal, channel->exit_signal, namelen);
1831
0
                (*exitsignal)[namelen] = '\0';
1832
0
            }
1833
0
            if(exitsignal_len)
1834
0
                *exitsignal_len = namelen;
1835
0
        }
1836
0
        else {
1837
0
            if(exitsignal)
1838
0
                *exitsignal = NULL;
1839
0
            if(exitsignal_len)
1840
0
                *exitsignal_len = 0;
1841
0
        }
1842
1843
        /* TODO: set error message and language tag */
1844
1845
0
        if(errmsg)
1846
0
            *errmsg = NULL;
1847
1848
0
        if(errmsg_len)
1849
0
            *errmsg_len = 0;
1850
1851
0
        if(langtag)
1852
0
            *langtag = NULL;
1853
1854
0
        if(langtag_len)
1855
0
            *langtag_len = 0;
1856
0
    }
1857
1858
0
    return LIBSSH2_ERROR_NONE;
1859
0
}
1860
1861
/*
1862
 * _libssh2_channel_receive_window_adjust
1863
 *
1864
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1865
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1866
 * adjustment amount will be queued for a later packet.
1867
 *
1868
 * Calls _libssh2_error() !
1869
 */
1870
int
1871
_libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel,
1872
                                       uint32_t adjustment,
1873
                                       unsigned char force,
1874
                                       unsigned int *store)
1875
0
{
1876
0
    int rc;
1877
1878
0
    if(store)
1879
0
        *store = channel->remote.window_size;
1880
1881
0
    if(channel->adjust_state == libssh2_NB_state_idle) {
1882
0
        if(!force
1883
0
            && (adjustment + channel->adjust_queue <
1884
0
                LIBSSH2_CHANNEL_MINADJUST)) {
1885
0
            _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1886
0
                           "Queueing %u bytes for receive window adjustment "
1887
0
                           "for channel %u/%u",
1888
0
                           adjustment, channel->local.id, channel->remote.id));
1889
0
            channel->adjust_queue += adjustment;
1890
0
            return 0;
1891
0
        }
1892
1893
0
        if(!adjustment && !channel->adjust_queue) {
1894
0
            return 0;
1895
0
        }
1896
1897
0
        adjustment += channel->adjust_queue;
1898
0
        channel->adjust_queue = 0;
1899
1900
        /* Adjust the window based on the block we just freed */
1901
0
        channel->adjust_adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
1902
0
        _libssh2_htonu32(&channel->adjust_adjust[1], channel->remote.id);
1903
0
        _libssh2_htonu32(&channel->adjust_adjust[5], adjustment);
1904
0
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
1905
0
                       "Adjusting window %u bytes for data on "
1906
0
                       "channel %u/%u",
1907
0
                       adjustment, channel->local.id, channel->remote.id));
1908
1909
0
        channel->adjust_state = libssh2_NB_state_created;
1910
0
    }
1911
1912
0
    rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9,
1913
0
                                 NULL, 0);
1914
0
    if(rc == LIBSSH2_ERROR_EAGAIN) {
1915
0
        _libssh2_error(channel->session, rc,
1916
0
                       "Would block sending window adjust");
1917
0
        return rc;
1918
0
    }
1919
0
    else if(rc) {
1920
0
        channel->adjust_queue = adjustment;
1921
0
        return _libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND,
1922
0
                              "Unable to send transfer-window adjustment "
1923
0
                              "packet, deferring");
1924
0
    }
1925
0
    else {
1926
0
        channel->remote.window_size += adjustment;
1927
0
    }
1928
1929
0
    channel->adjust_state = libssh2_NB_state_idle;
1930
1931
0
    return 0;
1932
0
}
1933
1934
#ifndef LIBSSH2_NO_DEPRECATED
1935
/*
1936
 * libssh2_channel_receive_window_adjust (DEPRECATED, DO NOT USE!)
1937
 *
1938
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1939
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1940
 * adjustment amount will be queued for a later packet.
1941
 *
1942
 * Returns the new size of the receive window (as understood by remote end).
1943
 * Note that it might return EAGAIN too which is highly stupid.
1944
 *
1945
 */
1946
LIBSSH2_API unsigned long
1947
libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel,
1948
                                      unsigned long adj,
1949
                                      unsigned char force)
1950
0
{
1951
0
    unsigned int window;
1952
0
    int rc;
1953
1954
0
    if(!channel)
1955
0
        return (unsigned long)LIBSSH2_ERROR_BAD_USE;
1956
1957
0
    BLOCK_ADJUST(rc, channel->session,
1958
0
                 _libssh2_channel_receive_window_adjust(channel,
1959
0
                                                        (uint32_t)adj,
1960
0
                                                        force, &window));
1961
1962
    /* stupid - but this is how it was made to work before and this is just
1963
       kept for backwards compatibility */
1964
0
    return rc ? (unsigned long)rc : window;
1965
0
}
1966
#endif
1967
1968
/*
1969
 * libssh2_channel_receive_window_adjust2
1970
 *
1971
 * Adjust the receive window for a channel by adjustment bytes. If the amount
1972
 * to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0 the
1973
 * adjustment amount will be queued for a later packet.
1974
 *
1975
 * Stores the new size of the receive window in the data 'window' points to.
1976
 *
1977
 * Returns the "normal" error code: 0 for success, negative for failure.
1978
 */
1979
LIBSSH2_API int
1980
libssh2_channel_receive_window_adjust2(LIBSSH2_CHANNEL *channel,
1981
                                       unsigned long adj,
1982
                                       unsigned char force,
1983
                                       unsigned int *window)
1984
0
{
1985
0
    int rc;
1986
1987
0
    if(!channel)
1988
0
        return LIBSSH2_ERROR_BAD_USE;
1989
1990
0
    BLOCK_ADJUST(rc, channel->session,
1991
0
                 _libssh2_channel_receive_window_adjust(channel,
1992
0
                                                        (uint32_t)adj,
1993
0
                                                        force, window));
1994
0
    return rc;
1995
0
}
1996
1997
int
1998
_libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode)
1999
0
{
2000
0
    if(channel->extData2_state == libssh2_NB_state_idle) {
2001
0
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
2002
0
                       "Setting channel %u/%u handle_extended_data"
2003
0
                       " mode to %d",
2004
0
                       channel->local.id, channel->remote.id, ignore_mode));
2005
0
        channel->remote.extended_data_ignore_mode = (char)ignore_mode;
2006
2007
0
        channel->extData2_state = libssh2_NB_state_created;
2008
0
    }
2009
2010
0
    if(channel->extData2_state == libssh2_NB_state_idle) {
2011
0
        if(ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) {
2012
0
            int rc =
2013
0
                _libssh2_channel_flush(channel,
2014
0
                                       LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA);
2015
0
            if(LIBSSH2_ERROR_EAGAIN == rc)
2016
0
                return rc;
2017
0
        }
2018
0
    }
2019
2020
0
    channel->extData2_state = libssh2_NB_state_idle;
2021
0
    return 0;
2022
0
}
2023
2024
/*
2025
 * libssh2_channel_handle_extended_data2
2026
 *
2027
 */
2028
LIBSSH2_API int
2029
libssh2_channel_handle_extended_data2(LIBSSH2_CHANNEL *channel,
2030
                                      int mode)
2031
0
{
2032
0
    int rc;
2033
2034
0
    if(!channel)
2035
0
        return LIBSSH2_ERROR_BAD_USE;
2036
2037
0
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_extended_data(channel,
2038
0
                                                                      mode));
2039
0
    return rc;
2040
0
}
2041
2042
#ifndef LIBSSH2_NO_DEPRECATED
2043
/*
2044
 * libssh2_channel_handle_extended_data (DEPRECATED, DO NOT USE!)
2045
 *
2046
 * How should extended data look to the calling app?  Keep it in separate
2047
 * channels[_read() _read_stdder()]? (NORMAL) Merge the extended data to the
2048
 * standard data? [everything via _read()]? (MERGE) Ignore it entirely [toss
2049
 * out packets as they come in]? (IGNORE)
2050
 */
2051
LIBSSH2_API void
2052
libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel,
2053
                                     int ignore_mode)
2054
0
{
2055
0
    (void)libssh2_channel_handle_extended_data2(channel, ignore_mode);
2056
0
}
2057
#endif
2058
2059
2060
/*
2061
 * _libssh2_channel_read
2062
 *
2063
 * Read data from a channel
2064
 *
2065
 * It is important to not return 0 until the currently read channel is
2066
 * complete. If we read stuff from the wire but it was no payload data to fill
2067
 * in the buffer with, we MUST make sure to return LIBSSH2_ERROR_EAGAIN.
2068
 *
2069
 * The receive window must be maintained (enlarged) by the user of this
2070
 * function.
2071
 */
2072
ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
2073
                              char *buf, size_t buflen)
2074
0
{
2075
0
    LIBSSH2_SESSION *session = channel->session;
2076
0
    int rc;
2077
0
    size_t bytes_read = 0;
2078
0
    size_t bytes_want;
2079
0
    int unlink_packet;
2080
0
    LIBSSH2_PACKET *read_packet;
2081
0
    LIBSSH2_PACKET *read_next;
2082
2083
0
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2084
0
                   "channel_read() wants %ld bytes from channel %u/%u "
2085
0
                   "stream #%d",
2086
0
                   (long)buflen, channel->local.id, channel->remote.id,
2087
0
                   stream_id));
2088
2089
    /* expand the receiving window first if it has become too narrow */
2090
0
    if((channel->read_state == libssh2_NB_state_jump1) ||
2091
0
       (channel->remote.window_size <
2092
0
        channel->remote.window_size_initial / 4 * 3 + buflen)) {
2093
2094
0
        uint32_t adjustment = (uint32_t)(channel->remote.window_size_initial +
2095
0
            buflen - channel->remote.window_size);
2096
0
        if(adjustment < LIBSSH2_CHANNEL_MINADJUST)
2097
0
            adjustment = LIBSSH2_CHANNEL_MINADJUST;
2098
2099
        /* the actual window adjusting may not finish so we need to deal with
2100
           this special state here */
2101
0
        channel->read_state = libssh2_NB_state_jump1;
2102
0
        rc = _libssh2_channel_receive_window_adjust(channel, adjustment,
2103
0
                                                    0, NULL);
2104
0
        if(rc)
2105
0
            return rc;
2106
2107
0
        channel->read_state = libssh2_NB_state_idle;
2108
0
    }
2109
2110
    /* Process all pending incoming packets. Tests prove that this way
2111
       produces faster transfers. */
2112
0
    do {
2113
0
        rc = _libssh2_transport_read(session);
2114
0
    } while(rc > 0);
2115
2116
0
    if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
2117
0
        return _libssh2_error(session, rc, "transport read");
2118
2119
0
    read_packet = _libssh2_list_first(&session->packets);
2120
0
    while(read_packet && (bytes_read < buflen)) {
2121
        /* previously this loop condition also checked for
2122
           !channel->remote.close but we cannot let it do this:
2123
2124
           We may have a series of packets to read that are still pending even
2125
           if a close has been received. Acknowledging the close too early
2126
           makes us flush buffers prematurely and loose data.
2127
        */
2128
2129
0
        LIBSSH2_PACKET *readpkt = read_packet;
2130
2131
        /* In case packet gets destroyed during this iteration */
2132
0
        read_next = _libssh2_list_next(&readpkt->node);
2133
2134
0
        if(readpkt->data_len < 5) {
2135
0
            read_packet = read_next;
2136
2137
0
            if(readpkt->data_len != 1 ||
2138
0
                readpkt->data[0] != SSH_MSG_REQUEST_FAILURE) {
2139
0
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2140
0
                               "Unexpected packet length"));
2141
0
            }
2142
2143
0
            continue;
2144
0
        }
2145
2146
0
        channel->read_local_id =
2147
0
            _libssh2_ntohu32(readpkt->data + 1);
2148
2149
        /*
2150
         * Either we asked for a specific extended data stream
2151
         * (and data was available),
2152
         * or the standard stream (and data was available),
2153
         * or the standard stream with extended_data_merge
2154
         * enabled and data was available
2155
         */
2156
0
        if((stream_id
2157
0
             && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2158
0
             && (channel->local.id == channel->read_local_id)
2159
0
             && (readpkt->data_len >= 9)
2160
0
             && (stream_id == (int) _libssh2_ntohu32(readpkt->data + 5)))
2161
0
            || (!stream_id && (readpkt->data[0] == SSH_MSG_CHANNEL_DATA)
2162
0
                && (channel->local.id == channel->read_local_id))
2163
0
            || (!stream_id
2164
0
                && (readpkt->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2165
0
                && (channel->local.id == channel->read_local_id)
2166
0
                && (channel->remote.extended_data_ignore_mode ==
2167
0
                    LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2168
2169
            /* figure out much more data we want to read */
2170
0
            bytes_want = buflen - bytes_read;
2171
0
            unlink_packet = FALSE;
2172
2173
0
            if(bytes_want >= (readpkt->data_len - readpkt->data_head)) {
2174
                /* we want more than this node keeps, so adjust the number and
2175
                   delete this node after the copy */
2176
0
                bytes_want = readpkt->data_len - readpkt->data_head;
2177
0
                unlink_packet = TRUE;
2178
0
            }
2179
2180
0
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2181
0
                           "channel_read() got %ld of data from %u/%u/%d%s",
2182
0
                           (long)bytes_want, channel->local.id,
2183
0
                           channel->remote.id, stream_id,
2184
0
                           unlink_packet ? " [ul]" : ""));
2185
2186
            /* copy data from this struct to the target buffer */
2187
0
            memcpy(&buf[bytes_read],
2188
0
                   &readpkt->data[readpkt->data_head], bytes_want);
2189
2190
            /* advance pointer and counter */
2191
0
            readpkt->data_head += bytes_want;
2192
0
            bytes_read += bytes_want;
2193
2194
            /* if drained, remove from list */
2195
0
            if(unlink_packet) {
2196
                /* detach readpkt from session->packets list */
2197
0
                _libssh2_list_remove(&readpkt->node);
2198
2199
0
                LIBSSH2_FREE(session, readpkt->data);
2200
0
                LIBSSH2_FREE(session, readpkt);
2201
0
            }
2202
0
        }
2203
2204
        /* check the next struct in the chain */
2205
0
        read_packet = read_next;
2206
0
    }
2207
2208
0
    if(!bytes_read) {
2209
        /* If the channel is already at EOF or even closed, we need to signal
2210
           that back. We may have gotten that info while draining the incoming
2211
           transport layer until EAGAIN so we must not be fooled by that
2212
           return code. */
2213
0
        if(channel->remote.eof || channel->remote.close)
2214
0
            return 0;
2215
0
        else if(rc != LIBSSH2_ERROR_EAGAIN)
2216
0
            return 0;
2217
2218
        /* if the transport layer said EAGAIN then we say so as well */
2219
0
        return _libssh2_error(session, rc, "would block");
2220
0
    }
2221
2222
0
    channel->read_avail -= bytes_read;
2223
0
    channel->remote.window_size -= (uint32_t)bytes_read;
2224
2225
0
    return bytes_read;
2226
0
}
2227
2228
/*
2229
 * libssh2_channel_read_ex
2230
 *
2231
 * Read data from a channel (blocking or non-blocking depending on set state)
2232
 *
2233
 * When this is done non-blocking, it is important to not return 0 until the
2234
 * currently read channel is complete. If we read stuff from the wire but it
2235
 * was no payload data to fill in the buffer with, we MUST make sure to return
2236
 * LIBSSH2_ERROR_EAGAIN.
2237
 *
2238
 * This function will first make sure there's a receive window enough to
2239
 * receive a full buffer's wort of contents. An application may choose to
2240
 * adjust the receive window more to increase transfer performance.
2241
 */
2242
LIBSSH2_API ssize_t
2243
libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, char *buf,
2244
                        size_t buflen)
2245
0
{
2246
0
    ssize_t rc;
2247
0
    unsigned long recv_window;
2248
2249
0
    if(!channel)
2250
0
        return LIBSSH2_ERROR_BAD_USE;
2251
2252
0
    recv_window = libssh2_channel_window_read_ex(channel, NULL, NULL);
2253
2254
0
    if(buflen > recv_window) {
2255
0
        BLOCK_ADJUST(rc, channel->session,
2256
0
                     _libssh2_channel_receive_window_adjust(channel,
2257
0
                                                   (uint32_t)buflen, 1, NULL));
2258
0
    }
2259
2260
0
    BLOCK_ADJUST(rc, channel->session,
2261
0
                 _libssh2_channel_read(channel, stream_id, buf, buflen));
2262
0
    return rc;
2263
0
}
2264
2265
/*
2266
 * _libssh2_channel_packet_data_len
2267
 *
2268
 * Return the size of the data block of the current packet, or 0 if there
2269
 * isn't a packet.
2270
 */
2271
size_t
2272
_libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
2273
0
{
2274
0
    LIBSSH2_SESSION *session = channel->session;
2275
0
    LIBSSH2_PACKET *read_packet;
2276
0
    LIBSSH2_PACKET *next_packet;
2277
0
    uint32_t read_local_id;
2278
2279
0
    read_packet = _libssh2_list_first(&session->packets);
2280
0
    if(!read_packet)
2281
0
        return 0;
2282
2283
0
    while(read_packet) {
2284
2285
0
        next_packet = _libssh2_list_next(&read_packet->node);
2286
2287
0
        if(read_packet->data_len < 5) {
2288
0
            read_packet = next_packet;
2289
0
            _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2290
0
                           "Unexpected packet length"));
2291
0
            continue;
2292
0
        }
2293
2294
0
        read_local_id = _libssh2_ntohu32(read_packet->data + 1);
2295
2296
        /*
2297
         * Either we asked for a specific extended data stream
2298
         * (and data was available),
2299
         * or the standard stream (and data was available),
2300
         * or the standard stream with extended_data_merge
2301
         * enabled and data was available
2302
         */
2303
0
        if((stream_id
2304
0
             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2305
0
             && (channel->local.id == read_local_id)
2306
0
             && (read_packet->data_len >= 9)
2307
0
             && (stream_id == (int) _libssh2_ntohu32(read_packet->data + 5)))
2308
0
            ||
2309
0
            (!stream_id
2310
0
             && (read_packet->data[0] == SSH_MSG_CHANNEL_DATA)
2311
0
             && (channel->local.id == read_local_id))
2312
0
            ||
2313
0
            (!stream_id
2314
0
             && (read_packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA)
2315
0
             && (channel->local.id == read_local_id)
2316
0
             && (channel->remote.extended_data_ignore_mode
2317
0
                 == LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE))) {
2318
0
            return read_packet->data_len - read_packet->data_head;
2319
0
        }
2320
2321
0
        read_packet = next_packet;
2322
0
    }
2323
2324
0
    return 0;
2325
0
}
2326
2327
/*
2328
 * _libssh2_channel_write
2329
 *
2330
 * Send data to a channel. Note that if this returns EAGAIN, the caller must
2331
 * call this function again with the SAME input arguments.
2332
 *
2333
 * Returns: number of bytes sent, or if it returns a negative number, that is
2334
 * the error code!
2335
 */
2336
ssize_t
2337
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
2338
                       const unsigned char *buf, size_t buflen)
2339
0
{
2340
0
    int rc = 0;
2341
0
    LIBSSH2_SESSION *session = channel->session;
2342
0
    ssize_t wrote = 0; /* counter for this specific this call */
2343
2344
    /* In theory we could split larger buffers into several smaller packets
2345
     * but it turns out to be really hard and nasty to do while still offering
2346
     * the API/prototype.
2347
     *
2348
     * Instead we only deal with the first 32K in this call and for the parent
2349
     * function to call it again with the remainder! 32K is a conservative
2350
     * limit based on the text in RFC4253 section 6.1.
2351
     */
2352
0
    if(buflen > 32700)
2353
0
        buflen = 32700;
2354
2355
0
    if(channel->write_state == libssh2_NB_state_idle) {
2356
0
        unsigned char *s = channel->write_packet;
2357
2358
0
        _libssh2_debug((channel->session, LIBSSH2_TRACE_CONN,
2359
0
                       "Writing %ld bytes on channel %u/%u, stream #%d",
2360
0
                       (long)buflen, channel->local.id, channel->remote.id,
2361
0
                       stream_id));
2362
2363
0
        if(channel->local.close)
2364
0
            return _libssh2_error(channel->session,
2365
0
                                  LIBSSH2_ERROR_CHANNEL_CLOSED,
2366
0
                                  "We have already closed this channel");
2367
0
        else if(channel->local.eof)
2368
0
            return _libssh2_error(channel->session,
2369
0
                                  LIBSSH2_ERROR_CHANNEL_EOF_SENT,
2370
0
                                  "EOF has already been received, "
2371
0
                                  "data might be ignored");
2372
2373
        /* drain the incoming flow first, mostly to make sure we get all
2374
         * pending window adjust packets */
2375
0
        do
2376
0
            rc = _libssh2_transport_read(session);
2377
0
        while(rc > 0);
2378
2379
0
        if((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN)) {
2380
0
            return _libssh2_error(channel->session, rc,
2381
0
                                  "Failure while draining incoming flow");
2382
0
        }
2383
2384
0
        if(channel->local.window_size <= 0) {
2385
            /* there's no room for data so we stop */
2386
2387
            /* Waiting on the socket to be writable would be wrong because we
2388
             * would be back here immediately, but a readable socket might
2389
             * herald an incoming window adjustment.
2390
             */
2391
0
            session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND;
2392
2393
0
            return rc == LIBSSH2_ERROR_EAGAIN ? rc : 0;
2394
0
        }
2395
2396
0
        channel->write_bufwrite = buflen;
2397
2398
0
        *(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA :
2399
0
            SSH_MSG_CHANNEL_DATA;
2400
0
        _libssh2_store_u32(&s, channel->remote.id);
2401
0
        if(stream_id)
2402
0
            _libssh2_store_u32(&s, stream_id);
2403
2404
        /* Don't exceed the remote end's limits */
2405
        /* REMEMBER local means local as the SOURCE of the data */
2406
0
        if(channel->write_bufwrite > channel->local.window_size) {
2407
0
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2408
0
                           "Splitting write block due to %u byte "
2409
0
                           "window_size on %u/%u/%d",
2410
0
                           channel->local.window_size, channel->local.id,
2411
0
                           channel->remote.id, stream_id));
2412
0
            channel->write_bufwrite = channel->local.window_size;
2413
0
        }
2414
0
        if(channel->write_bufwrite > channel->local.packet_size) {
2415
0
            _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2416
0
                           "Splitting write block due to %u byte "
2417
0
                           "packet_size on %u/%u/%d",
2418
0
                           channel->local.packet_size, channel->local.id,
2419
0
                           channel->remote.id, stream_id));
2420
0
            channel->write_bufwrite = channel->local.packet_size;
2421
0
        }
2422
        /* store the size here only, the buffer is passed in as-is to
2423
           _libssh2_transport_send() */
2424
0
        _libssh2_store_u32(&s, (uint32_t)channel->write_bufwrite);
2425
0
        channel->write_packet_len = s - channel->write_packet;
2426
2427
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2428
0
                       "Sending %ld bytes on channel %u/%u, stream_id=%d",
2429
0
                       (long)channel->write_bufwrite, channel->local.id,
2430
0
                       channel->remote.id, stream_id));
2431
2432
0
        channel->write_state = libssh2_NB_state_created;
2433
0
    }
2434
2435
0
    if(channel->write_state == libssh2_NB_state_created) {
2436
0
        rc = _libssh2_transport_send(session, channel->write_packet,
2437
0
                                     channel->write_packet_len,
2438
0
                                     buf, channel->write_bufwrite);
2439
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2440
0
            return _libssh2_error(session, rc,
2441
0
                                  "Unable to send channel data");
2442
0
        }
2443
0
        else if(rc) {
2444
0
            channel->write_state = libssh2_NB_state_idle;
2445
0
            return _libssh2_error(session, rc,
2446
0
                                  "Unable to send channel data");
2447
0
        }
2448
        /* Shrink local window size */
2449
0
        channel->local.window_size -= (uint32_t)channel->write_bufwrite;
2450
2451
0
        wrote += channel->write_bufwrite;
2452
2453
        /* Since _libssh2_transport_write() succeeded, we must return
2454
           now to allow the caller to provide the next chunk of data.
2455
2456
           We cannot move on to send the next piece of data that may
2457
           already have been provided in this same function call, as we
2458
           risk getting EAGAIN for that and we can't return information
2459
           both about sent data as well as EAGAIN. So, by returning short
2460
           now, the caller will call this function again with new data to
2461
           send */
2462
2463
0
        channel->write_state = libssh2_NB_state_idle;
2464
2465
0
        return wrote;
2466
0
    }
2467
2468
0
    return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */
2469
0
}
2470
2471
/*
2472
 * libssh2_channel_write_ex
2473
 *
2474
 * Send data to a channel
2475
 */
2476
LIBSSH2_API ssize_t
2477
libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id,
2478
                         const char *buf, size_t buflen)
2479
0
{
2480
0
    ssize_t rc;
2481
2482
0
    if(!channel)
2483
0
        return LIBSSH2_ERROR_BAD_USE;
2484
2485
0
    BLOCK_ADJUST(rc, channel->session,
2486
0
                 _libssh2_channel_write(channel, stream_id,
2487
0
                                        (const unsigned char *)buf, buflen));
2488
0
    return rc;
2489
0
}
2490
2491
/*
2492
 * channel_send_eof
2493
 *
2494
 * Send EOF on channel
2495
 */
2496
static int channel_send_eof(LIBSSH2_CHANNEL *channel)
2497
0
{
2498
0
    LIBSSH2_SESSION *session = channel->session;
2499
0
    unsigned char packet[5];    /* packet_type(1) + channelno(4) */
2500
0
    int rc;
2501
2502
0
    _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2503
0
                   "Sending EOF on channel %u/%u",
2504
0
                   channel->local.id, channel->remote.id));
2505
0
    packet[0] = SSH_MSG_CHANNEL_EOF;
2506
0
    _libssh2_htonu32(packet + 1, channel->remote.id);
2507
0
    rc = _libssh2_transport_send(session, packet, 5, NULL, 0);
2508
0
    if(rc == LIBSSH2_ERROR_EAGAIN) {
2509
0
        _libssh2_error(session, rc,
2510
0
                       "Would block sending EOF");
2511
0
        return rc;
2512
0
    }
2513
0
    else if(rc) {
2514
0
        return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
2515
0
                              "Unable to send EOF on channel");
2516
0
    }
2517
0
    channel->local.eof = 1;
2518
2519
0
    return 0;
2520
0
}
2521
2522
/*
2523
 * libssh2_channel_send_eof
2524
 *
2525
 * Send EOF on channel
2526
 */
2527
LIBSSH2_API int
2528
libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel)
2529
0
{
2530
0
    int rc;
2531
2532
0
    if(!channel)
2533
0
        return LIBSSH2_ERROR_BAD_USE;
2534
2535
0
    BLOCK_ADJUST(rc, channel->session, channel_send_eof(channel));
2536
0
    return rc;
2537
0
}
2538
2539
/*
2540
 * libssh2_channel_eof
2541
 *
2542
 * Read channel's eof status
2543
 */
2544
LIBSSH2_API int
2545
libssh2_channel_eof(LIBSSH2_CHANNEL * channel)
2546
0
{
2547
0
    LIBSSH2_SESSION *session;
2548
0
    LIBSSH2_PACKET *packet;
2549
0
    LIBSSH2_PACKET *next_packet;
2550
2551
0
    if(!channel)
2552
0
        return LIBSSH2_ERROR_BAD_USE;
2553
2554
0
    session = channel->session;
2555
0
    packet = _libssh2_list_first(&session->packets);
2556
2557
0
    while(packet) {
2558
2559
0
        next_packet = _libssh2_list_next(&packet->node);
2560
2561
0
        if(packet->data_len < 1) {
2562
0
            packet = next_packet;
2563
0
            _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2564
0
                           "Unexpected packet length"));
2565
0
            continue;
2566
0
        }
2567
2568
0
        if(((packet->data[0] == SSH_MSG_CHANNEL_DATA)
2569
0
            || (packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA))
2570
0
            && ((packet->data_len >= 5)
2571
0
            && (channel->local.id == _libssh2_ntohu32(packet->data + 1)))) {
2572
            /* There's data waiting to be read yet, mask the EOF status */
2573
0
            return 0;
2574
0
        }
2575
0
        packet = next_packet;
2576
0
    }
2577
2578
0
    return channel->remote.eof;
2579
0
}
2580
2581
/*
2582
 * channel_wait_eof
2583
 *
2584
 * Awaiting channel EOF
2585
 */
2586
static int channel_wait_eof(LIBSSH2_CHANNEL *channel)
2587
0
{
2588
0
    LIBSSH2_SESSION *session = channel->session;
2589
0
    int rc;
2590
2591
0
    if(channel->wait_eof_state == libssh2_NB_state_idle) {
2592
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2593
0
                       "Awaiting EOF for channel %u/%u", channel->local.id,
2594
0
                       channel->remote.id));
2595
2596
0
        channel->wait_eof_state = libssh2_NB_state_created;
2597
0
    }
2598
2599
    /*
2600
     * While channel is not eof, read more packets from the network.
2601
     * Either the EOF will be set or network timeout will occur.
2602
     */
2603
0
    do {
2604
0
        if(channel->remote.eof) {
2605
0
            break;
2606
0
        }
2607
2608
0
        if((channel->remote.window_size == channel->read_avail) &&
2609
0
            session->api_block_mode)
2610
0
            return _libssh2_error(session, LIBSSH2_ERROR_CHANNEL_WINDOW_FULL,
2611
0
                                  "Receiving channel window "
2612
0
                                  "has been exhausted");
2613
2614
0
        rc = _libssh2_transport_read(session);
2615
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2616
0
            return rc;
2617
0
        }
2618
0
        else if(rc < 0) {
2619
0
            channel->wait_eof_state = libssh2_NB_state_idle;
2620
0
            return _libssh2_error(session, rc,
2621
0
                                  "_libssh2_transport_read() bailed out");
2622
0
        }
2623
0
    } while(1);
2624
2625
0
    channel->wait_eof_state = libssh2_NB_state_idle;
2626
2627
0
    return 0;
2628
0
}
2629
2630
/*
2631
 * libssh2_channel_wait_eof
2632
 *
2633
 * Awaiting channel EOF
2634
 */
2635
LIBSSH2_API int
2636
libssh2_channel_wait_eof(LIBSSH2_CHANNEL *channel)
2637
0
{
2638
0
    int rc;
2639
2640
0
    if(!channel)
2641
0
        return LIBSSH2_ERROR_BAD_USE;
2642
2643
0
    BLOCK_ADJUST(rc, channel->session, channel_wait_eof(channel));
2644
0
    return rc;
2645
0
}
2646
2647
int _libssh2_channel_close(LIBSSH2_CHANNEL * channel)
2648
0
{
2649
0
    LIBSSH2_SESSION *session = channel->session;
2650
0
    int rc = 0;
2651
2652
0
    if(channel->local.close) {
2653
        /* Already closed, act like we sent another close,
2654
         * even though we didn't... shhhhhh */
2655
0
        channel->close_state = libssh2_NB_state_idle;
2656
0
        return 0;
2657
0
    }
2658
2659
0
    if(!channel->local.eof) {
2660
0
        rc = channel_send_eof(channel);
2661
0
        if(rc) {
2662
0
            if(rc == LIBSSH2_ERROR_EAGAIN) {
2663
0
                return rc;
2664
0
            }
2665
0
            _libssh2_error(session, rc,
2666
0
                           "Unable to send EOF, but closing channel anyway");
2667
0
        }
2668
0
    }
2669
2670
    /* ignore if we have received a remote eof or not, as it is now too
2671
       late for us to wait for it. Continue closing! */
2672
2673
0
    if(channel->close_state == libssh2_NB_state_idle) {
2674
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN, "Closing channel %u/%u",
2675
0
                       channel->local.id, channel->remote.id));
2676
2677
0
        channel->close_packet[0] = SSH_MSG_CHANNEL_CLOSE;
2678
0
        _libssh2_htonu32(channel->close_packet + 1, channel->remote.id);
2679
2680
0
        channel->close_state = libssh2_NB_state_created;
2681
0
    }
2682
2683
0
    if(channel->close_state == libssh2_NB_state_created) {
2684
0
        rc = _libssh2_transport_send(session, channel->close_packet, 5,
2685
0
                                     NULL, 0);
2686
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
2687
0
            _libssh2_error(session, rc,
2688
0
                           "Would block sending close-channel");
2689
0
            return rc;
2690
2691
0
        }
2692
0
        else if(rc) {
2693
0
            _libssh2_error(session, rc,
2694
0
                           "Unable to send close-channel request, "
2695
0
                           "but closing anyway");
2696
            /* skip waiting for the response and fall through to
2697
               LIBSSH2_CHANNEL_CLOSE below */
2698
2699
0
        }
2700
0
        else
2701
0
            channel->close_state = libssh2_NB_state_sent;
2702
0
    }
2703
2704
0
    if(channel->close_state == libssh2_NB_state_sent) {
2705
        /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */
2706
2707
0
        while(!channel->remote.close && !rc &&
2708
0
               (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED))
2709
0
            rc = _libssh2_transport_read(session);
2710
0
    }
2711
2712
0
    if(rc != LIBSSH2_ERROR_EAGAIN) {
2713
        /* set the local close state first when we're perfectly confirmed to
2714
           not do any more EAGAINs */
2715
0
        channel->local.close = 1;
2716
2717
        /* We call the callback last in this function to make it keep the local
2718
           data as long as EAGAIN is returned. */
2719
0
        if(channel->close_cb) {
2720
0
            LIBSSH2_CHANNEL_CLOSE(session, channel);
2721
0
        }
2722
2723
0
        channel->close_state = libssh2_NB_state_idle;
2724
0
    }
2725
2726
    /* return 0 or an error */
2727
0
    return rc >= 0 ? 0 : rc;
2728
0
}
2729
2730
/*
2731
 * libssh2_channel_close
2732
 *
2733
 * Close a channel
2734
 */
2735
LIBSSH2_API int
2736
libssh2_channel_close(LIBSSH2_CHANNEL *channel)
2737
0
{
2738
0
    int rc;
2739
2740
0
    if(!channel)
2741
0
        return LIBSSH2_ERROR_BAD_USE;
2742
2743
0
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_close(channel));
2744
0
    return rc;
2745
0
}
2746
2747
/*
2748
 * channel_wait_closed
2749
 *
2750
 * Awaiting channel close after EOF
2751
 */
2752
static int channel_wait_closed(LIBSSH2_CHANNEL *channel)
2753
0
{
2754
0
    LIBSSH2_SESSION *session = channel->session;
2755
0
    int rc;
2756
2757
0
    if(!channel->remote.eof) {
2758
0
        return _libssh2_error(session, LIBSSH2_ERROR_INVAL,
2759
0
                              "libssh2_channel_wait_closed() invoked when "
2760
0
                              "channel is not in EOF state");
2761
0
    }
2762
2763
0
    if(channel->wait_closed_state == libssh2_NB_state_idle) {
2764
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2765
0
                       "Awaiting close of channel %u/%u", channel->local.id,
2766
0
                       channel->remote.id));
2767
2768
0
        channel->wait_closed_state = libssh2_NB_state_created;
2769
0
    }
2770
2771
    /*
2772
     * While channel is not closed, read more packets from the network.
2773
     * Either the channel will be closed or network timeout will occur.
2774
     */
2775
0
    if(!channel->remote.close) {
2776
0
        do {
2777
0
            rc = _libssh2_transport_read(session);
2778
0
            if(channel->remote.close)
2779
                /* it is now closed, move on! */
2780
0
                break;
2781
0
        } while(rc > 0);
2782
0
        if(rc < 0)
2783
0
            return rc;
2784
0
    }
2785
2786
0
    channel->wait_closed_state = libssh2_NB_state_idle;
2787
2788
0
    return 0;
2789
0
}
2790
2791
/*
2792
 * libssh2_channel_wait_closed
2793
 *
2794
 * Awaiting channel close after EOF
2795
 */
2796
LIBSSH2_API int
2797
libssh2_channel_wait_closed(LIBSSH2_CHANNEL *channel)
2798
0
{
2799
0
    int rc;
2800
2801
0
    if(!channel)
2802
0
        return LIBSSH2_ERROR_BAD_USE;
2803
2804
0
    BLOCK_ADJUST(rc, channel->session, channel_wait_closed(channel));
2805
0
    return rc;
2806
0
}
2807
2808
/*
2809
 * _libssh2_channel_free
2810
 *
2811
 * Make sure a channel is closed, then remove the channel from the session
2812
 * and free its resource(s)
2813
 *
2814
 * Returns 0 on success, negative on failure
2815
 */
2816
int _libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2817
0
{
2818
0
    LIBSSH2_SESSION *session = channel->session;
2819
0
    unsigned char channel_id[4];
2820
0
    unsigned char *data;
2821
0
    size_t data_len;
2822
0
    int rc;
2823
2824
0
    assert(session);
2825
2826
0
    if(channel->free_state == libssh2_NB_state_idle) {
2827
0
        _libssh2_debug((session, LIBSSH2_TRACE_CONN,
2828
0
                       "Freeing channel %u/%u resources", channel->local.id,
2829
0
                       channel->remote.id));
2830
2831
0
        channel->free_state = libssh2_NB_state_created;
2832
0
    }
2833
2834
    /* Allow channel freeing even when the socket has lost its connection */
2835
0
    if(!channel->local.close
2836
0
        && (session->socket_state == LIBSSH2_SOCKET_CONNECTED)) {
2837
0
        rc = _libssh2_channel_close(channel);
2838
2839
0
        if(rc == LIBSSH2_ERROR_EAGAIN)
2840
0
            return rc;
2841
2842
        /* ignore all other errors as they otherwise risk blocking the channel
2843
           free from happening */
2844
0
    }
2845
2846
0
    channel->free_state = libssh2_NB_state_idle;
2847
2848
0
    if(channel->exit_signal) {
2849
0
        LIBSSH2_FREE(session, channel->exit_signal);
2850
0
    }
2851
2852
    /*
2853
     * channel->remote.close *might* not be set yet, Well...
2854
     * We've sent the close packet, what more do you want?
2855
     * Just let packet_add ignore it when it finally arrives
2856
     */
2857
2858
    /* Clear out packets meant for this channel */
2859
0
    _libssh2_htonu32(channel_id, channel->local.id);
2860
0
    while((_libssh2_packet_ask(session, SSH_MSG_CHANNEL_DATA, &data,
2861
0
                               &data_len, 1, channel_id, 4) >= 0)
2862
0
          ||
2863
0
          (_libssh2_packet_ask(session, SSH_MSG_CHANNEL_EXTENDED_DATA, &data,
2864
0
                               &data_len, 1, channel_id, 4) >= 0)) {
2865
0
        LIBSSH2_FREE(session, data);
2866
0
    }
2867
2868
    /* free "channel_type" */
2869
0
    if(channel->channel_type) {
2870
0
        LIBSSH2_FREE(session, channel->channel_type);
2871
0
    }
2872
2873
    /* Unlink from channel list */
2874
0
    _libssh2_list_remove(&channel->node);
2875
2876
    /*
2877
     * Make sure all memory used in the state variables are free
2878
     */
2879
0
    if(channel->setenv_packet) {
2880
0
        LIBSSH2_FREE(session, channel->setenv_packet);
2881
0
    }
2882
0
    if(channel->reqX11_packet) {
2883
0
        LIBSSH2_FREE(session, channel->reqX11_packet);
2884
0
    }
2885
0
    if(channel->process_packet) {
2886
0
        LIBSSH2_FREE(session, channel->process_packet);
2887
0
    }
2888
2889
0
    LIBSSH2_FREE(session, channel);
2890
2891
0
    return 0;
2892
0
}
2893
2894
/*
2895
 * libssh2_channel_free
2896
 *
2897
 * Make sure a channel is closed, then remove the channel from the session
2898
 * and free its resource(s)
2899
 *
2900
 * Returns 0 on success, negative on failure
2901
 */
2902
LIBSSH2_API int
2903
libssh2_channel_free(LIBSSH2_CHANNEL *channel)
2904
0
{
2905
0
    int rc;
2906
2907
0
    if(!channel)
2908
0
        return LIBSSH2_ERROR_BAD_USE;
2909
2910
0
    BLOCK_ADJUST(rc, channel->session, _libssh2_channel_free(channel));
2911
0
    return rc;
2912
0
}
2913
/*
2914
 * libssh2_channel_window_read_ex
2915
 *
2916
 * Check the status of the read window. Returns the number of bytes which the
2917
 * remote end may send without overflowing the window limit read_avail (if
2918
 * passed) will be populated with the number of bytes actually available to be
2919
 * read window_size_initial (if passed) will be populated with the
2920
 * window_size_initial as defined by the channel_open request
2921
 */
2922
LIBSSH2_API unsigned long
2923
libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel,
2924
        /* FIXME: -> size_t */ unsigned long *read_avail,
2925
                               unsigned long *window_size_initial)
2926
0
{
2927
0
    if(!channel)
2928
0
        return 0; /* no channel, no window! */
2929
2930
0
    if(window_size_initial) {
2931
0
        *window_size_initial = channel->remote.window_size_initial;
2932
0
    }
2933
2934
0
    if(read_avail) {
2935
0
        size_t bytes_queued = 0;
2936
0
        LIBSSH2_PACKET *next_packet;
2937
0
        LIBSSH2_PACKET *packet =
2938
0
            _libssh2_list_first(&channel->session->packets);
2939
2940
0
        while(packet) {
2941
0
            unsigned char packet_type;
2942
0
               next_packet = _libssh2_list_next(&packet->node);
2943
2944
0
            if(packet->data_len < 1) {
2945
0
                packet = next_packet;
2946
0
                _libssh2_debug((channel->session, LIBSSH2_TRACE_ERROR,
2947
0
                               "Unexpected packet length"));
2948
0
                continue;
2949
0
            }
2950
2951
0
            packet_type = packet->data[0];
2952
2953
0
            if(((packet_type == SSH_MSG_CHANNEL_DATA)
2954
0
                || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA))
2955
0
               && ((packet->data_len >= 5)
2956
0
                   && (_libssh2_ntohu32(packet->data + 1) ==
2957
0
                       channel->local.id))) {
2958
0
                bytes_queued += packet->data_len - packet->data_head;
2959
0
            }
2960
2961
0
            packet = next_packet;
2962
0
        }
2963
2964
0
        *read_avail = (unsigned long)bytes_queued;
2965
0
    }
2966
2967
0
    return channel->remote.window_size;
2968
0
}
2969
2970
/*
2971
 * libssh2_channel_window_write_ex
2972
 *
2973
 * Check the status of the write window Returns the number of bytes which may
2974
 * be safely written on the channel without blocking window_size_initial (if
2975
 * passed) will be populated with the size of the initial window as defined by
2976
 * the channel_open request
2977
 */
2978
LIBSSH2_API unsigned long
2979
libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel,
2980
                                unsigned long *window_size_initial)
2981
0
{
2982
0
    if(!channel)
2983
0
        return 0; /* no channel, no window! */
2984
2985
0
    if(window_size_initial) {
2986
        /* For locally initiated channels this is very often 0, so it's not
2987
         * *that* useful as information goes */
2988
0
        *window_size_initial = channel->local.window_size_initial;
2989
0
    }
2990
2991
0
    return channel->local.window_size;
2992
0
}
2993
2994
/* A signal can be delivered to the remote process/service using the
2995
   following message.  Some systems may not implement signals, in which
2996
   case they SHOULD ignore this message.
2997
2998
      byte      SSH_MSG_CHANNEL_REQUEST
2999
      uint32    recipient channel
3000
      string    "signal"
3001
      boolean   FALSE
3002
      string    signal name (without the "SIG" prefix)
3003
3004
   'signal name' values will be encoded as discussed in the passage
3005
   describing SSH_MSG_CHANNEL_REQUEST messages using "exit-signal" in
3006
   this section.
3007
 */
3008
static int channel_signal(LIBSSH2_CHANNEL *channel,
3009
                          const char *signame,
3010
                          size_t signame_len)
3011
0
{
3012
0
    LIBSSH2_SESSION *session = channel->session;
3013
0
    int retcode = LIBSSH2_ERROR_PROTO;
3014
3015
0
    if(channel->sendsignal_state == libssh2_NB_state_idle) {
3016
0
        unsigned char *s;
3017
3018
        /* 20 = packet_type(1) + channel(4) +
3019
                signal_len + sizeof(signal) - 1 + want_reply(1) +
3020
                signame_len_len(4) */
3021
0
        channel->sendsignal_packet_len = 20 + signame_len;
3022
3023
0
        s = channel->sendsignal_packet =
3024
0
            LIBSSH2_ALLOC(session, channel->sendsignal_packet_len);
3025
0
        if(!channel->sendsignal_packet)
3026
0
            return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
3027
0
                                  "Unable to allocate memory for "
3028
0
                                  "signal request");
3029
3030
0
        *(s++) = SSH_MSG_CHANNEL_REQUEST;
3031
0
        _libssh2_store_u32(&s, channel->remote.id);
3032
0
        _libssh2_store_str(&s, "signal", sizeof("signal") - 1);
3033
0
        *(s++) = 0x00;  /* Don't reply */
3034
0
        _libssh2_store_str(&s, signame, signame_len);
3035
3036
0
        channel->sendsignal_state = libssh2_NB_state_created;
3037
0
    }
3038
3039
0
    if(channel->sendsignal_state == libssh2_NB_state_created) {
3040
0
        int rc;
3041
3042
0
        rc = _libssh2_transport_send(session, channel->sendsignal_packet,
3043
0
                                     channel->sendsignal_packet_len,
3044
0
                                     NULL, 0);
3045
0
        if(rc == LIBSSH2_ERROR_EAGAIN) {
3046
0
            _libssh2_error(session, rc, "Would block sending signal request");
3047
0
            return rc;
3048
0
        }
3049
0
        else if(rc) {
3050
0
            LIBSSH2_FREE(session, channel->sendsignal_packet);
3051
0
            channel->sendsignal_state = libssh2_NB_state_idle;
3052
0
            return _libssh2_error(session, rc, "Unable to send signal packet");
3053
0
        }
3054
0
        LIBSSH2_FREE(session, channel->sendsignal_packet);
3055
0
        retcode = LIBSSH2_ERROR_NONE;
3056
0
    }
3057
3058
0
    channel->sendsignal_state = libssh2_NB_state_idle;
3059
3060
0
    return retcode;
3061
0
}
3062
3063
LIBSSH2_API int
3064
libssh2_channel_signal_ex(LIBSSH2_CHANNEL *channel,
3065
                          const char *signame,
3066
                          size_t signame_len)
3067
0
{
3068
0
    int rc;
3069
3070
0
    if(!channel)
3071
0
        return LIBSSH2_ERROR_BAD_USE;
3072
3073
0
    BLOCK_ADJUST(rc, channel->session,
3074
0
                 channel_signal(channel, signame, signame_len));
3075
0
    return rc;
3076
0
}