Coverage Report

Created: 2026-07-15 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh/src/channels.c
Line
Count
Source
1
/*
2
 * channels.c - SSH channel functions
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2003-2013 by Aris Adamantiadis
7
 * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
8
 *
9
 * The SSH Library is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or (at your
12
 * option) any later version.
13
 *
14
 * The SSH Library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17
 * License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with the SSH Library; see the file COPYING.  If not, write to
21
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22
 * MA 02111-1307, USA.
23
 */
24
25
#include "config.h"
26
27
#include <limits.h>
28
#include <stdio.h>
29
#include <errno.h>
30
#include <time.h>
31
#include <stdbool.h>
32
#include <string.h>
33
#ifdef HAVE_SYS_TIME_H
34
#include <sys/time.h>
35
#endif /* HAVE_SYS_TIME_H */
36
37
#ifndef _WIN32
38
#include <netinet/in.h>
39
#include <arpa/inet.h>
40
#endif
41
42
#include "libssh/priv.h"
43
#include "libssh/ssh2.h"
44
#include "libssh/buffer.h"
45
#include "libssh/packet.h"
46
#include "libssh/socket.h"
47
#include "libssh/channels.h"
48
#include "libssh/session.h"
49
#include "libssh/misc.h"
50
#include "libssh/messages.h"
51
#if WITH_SERVER
52
#include "libssh/server.h"
53
#endif
54
55
/*
56
 * All implementations MUST be able to process packets with an
57
 * uncompressed payload length of 32768 bytes or less and a total packet
58
 * size of 35000 bytes or less.
59
 */
60
0
#define CHANNEL_MAX_PACKET 32768
61
62
/*
63
 * WINDOW_DEFAULT matches the default OpenSSH session window size.
64
 * This controls how much data the peer can send before needing to receive
65
 * a round-trip SSH2_MSG_CHANNEL_WINDOW_ADJUST message that increases the window.
66
 */
67
0
#define WINDOW_DEFAULT (64*CHANNEL_MAX_PACKET)
68
69
/**
70
 * @defgroup libssh_channel The SSH channel functions
71
 * @ingroup libssh
72
 *
73
 * Functions that manage a SSH channel.
74
 *
75
 * @{
76
 */
77
78
static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet);
79
80
/**
81
 * @brief Allocate a new channel.
82
 *
83
 * @param[in]  session  The ssh session to use.
84
 *
85
 * @return              A pointer to a newly allocated channel, NULL on error.
86
 *                      The channel needs to be freed with ssh_channel_free().
87
 *
88
 * @see ssh_channel_free()
89
 */
90
ssh_channel ssh_channel_new(ssh_session session)
91
0
{
92
0
    ssh_channel channel = NULL;
93
94
0
    if (session == NULL) {
95
0
        return NULL;
96
0
    }
97
98
    /* Check if we have an authenticated session */
99
0
    if (!(session->flags & SSH_SESSION_FLAG_AUTHENTICATED)) {
100
0
        return NULL;
101
0
    }
102
103
0
    channel = calloc(1, sizeof(struct ssh_channel_struct));
104
0
    if (channel == NULL) {
105
0
        ssh_set_error_oom(session);
106
0
        return NULL;
107
0
    }
108
109
0
    channel->stdout_buffer = ssh_buffer_new();
110
0
    if (channel->stdout_buffer == NULL) {
111
0
        ssh_set_error_oom(session);
112
0
        SAFE_FREE(channel);
113
0
        return NULL;
114
0
    }
115
116
0
    channel->stderr_buffer = ssh_buffer_new();
117
0
    if (channel->stderr_buffer == NULL) {
118
0
        ssh_set_error_oom(session);
119
0
        SSH_BUFFER_FREE(channel->stdout_buffer);
120
0
        SAFE_FREE(channel);
121
0
        return NULL;
122
0
    }
123
124
0
    channel->session = session;
125
0
    channel->exit.code = (uint32_t)-1;
126
0
    channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
127
128
0
    if (session->channels == NULL) {
129
0
        session->channels = ssh_list_new();
130
0
        if (session->channels == NULL) {
131
0
            ssh_set_error_oom(session);
132
0
            SSH_BUFFER_FREE(channel->stdout_buffer);
133
0
            SSH_BUFFER_FREE(channel->stderr_buffer);
134
0
            SAFE_FREE(channel);
135
0
            return NULL;
136
0
        }
137
0
    }
138
139
0
    ssh_list_prepend(session->channels, channel);
140
141
    /* Set states explicitly */
142
0
    channel->state = SSH_CHANNEL_STATE_NOT_OPEN;
143
0
    channel->request_state = SSH_CHANNEL_REQ_STATE_NONE;
144
145
0
    return channel;
146
0
}
147
148
/**
149
 * @internal
150
 *
151
 * @brief Create a new channel identifier.
152
 *
153
 * @param[in]  session  The SSH session to use.
154
 *
155
 * @return              The new channel identifier.
156
 */
157
uint32_t ssh_channel_new_id(ssh_session session)
158
0
{
159
0
    return ++(session->maxchannel);
160
0
}
161
162
/**
163
 * @internal
164
 *
165
 * @brief Handle a SSH_PACKET_CHANNEL_OPEN_CONFIRMATION packet.
166
 *
167
 * Constructs the channel object.
168
 */
169
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf)
170
0
{
171
0
    uint32_t channelid = 0;
172
0
    ssh_channel channel = NULL;
173
0
    int rc;
174
0
    (void)type;
175
0
    (void)user;
176
177
0
    SSH_LOG(SSH_LOG_PACKET, "Received SSH2_MSG_CHANNEL_OPEN_CONFIRMATION");
178
179
0
    rc = ssh_buffer_unpack(packet, "d", &channelid);
180
0
    if (rc != SSH_OK)
181
0
        goto error;
182
0
    channel = ssh_channel_from_local(session, channelid);
183
0
    if (channel == NULL) {
184
0
        ssh_set_error(session,
185
0
                      SSH_FATAL,
186
0
                      "Unknown channel id %" PRIu32,
187
0
                      (uint32_t)channelid);
188
        /* TODO: Set error marking in channel object */
189
190
0
        return SSH_PACKET_USED;
191
0
    }
192
193
0
    rc = ssh_buffer_unpack(packet,
194
0
                           "ddd",
195
0
                           &channel->remote_channel,
196
0
                           &channel->remote_window,
197
0
                           &channel->remote_maxpacket);
198
0
    if (rc != SSH_OK)
199
0
        goto error;
200
201
0
    if (channel->remote_maxpacket == 0) {
202
0
        SSH_LOG(SSH_LOG_RARE,
203
0
                "Invalid maximum packet size 0 in "
204
0
                "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION");
205
0
        goto error;
206
0
    }
207
208
0
    SSH_LOG(SSH_LOG_DEBUG,
209
0
            "Received a CHANNEL_OPEN_CONFIRMATION for channel %" PRIu32
210
0
            ":%" PRIu32,
211
0
            channel->local_channel,
212
0
            channel->remote_channel);
213
214
0
    if (channel->state != SSH_CHANNEL_STATE_OPENING) {
215
0
        SSH_LOG(SSH_LOG_RARE,
216
0
                "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect "
217
0
                "channel state %d",
218
0
                channel->state);
219
0
        goto error;
220
0
    }
221
222
0
    SSH_LOG(SSH_LOG_DEBUG,
223
0
            "Remote window : %" PRIu32 ", maxpacket : %" PRIu32,
224
0
            channel->remote_window,
225
0
            channel->remote_maxpacket);
226
227
0
    channel->state = SSH_CHANNEL_STATE_OPEN;
228
0
    channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND;
229
230
0
    ssh_callbacks_execute_list(channel->callbacks,
231
0
                               ssh_channel_callbacks,
232
0
                               channel_open_response_function,
233
0
                               channel->session,
234
0
                               channel,
235
0
                               true /* is_success */);
236
237
0
    return SSH_PACKET_USED;
238
239
0
error:
240
0
    ssh_set_error(session, SSH_FATAL, "Invalid packet");
241
0
    return SSH_PACKET_USED;
242
0
}
243
244
/**
245
 * @internal
246
 *
247
 * @brief Handle a SSH_CHANNEL_OPEN_FAILURE and set the state of the channel.
248
 */
249
SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail)
250
0
{
251
0
    ssh_channel channel = NULL;
252
0
    char *error = NULL;
253
0
    uint32_t code;
254
0
    int rc;
255
0
    (void)user;
256
0
    (void)type;
257
258
0
    channel = channel_from_msg(session, packet);
259
0
    if (channel == NULL) {
260
0
        SSH_LOG(SSH_LOG_RARE, "Invalid channel in packet");
261
0
        return SSH_PACKET_USED;
262
0
    }
263
264
0
    rc = ssh_buffer_unpack(packet, "ds", &code, &error);
265
0
    if (rc != SSH_OK) {
266
0
        ssh_set_error(session, SSH_FATAL, "Invalid packet");
267
0
        return SSH_PACKET_USED;
268
0
    }
269
270
0
    if (channel->state != SSH_CHANNEL_STATE_OPENING) {
271
0
        SSH_LOG(SSH_LOG_RARE,
272
0
                "SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel "
273
0
                "state %d",
274
0
                channel->state);
275
0
        SAFE_FREE(error);
276
0
        goto error;
277
0
    }
278
279
0
    ssh_set_error(session,
280
0
                  SSH_REQUEST_DENIED,
281
0
                  "Channel opening failure: channel %" PRIu32 " error (%" PRIu32
282
0
                  ") %s",
283
0
                  channel->local_channel,
284
0
                  code,
285
0
                  error);
286
0
    SAFE_FREE(error);
287
0
    channel->state = SSH_CHANNEL_STATE_OPEN_DENIED;
288
289
0
    ssh_callbacks_execute_list(channel->callbacks,
290
0
                               ssh_channel_callbacks,
291
0
                               channel_open_response_function,
292
0
                               channel->session,
293
0
                               channel,
294
0
                               false /* is_success */);
295
296
0
    return SSH_PACKET_USED;
297
298
0
error:
299
0
  ssh_set_error(session, SSH_FATAL, "Invalid packet");
300
0
  return SSH_PACKET_USED;
301
0
}
302
303
static int ssh_channel_open_termination(void *c)
304
0
{
305
0
  ssh_channel channel = (ssh_channel) c;
306
0
  if (channel->state != SSH_CHANNEL_STATE_OPENING ||
307
0
      channel->session->session_state == SSH_SESSION_STATE_ERROR)
308
0
    return 1;
309
0
  else
310
0
    return 0;
311
0
}
312
313
/**
314
 * @internal
315
 *
316
 * @brief Open a channel by sending a SSH_OPEN_CHANNEL message and
317
 *        wait for the reply.
318
 *
319
 * @param[in]  channel  The current channel.
320
 *
321
 * @param[in]  type   A C string describing the kind of channel (e.g. "exec").
322
 *
323
 * @param[in]  window   The receiving window of the channel. The window is the
324
 *                      maximum size of data that can stay in buffers and
325
 *                      network.
326
 *
327
 * @param[in]  maxpacket The maximum packet size allowed (like MTU).
328
 *
329
 * @param[in]  payload   The buffer containing additional payload for the query.
330
 *
331
 * @return             `SSH_OK` if successful; `SSH_ERROR` otherwise.
332
 */
333
static int
334
channel_open(ssh_channel channel,
335
             const char *type,
336
             uint32_t window,
337
             uint32_t maxpacket,
338
             ssh_buffer payload)
339
0
{
340
0
    ssh_session session = channel->session;
341
0
    int err = SSH_ERROR;
342
0
    int rc;
343
344
0
    switch (channel->state) {
345
0
    case SSH_CHANNEL_STATE_NOT_OPEN:
346
0
        break;
347
0
    case SSH_CHANNEL_STATE_OPENING:
348
0
        goto pending;
349
0
    case SSH_CHANNEL_STATE_OPEN:
350
0
    case SSH_CHANNEL_STATE_CLOSED:
351
0
    case SSH_CHANNEL_STATE_OPEN_DENIED:
352
0
        goto end;
353
0
    default:
354
0
        ssh_set_error(session, SSH_FATAL, "Bad state in channel_open: %d",
355
0
                      channel->state);
356
0
    }
357
358
0
    channel->local_channel = ssh_channel_new_id(session);
359
0
    channel->local_maxpacket = maxpacket;
360
0
    channel->local_window = window;
361
362
0
    SSH_LOG(SSH_LOG_DEBUG,
363
0
            "Creating a channel %" PRIu32 " with %" PRIu32 " window and %" PRIu32 " max packet",
364
0
            channel->local_channel, window, maxpacket);
365
366
0
    rc = ssh_buffer_pack(session->out_buffer,
367
0
                         "bsddd",
368
0
                         SSH2_MSG_CHANNEL_OPEN,
369
0
                         type,
370
0
                         channel->local_channel,
371
0
                         channel->local_window,
372
0
                         channel->local_maxpacket);
373
0
    if (rc != SSH_OK) {
374
0
        ssh_set_error_oom(session);
375
0
        return err;
376
0
    }
377
378
0
    if (payload != NULL) {
379
0
        if (ssh_buffer_add_buffer(session->out_buffer, payload) < 0) {
380
0
            ssh_set_error_oom(session);
381
382
0
            return err;
383
0
        }
384
0
    }
385
0
    channel->state = SSH_CHANNEL_STATE_OPENING;
386
0
    if (ssh_packet_send(session) == SSH_ERROR) {
387
0
        return err;
388
0
    }
389
390
0
    SSH_LOG(SSH_LOG_PACKET,
391
0
            "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %" PRIu32,
392
0
            type, channel->local_channel);
393
394
0
pending:
395
    /* wait until channel is opened by server */
396
0
    err = ssh_handle_packets_termination(session,
397
0
                                         SSH_TIMEOUT_DEFAULT,
398
0
                                         ssh_channel_open_termination,
399
0
                                         channel);
400
401
0
    if (session->session_state == SSH_SESSION_STATE_ERROR) {
402
0
        err = SSH_ERROR;
403
0
    }
404
405
0
end:
406
    /* This needs to pass the SSH_AGAIN from the above,
407
     * but needs to catch failed channel states */
408
0
    if (channel->state == SSH_CHANNEL_STATE_OPEN) {
409
0
        err = SSH_OK;
410
0
    } else if (err != SSH_AGAIN) {
411
        /* Messages were handled correctly, but the channel state is invalid */
412
0
        err = SSH_ERROR;
413
0
    }
414
415
0
    return err;
416
0
}
417
418
/* return channel with corresponding local id, or NULL if not found */
419
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id)
420
0
{
421
0
    struct ssh_iterator *it = NULL;
422
0
    ssh_channel channel = NULL;
423
424
0
    for (it = ssh_list_get_iterator(session->channels); it != NULL;
425
0
         it = it->next) {
426
0
        channel = ssh_iterator_value(ssh_channel, it);
427
0
        if (channel == NULL) {
428
0
            continue;
429
0
        }
430
0
        if (channel->local_channel == id) {
431
0
            return channel;
432
0
        }
433
0
    }
434
435
0
    return NULL;
436
0
}
437
438
/**
439
 * @internal
440
 * @brief grows the local window and sends a packet to the other party
441
 * @param session SSH session
442
 * @param channel SSH channel
443
 * @return            `SSH_OK` if successful; `SSH_ERROR` otherwise.
444
 */
445
static int grow_window(ssh_session session,
446
                       ssh_channel channel)
447
0
{
448
0
  uint32_t used;
449
0
  uint32_t increment;
450
0
  int rc;
451
452
  /* Calculate the increment taking into account what the peer may still send
453
   * (local_window) and what we've already buffered (stdout_buffer and
454
   * stderr_buffer).
455
  */
456
0
  used = channel->local_window;
457
0
  if (channel->stdout_buffer != NULL) {
458
0
    used += ssh_buffer_get_len(channel->stdout_buffer);
459
0
  }
460
0
  if (channel->stderr_buffer != NULL) {
461
0
    used += ssh_buffer_get_len(channel->stderr_buffer);
462
0
  }
463
  /* Avoid a negative increment in case the peer sent more than the window allowed */
464
0
  increment = WINDOW_DEFAULT > used ? WINDOW_DEFAULT - used : 0;
465
  /* Don't grow until we can request at least half a window */
466
0
  if (increment < (WINDOW_DEFAULT / 2)) {
467
0
    SSH_LOG(SSH_LOG_DEBUG,
468
0
        "growing window (channel %" PRIu32 ":%" PRIu32 ") to %" PRIu32 " bytes : not needed (%" PRIu32 " bytes)",
469
0
        channel->local_channel, channel->remote_channel, WINDOW_DEFAULT,
470
0
        channel->local_window);
471
472
0
    return SSH_OK;
473
0
  }
474
475
0
  rc = ssh_buffer_pack(session->out_buffer,
476
0
                       "bdd",
477
0
                       SSH2_MSG_CHANNEL_WINDOW_ADJUST,
478
0
                       channel->remote_channel,
479
0
                       increment);
480
0
  if (rc != SSH_OK) {
481
0
    ssh_set_error_oom(session);
482
0
    goto error;
483
0
  }
484
485
0
  if (ssh_packet_send(session) == SSH_ERROR) {
486
0
    goto error;
487
0
  }
488
489
0
  SSH_LOG(SSH_LOG_DEBUG,
490
0
      "growing window (channel %" PRIu32 ":%" PRIu32 ") by %" PRIu32 " bytes",
491
0
      channel->local_channel,
492
0
      channel->remote_channel,
493
0
      increment);
494
495
0
  channel->local_window += increment;
496
497
0
  return SSH_OK;
498
0
error:
499
0
  ssh_buffer_reinit(session->out_buffer);
500
501
0
  return SSH_ERROR;
502
0
}
503
504
/**
505
 * @internal
506
 *
507
 * @brief Parse a channel-related packet to resolve it to a ssh_channel.
508
 *
509
 * @param[in]  session  The current SSH session.
510
 *
511
 * @param[in]  packet   The buffer to parse packet from. The read pointer will
512
 *                      be moved after the call.
513
 *
514
 * @return              The related ssh_channel, or NULL if the channel is
515
 *                      unknown or the packet is invalid.
516
 */
517
static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet)
518
0
{
519
0
    ssh_channel channel = NULL;
520
0
    uint32_t chan;
521
0
    int rc;
522
523
0
    rc = ssh_buffer_unpack(packet, "d", &chan);
524
0
    if (rc != SSH_OK) {
525
0
        ssh_set_error(session,
526
0
                      SSH_FATAL,
527
0
                      "Getting channel from message: short read");
528
0
        return NULL;
529
0
    }
530
531
0
    channel = ssh_channel_from_local(session, chan);
532
0
    if (channel == NULL) {
533
0
        ssh_set_error(session,
534
0
                      SSH_FATAL,
535
0
                      "Server specified invalid channel %" PRIu32,
536
0
                      (uint32_t)chan);
537
0
    }
538
539
0
    return channel;
540
0
}
541
542
SSH_PACKET_CALLBACK(channel_rcv_change_window)
543
0
{
544
0
    ssh_channel channel = NULL;
545
0
    uint32_t bytes;
546
0
    int rc;
547
0
    bool was_empty;
548
549
0
    (void)user;
550
0
    (void)type;
551
552
0
    channel = channel_from_msg(session, packet);
553
0
    if (channel == NULL) {
554
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
555
0
    }
556
557
0
    rc = ssh_buffer_unpack(packet, "d", &bytes);
558
0
    if (channel == NULL || rc != SSH_OK) {
559
0
        SSH_LOG(SSH_LOG_PACKET,
560
0
                "Error getting a window adjust message: invalid packet");
561
562
0
        return SSH_PACKET_USED;
563
0
    }
564
565
0
    SSH_LOG(SSH_LOG_DEBUG,
566
0
            "Adding %" PRIu32 " bytes to channel (%" PRIu32 ":%" PRIu32
567
0
            ") (from %" PRIu32 " bytes)",
568
0
            bytes,
569
0
            channel->local_channel,
570
0
            channel->remote_channel,
571
0
            channel->remote_window);
572
573
0
    was_empty = channel->remote_window == 0;
574
575
0
    if (UINT32_MAX - channel->remote_window < bytes) {
576
0
        ssh_set_error(session,
577
0
                      SSH_FATAL,
578
0
                      "Window adjust %" PRIu32 " overflows remote window.",
579
0
                      bytes);
580
0
        session->session_state = SSH_SESSION_STATE_ERROR;
581
0
        return SSH_PACKET_USED;
582
0
    }
583
584
0
    channel->remote_window += bytes;
585
586
    /* Writing to the channel is non-blocking until the receive window is empty.
587
     * When the receive window becomes non-zero again, call
588
     * channel_write_wontblock_function. */
589
0
    if (was_empty && bytes > 0) {
590
0
        ssh_callbacks_execute_list(channel->callbacks,
591
0
                                   ssh_channel_callbacks,
592
0
                                   channel_write_wontblock_function,
593
0
                                   session,
594
0
                                   channel,
595
0
                                   channel->remote_window);
596
0
    }
597
598
0
    return SSH_PACKET_USED;
599
0
}
600
601
/* is_stderr is set to 1 if the data are extended, ie stderr */
602
SSH_PACKET_CALLBACK(channel_rcv_data)
603
0
{
604
0
    ssh_channel channel = NULL;
605
0
    ssh_string str = NULL;
606
0
    ssh_buffer buf = NULL;
607
0
    void *data = NULL;
608
0
    uint32_t len;
609
0
    int extended, is_stderr = 0;
610
0
    int rest;
611
612
0
    (void)user;
613
614
0
    if (type == SSH2_MSG_CHANNEL_DATA) {
615
0
        extended = 0;
616
0
    } else { /* SSH_MSG_CHANNEL_EXTENDED_DATA */
617
0
        extended = 1;
618
0
    }
619
620
0
    channel = channel_from_msg(session, packet);
621
0
    if (channel == NULL) {
622
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
623
624
0
        return SSH_PACKET_USED;
625
0
    }
626
627
0
    if (extended) {
628
0
        uint32_t data_type_code, rc;
629
0
        rc = ssh_buffer_get_u32(packet, &data_type_code);
630
0
        if (rc != sizeof(uint32_t)) {
631
0
            SSH_LOG(SSH_LOG_PACKET,
632
0
                    "Failed to read data type code: rc = %" PRIu32, rc);
633
634
0
            return SSH_PACKET_USED;
635
0
        }
636
0
        is_stderr = 1;
637
0
        data_type_code = ntohl(data_type_code);
638
0
        if (data_type_code != SSH2_EXTENDED_DATA_STDERR) {
639
0
            SSH_LOG(SSH_LOG_PACKET, "Invalid data type code %" PRIu32 "!",
640
0
                    data_type_code);
641
0
        }
642
0
    }
643
644
0
    str = ssh_buffer_get_ssh_string(packet);
645
0
    if (str == NULL) {
646
0
        SSH_LOG(SSH_LOG_PACKET, "Invalid data packet!");
647
648
0
        return SSH_PACKET_USED;
649
0
    }
650
    /* STRING_SIZE_MAX < UINT32_MAX */
651
0
    len = (uint32_t)ssh_string_len(str);
652
653
0
    SSH_LOG(SSH_LOG_PACKET,
654
0
            "Channel receiving %" PRIu32 " bytes data%s (local win=%" PRIu32
655
0
            " remote win=%" PRIu32 ") on channel %" PRIu32 ":%" PRIu32,
656
0
            len,
657
0
            is_stderr ? " in stderr" : "",
658
0
            channel->local_window,
659
0
            channel->remote_window,
660
0
            channel->local_channel,
661
0
            channel->remote_channel);
662
663
0
    if (len > channel->local_window) {
664
0
        SSH_LOG(SSH_LOG_RARE,
665
0
                "Data packet too big for our window(%" PRIu32 " vs %" PRIu32 ")",
666
0
                len,
667
0
                channel->local_window);
668
669
0
        SSH_STRING_FREE(str);
670
671
0
        ssh_set_error(session, SSH_FATAL, "Window exceeded");
672
673
0
        return SSH_PACKET_USED;
674
0
    }
675
676
0
    data = ssh_string_data(str);
677
0
    if (channel_default_bufferize(channel, data, len, is_stderr) < 0) {
678
0
        SSH_STRING_FREE(str);
679
680
0
        return SSH_PACKET_USED;
681
0
    }
682
683
0
    channel->local_window -= len;
684
685
0
    SSH_LOG(SSH_LOG_PACKET,
686
0
            "Channel windows are now (local win=%" PRIu32 " remote win=%" PRIu32 ")",
687
0
            channel->local_window,
688
0
            channel->remote_window);
689
690
0
    SSH_STRING_FREE(str);
691
692
0
    if (is_stderr) {
693
0
        buf = channel->stderr_buffer;
694
0
    } else {
695
0
        buf = channel->stdout_buffer;
696
0
    }
697
698
0
    ssh_callbacks_iterate(channel->callbacks,
699
0
                          ssh_channel_callbacks,
700
0
                          channel_data_function) {
701
0
        if (ssh_buffer_get(buf) == NULL) {
702
0
            break;
703
0
        }
704
0
        rest = ssh_callbacks_iterate_exec(channel_data_function,
705
0
                                          channel->session,
706
0
                                          channel,
707
0
                                          ssh_buffer_get(buf),
708
0
                                          ssh_buffer_get_len(buf),
709
0
                                          is_stderr);
710
0
        if (rest > 0) {
711
0
            int rc;
712
0
            if (channel->counter != NULL) {
713
0
                channel->counter->in_bytes += rest;
714
0
            }
715
0
            ssh_buffer_pass_bytes(buf, rest);
716
717
0
            rc = grow_window(session, channel);
718
0
            if (rc == SSH_ERROR) {
719
0
              return -1;
720
0
            }
721
0
        }
722
0
    }
723
0
    ssh_callbacks_iterate_end();
724
725
0
    return SSH_PACKET_USED;
726
0
}
727
728
SSH_PACKET_CALLBACK(channel_rcv_eof)
729
0
{
730
0
    ssh_channel channel = NULL;
731
0
    (void)user;
732
0
    (void)type;
733
734
0
    channel = channel_from_msg(session, packet);
735
0
    if (channel == NULL) {
736
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
737
738
0
        return SSH_PACKET_USED;
739
0
    }
740
741
0
    SSH_LOG(SSH_LOG_PACKET,
742
0
            "Received eof on channel (%" PRIu32 ":%" PRIu32 ")",
743
0
            channel->local_channel,
744
0
            channel->remote_channel);
745
    /* channel->remote_window = 0; */
746
0
    channel->remote_eof = 1;
747
748
0
    ssh_callbacks_execute_list(channel->callbacks,
749
0
                               ssh_channel_callbacks,
750
0
                               channel_eof_function,
751
0
                               channel->session,
752
0
                               channel);
753
754
0
    return SSH_PACKET_USED;
755
0
}
756
757
static bool ssh_channel_has_unread_data(ssh_channel channel)
758
0
{
759
0
    if (channel == NULL) {
760
0
        return false;
761
0
    }
762
763
0
    if ((channel->stdout_buffer &&
764
0
         ssh_buffer_get_len(channel->stdout_buffer) > 0) ||
765
0
        (channel->stderr_buffer &&
766
0
         ssh_buffer_get_len(channel->stderr_buffer) > 0))
767
0
    {
768
0
        return true;
769
0
    }
770
771
0
    return false;
772
0
}
773
774
SSH_PACKET_CALLBACK(channel_rcv_close)
775
0
{
776
0
    ssh_channel channel = NULL;
777
0
    (void)user;
778
0
    (void)type;
779
780
0
    channel = channel_from_msg(session,packet);
781
0
    if (channel == NULL) {
782
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
783
784
0
        return SSH_PACKET_USED;
785
0
    }
786
787
0
    SSH_LOG(SSH_LOG_PACKET,
788
0
        "Received close on channel (%" PRIu32 ":%" PRIu32 ")",
789
0
        channel->local_channel,
790
0
        channel->remote_channel);
791
792
0
    if (!ssh_channel_has_unread_data(channel)) {
793
0
        channel->state = SSH_CHANNEL_STATE_CLOSED;
794
0
    } else {
795
0
        channel->delayed_close = 1;
796
0
    }
797
798
0
    if (channel->remote_eof == 0) {
799
0
        SSH_LOG(SSH_LOG_PACKET,
800
0
            "Remote host not polite enough to send an eof before close");
801
0
    }
802
    /*
803
    * The remote eof doesn't break things if there was still data into read
804
    * buffer because the eof is ignored until the buffer is empty.
805
    */
806
0
    channel->remote_eof = 1;
807
808
0
    ssh_callbacks_execute_list(channel->callbacks,
809
0
                               ssh_channel_callbacks,
810
0
                               channel_close_function,
811
0
                               channel->session,
812
0
                               channel);
813
814
0
    channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE;
815
0
    if(channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL)
816
0
        ssh_channel_do_free(channel);
817
818
0
    return SSH_PACKET_USED;
819
0
}
820
821
SSH_PACKET_CALLBACK(channel_rcv_request)
822
0
{
823
0
    ssh_channel channel = NULL;
824
0
    char *request = NULL;
825
0
    uint8_t want_reply;
826
0
    int rc;
827
0
    (void)user;
828
0
    (void)type;
829
830
0
    channel = channel_from_msg(session, packet);
831
0
    if (channel == NULL) {
832
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
833
0
        return SSH_PACKET_USED;
834
0
    }
835
836
0
    rc = ssh_buffer_unpack(packet, "sb", &request, &want_reply);
837
0
    if (rc != SSH_OK) {
838
0
        SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST");
839
0
        return SSH_PACKET_USED;
840
0
    }
841
842
0
    if (strcmp(request, "exit-status") == 0) {
843
0
        SAFE_FREE(request);
844
0
        rc = ssh_buffer_unpack(packet, "d", &channel->exit.code);
845
0
        if (rc != SSH_OK) {
846
0
            SSH_LOG(SSH_LOG_PACKET, "Invalid exit-status packet");
847
0
            return SSH_PACKET_USED;
848
0
        }
849
0
        channel->exit.status = true;
850
851
0
        SSH_LOG(SSH_LOG_PACKET,
852
0
                "received exit-status %u on channel %" PRIu32 ":%" PRIu32,
853
0
                channel->exit.code,
854
0
                channel->local_channel,
855
0
                channel->remote_channel);
856
857
0
        ssh_callbacks_execute_list(channel->callbacks,
858
0
                                   ssh_channel_callbacks,
859
0
                                   channel_exit_status_function,
860
0
                                   channel->session,
861
0
                                   channel,
862
0
                                   channel->exit.code);
863
864
0
        return SSH_PACKET_USED;
865
0
    }
866
867
0
    if (strcmp(request, "signal") == 0) {
868
0
        char *sig = NULL;
869
870
0
        SAFE_FREE(request);
871
0
        SSH_LOG(SSH_LOG_PACKET, "received signal");
872
873
0
        rc = ssh_buffer_unpack(packet, "s", &sig);
874
0
        if (rc != SSH_OK) {
875
0
            SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST");
876
0
            return SSH_PACKET_USED;
877
0
        }
878
879
0
        SSH_LOG(SSH_LOG_PACKET, "Remote connection sent a signal SIG %s", sig);
880
0
        ssh_callbacks_execute_list(channel->callbacks,
881
0
                                   ssh_channel_callbacks,
882
0
                                   channel_signal_function,
883
0
                                   channel->session,
884
0
                                   channel,
885
0
                                   sig);
886
0
        SAFE_FREE(sig);
887
888
0
        return SSH_PACKET_USED;
889
0
    }
890
891
0
    if (strcmp(request, "exit-signal") == 0) {
892
0
        const char *core = "(core dumped)";
893
0
        char *sig = NULL;
894
0
        char *errmsg = NULL;
895
0
        char *lang = NULL;
896
0
        uint8_t core_dumped;
897
898
0
        SAFE_FREE(request);
899
900
0
        rc = ssh_buffer_unpack(packet,
901
0
                               "sbss",
902
0
                               &sig,         /* signal name */
903
0
                               &core_dumped, /* core dumped */
904
0
                               &errmsg,      /* error message */
905
0
                               &lang);
906
0
        if (rc != SSH_OK) {
907
0
            SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST");
908
0
            return SSH_PACKET_USED;
909
0
        }
910
911
0
        if (core_dumped == 0) {
912
0
            core = "";
913
0
        }
914
915
0
        SSH_LOG(SSH_LOG_PACKET,
916
0
                "Remote connection closed by signal SIG %s %s",
917
0
                sig,
918
0
                core);
919
0
        ssh_callbacks_execute_list(channel->callbacks,
920
0
                                   ssh_channel_callbacks,
921
0
                                   channel_exit_signal_function,
922
0
                                   channel->session,
923
0
                                   channel,
924
0
                                   sig,
925
0
                                   core_dumped,
926
0
                                   errmsg,
927
0
                                   lang);
928
929
0
        channel->exit.core_dumped = core_dumped;
930
0
        if (sig != NULL) {
931
0
            SAFE_FREE(channel->exit.signal);
932
0
            channel->exit.signal = sig;
933
0
        }
934
0
        channel->exit.status = true;
935
936
0
        SAFE_FREE(lang);
937
0
        SAFE_FREE(errmsg);
938
939
0
        return SSH_PACKET_USED;
940
0
    }
941
0
    if (strcmp(request, "keepalive@openssh.com") == 0) {
942
0
        SAFE_FREE(request);
943
0
        SSH_LOG(SSH_LOG_DEBUG, "Responding to Openssh's keepalive");
944
945
0
        rc = ssh_buffer_pack(session->out_buffer,
946
0
                             "bd",
947
0
                             SSH2_MSG_CHANNEL_FAILURE,
948
0
                             channel->remote_channel);
949
0
        if (rc != SSH_OK) {
950
0
            return SSH_PACKET_USED;
951
0
        }
952
0
        ssh_packet_send(session);
953
954
0
        return SSH_PACKET_USED;
955
0
    }
956
957
0
    if (strcmp(request, "auth-agent-req") == 0 ||
958
0
        strcmp(request, "auth-agent-req@openssh.com") == 0) {
959
0
        int status;
960
961
0
        SAFE_FREE(request);
962
0
        SSH_LOG(SSH_LOG_DEBUG, "Received an auth-agent-req request");
963
964
0
        status = SSH2_MSG_CHANNEL_FAILURE;
965
0
        ssh_callbacks_iterate (channel->callbacks,
966
0
                               ssh_channel_callbacks,
967
0
                               channel_auth_agent_req_function) {
968
0
            ssh_callbacks_iterate_exec(channel_auth_agent_req_function,
969
0
                                       channel->session,
970
0
                                       channel);
971
            /* in lieu of a return value, if the callback exists it's supported
972
             */
973
0
            status = SSH2_MSG_CHANNEL_SUCCESS;
974
0
            break;
975
0
        }
976
0
        ssh_callbacks_iterate_end();
977
978
0
        if (want_reply) {
979
0
            rc = ssh_buffer_pack(session->out_buffer,
980
0
                                 "bd",
981
0
                                 status,
982
0
                                 channel->remote_channel);
983
0
            if (rc != SSH_OK) {
984
0
                return SSH_PACKET_USED;
985
0
            }
986
0
            ssh_packet_send(session);
987
0
        }
988
989
0
        return SSH_PACKET_USED;
990
0
    }
991
0
#ifdef WITH_SERVER
992
    /* If we are here, that means we have a request that is not in the
993
     * understood client requests. That means we need to create a ssh message to
994
     * be passed to the user code handling ssh messages
995
     */
996
0
    ssh_message_handle_channel_request(session,
997
0
                                       channel,
998
0
                                       packet,
999
0
                                       request,
1000
0
                                       want_reply);
1001
#else
1002
    SSH_LOG(SSH_LOG_DEBUG, "Unhandled channel request %s", request);
1003
#endif
1004
1005
0
    SAFE_FREE(request);
1006
1007
0
    return SSH_PACKET_USED;
1008
0
}
1009
1010
/*
1011
 * When data has been received from the ssh server, it can be applied to the
1012
 * known user function, with help of the callback, or inserted here
1013
 *
1014
 * FIXME is the window changed?
1015
 */
1016
int channel_default_bufferize(ssh_channel channel,
1017
                              void *data, uint32_t len,
1018
                              bool is_stderr)
1019
0
{
1020
0
    ssh_session session = NULL;
1021
1022
0
    if (channel == NULL) {
1023
0
        return -1;
1024
0
    }
1025
1026
0
    session = channel->session;
1027
1028
0
    if (data == NULL) {
1029
0
        ssh_set_error_invalid(session);
1030
0
        return -1;
1031
0
    }
1032
1033
0
    SSH_LOG(SSH_LOG_PACKET,
1034
0
            "placing %" PRIu32 " bytes into channel buffer (%s)",
1035
0
            len,
1036
0
            is_stderr ? "stderr" : "stdout");
1037
0
    if (!is_stderr) {
1038
        /* stdout */
1039
0
        if (channel->stdout_buffer == NULL) {
1040
0
            channel->stdout_buffer = ssh_buffer_new();
1041
0
            if (channel->stdout_buffer == NULL) {
1042
0
                ssh_set_error_oom(session);
1043
0
                return -1;
1044
0
            }
1045
0
        }
1046
1047
0
        if (ssh_buffer_add_data(channel->stdout_buffer, data, len) < 0) {
1048
0
            ssh_set_error_oom(session);
1049
0
            SSH_BUFFER_FREE(channel->stdout_buffer);
1050
0
            channel->stdout_buffer = NULL;
1051
0
            return -1;
1052
0
        }
1053
0
    } else {
1054
        /* stderr */
1055
0
        if (channel->stderr_buffer == NULL) {
1056
0
            channel->stderr_buffer = ssh_buffer_new();
1057
0
            if (channel->stderr_buffer == NULL) {
1058
0
                ssh_set_error_oom(session);
1059
0
                return -1;
1060
0
            }
1061
0
        }
1062
1063
0
        if (ssh_buffer_add_data(channel->stderr_buffer, data, len) < 0) {
1064
0
            ssh_set_error_oom(session);
1065
0
            SSH_BUFFER_FREE(channel->stderr_buffer);
1066
0
            channel->stderr_buffer = NULL;
1067
0
            return -1;
1068
0
        }
1069
0
    }
1070
1071
0
    return 0;
1072
0
}
1073
1074
/**
1075
 * @brief Open a session channel (suited for a shell, not TCP forwarding).
1076
 *
1077
 * @param[in]  channel  An allocated channel.
1078
 *
1079
 * @return              `SSH_OK` on success,
1080
 *                      `SSH_ERROR` if an error occurred,
1081
 *                      `SSH_AGAIN` if in nonblocking mode and call has
1082
 *                      to be done again.
1083
 *
1084
 * @see ssh_channel_open_forward()
1085
 * @see ssh_channel_request_env()
1086
 * @see ssh_channel_request_shell()
1087
 * @see ssh_channel_request_exec()
1088
 */
1089
int ssh_channel_open_session(ssh_channel channel)
1090
0
{
1091
0
  if (channel == NULL) {
1092
0
      return SSH_ERROR;
1093
0
  }
1094
1095
0
  return channel_open(channel,
1096
0
                      "session",
1097
0
                      WINDOW_DEFAULT,
1098
0
                      CHANNEL_MAX_PACKET,
1099
0
                      NULL);
1100
0
}
1101
1102
/**
1103
 * @brief Open an agent authentication forwarding channel. This type of channel
1104
 * can be opened by a server towards a client in order to provide SSH-Agent
1105
 * services to the server-side process. This channel can only be opened if the
1106
 * client claimed support by sending a channel request beforehand.
1107
 *
1108
 * @param[in]  channel  An allocated channel.
1109
 *
1110
 * @return              `SSH_OK` on success,
1111
 *                      `SSH_ERROR` if an error occurred,
1112
 *                      `SSH_AGAIN` if in nonblocking mode and call has
1113
 *                      to be done again.
1114
 *
1115
 * @see ssh_channel_open_forward()
1116
 */
1117
int ssh_channel_open_auth_agent(ssh_channel channel)
1118
0
{
1119
0
  if (channel == NULL) {
1120
0
      return SSH_ERROR;
1121
0
  }
1122
1123
  /* FIXME use "auth-agent" from RFC9987 when it gets addoption */
1124
0
  return channel_open(channel,
1125
0
                      "auth-agent@openssh.com",
1126
0
                      WINDOW_DEFAULT,
1127
0
                      CHANNEL_MAX_PACKET,
1128
0
                      NULL);
1129
0
}
1130
1131
/**
1132
 * @brief Open a TCP/IP forwarding channel.
1133
 *
1134
 * @param[in]  channel  An allocated channel.
1135
 *
1136
 * @param[in]  remotehost The remote host to connected (host name or IP).
1137
 *
1138
 * @param[in]  remoteport The remote port.
1139
 *
1140
 * @param[in]  sourcehost The numeric IP address of the machine from where the
1141
 *                        connection request originates. This is mostly for
1142
 *                        logging purposes.
1143
 *
1144
 * @param[in]  localport  The port on the host from where the connection
1145
 *                        originated. This is mostly for logging purposes.
1146
 *
1147
 * @return              `SSH_OK` on success,
1148
 *                      `SSH_ERROR` if an error occurred,
1149
 *                      `SSH_AGAIN` if in nonblocking mode and call has
1150
 *                      to be done again.
1151
 *
1152
 * @warning This function does not bind the local port and does not
1153
 * automatically forward the content of a socket to the channel. You still have
1154
 * to use ssh_channel_read and ssh_channel_write for this.
1155
 */
1156
int ssh_channel_open_forward(ssh_channel channel, const char *remotehost,
1157
    int remoteport, const char *sourcehost, int localport)
1158
0
{
1159
0
    ssh_session session = NULL;
1160
0
    ssh_buffer payload = NULL;
1161
0
    ssh_string str = NULL;
1162
0
    int rc = SSH_ERROR;
1163
1164
0
    if (channel == NULL) {
1165
0
        return rc;
1166
0
    }
1167
1168
0
    session = channel->session;
1169
1170
0
    if (remotehost == NULL || sourcehost == NULL) {
1171
0
        ssh_set_error_invalid(session);
1172
0
        return rc;
1173
0
    }
1174
1175
0
    payload = ssh_buffer_new();
1176
0
    if (payload == NULL) {
1177
0
        ssh_set_error_oom(session);
1178
0
        goto error;
1179
0
    }
1180
1181
0
    rc = ssh_buffer_pack(payload,
1182
0
                         "sdsd",
1183
0
                         remotehost,
1184
0
                         remoteport,
1185
0
                         sourcehost,
1186
0
                         localport);
1187
0
    if (rc != SSH_OK) {
1188
0
        ssh_set_error_oom(session);
1189
0
        goto error;
1190
0
    }
1191
1192
0
    rc = channel_open(channel,
1193
0
                      "direct-tcpip",
1194
0
                      WINDOW_DEFAULT,
1195
0
                      CHANNEL_MAX_PACKET,
1196
0
                      payload);
1197
1198
0
error:
1199
0
    SSH_BUFFER_FREE(payload);
1200
0
    SSH_STRING_FREE(str);
1201
1202
0
    return rc;
1203
0
}
1204
1205
/**
1206
 * @brief Open a TCP/IP - UNIX domain socket forwarding channel.
1207
 *
1208
 * @param[in]  channel  An allocated channel.
1209
 *
1210
 * @param[in]  remotepath   The UNIX socket path on the remote machine
1211
 *
1212
 * @param[in]  sourcehost   The numeric IP address of the machine from where the
1213
 *                          connection request originates. This is mostly for
1214
 *                          logging purposes.
1215
 *
1216
 * @param[in]  localport    The port on the host from where the connection
1217
 *                          originated. This is mostly for logging purposes.
1218
 *
1219
 * @return              `SSH_OK on` success,
1220
 *                      `SSH_ERROR` if an error occurred,
1221
 *                      `SSH_AGAIN` if in nonblocking mode and call has
1222
 *                      to be done again.
1223
 *
1224
 * @warning This function does not bind the local port and does not
1225
 * automatically forward the content of a socket to the channel.
1226
 * You still have to use ssh_channel_read and ssh_channel_write for this.
1227
 * @warning Requires support of OpenSSH for UNIX domain socket forwarding.
1228
 */
1229
int ssh_channel_open_forward_unix(ssh_channel channel,
1230
                                  const char *remotepath,
1231
                                  const char *sourcehost,
1232
                                  int localport)
1233
0
{
1234
0
    ssh_session session = NULL;
1235
0
    ssh_buffer payload = NULL;
1236
0
    int rc = SSH_ERROR;
1237
0
    int version;
1238
1239
0
    if (channel == NULL) {
1240
0
        return rc;
1241
0
    }
1242
1243
0
    session = channel->session;
1244
1245
0
    version = ssh_get_openssh_version(session);
1246
0
    if (version == 0) {
1247
0
        ssh_set_error(session,
1248
0
                      SSH_REQUEST_DENIED,
1249
0
                      "We're not connected to an OpenSSH server!");
1250
0
        return SSH_ERROR;
1251
0
    }
1252
1253
0
    if (remotepath == NULL || sourcehost == NULL) {
1254
0
        ssh_set_error_invalid(session);
1255
0
        return rc;
1256
0
    }
1257
1258
0
    payload = ssh_buffer_new();
1259
0
    if (payload == NULL) {
1260
0
        ssh_set_error_oom(session);
1261
0
        goto error;
1262
0
    }
1263
1264
0
    rc = ssh_buffer_pack(payload,
1265
0
                         "ssd",
1266
0
                         remotepath,
1267
0
                         sourcehost,
1268
0
                         localport);
1269
0
    if (rc != SSH_OK) {
1270
0
        ssh_set_error_oom(session);
1271
0
        goto error;
1272
0
    }
1273
1274
0
    rc = channel_open(channel,
1275
0
                      "direct-streamlocal@openssh.com",
1276
0
                      WINDOW_DEFAULT,
1277
0
                      CHANNEL_MAX_PACKET,
1278
0
                      payload);
1279
1280
0
error:
1281
0
    SSH_BUFFER_FREE(payload);
1282
1283
0
    return rc;
1284
0
}
1285
1286
/**
1287
 * @brief Close and free a channel.
1288
 *
1289
 * @param[in]  channel  The channel to free.
1290
 *
1291
 * @warning Any data unread on this channel will be lost.
1292
 */
1293
void ssh_channel_free(ssh_channel channel)
1294
0
{
1295
0
    ssh_session session = NULL;
1296
1297
0
    if (channel == NULL) {
1298
0
        return;
1299
0
    }
1300
1301
0
    session = channel->session;
1302
0
    if (session->alive) {
1303
0
        bool send_close = false;
1304
1305
0
        switch (channel->state) {
1306
0
        case SSH_CHANNEL_STATE_OPEN:
1307
0
            send_close = true;
1308
0
            break;
1309
0
        case SSH_CHANNEL_STATE_CLOSED:
1310
0
            if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) {
1311
0
                send_close = true;
1312
0
            }
1313
0
            if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_LOCAL) {
1314
0
                send_close = false;
1315
0
            }
1316
0
            break;
1317
0
        default:
1318
0
            send_close = false;
1319
0
            break;
1320
0
        }
1321
1322
0
        if (send_close) {
1323
0
            ssh_channel_close(channel);
1324
0
        }
1325
0
    }
1326
0
    channel->flags |= SSH_CHANNEL_FLAG_FREED_LOCAL;
1327
1328
0
    if (channel->callbacks != NULL) {
1329
0
        ssh_list_free(channel->callbacks);
1330
0
        channel->callbacks = NULL;
1331
0
    }
1332
1333
    /* The idea behind the flags is the following : it is well possible
1334
     * that a client closes a channel that still exists on the server side.
1335
     * We definitively close the channel when we receive a close message *and*
1336
     * the user closed it.
1337
     */
1338
0
    if ((channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) ||
1339
0
        (channel->flags & SSH_CHANNEL_FLAG_NOT_BOUND)) {
1340
0
        ssh_channel_do_free(channel);
1341
0
    }
1342
0
}
1343
1344
/**
1345
 * @internal
1346
 * @brief Effectively free a channel, without caring about flags
1347
 */
1348
1349
void ssh_channel_do_free(ssh_channel channel)
1350
0
{
1351
0
    struct ssh_iterator *it = NULL;
1352
0
    ssh_session session = channel->session;
1353
1354
0
    it = ssh_list_find(session->channels, channel);
1355
0
    if (it != NULL) {
1356
0
        ssh_list_remove(session->channels, it);
1357
0
    }
1358
1359
0
    SSH_BUFFER_FREE(channel->stdout_buffer);
1360
0
    SSH_BUFFER_FREE(channel->stderr_buffer);
1361
1362
0
    if (channel->callbacks != NULL) {
1363
0
        ssh_list_free(channel->callbacks);
1364
0
        channel->callbacks = NULL;
1365
0
    }
1366
0
    SAFE_FREE(channel->exit.signal);
1367
1368
0
    channel->session = NULL;
1369
0
    SAFE_FREE(channel);
1370
0
}
1371
1372
/**
1373
 * @brief Send an end of file on the channel.
1374
 *
1375
 * This doesn't close the channel. You may still read from it but not write.
1376
 *
1377
 * @param[in]  channel  The channel to send the eof to.
1378
 *
1379
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred.
1380
 *
1381
 * Example:
1382
@code
1383
   rc = ssh_channel_send_eof(channel);
1384
   if (rc == SSH_ERROR) {
1385
       return -1;
1386
   }
1387
   while(!ssh_channel_is_eof(channel)) {
1388
       rc = ssh_channel_read(channel, buf, sizeof(buf), 0);
1389
       if (rc == SSH_ERROR) {
1390
           return -1;
1391
       }
1392
   }
1393
   ssh_channel_close(channel);
1394
@endcode
1395
 *
1396
 * @see ssh_channel_close()
1397
 * @see ssh_channel_free()
1398
 * @see ssh_channel_is_eof()
1399
 */
1400
int ssh_channel_send_eof(ssh_channel channel)
1401
0
{
1402
0
    ssh_session session = NULL;
1403
0
    int rc = SSH_ERROR;
1404
0
    int err;
1405
1406
0
    if (channel == NULL || channel->session == NULL) {
1407
0
        return rc;
1408
0
    }
1409
1410
    /* If the EOF has already been sent we're done here. */
1411
0
    if (channel->local_eof != 0) {
1412
0
        return SSH_OK;
1413
0
    }
1414
1415
0
    session = channel->session;
1416
1417
0
    err = ssh_buffer_pack(session->out_buffer,
1418
0
                          "bd",
1419
0
                          SSH2_MSG_CHANNEL_EOF,
1420
0
                          channel->remote_channel);
1421
0
    if (err != SSH_OK) {
1422
0
        ssh_set_error_oom(session);
1423
0
        goto error;
1424
0
    }
1425
1426
0
    rc = ssh_packet_send(session);
1427
0
    SSH_LOG(SSH_LOG_PACKET,
1428
0
        "Sent a EOF on client channel (%" PRIu32 ":%" PRIu32 ")",
1429
0
        channel->local_channel,
1430
0
        channel->remote_channel);
1431
0
    if (rc != SSH_OK) {
1432
0
        goto error;
1433
0
    }
1434
1435
0
    rc = ssh_channel_flush(channel);
1436
0
    if (rc == SSH_ERROR) {
1437
0
        goto error;
1438
0
    }
1439
0
    channel->local_eof = 1;
1440
1441
0
    return rc;
1442
0
error:
1443
0
    ssh_buffer_reinit(session->out_buffer);
1444
1445
0
    return rc;
1446
0
}
1447
1448
/**
1449
 * @brief Close a channel.
1450
 *
1451
 * This sends an end of file and then closes the channel. You won't be able
1452
 * to recover any data the server was going to send or was in buffers.
1453
 *
1454
 * @param[in]  channel  The channel to close.
1455
 *
1456
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred.
1457
 *
1458
 * @see ssh_channel_free()
1459
 * @see ssh_channel_is_eof()
1460
 */
1461
int ssh_channel_close(ssh_channel channel)
1462
0
{
1463
0
    ssh_session session = NULL;
1464
0
    int rc = 0;
1465
1466
0
    if(channel == NULL) {
1467
0
        return SSH_ERROR;
1468
0
    }
1469
1470
    /* If the channel close has already been sent we're done here. */
1471
0
    if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_LOCAL) {
1472
0
        return SSH_OK;
1473
0
    }
1474
1475
0
    session = channel->session;
1476
1477
0
    rc = ssh_channel_send_eof(channel);
1478
0
    if (rc != SSH_OK) {
1479
0
        return rc;
1480
0
    }
1481
1482
0
    rc = ssh_buffer_pack(session->out_buffer,
1483
0
                         "bd",
1484
0
                         SSH2_MSG_CHANNEL_CLOSE,
1485
0
                         channel->remote_channel);
1486
0
    if (rc != SSH_OK) {
1487
0
        ssh_set_error_oom(session);
1488
0
        goto error;
1489
0
    }
1490
1491
0
    rc = ssh_packet_send(session);
1492
0
    SSH_LOG(SSH_LOG_PACKET,
1493
0
            "Sent a close on client channel (%" PRIu32 ":%" PRIu32 ")",
1494
0
            channel->local_channel,
1495
0
            channel->remote_channel);
1496
1497
0
    if (rc == SSH_OK) {
1498
0
        channel->state = SSH_CHANNEL_STATE_CLOSED;
1499
0
        channel->flags |= SSH_CHANNEL_FLAG_CLOSED_LOCAL;
1500
0
    }
1501
1502
0
    rc = ssh_channel_flush(channel);
1503
0
    if(rc == SSH_ERROR) {
1504
0
        goto error;
1505
0
    }
1506
1507
0
    return rc;
1508
0
error:
1509
0
    ssh_buffer_reinit(session->out_buffer);
1510
1511
0
    return rc;
1512
0
}
1513
1514
/* this termination function waits for a window growing condition */
1515
static int ssh_channel_waitwindow_termination(void *c)
1516
0
{
1517
0
  ssh_channel channel = (ssh_channel) c;
1518
0
  if (channel->remote_window > 0 ||
1519
0
      channel->session->session_state == SSH_SESSION_STATE_ERROR ||
1520
0
      channel->state == SSH_CHANNEL_STATE_CLOSED)
1521
0
    return 1;
1522
0
  else
1523
0
    return 0;
1524
0
}
1525
1526
/* This termination function waits until the session is not in blocked status
1527
 * anymore, e.g. because of a key re-exchange.
1528
 */
1529
static int ssh_waitsession_unblocked(void *s)
1530
0
{
1531
0
    ssh_session session = (ssh_session)s;
1532
0
    switch (session->session_state){
1533
0
        case SSH_SESSION_STATE_DH:
1534
0
        case SSH_SESSION_STATE_INITIAL_KEX:
1535
0
        case SSH_SESSION_STATE_KEXINIT_RECEIVED:
1536
0
            return 0;
1537
0
        default:
1538
0
            return 1;
1539
0
    }
1540
0
}
1541
/**
1542
 * @internal
1543
 * @brief Flushes a channel (and its session) until the output buffer
1544
 * is empty, or timeout elapsed.
1545
 * @param channel SSH channel
1546
 * @return  `SSH_OK` On success,
1547
 *          `SSH_ERROR` On error.
1548
 *          `SSH_AGAIN` Timeout elapsed (or in nonblocking mode).
1549
 */
1550
int ssh_channel_flush(ssh_channel channel)
1551
0
{
1552
0
    return ssh_blocking_flush(channel->session, SSH_TIMEOUT_DEFAULT);
1553
0
}
1554
1555
static int channel_write_common(ssh_channel channel,
1556
                                const void *data,
1557
                                uint32_t len, int is_stderr)
1558
0
{
1559
0
    ssh_session session = NULL;
1560
0
    uint32_t origlen = len;
1561
0
    uint32_t effectivelen;
1562
0
    int rc;
1563
1564
0
    if (channel == NULL) {
1565
0
        return -1;
1566
0
    }
1567
0
    session = channel->session;
1568
0
    if (data == NULL) {
1569
0
        ssh_set_error_invalid(session);
1570
0
        return -1;
1571
0
    }
1572
1573
0
    if (len > INT_MAX) {
1574
0
        SSH_LOG(SSH_LOG_TRACE,
1575
0
                "Length (%" PRIu32 ") is bigger than INT_MAX",
1576
0
                len);
1577
0
        return SSH_ERROR;
1578
0
    }
1579
1580
0
    if (channel->local_eof) {
1581
0
        ssh_set_error(session,
1582
0
                      SSH_REQUEST_DENIED,
1583
0
                      "Can't write to channel %" PRIu32 ":%" PRIu32
1584
0
                      " after EOF was sent",
1585
0
                      channel->local_channel,
1586
0
                      channel->remote_channel);
1587
0
        return -1;
1588
0
    }
1589
1590
0
    if (channel->state != SSH_CHANNEL_STATE_OPEN ||
1591
0
        channel->delayed_close != 0) {
1592
0
        ssh_set_error(session, SSH_REQUEST_DENIED, "Remote channel is closed");
1593
1594
0
        return -1;
1595
0
    }
1596
1597
0
    if (session->session_state == SSH_SESSION_STATE_ERROR) {
1598
0
        return SSH_ERROR;
1599
0
    }
1600
1601
0
    if (ssh_waitsession_unblocked(session) == 0) {
1602
0
        rc = ssh_handle_packets_termination(session,
1603
0
                                            SSH_TIMEOUT_DEFAULT,
1604
0
                                            ssh_waitsession_unblocked,
1605
0
                                            session);
1606
0
        if (rc == SSH_ERROR || !ssh_waitsession_unblocked(session))
1607
0
            goto out;
1608
0
    }
1609
0
    while (len > 0) {
1610
0
        if (channel->remote_window < len) {
1611
0
            SSH_LOG(SSH_LOG_DEBUG,
1612
0
                    "Remote window is %" PRIu32
1613
0
                    " bytes. going to write %" PRIu32 " bytes",
1614
0
                    channel->remote_window,
1615
0
                    len);
1616
            /* When the window is zero, wait for it to grow */
1617
0
            if (channel->remote_window == 0) {
1618
                /* nothing can be written */
1619
0
                SSH_LOG(SSH_LOG_DEBUG, "Wait for a growing window message...");
1620
0
                rc = ssh_handle_packets_termination(
1621
0
                    session,
1622
0
                    SSH_TIMEOUT_DEFAULT,
1623
0
                    ssh_channel_waitwindow_termination,
1624
0
                    channel);
1625
0
                if (rc == SSH_ERROR ||
1626
0
                    !ssh_channel_waitwindow_termination(channel) ||
1627
0
                    session->session_state == SSH_SESSION_STATE_ERROR ||
1628
0
                    channel->state == SSH_CHANNEL_STATE_CLOSED)
1629
0
                    goto out;
1630
0
                continue;
1631
0
            }
1632
            /* When the window is non-zero, accept data up to the window size */
1633
0
            effectivelen = MIN(len, channel->remote_window);
1634
0
        } else {
1635
0
            effectivelen = len;
1636
0
        }
1637
1638
        /*
1639
         * Like OpenSSH, don't subtract bytes for the header fields
1640
         * and allow to send a payload of remote_maxpacket length.
1641
         */
1642
0
        effectivelen = MIN(effectivelen, channel->remote_maxpacket);
1643
1644
0
        rc = ssh_buffer_pack(session->out_buffer,
1645
0
                             "bd",
1646
0
                             is_stderr ? SSH2_MSG_CHANNEL_EXTENDED_DATA
1647
0
                                       : SSH2_MSG_CHANNEL_DATA,
1648
0
                             channel->remote_channel);
1649
0
        if (rc != SSH_OK) {
1650
0
            ssh_set_error_oom(session);
1651
0
            goto error;
1652
0
        }
1653
1654
        /* stderr message has an extra field */
1655
0
        if (is_stderr) {
1656
0
            rc = ssh_buffer_pack(session->out_buffer,
1657
0
                                 "d",
1658
0
                                 SSH2_EXTENDED_DATA_STDERR);
1659
0
            if (rc != SSH_OK) {
1660
0
                ssh_set_error_oom(session);
1661
0
                goto error;
1662
0
            }
1663
0
        }
1664
1665
        /* append payload data */
1666
0
        rc = ssh_buffer_pack(session->out_buffer,
1667
0
                             "dP",
1668
0
                             effectivelen,
1669
0
                             (size_t)effectivelen,
1670
0
                             data);
1671
0
        if (rc != SSH_OK) {
1672
0
            ssh_set_error_oom(session);
1673
0
            goto error;
1674
0
        }
1675
1676
0
        rc = ssh_packet_send(session);
1677
0
        if (rc == SSH_ERROR) {
1678
0
            return SSH_ERROR;
1679
0
        }
1680
1681
0
        SSH_LOG(SSH_LOG_PACKET,
1682
0
                "ssh_channel_write wrote %" PRIu32 " bytes",
1683
0
                effectivelen);
1684
1685
0
        channel->remote_window -= effectivelen;
1686
0
        len -= effectivelen;
1687
0
        data = ((uint8_t *)data + effectivelen);
1688
0
        if (channel->counter != NULL) {
1689
0
            channel->counter->out_bytes += effectivelen;
1690
0
        }
1691
0
    }
1692
1693
    /* it's a good idea to flush the socket now */
1694
0
    rc = ssh_channel_flush(channel);
1695
0
    if (rc == SSH_ERROR) {
1696
0
        goto error;
1697
0
    }
1698
1699
0
out:
1700
0
    return (int)(origlen - len);
1701
1702
0
error:
1703
0
    ssh_buffer_reinit(session->out_buffer);
1704
1705
0
    return SSH_ERROR;
1706
0
}
1707
1708
/**
1709
 * @brief Get the remote window size.
1710
 *
1711
 * This is the maximum amount of bytes the remote side expects us to send
1712
 * before growing the window again.
1713
 *
1714
 * @param[in] channel The channel to query.
1715
 *
1716
 * @return            The remote window size
1717
 *
1718
 * @warning A nonzero return value does not guarantee the socket is ready
1719
 *          to send that much data. Buffering may happen in the local SSH
1720
 *          packet buffer, so beware of really big window sizes.
1721
 *
1722
 * @warning A zero return value means ssh_channel_write (default settings)
1723
 *          will block until the window grows back.
1724
 */
1725
uint32_t ssh_channel_window_size(ssh_channel channel)
1726
0
{
1727
0
    return channel->remote_window;
1728
0
}
1729
1730
/**
1731
 * @brief Blocking write on a channel.
1732
 *
1733
 * @param[in]  channel  The channel to write to.
1734
 *
1735
 * @param[in]  data     A pointer to the data to write.
1736
 *
1737
 * @param[in]  len      The length of the buffer to write to.
1738
 *
1739
 * @return              The number of bytes written, `SSH_ERROR` on error.
1740
 *
1741
 * @see ssh_channel_read()
1742
 */
1743
int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
1744
0
{
1745
0
    return channel_write_common(channel, data, len, 0);
1746
0
}
1747
1748
/**
1749
 * @brief Check if the channel is open or not.
1750
 *
1751
 * @param[in]  channel  The channel to check.
1752
 *
1753
 * @return              0 if channel is closed, nonzero otherwise.
1754
 *
1755
 * @see ssh_channel_is_closed()
1756
 */
1757
int ssh_channel_is_open(ssh_channel channel)
1758
0
{
1759
0
    if (channel == NULL || channel->session == NULL) {
1760
0
        return 0;
1761
0
    }
1762
0
    return (channel->state == SSH_CHANNEL_STATE_OPEN && channel->session->alive != 0);
1763
0
}
1764
1765
/**
1766
 * @brief Check if the channel is closed or not.
1767
 *
1768
 * @param[in]  channel  The channel to check.
1769
 *
1770
 * @return              0 if channel is opened, nonzero otherwise.
1771
 *
1772
 * @see ssh_channel_is_open()
1773
 */
1774
int ssh_channel_is_closed(ssh_channel channel)
1775
0
{
1776
0
    if (channel == NULL || channel->session == NULL) {
1777
0
        return SSH_ERROR;
1778
0
    }
1779
0
    return (channel->state != SSH_CHANNEL_STATE_OPEN || channel->session->alive == 0);
1780
0
}
1781
1782
/**
1783
 * @brief Check if remote has sent an EOF.
1784
 *
1785
 * @param[in]  channel  The channel to check.
1786
 *
1787
 * @return              0 if there is no EOF, nonzero otherwise.
1788
 */
1789
int ssh_channel_is_eof(ssh_channel channel)
1790
0
{
1791
0
    if (channel == NULL) {
1792
0
        return SSH_ERROR;
1793
0
    }
1794
0
    if (ssh_channel_has_unread_data(channel)) {
1795
0
        return 0;
1796
0
    }
1797
1798
0
    return (channel->remote_eof != 0);
1799
0
}
1800
1801
/**
1802
 * @brief Put the channel into blocking or nonblocking mode.
1803
 *
1804
 * @param[in]  channel  The channel to use.
1805
 *
1806
 * @param[in]  blocking A boolean for blocking or nonblocking.
1807
 *
1808
 * @warning    A side-effect of this is to put the whole session
1809
 *             in non-blocking mode.
1810
 * @see ssh_set_blocking()
1811
 */
1812
void ssh_channel_set_blocking(ssh_channel channel, int blocking)
1813
0
{
1814
0
    if (channel == NULL) {
1815
0
        return;
1816
0
    }
1817
0
    ssh_set_blocking(channel->session, blocking);
1818
0
}
1819
1820
/**
1821
 * @internal
1822
 *
1823
 * @brief handle a SSH_CHANNEL_SUCCESS packet and set the channel state.
1824
 */
1825
SSH_PACKET_CALLBACK(ssh_packet_channel_success)
1826
0
{
1827
0
    ssh_channel channel = NULL;
1828
0
    (void)type;
1829
0
    (void)user;
1830
1831
0
    channel = channel_from_msg(session, packet);
1832
0
    if (channel == NULL) {
1833
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
1834
0
        return SSH_PACKET_USED;
1835
0
    }
1836
1837
0
    SSH_LOG(SSH_LOG_PACKET,
1838
0
            "Received SSH_CHANNEL_SUCCESS on channel (%" PRIu32 ":%" PRIu32 ")",
1839
0
            channel->local_channel,
1840
0
            channel->remote_channel);
1841
0
    if (channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING) {
1842
0
        SSH_LOG(SSH_LOG_RARE,
1843
0
                "SSH_CHANNEL_SUCCESS received in incorrect state %d",
1844
0
                channel->request_state);
1845
0
    } else {
1846
0
        channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED;
1847
1848
0
        ssh_callbacks_execute_list(channel->callbacks,
1849
0
                                   ssh_channel_callbacks,
1850
0
                                   channel_request_response_function,
1851
0
                                   channel->session,
1852
0
                                   channel);
1853
0
    }
1854
1855
0
    return SSH_PACKET_USED;
1856
0
}
1857
1858
/**
1859
 * @internal
1860
 *
1861
 * @brief Handle a SSH_CHANNEL_FAILURE packet and set the channel state.
1862
 */
1863
SSH_PACKET_CALLBACK(ssh_packet_channel_failure)
1864
0
{
1865
0
    ssh_channel channel = NULL;
1866
0
    (void)type;
1867
0
    (void)user;
1868
1869
0
    channel = channel_from_msg(session, packet);
1870
0
    if (channel == NULL) {
1871
0
        SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session));
1872
1873
0
        return SSH_PACKET_USED;
1874
0
    }
1875
1876
0
    SSH_LOG(SSH_LOG_PACKET,
1877
0
            "Received SSH_CHANNEL_FAILURE on channel (%" PRIu32 ":%" PRIu32 ")",
1878
0
            channel->local_channel,
1879
0
            channel->remote_channel);
1880
0
    if (channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING) {
1881
0
        SSH_LOG(SSH_LOG_RARE,
1882
0
                "SSH_CHANNEL_FAILURE received in incorrect state %d",
1883
0
                channel->request_state);
1884
0
    } else {
1885
0
        channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED;
1886
1887
0
        ssh_callbacks_execute_list(channel->callbacks,
1888
0
                                   ssh_channel_callbacks,
1889
0
                                   channel_request_response_function,
1890
0
                                   channel->session,
1891
0
                                   channel);
1892
0
    }
1893
1894
0
    return SSH_PACKET_USED;
1895
0
}
1896
1897
static int ssh_channel_request_termination(void *c)
1898
0
{
1899
0
  ssh_channel channel = (ssh_channel)c;
1900
0
  if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING ||
1901
0
      channel->session->session_state == SSH_SESSION_STATE_ERROR)
1902
0
    return 1;
1903
0
  else
1904
0
    return 0;
1905
0
}
1906
1907
static int channel_request(ssh_channel channel, const char *request,
1908
    ssh_buffer buffer, int reply)
1909
0
{
1910
0
  ssh_session session = channel->session;
1911
0
  int rc = SSH_ERROR;
1912
0
  int ret;
1913
1914
0
  switch(channel->request_state){
1915
0
  case SSH_CHANNEL_REQ_STATE_NONE:
1916
0
    break;
1917
0
  default:
1918
0
    goto pending;
1919
0
  }
1920
1921
0
  ret = ssh_buffer_pack(session->out_buffer,
1922
0
                        "bdsb",
1923
0
                        SSH2_MSG_CHANNEL_REQUEST,
1924
0
                        channel->remote_channel,
1925
0
                        request,
1926
0
                        reply == 0 ? 0 : 1);
1927
0
  if (ret != SSH_OK) {
1928
0
    ssh_set_error_oom(session);
1929
0
    goto error;
1930
0
  }
1931
1932
0
  if (buffer != NULL) {
1933
0
    if (ssh_buffer_add_data(session->out_buffer, ssh_buffer_get(buffer),
1934
0
        ssh_buffer_get_len(buffer)) < 0) {
1935
0
      ssh_set_error_oom(session);
1936
0
      goto error;
1937
0
    }
1938
0
  }
1939
0
  channel->request_state = SSH_CHANNEL_REQ_STATE_PENDING;
1940
0
  if (ssh_packet_send(session) == SSH_ERROR) {
1941
0
    return rc;
1942
0
  }
1943
1944
0
  SSH_LOG(SSH_LOG_PACKET,
1945
0
          "Sent a SSH_MSG_CHANNEL_REQUEST %s on channel %" PRIu32 ":%" PRIu32,
1946
0
          request,
1947
0
          channel->local_channel,
1948
0
          channel->remote_channel);
1949
0
  if (reply == 0) {
1950
0
    channel->request_state = SSH_CHANNEL_REQ_STATE_NONE;
1951
0
    return SSH_OK;
1952
0
  }
1953
0
pending:
1954
0
  rc = ssh_handle_packets_termination(session,
1955
0
                                      SSH_TIMEOUT_DEFAULT,
1956
0
                                      ssh_channel_request_termination,
1957
0
                                      channel);
1958
1959
0
  if(session->session_state == SSH_SESSION_STATE_ERROR || rc == SSH_ERROR) {
1960
0
      channel->request_state = SSH_CHANNEL_REQ_STATE_ERROR;
1961
0
  }
1962
  /* we received something */
1963
0
  switch (channel->request_state){
1964
0
    case SSH_CHANNEL_REQ_STATE_ERROR:
1965
0
      rc=SSH_ERROR;
1966
0
      break;
1967
0
    case SSH_CHANNEL_REQ_STATE_DENIED:
1968
0
      ssh_set_error(session,
1969
0
                    SSH_REQUEST_DENIED,
1970
0
                    "Channel request %s failed on channel %" PRIu32 ":%" PRIu32,
1971
0
                    request,
1972
0
                    channel->local_channel,
1973
0
                    channel->remote_channel);
1974
0
      rc=SSH_ERROR;
1975
0
      break;
1976
0
    case SSH_CHANNEL_REQ_STATE_ACCEPTED:
1977
0
      SSH_LOG(SSH_LOG_DEBUG,
1978
0
              "Channel request %s success on channel %" PRIu32 ":%" PRIu32,
1979
0
              request,
1980
0
              channel->local_channel,
1981
0
              channel->remote_channel);
1982
0
      rc=SSH_OK;
1983
0
      break;
1984
0
    case SSH_CHANNEL_REQ_STATE_PENDING:
1985
0
      rc = SSH_AGAIN;
1986
0
      return rc;
1987
0
    case SSH_CHANNEL_REQ_STATE_NONE:
1988
      /* Never reached */
1989
0
      ssh_set_error(session, SSH_FATAL, "Invalid state in channel_request()");
1990
0
      rc=SSH_ERROR;
1991
0
      break;
1992
0
  }
1993
0
  channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
1994
1995
0
  return rc;
1996
0
error:
1997
0
  ssh_buffer_reinit(session->out_buffer);
1998
1999
0
  return rc;
2000
0
}
2001
2002
/**
2003
 * @brief Request a pty with a specific type and size.
2004
 *
2005
 * @param[in]  channel  The channel to send the request.
2006
 *
2007
 * @param[in]  terminal The terminal type ("vt100, xterm,...").
2008
 *
2009
 * @param[in]  col      The number of columns.
2010
 *
2011
 * @param[in]  row      The number of rows.
2012
 *
2013
 * @param[in]  modes    Encoded SSH terminal modes for the PTY
2014
 *
2015
 * @param[in]  modes_len Number of bytes in 'modes'
2016
 *
2017
 * @return              `SSH_OK` on success,
2018
 *                      `SSH_ERROR` if an error occurred,
2019
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2020
 *                      to be done again.
2021
 */
2022
int ssh_channel_request_pty_size_modes(ssh_channel channel, const char *terminal,
2023
    int col, int row, const unsigned char* modes, size_t modes_len)
2024
0
{
2025
0
    ssh_session session = NULL;
2026
0
    ssh_buffer buffer = NULL;
2027
0
    int rc = SSH_ERROR;
2028
2029
0
    if (channel == NULL) {
2030
0
        return SSH_ERROR;
2031
0
    }
2032
0
    session = channel->session;
2033
2034
0
    if (terminal == NULL) {
2035
0
        ssh_set_error_invalid(channel->session);
2036
0
        return rc;
2037
0
    }
2038
2039
0
    switch (channel->request_state) {
2040
0
    case SSH_CHANNEL_REQ_STATE_NONE:
2041
0
        break;
2042
0
    default:
2043
0
        goto pending;
2044
0
    }
2045
2046
0
    buffer = ssh_buffer_new();
2047
0
    if (buffer == NULL) {
2048
0
        ssh_set_error_oom(session);
2049
0
        goto error;
2050
0
    }
2051
2052
0
    rc = ssh_buffer_pack(buffer,
2053
0
                         "sdddddP",
2054
0
                         terminal,
2055
0
                         col,
2056
0
                         row,
2057
0
                         0, /* pix */
2058
0
                         0, /* pix */
2059
0
                         (uint32_t)modes_len,
2060
0
                         (size_t)modes_len,
2061
0
                         modes);
2062
2063
0
    if (rc != SSH_OK) {
2064
0
        ssh_set_error_oom(session);
2065
0
        goto error;
2066
0
    }
2067
0
pending:
2068
0
    rc = channel_request(channel, "pty-req", buffer, 1);
2069
0
error:
2070
0
    SSH_BUFFER_FREE(buffer);
2071
2072
0
    return rc;
2073
0
}
2074
2075
/**
2076
 * @brief Request a PTY with a specific size using current TTY modes.
2077
 *
2078
 * Encodes @p terminal modes from the current TTY and sends a PTY request
2079
 * for the given channel, terminal type, and size in columns/rows.
2080
 *
2081
 * @param[in] channel  The channel to send the request on.
2082
 * @param[in] terminal The terminal type (e.g. "xterm").
2083
 * @param[in] col      Number of columns.
2084
 * @param[in] row      Number of rows.
2085
 *
2086
 * @return `SSH_OK` on success; `SSH_ERROR` on failure.
2087
 */
2088
int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal,
2089
    int col, int row)
2090
0
{
2091
    /* use modes from the current TTY */
2092
0
    unsigned char modes_buf[SSH_TTY_MODES_MAX_BUFSIZE];
2093
0
    int rc = encode_current_tty_opts(modes_buf, sizeof(modes_buf));
2094
0
    if (rc < 0) {
2095
0
        return rc;
2096
0
    }
2097
0
    return ssh_channel_request_pty_size_modes(channel,
2098
0
                                              terminal,
2099
0
                                              col,
2100
0
                                              row,
2101
0
                                              modes_buf,
2102
0
                                              (size_t)rc);
2103
0
}
2104
2105
/**
2106
 * @brief Request a PTY.
2107
 *
2108
 * @param[in]  channel  The channel to send the request.
2109
 *
2110
 * @return              `SSH_OK` on success,
2111
 *                      `SSH_ERROR` if an error occurred,
2112
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2113
 *                      to be done again.
2114
 *
2115
 * @see ssh_channel_request_pty_size()
2116
 */
2117
int ssh_channel_request_pty(ssh_channel channel)
2118
0
{
2119
0
  return ssh_channel_request_pty_size(channel, "xterm", 80, 24);
2120
0
}
2121
2122
/**
2123
 * @brief Change the size of the terminal associated to a channel.
2124
 *
2125
 * @param[in]  channel  The channel to change the size.
2126
 *
2127
 * @param[in]  cols     The new number of columns.
2128
 *
2129
 * @param[in]  rows     The new number of rows.
2130
 *
2131
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred.
2132
 *
2133
 * @warning Do not call it from a signal handler if you are not sure any other
2134
 *          libssh function using the same channel/session is running at the
2135
 *          same time (not 100% threadsafe).
2136
 */
2137
int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows)
2138
0
{
2139
0
  ssh_session session = channel->session;
2140
0
  ssh_buffer buffer = NULL;
2141
0
  int rc = SSH_ERROR;
2142
2143
0
  buffer = ssh_buffer_new();
2144
0
  if (buffer == NULL) {
2145
0
    ssh_set_error_oom(session);
2146
0
    goto error;
2147
0
  }
2148
2149
0
  rc = ssh_buffer_pack(buffer,
2150
0
                       "dddd",
2151
0
                       cols,
2152
0
                       rows,
2153
0
                       0, /* pix */
2154
0
                       0 /* pix */);
2155
0
  if (rc != SSH_OK) {
2156
0
    ssh_set_error_oom(session);
2157
0
    goto error;
2158
0
  }
2159
2160
0
  rc = channel_request(channel, "window-change", buffer, 0);
2161
0
error:
2162
0
  SSH_BUFFER_FREE(buffer);
2163
2164
0
  return rc;
2165
0
}
2166
2167
/**
2168
 * @brief Request a shell.
2169
 *
2170
 * @param[in]  channel  The channel to send the request.
2171
 *
2172
 * @return              `SSH_OK` on success,
2173
 *                      `SSH_ERROR` if an error occurred,
2174
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2175
 *                      to be done again.
2176
 */
2177
int ssh_channel_request_shell(ssh_channel channel)
2178
0
{
2179
0
    if (channel == NULL) {
2180
0
        return SSH_ERROR;
2181
0
    }
2182
2183
0
    return channel_request(channel, "shell", NULL, 1);
2184
0
}
2185
2186
/**
2187
 * @brief Request a subsystem (for example "sftp").
2188
 *
2189
 * @param[in]  channel  The channel to send the request.
2190
 *
2191
 * @param[in]  subsys   The subsystem to request (for example "sftp").
2192
 *
2193
 * @return              `SSH_OK` on success,
2194
 *                      `SSH_ERROR` if an error occurred,
2195
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2196
 *                      to be done again.
2197
 *
2198
 * @warning You normally don't have to call it for sftp, see sftp_new().
2199
 */
2200
int ssh_channel_request_subsystem(ssh_channel channel, const char *subsys)
2201
0
{
2202
0
  ssh_buffer buffer = NULL;
2203
0
  int rc = SSH_ERROR;
2204
2205
0
  if(channel == NULL) {
2206
0
      return SSH_ERROR;
2207
0
  }
2208
0
  if(subsys == NULL) {
2209
0
      ssh_set_error_invalid(channel->session);
2210
0
      return rc;
2211
0
  }
2212
0
  switch(channel->request_state){
2213
0
  case SSH_CHANNEL_REQ_STATE_NONE:
2214
0
    break;
2215
0
  default:
2216
0
    goto pending;
2217
0
  }
2218
2219
0
  buffer = ssh_buffer_new();
2220
0
  if (buffer == NULL) {
2221
0
    ssh_set_error_oom(channel->session);
2222
0
    goto error;
2223
0
  }
2224
2225
0
  rc = ssh_buffer_pack(buffer, "s", subsys);
2226
0
  if (rc != SSH_OK) {
2227
0
    ssh_set_error_oom(channel->session);
2228
0
    goto error;
2229
0
  }
2230
0
pending:
2231
0
  rc = channel_request(channel, "subsystem", buffer, 1);
2232
0
error:
2233
0
  SSH_BUFFER_FREE(buffer);
2234
2235
0
  return rc;
2236
0
}
2237
2238
/**
2239
 * @brief Request sftp subsystem on the channel
2240
 *
2241
 * @param[in]  channel The channel to request the sftp subsystem.
2242
 *
2243
 * @return              `SSH_OK` on success,
2244
 *                      `SSH_ERROR` if an error occurred,
2245
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2246
 *                      to be done again.
2247
 *
2248
 * @note You should use sftp_new() which does this for you.
2249
 */
2250
int ssh_channel_request_sftp( ssh_channel channel)
2251
0
{
2252
0
    if(channel == NULL) {
2253
0
        return SSH_ERROR;
2254
0
    }
2255
0
    return ssh_channel_request_subsystem(channel, "sftp");
2256
0
}
2257
2258
static char *generate_cookie(void)
2259
0
{
2260
0
  static const char *hex = "0123456789abcdef";
2261
0
  char s[36];
2262
0
  unsigned char rnd[16];
2263
0
  int ok;
2264
0
  int i;
2265
2266
0
  ok = ssh_get_random(rnd, sizeof(rnd), 0);
2267
0
  if (!ok) {
2268
0
      return NULL;
2269
0
  }
2270
2271
0
  for (i = 0; i < 16; i++) {
2272
0
    s[i*2] = hex[rnd[i] & 0x0f];
2273
0
    s[i*2+1] = hex[rnd[i] >> 4];
2274
0
  }
2275
0
  s[32] = '\0';
2276
0
  return strdup(s);
2277
0
}
2278
2279
/**
2280
 * @brief Sends the "x11-req" channel request over an existing session channel.
2281
 *
2282
 * This will enable redirecting the display of the remote X11 applications to
2283
 * local X server over a secure tunnel.
2284
 *
2285
 * @param[in]  channel  An existing session channel where the remote X11
2286
 *                      applications are going to be executed.
2287
 *
2288
 * @param[in]  single_connection A boolean to mark only one X11 app will be
2289
 *                               redirected.
2290
 *
2291
 * @param[in]  protocol A x11 authentication protocol. Pass NULL to use the
2292
 *                      default value MIT-MAGIC-COOKIE-1.
2293
 *
2294
 * @param[in]  cookie   A x11 authentication cookie. Pass NULL to generate
2295
 *                      a random cookie.
2296
 *
2297
 * @param[in] screen_number The screen number.
2298
 *
2299
 * @return              `SSH_OK` on success,
2300
 *                      `SSH_ERROR` if an error occurred,
2301
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2302
 *                      to be done again.
2303
 */
2304
int ssh_channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
2305
    const char *cookie, int screen_number)
2306
0
{
2307
0
  ssh_buffer buffer = NULL;
2308
0
  char *c = NULL;
2309
0
  int rc = SSH_ERROR;
2310
2311
0
  if(channel == NULL) {
2312
0
      return SSH_ERROR;
2313
0
  }
2314
0
  switch(channel->request_state){
2315
0
  case SSH_CHANNEL_REQ_STATE_NONE:
2316
0
    break;
2317
0
  default:
2318
0
    goto pending;
2319
0
  }
2320
2321
0
  buffer = ssh_buffer_new();
2322
0
  if (buffer == NULL) {
2323
0
    ssh_set_error_oom(channel->session);
2324
0
    goto error;
2325
0
  }
2326
2327
0
  if (cookie == NULL) {
2328
0
    c = generate_cookie();
2329
0
    if (c == NULL) {
2330
0
      ssh_set_error_oom(channel->session);
2331
0
      goto error;
2332
0
    }
2333
0
  }
2334
2335
0
  rc = ssh_buffer_pack(buffer,
2336
0
                       "bssd",
2337
0
                       single_connection == 0 ? 0 : 1,
2338
0
                       protocol ? protocol : "MIT-MAGIC-COOKIE-1",
2339
0
                       cookie ? cookie : c,
2340
0
                       screen_number);
2341
0
  if (c != NULL){
2342
0
      SAFE_FREE(c);
2343
0
  }
2344
0
  if (rc != SSH_OK) {
2345
0
    ssh_set_error_oom(channel->session);
2346
0
    goto error;
2347
0
  }
2348
0
pending:
2349
0
  rc = channel_request(channel, "x11-req", buffer, 1);
2350
2351
0
error:
2352
0
  SSH_BUFFER_FREE(buffer);
2353
0
  return rc;
2354
0
}
2355
2356
static ssh_channel ssh_channel_accept(ssh_session session, int channeltype,
2357
    int timeout_ms, int *destination_port, char **originator, int *originator_port)
2358
0
{
2359
0
#ifndef _WIN32
2360
0
  static const struct timespec ts = {
2361
0
    .tv_sec = 0,
2362
0
    .tv_nsec = 50000000 /* 50ms */
2363
0
  };
2364
0
#endif
2365
0
  ssh_message msg = NULL;
2366
0
  ssh_channel channel = NULL;
2367
0
  struct ssh_iterator *iterator = NULL;
2368
0
  int t;
2369
2370
  /*
2371
   * We sleep for 50 ms in ssh_handle_packets() and later sleep for
2372
   * 50 ms. So we need to decrement by 100 ms.
2373
   */
2374
0
  for (t = timeout_ms; t >= 0; t -= 100) {
2375
0
    if (timeout_ms == 0) {
2376
0
        ssh_handle_packets(session, 0);
2377
0
    } else {
2378
0
        ssh_handle_packets(session, 50);
2379
0
    }
2380
2381
0
    if (session->ssh_message_list) {
2382
0
      iterator = ssh_list_get_iterator(session->ssh_message_list);
2383
0
      while (iterator) {
2384
0
        msg = (ssh_message)iterator->data;
2385
0
        if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL_OPEN &&
2386
0
            ssh_message_subtype(msg) == channeltype) {
2387
0
          ssh_list_remove(session->ssh_message_list, iterator);
2388
0
          channel = ssh_message_channel_request_open_reply_accept(msg);
2389
0
          if(destination_port) {
2390
0
            *destination_port=msg->channel_request_open.destination_port;
2391
0
          }
2392
0
          if(originator) {
2393
0
            *originator=strdup(msg->channel_request_open.originator);
2394
0
          }
2395
0
          if(originator_port) {
2396
0
            *originator_port=msg->channel_request_open.originator_port;
2397
0
          }
2398
2399
0
          ssh_message_free(msg);
2400
0
          return channel;
2401
0
        }
2402
0
        iterator = iterator->next;
2403
0
      }
2404
0
    }
2405
0
    if(t>0){
2406
#ifdef _WIN32
2407
      Sleep(50); /* 50ms */
2408
#else
2409
0
      nanosleep(&ts, NULL);
2410
0
#endif
2411
0
    }
2412
0
  }
2413
2414
0
  ssh_set_error(session, SSH_NO_ERROR, "No channel request of this type from server");
2415
0
  return NULL;
2416
0
}
2417
2418
/**
2419
 * @brief Accept an X11 forwarding channel.
2420
 *
2421
 * @param[in]  channel  An x11-enabled session channel.
2422
 *
2423
 * @param[in]  timeout_ms Timeout in milliseconds.
2424
 *
2425
 * @return              A newly created channel, or NULL if no X11 request from
2426
 *                      the server.
2427
 */
2428
ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms)
2429
0
{
2430
0
    return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms, NULL, NULL, NULL);
2431
0
}
2432
2433
/**
2434
 * @brief Send an "auth-agent-req" channel request over an existing session
2435
 * channel.
2436
 *
2437
 * This client-side request will enable forwarding the agent over an secure
2438
 * tunnel. When the server is ready to open one authentication agent channel, an
2439
 * ssh_channel_open_request_auth_agent_callback event will be generated.
2440
 *
2441
 * @param[in]  channel  The channel to send signal.
2442
 *
2443
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred
2444
 */
2445
0
int ssh_channel_request_auth_agent(ssh_channel channel) {
2446
0
  if (channel == NULL) {
2447
0
    return SSH_ERROR;
2448
0
  }
2449
2450
0
  return channel_request(channel, "auth-agent-req@openssh.com", NULL, 0);
2451
0
}
2452
2453
/**
2454
 * @internal
2455
 *
2456
 * @brief Handle a SSH_REQUEST_SUCCESS packet normally sent after a global
2457
 * request.
2458
 */
2459
0
SSH_PACKET_CALLBACK(ssh_request_success){
2460
0
  (void)type;
2461
0
  (void)user;
2462
0
  (void)packet;
2463
2464
0
  SSH_LOG(SSH_LOG_PACKET,
2465
0
      "Received SSH_REQUEST_SUCCESS");
2466
0
  if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){
2467
0
    SSH_LOG(SSH_LOG_RARE, "SSH_REQUEST_SUCCESS received in incorrect state %d",
2468
0
        session->global_req_state);
2469
0
  } else {
2470
0
    session->global_req_state=SSH_CHANNEL_REQ_STATE_ACCEPTED;
2471
0
  }
2472
2473
0
  return SSH_PACKET_USED;
2474
0
}
2475
2476
/**
2477
 * @internal
2478
 *
2479
 * @brief Handle a SSH_REQUEST_DENIED packet normally sent after a global
2480
 * request.
2481
 */
2482
0
SSH_PACKET_CALLBACK(ssh_request_denied){
2483
0
  (void)type;
2484
0
  (void)user;
2485
0
  (void)packet;
2486
2487
0
  SSH_LOG(SSH_LOG_PACKET,
2488
0
      "Received SSH_REQUEST_FAILURE");
2489
0
  if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){
2490
0
    SSH_LOG(SSH_LOG_RARE, "SSH_REQUEST_DENIED received in incorrect state %d",
2491
0
        session->global_req_state);
2492
0
  } else {
2493
0
    session->global_req_state=SSH_CHANNEL_REQ_STATE_DENIED;
2494
0
  }
2495
2496
0
  return SSH_PACKET_USED;
2497
2498
0
}
2499
2500
static int ssh_global_request_termination(void *s)
2501
0
{
2502
0
  ssh_session session = (ssh_session) s;
2503
0
  if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING ||
2504
0
      session->session_state == SSH_SESSION_STATE_ERROR)
2505
0
    return 1;
2506
0
  else
2507
0
    return 0;
2508
0
}
2509
2510
/**
2511
 * @internal
2512
 *
2513
 * @brief Send a global request (needed for forward listening) and wait for the
2514
 * result.
2515
 *
2516
 * @param[in]  session  The SSH session handle.
2517
 *
2518
 * @param[in]  request  The type of request (defined in RFC).
2519
 *
2520
 * @param[in]  buffer   Additional data to put in packet.
2521
 *
2522
 * @param[in]  reply    Set if you expect a reply from server.
2523
 *
2524
 * @return              `SSH_OK` on success,
2525
 *                      `SSH_ERROR` if an error occurred,
2526
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2527
 *                      to be done again.
2528
 */
2529
int ssh_global_request(ssh_session session,
2530
                       const char *request,
2531
                       ssh_buffer buffer,
2532
                       int reply)
2533
0
{
2534
0
  int rc;
2535
2536
0
  switch (session->global_req_state) {
2537
0
  case SSH_CHANNEL_REQ_STATE_NONE:
2538
0
    break;
2539
0
  default:
2540
0
    goto pending;
2541
0
  }
2542
2543
0
  rc = ssh_buffer_pack(session->out_buffer,
2544
0
                       "bsb",
2545
0
                       SSH2_MSG_GLOBAL_REQUEST,
2546
0
                       request,
2547
0
                       reply == 0 ? 0 : 1);
2548
0
  if (rc != SSH_OK){
2549
0
      ssh_set_error_oom(session);
2550
0
      rc = SSH_ERROR;
2551
0
      goto error;
2552
0
  }
2553
2554
0
  if (buffer != NULL) {
2555
0
      rc = ssh_buffer_add_data(session->out_buffer,
2556
0
                           ssh_buffer_get(buffer),
2557
0
                           ssh_buffer_get_len(buffer));
2558
0
      if (rc < 0) {
2559
0
          ssh_set_error_oom(session);
2560
0
          rc = SSH_ERROR;
2561
0
          goto error;
2562
0
      }
2563
0
  }
2564
2565
0
  session->global_req_state = SSH_CHANNEL_REQ_STATE_PENDING;
2566
0
  rc = ssh_packet_send(session);
2567
0
  if (rc == SSH_ERROR) {
2568
0
      return rc;
2569
0
  }
2570
2571
0
  SSH_LOG(SSH_LOG_PACKET,
2572
0
      "Sent a SSH_MSG_GLOBAL_REQUEST %s", request);
2573
2574
0
  if (reply == 0) {
2575
0
      session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
2576
2577
0
      return SSH_OK;
2578
0
  }
2579
0
pending:
2580
0
  rc = ssh_handle_packets_termination(session,
2581
0
                                      SSH_TIMEOUT_DEFAULT,
2582
0
                                      ssh_global_request_termination,
2583
0
                                      session);
2584
2585
0
  if(rc==SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR){
2586
0
    session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR;
2587
0
  }
2588
0
  switch(session->global_req_state){
2589
0
    case SSH_CHANNEL_REQ_STATE_ACCEPTED:
2590
0
      SSH_LOG(SSH_LOG_DEBUG, "Global request %s success",request);
2591
0
      rc=SSH_OK;
2592
0
      break;
2593
0
    case SSH_CHANNEL_REQ_STATE_DENIED:
2594
0
      SSH_LOG(SSH_LOG_PACKET,
2595
0
          "Global request %s failed", request);
2596
0
      ssh_set_error(session, SSH_REQUEST_DENIED,
2597
0
          "Global request %s failed", request);
2598
0
      rc=SSH_ERROR;
2599
0
      break;
2600
0
    case SSH_CHANNEL_REQ_STATE_ERROR:
2601
0
    case SSH_CHANNEL_REQ_STATE_NONE:
2602
0
      rc = SSH_ERROR;
2603
0
      break;
2604
0
    case SSH_CHANNEL_REQ_STATE_PENDING:
2605
0
      return SSH_AGAIN;
2606
0
  }
2607
0
  session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE;
2608
2609
0
  return rc;
2610
0
error:
2611
0
  ssh_buffer_reinit(session->out_buffer);
2612
2613
0
  return rc;
2614
0
}
2615
2616
/**
2617
 * @brief Sends the "tcpip-forward" global request to ask the server to begin
2618
 * listening for inbound connections.
2619
 *
2620
 * @param[in]  session  The ssh session to send the request.
2621
 *
2622
 * @param[in]  address  The address to bind to on the server. Pass NULL to bind
2623
 *                      to all available addresses on all protocol families
2624
 *                      supported by the server.
2625
 *
2626
 * @param[in]  port     The port to bind to on the server. Pass 0 to ask the
2627
 *                      server to allocate the next available unprivileged port
2628
 *                      number
2629
 *
2630
 * @param[in]  bound_port The pointer to get actual bound port. Pass NULL to
2631
 *                        ignore.
2632
 *
2633
 * @return              `SSH_OK` on success,
2634
 *                      `SSH_ERROR` if an error occurred,
2635
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2636
 *                      to be done again.
2637
 **/
2638
int ssh_channel_listen_forward(ssh_session session,
2639
                               const char *address,
2640
                               int port,
2641
                               int *bound_port)
2642
0
{
2643
0
  ssh_buffer buffer = NULL;
2644
0
  int rc = SSH_ERROR;
2645
2646
0
  if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE)
2647
0
    goto pending;
2648
2649
0
  buffer = ssh_buffer_new();
2650
0
  if (buffer == NULL) {
2651
0
    ssh_set_error_oom(session);
2652
0
    goto error;
2653
0
  }
2654
2655
0
  rc = ssh_buffer_pack(buffer,
2656
0
                       "sd",
2657
0
                       address ? address : "",
2658
0
                       port);
2659
0
  if (rc != SSH_OK){
2660
0
    ssh_set_error_oom(session);
2661
0
    goto error;
2662
0
  }
2663
0
pending:
2664
0
  rc = ssh_global_request(session, "tcpip-forward", buffer, 1);
2665
2666
  /* TODO: FIXME no guarantee the last packet we received contains
2667
   * that info */
2668
0
  if (rc == SSH_OK && port == 0 && bound_port != NULL) {
2669
0
    rc = ssh_buffer_unpack(session->in_buffer, "d", bound_port);
2670
0
    if (rc != SSH_OK)
2671
0
        *bound_port = 0;
2672
0
  }
2673
2674
0
error:
2675
0
  SSH_BUFFER_FREE(buffer);
2676
0
  return rc;
2677
0
}
2678
2679
/* DEPRECATED */
2680
int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port)
2681
0
{
2682
0
  return ssh_channel_listen_forward(session, address, port, bound_port);
2683
0
}
2684
2685
/* DEPRECATED */
2686
ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms)
2687
0
{
2688
0
    return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL, NULL, NULL);
2689
0
}
2690
2691
/**
2692
 * @brief Accept an incoming TCP/IP forwarding channel and get some information
2693
 * about incoming connection
2694
 *
2695
 * @param[in]  session    The ssh session to use.
2696
 *
2697
 * @param[in]  timeout_ms A timeout in milliseconds.
2698
 *
2699
 * @param[in]  destination_port A pointer to destination port or NULL.
2700
 *
2701
 * @return Newly created channel, or NULL if no incoming channel request from
2702
 *         the server
2703
 */
2704
0
ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int* destination_port) {
2705
0
  return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, destination_port, NULL, NULL);
2706
0
}
2707
2708
/**
2709
 * @brief Accept an incoming TCP/IP forwarding channel and get information
2710
 * about incoming connection
2711
 *
2712
 * @param[in]  session    The ssh session to use.
2713
 *
2714
 * @param[in]  timeout_ms A timeout in milliseconds.
2715
 *
2716
 * @param[out]  destination_port A pointer to destination port or NULL.
2717
 *
2718
 * @param[out]  originator A pointer to a pointer to a string of originator host or NULL.
2719
 *              That the caller is responsible for to ssh_string_free_char().
2720
 *
2721
 * @param[out]  originator_port A pointer to originator port or NULL.
2722
 *
2723
 * @return Newly created channel, or NULL if no incoming channel request from
2724
 *         the server
2725
 *
2726
 * @see ssh_string_free_char()
2727
 */
2728
0
ssh_channel ssh_channel_open_forward_port(ssh_session session, int timeout_ms, int *destination_port, char **originator, int *originator_port) {
2729
0
  return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, destination_port, originator, originator_port);
2730
0
}
2731
2732
/**
2733
 * @brief Sends the "cancel-tcpip-forward" global request to ask the server to
2734
 *        cancel the tcpip-forward request.
2735
 *
2736
 * @param[in]  session  The ssh session to send the request.
2737
 *
2738
 * @param[in]  address  The bound address on the server.
2739
 *
2740
 * @param[in]  port     The bound port on the server.
2741
 *
2742
 * @return              `SSH_OK` on success,
2743
 *                      `SSH_ERROR` if an error occurred,
2744
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2745
 *                      to be done again.
2746
 */
2747
int ssh_channel_cancel_forward(ssh_session session,
2748
                               const char *address,
2749
                               int port)
2750
0
{
2751
0
  ssh_buffer buffer = NULL;
2752
0
  int rc = SSH_ERROR;
2753
2754
0
  if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE)
2755
0
    goto pending;
2756
2757
0
  buffer = ssh_buffer_new();
2758
0
  if (buffer == NULL) {
2759
0
    ssh_set_error_oom(session);
2760
0
    goto error;
2761
0
  }
2762
2763
0
  rc = ssh_buffer_pack(buffer, "sd",
2764
0
                       address ? address : "",
2765
0
                       port);
2766
0
  if (rc != SSH_OK){
2767
0
      ssh_set_error_oom(session);
2768
0
      goto error;
2769
0
  }
2770
0
pending:
2771
0
  rc = ssh_global_request(session, "cancel-tcpip-forward", buffer, 1);
2772
2773
0
error:
2774
0
  SSH_BUFFER_FREE(buffer);
2775
0
  return rc;
2776
0
}
2777
2778
/* DEPRECATED */
2779
int ssh_forward_cancel(ssh_session session, const char *address, int port)
2780
0
{
2781
0
    return ssh_channel_cancel_forward(session, address, port);
2782
0
}
2783
2784
/**
2785
 * @brief Set environment variables.
2786
 *
2787
 * @param[in]  channel  The channel to set the environment variables.
2788
 *
2789
 * @param[in]  name     The name of the variable.
2790
 *
2791
 * @param[in]  value    The value to set.
2792
 *
2793
 * @return              `SSH_OK` on success,
2794
 *                      `SSH_ERROR` if an error occurred,
2795
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2796
 *                      to be done again.
2797
 * @warning Some environment variables may be refused by security reasons.
2798
 */
2799
int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value)
2800
0
{
2801
0
  ssh_buffer buffer = NULL;
2802
0
  int rc = SSH_ERROR;
2803
2804
0
  if(channel == NULL) {
2805
0
      return SSH_ERROR;
2806
0
  }
2807
0
  if(name == NULL || value == NULL) {
2808
0
      ssh_set_error_invalid(channel->session);
2809
0
      return rc;
2810
0
  }
2811
0
  switch(channel->request_state){
2812
0
  case SSH_CHANNEL_REQ_STATE_NONE:
2813
0
    break;
2814
0
  default:
2815
0
    goto pending;
2816
0
  }
2817
0
  buffer = ssh_buffer_new();
2818
0
  if (buffer == NULL) {
2819
0
    ssh_set_error_oom(channel->session);
2820
0
    goto error;
2821
0
  }
2822
2823
0
  rc = ssh_buffer_pack(buffer,
2824
0
                       "ss",
2825
0
                       name,
2826
0
                       value);
2827
0
  if (rc != SSH_OK){
2828
0
    ssh_set_error_oom(channel->session);
2829
0
    goto error;
2830
0
  }
2831
0
pending:
2832
0
  rc = channel_request(channel, "env", buffer,1);
2833
0
error:
2834
0
  SSH_BUFFER_FREE(buffer);
2835
2836
0
  return rc;
2837
0
}
2838
2839
/**
2840
 * @brief Run a shell command without an interactive shell.
2841
 *
2842
 * This is similar to 'sh -c command'.
2843
 *
2844
 * @param[in]  channel  The channel to execute the command.
2845
 *
2846
 * @param[in]  cmd      The command to execute
2847
 *                      (e.g. "ls ~/ -al | grep -i reports").
2848
 *
2849
 * @return              `SSH_OK` on success,
2850
 *                      `SSH_ERROR` if an error occurred,
2851
 *                      `SSH_AGAIN` if in nonblocking mode and call has
2852
 *                      to be done again.
2853
 *
2854
 * Example:
2855
@code
2856
   rc = ssh_channel_request_exec(channel, "ps aux");
2857
   if (rc > 0) {
2858
       return -1;
2859
   }
2860
2861
   while ((rc = ssh_channel_read(channel, buffer, sizeof(buffer), 0)) > 0) {
2862
       if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) {
2863
           return -1;
2864
       }
2865
   }
2866
@endcode
2867
 *
2868
 * @warning In a single channel, only ONE command can be executed!
2869
 * If you want to executed multiple commands, allocate separate channels for
2870
 * them or consider opening interactive shell.
2871
 * Attempting to run multiple consecutive commands in one channel will fail.
2872
 * See RFC 4254 Section 6.5.
2873
 *
2874
 * @see ssh_channel_request_shell()
2875
 */
2876
int ssh_channel_request_exec(ssh_channel channel, const char *cmd)
2877
0
{
2878
0
  ssh_buffer buffer = NULL;
2879
0
  int rc = SSH_ERROR;
2880
2881
0
  if(channel == NULL) {
2882
0
      return SSH_ERROR;
2883
0
  }
2884
0
  if(cmd == NULL) {
2885
0
      ssh_set_error_invalid(channel->session);
2886
0
      return rc;
2887
0
  }
2888
2889
0
  switch(channel->request_state){
2890
0
  case SSH_CHANNEL_REQ_STATE_NONE:
2891
0
    break;
2892
0
  default:
2893
0
    goto pending;
2894
0
  }
2895
0
  buffer = ssh_buffer_new();
2896
0
  if (buffer == NULL) {
2897
0
    ssh_set_error_oom(channel->session);
2898
0
    goto error;
2899
0
  }
2900
2901
0
  rc = ssh_buffer_pack(buffer, "s", cmd);
2902
2903
0
  if (rc != SSH_OK) {
2904
0
    ssh_set_error_oom(channel->session);
2905
0
    goto error;
2906
0
  }
2907
0
pending:
2908
0
  rc = channel_request(channel, "exec", buffer, 1);
2909
0
error:
2910
0
  SSH_BUFFER_FREE(buffer);
2911
0
  return rc;
2912
0
}
2913
2914
/**
2915
 * @brief Send a signal to remote process (as described in RFC 4254,
2916
 * section 6.9).
2917
 *
2918
 * Sends a signal 'sig' to the remote process.
2919
 * Note, that remote system may not support signals concept.
2920
 * In such a case this request will be silently ignored.
2921
 *
2922
 * @param[in]  channel  The channel to send signal.
2923
 *
2924
 * @param[in]  sig      The signal to send (without SIG prefix)
2925
 *                      \n\n
2926
 *                      SIGABRT  -> ABRT \n
2927
 *                      SIGALRM  -> ALRM \n
2928
 *                      SIGFPE   -> FPE  \n
2929
 *                      SIGHUP   -> HUP  \n
2930
 *                      SIGILL   -> ILL  \n
2931
 *                      SIGINT   -> INT  \n
2932
 *                      SIGKILL  -> KILL \n
2933
 *                      SIGPIPE  -> PIPE \n
2934
 *                      SIGQUIT  -> QUIT \n
2935
 *                      SIGSEGV  -> SEGV \n
2936
 *                      SIGTERM  -> TERM \n
2937
 *                      SIGUSR1  -> USR1 \n
2938
 *                      SIGUSR2  -> USR2 \n
2939
 *
2940
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred.
2941
 */
2942
int ssh_channel_request_send_signal(ssh_channel channel, const char *sig)
2943
0
{
2944
0
  ssh_buffer buffer = NULL;
2945
0
  int rc = SSH_ERROR;
2946
2947
0
  if (channel == NULL) {
2948
0
      return SSH_ERROR;
2949
0
  }
2950
0
  if (sig == NULL) {
2951
0
      ssh_set_error_invalid(channel->session);
2952
0
      return rc;
2953
0
  }
2954
2955
0
  buffer = ssh_buffer_new();
2956
0
  if (buffer == NULL) {
2957
0
    ssh_set_error_oom(channel->session);
2958
0
    goto error;
2959
0
  }
2960
2961
0
  rc = ssh_buffer_pack(buffer, "s", sig);
2962
0
  if (rc != SSH_OK) {
2963
0
    ssh_set_error_oom(channel->session);
2964
0
    goto error;
2965
0
  }
2966
2967
0
  rc = channel_request(channel, "signal", buffer, 0);
2968
0
error:
2969
0
  SSH_BUFFER_FREE(buffer);
2970
0
  return rc;
2971
0
}
2972
2973
/**
2974
 * @brief Send a break signal to the server (as described in RFC 4335).
2975
 *
2976
 * Sends a break signal to the remote process.
2977
 * Note, that remote system may not support breaks.
2978
 * In such a case this request will be silently ignored.
2979
 *
2980
 * @param[in]  channel  The channel to send the break to.
2981
 *
2982
 * @param[in]  length   The break-length in milliseconds to send.
2983
 *
2984
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred
2985
 */
2986
int ssh_channel_request_send_break(ssh_channel channel, uint32_t length)
2987
0
{
2988
0
    ssh_buffer buffer = NULL;
2989
0
    int rc = SSH_ERROR;
2990
2991
0
    if (channel == NULL) {
2992
0
        return SSH_ERROR;
2993
0
    }
2994
2995
0
    buffer = ssh_buffer_new();
2996
0
    if (buffer == NULL) {
2997
0
        ssh_set_error_oom(channel->session);
2998
0
        goto error;
2999
0
    }
3000
3001
0
    rc = ssh_buffer_pack(buffer, "d", length);
3002
0
    if (rc != SSH_OK) {
3003
0
        ssh_set_error_oom(channel->session);
3004
0
        goto error;
3005
0
    }
3006
3007
0
    rc = channel_request(channel, "break", buffer, 0);
3008
3009
0
error:
3010
0
    SSH_BUFFER_FREE(buffer);
3011
0
    return rc;
3012
0
}
3013
3014
/**
3015
 * @brief Read data from a channel into a buffer.
3016
 *
3017
 * @param[in]  channel  The channel to read from.
3018
 *
3019
 * @param[out]  buffer   The buffer which will get the data.
3020
 *
3021
 * @param[in]  count    The count of bytes to be read. If it is bigger than 0,
3022
 * the exact size will be read, else (bytes=0) it will return once anything is
3023
 * available.
3024
 *
3025
 * @param is_stderr     A boolean value to mark reading from the stderr stream.
3026
 *
3027
 * @return              The number of bytes read, 0 on end of file, `SSH_AGAIN`
3028
 * on timeout and `SSH_ERROR` on error.
3029
 *
3030
 * @deprecated          Please use ssh_channel_read instead
3031
 * @warning             This function doesn't work in nonblocking/timeout mode
3032
 * @see ssh_channel_read
3033
 */
3034
int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
3035
    int is_stderr)
3036
0
{
3037
0
    ssh_session session = NULL;
3038
0
    char *buffer_tmp = NULL;
3039
0
    int r;
3040
0
    uint32_t total = 0;
3041
3042
0
    if (channel == NULL) {
3043
0
        return SSH_ERROR;
3044
0
    }
3045
0
    session = channel->session;
3046
3047
0
    if (buffer == NULL) {
3048
0
        ssh_set_error_invalid(channel->session);
3049
0
        return SSH_ERROR;
3050
0
    }
3051
3052
0
    ssh_buffer_reinit(buffer);
3053
0
    if (count == 0) {
3054
0
        do {
3055
0
            r = ssh_channel_poll(channel, is_stderr);
3056
0
            if (r < 0) {
3057
0
                return r;
3058
0
            }
3059
0
            if (r > 0) {
3060
0
                count = r;
3061
0
                buffer_tmp = ssh_buffer_allocate(buffer, count);
3062
0
                if (buffer_tmp == NULL) {
3063
0
                    ssh_set_error_oom(session);
3064
0
                    return SSH_ERROR;
3065
0
                }
3066
0
                r = ssh_channel_read(channel, buffer_tmp, r, is_stderr);
3067
0
                if (r < 0) {
3068
0
                    ssh_buffer_pass_bytes_end(buffer, count);
3069
0
                    return r;
3070
0
                }
3071
                /* Rollback the unused space */
3072
0
                ssh_buffer_pass_bytes_end(buffer, count - r);
3073
3074
0
                return r;
3075
0
            }
3076
0
            if (ssh_channel_is_eof(channel)) {
3077
0
                return 0;
3078
0
            }
3079
0
            ssh_handle_packets(channel->session, SSH_TIMEOUT_INFINITE);
3080
0
        } while (r == 0);
3081
0
    }
3082
3083
0
    buffer_tmp = ssh_buffer_allocate(buffer, count);
3084
0
    if (buffer_tmp == NULL) {
3085
0
        ssh_set_error_oom(session);
3086
0
        return SSH_ERROR;
3087
0
    }
3088
0
    while (total < count) {
3089
0
        r = ssh_channel_read(channel, buffer_tmp, count - total, is_stderr);
3090
0
        if (r < 0) {
3091
0
            ssh_buffer_pass_bytes_end(buffer, count);
3092
0
            return r;
3093
0
        }
3094
0
        if (r == 0) {
3095
            /* Rollback the unused space */
3096
0
            ssh_buffer_pass_bytes_end(buffer, count - total);
3097
0
            return total;
3098
0
        }
3099
0
        total += r;
3100
0
    }
3101
3102
0
    return total;
3103
0
}
3104
3105
struct ssh_channel_read_termination_struct {
3106
  ssh_channel channel;
3107
  ssh_buffer buffer;
3108
};
3109
3110
static int ssh_channel_read_termination(void *s)
3111
0
{
3112
0
  struct ssh_channel_read_termination_struct *ctx = s;
3113
0
  if (ssh_buffer_get_len(ctx->buffer) >= 1 ||
3114
0
      ctx->channel->remote_eof ||
3115
0
      ctx->channel->session->session_state == SSH_SESSION_STATE_ERROR)
3116
0
    return 1;
3117
0
  else
3118
0
    return 0;
3119
0
}
3120
3121
/**
3122
 * @brief Reads data from a channel.
3123
 *
3124
 * @param[in]  channel  The channel to read from.
3125
 *
3126
 * @param[out] dest     The destination buffer which will get the data.
3127
 *
3128
 * @param[in]  count    The count of bytes to be read.
3129
 *
3130
 * @param[in]  is_stderr A boolean value to mark reading from the stderr flow.
3131
 *
3132
 * @return              The number of bytes read, 0 on end of file, `SSH_AGAIN`
3133
 * on timeout and `SSH_ERROR` on error.
3134
 *
3135
 * @warning This function may return less than count bytes of data, and won't
3136
 * block until count bytes have been read.
3137
 */
3138
int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr)
3139
0
{
3140
0
    return ssh_channel_read_timeout(channel,
3141
0
                                    dest,
3142
0
                                    count,
3143
0
                                    is_stderr,
3144
0
                                    SSH_TIMEOUT_DEFAULT);
3145
0
}
3146
3147
/**
3148
 * @brief Reads data from a channel.
3149
 *
3150
 * @param[in]  channel     The channel to read from.
3151
 *
3152
 * @param[out] dest        The destination buffer which will get the data.
3153
 *
3154
 * @param[in]  count       The count of bytes to be read.
3155
 *
3156
 * @param[in]  is_stderr   A boolean value to mark reading from the stderr flow.
3157
 *
3158
 * @param[in]  timeout_ms  A timeout in milliseconds. A value of -1 means
3159
 *                         infinite timeout.
3160
 *
3161
 * @return              The number of bytes read, 0 on end of file, `SSH_AGAIN`
3162
 * on timeout, `SSH_ERROR` on error.
3163
 *
3164
 * @warning This function may return less than count bytes of data, and won't
3165
 *          block until count bytes have been read.
3166
 */
3167
int ssh_channel_read_timeout(ssh_channel channel,
3168
                             void *dest,
3169
                             uint32_t count,
3170
                             int is_stderr,
3171
                             int timeout_ms)
3172
0
{
3173
0
    ssh_session session = NULL;
3174
0
    ssh_buffer stdbuf = NULL;
3175
0
    uint32_t len;
3176
0
    struct ssh_channel_read_termination_struct ctx;
3177
0
    int rc;
3178
3179
0
    if (channel == NULL) {
3180
0
        return SSH_ERROR;
3181
0
    }
3182
0
    if (dest == NULL) {
3183
0
        ssh_set_error_invalid(channel->session);
3184
0
        return SSH_ERROR;
3185
0
    }
3186
3187
0
    session = channel->session;
3188
0
    stdbuf = channel->stdout_buffer;
3189
3190
0
    if (count == 0) {
3191
0
        return 0;
3192
0
    }
3193
3194
0
    if (is_stderr) {
3195
0
        stdbuf = channel->stderr_buffer;
3196
0
    }
3197
3198
0
    SSH_LOG(SSH_LOG_PACKET,
3199
0
            "Read (%" PRIu32 ") buffered : %" PRIu32 " bytes. Window: %" PRIu32,
3200
0
            count,
3201
0
            ssh_buffer_get_len(stdbuf),
3202
0
            channel->local_window);
3203
3204
    /* block reading until at least one byte has been read
3205
     * and ignore the trivial case count=0
3206
     */
3207
0
    ctx.channel = channel;
3208
0
    ctx.buffer = stdbuf;
3209
3210
0
    if (timeout_ms < SSH_TIMEOUT_DEFAULT) {
3211
0
        timeout_ms = SSH_TIMEOUT_INFINITE;
3212
0
    }
3213
3214
0
    rc = ssh_handle_packets_termination(session,
3215
0
                                        timeout_ms,
3216
0
                                        ssh_channel_read_termination,
3217
0
                                        &ctx);
3218
0
    if (rc == SSH_ERROR || rc == SSH_AGAIN) {
3219
0
        return rc;
3220
0
    }
3221
3222
    /*
3223
     * If the channel is closed or in an error state, reading from it is an
3224
     * error
3225
     */
3226
0
    if (session->session_state == SSH_SESSION_STATE_ERROR) {
3227
0
        return SSH_ERROR;
3228
0
    }
3229
    /* If the server closed the channel properly, there is nothing to do */
3230
0
    if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
3231
0
        return 0;
3232
0
    }
3233
0
    if (channel->state == SSH_CHANNEL_STATE_CLOSED) {
3234
0
        ssh_set_error(session, SSH_FATAL, "Remote channel is closed.");
3235
0
        return SSH_ERROR;
3236
0
    }
3237
0
    len = ssh_buffer_get_len(stdbuf);
3238
    /* Read count bytes if len is greater, everything otherwise */
3239
0
    len = (len > count ? count : len);
3240
0
    memcpy(dest, ssh_buffer_get(stdbuf), len);
3241
0
    ssh_buffer_pass_bytes(stdbuf, len);
3242
0
    if (channel->counter != NULL) {
3243
0
        channel->counter->in_bytes += len;
3244
0
    }
3245
    /* Try completing the delayed_close */
3246
0
    if (channel->delayed_close && !ssh_channel_has_unread_data(channel)) {
3247
0
        channel->state = SSH_CHANNEL_STATE_CLOSED;
3248
0
    }
3249
3250
0
    rc = grow_window(session, channel);
3251
0
    if (rc == SSH_ERROR) {
3252
0
        return -1;
3253
0
    }
3254
3255
0
    return len;
3256
0
}
3257
3258
/**
3259
 * @brief Do a nonblocking read on the channel.
3260
 *
3261
 * A nonblocking read on the specified channel. it will return <= count bytes of
3262
 * data read atomically. It will also trigger any callbacks set on the channel.
3263
 *
3264
 * @param[in]  channel  The channel to read from.
3265
 *
3266
 * @param[out] dest     A pointer to a destination buffer.
3267
 *
3268
 * @param[in]  count    The count of bytes of data to be read.
3269
 *
3270
 * @param[in]  is_stderr A boolean to select the stderr stream.
3271
 *
3272
 * @return              The number of bytes read, `SSH_AGAIN` if nothing is
3273
 * available, `SSH_ERROR` on error, and `SSH_EOF` if the channel is EOF.
3274
 *
3275
 * @see ssh_channel_is_eof()
3276
 */
3277
int ssh_channel_read_nonblocking(ssh_channel channel,
3278
                                 void *dest,
3279
                                 uint32_t count,
3280
                                 int is_stderr)
3281
0
{
3282
0
    ssh_session session = NULL;
3283
0
    uint32_t to_read;
3284
0
    int rc;
3285
0
    int blocking;
3286
3287
0
    if(channel == NULL) {
3288
0
        return SSH_ERROR;
3289
0
    }
3290
0
    if(dest == NULL) {
3291
0
        ssh_set_error_invalid(channel->session);
3292
0
        return SSH_ERROR;
3293
0
    }
3294
3295
0
    session = channel->session;
3296
3297
0
    rc = ssh_channel_poll(channel, is_stderr);
3298
3299
0
    if (rc <= 0) {
3300
0
        if (session->session_state == SSH_SESSION_STATE_ERROR){
3301
0
            return SSH_ERROR;
3302
0
        }
3303
3304
0
        return rc; /* may be an error code */
3305
0
    }
3306
3307
0
    to_read = (unsigned int)rc;
3308
3309
0
    if (to_read > count) {
3310
0
        to_read = count;
3311
0
    }
3312
0
    blocking = ssh_is_blocking(session);
3313
0
    ssh_set_blocking(session, 0);
3314
0
    rc = ssh_channel_read(channel, dest, to_read, is_stderr);
3315
0
    ssh_set_blocking(session,blocking);
3316
3317
0
    return rc;
3318
0
}
3319
3320
/**
3321
 * @brief Polls a channel for data to read.
3322
 *
3323
 * If callbacks are set on the channel, they will be called.
3324
 *
3325
 * @param[in]  channel  The channel to poll.
3326
 *
3327
 * @param[in]  is_stderr A boolean to select the stderr stream.
3328
 *
3329
 * @return              The number of bytes available for reading, 0 if nothing
3330
 *                      is available or `SSH_ERROR` on error.
3331
 *                      When a channel is freed the function returns
3332
 *                      `SSH_ERROR` immediately.
3333
 *
3334
 * @warning When the channel is in EOF state, the function returns `SSH_EOF`.
3335
 *
3336
 * @see ssh_channel_is_eof()
3337
 */
3338
int ssh_channel_poll(ssh_channel channel, int is_stderr)
3339
0
{
3340
0
  ssh_buffer stdbuf = NULL;
3341
3342
0
  if ((channel == NULL) || (channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL)) {
3343
0
      return SSH_ERROR;
3344
0
  }
3345
3346
0
  stdbuf = channel->stdout_buffer;
3347
3348
0
  if (is_stderr) {
3349
0
    stdbuf = channel->stderr_buffer;
3350
0
  }
3351
3352
0
  if (channel->remote_eof == 0) {
3353
0
    if (channel->session->session_state == SSH_SESSION_STATE_ERROR){
3354
0
      return SSH_ERROR;
3355
0
    }
3356
0
    if (ssh_handle_packets(channel->session, SSH_TIMEOUT_NONBLOCKING)==SSH_ERROR) {
3357
0
      return SSH_ERROR;
3358
0
    }
3359
0
  }
3360
3361
0
  if (ssh_buffer_get_len(stdbuf) > 0){
3362
0
    return ssh_buffer_get_len(stdbuf);
3363
0
  }
3364
3365
0
  if (channel->remote_eof) {
3366
0
    return SSH_EOF;
3367
0
  }
3368
3369
0
  return ssh_buffer_get_len(stdbuf);
3370
0
}
3371
3372
/**
3373
 * @brief Polls a channel for data to read, waiting for a certain timeout.
3374
 *
3375
 * @param[in]  channel   The channel to poll.
3376
 * @param[in]  timeout   Set an upper limit on the time for which this function
3377
 *                       will block, in milliseconds. Specifying a negative
3378
 *                       value means an infinite timeout. This parameter is
3379
 *                       passed to the poll() function.
3380
 * @param[in]  is_stderr A boolean to select the stderr stream.
3381
 *
3382
 * @return              The number of bytes available for reading,
3383
 *                      0 if nothing is available (timeout elapsed),
3384
 *                      `SSH_EOF` on end of file,
3385
 *                      `SSH_ERROR` on error.
3386
 *
3387
 * @warning When the channel is in EOF state, the function returns `SSH_EOF`.
3388
 *          When a channel is freed the function returns `SSH_ERROR`
3389
 *          immediately.
3390
 *
3391
 * @see ssh_channel_is_eof()
3392
 */
3393
int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
3394
0
{
3395
0
    ssh_session session = NULL;
3396
0
    ssh_buffer stdbuf = NULL;
3397
0
    struct ssh_channel_read_termination_struct ctx;
3398
0
    size_t len;
3399
0
    int rc;
3400
3401
0
    if ((channel == NULL) || (channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL)) {
3402
0
        return SSH_ERROR;
3403
0
    }
3404
3405
0
    session = channel->session;
3406
0
    stdbuf = channel->stdout_buffer;
3407
3408
0
    if (is_stderr) {
3409
0
        stdbuf = channel->stderr_buffer;
3410
0
    }
3411
0
    ctx.buffer = stdbuf;
3412
0
    ctx.channel = channel;
3413
0
    rc = ssh_handle_packets_termination(channel->session,
3414
0
                                        timeout,
3415
0
                                        ssh_channel_read_termination,
3416
0
                                        &ctx);
3417
0
    if (rc == SSH_ERROR ||
3418
0
        session->session_state == SSH_SESSION_STATE_ERROR) {
3419
0
        rc = SSH_ERROR;
3420
0
        goto out;
3421
0
    } else if (rc == SSH_AGAIN) {
3422
        /* If the above timeout expired, it is ok and we do not need to
3423
         * attempt to check the read buffer. The calling functions do not
3424
         * expect us to return SSH_AGAIN either here. */
3425
0
        rc = SSH_OK;
3426
0
        goto out;
3427
0
    }
3428
0
    len = ssh_buffer_get_len(stdbuf);
3429
0
    if (len > 0) {
3430
0
        if (len > INT_MAX) {
3431
0
            rc = SSH_ERROR;
3432
0
        } else {
3433
0
            rc = (int)len;
3434
0
        }
3435
0
        goto out;
3436
0
    }
3437
0
    if (channel->remote_eof) {
3438
0
        rc = SSH_EOF;
3439
0
    }
3440
3441
0
out:
3442
0
    return rc;
3443
0
}
3444
3445
/**
3446
 * @brief Recover the session in which belongs a channel.
3447
 *
3448
 * @param[in]  channel  The channel to recover the session from.
3449
 *
3450
 * @return              The session pointer.
3451
 */
3452
ssh_session ssh_channel_get_session(ssh_channel channel)
3453
0
{
3454
0
  if (channel == NULL) {
3455
0
      return NULL;
3456
0
  }
3457
3458
0
  return channel->session;
3459
0
}
3460
3461
static int ssh_channel_exit_status_termination(void *c)
3462
0
{
3463
0
    ssh_channel channel = c;
3464
0
    if (channel->exit.status ||
3465
        /* When a channel is closed, no exit status message can
3466
         * come anymore */
3467
0
        (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) ||
3468
0
        channel->session->session_state == SSH_SESSION_STATE_ERROR)
3469
0
    {
3470
0
        return 1;
3471
0
    }
3472
0
    return 0;
3473
0
}
3474
3475
/**
3476
 * @brief Get the exit state of the channel (error code from the executed
3477
 *        instruction or signal).
3478
 *
3479
 * @param[in]  channel  The channel to get the status from.
3480
 *
3481
 * @param[out] pexit_code   A pointer to an uint32_t to store the exit status.
3482
 *
3483
 * @param[out] pexit_signal A pointer to store the exit signal as a string.
3484
 *                         The signal is without the SIG prefix, e.g. "TERM" or
3485
 *                         "KILL"). The caller has to free the memory.
3486
 *
3487
 * @param[out] pcore_dumped A pointer to store a boolean value if it dumped a
3488
 *                          core.
3489
 *
3490
 * @return              `SSH_OK` on success, `SSH_AGAIN` if we don't have a
3491
 *                      status or an SSH error.
3492
 * @warning             This function may block until a timeout (or never)
3493
 *                      if the other side is not willing to close the channel.
3494
 *                      When a channel is freed the function returns
3495
 *                      `SSH_ERROR` immediately.
3496
 *
3497
 * If you're looking for an async handling of this register a callback for the
3498
 * exit status!
3499
 *
3500
 * @see ssh_channel_exit_status_callback
3501
 * @see ssh_channel_exit_signal_callback
3502
 */
3503
int ssh_channel_get_exit_state(ssh_channel channel,
3504
                               uint32_t *pexit_code,
3505
                               char **pexit_signal,
3506
                               int *pcore_dumped)
3507
0
{
3508
0
    ssh_session session = NULL;
3509
0
    int rc;
3510
3511
0
    if ((channel == NULL) || (channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL)) {
3512
0
        return SSH_ERROR;
3513
0
    }
3514
0
    session = channel->session;
3515
3516
0
    rc = ssh_handle_packets_termination(channel->session,
3517
0
                                        SSH_TIMEOUT_DEFAULT,
3518
0
                                        ssh_channel_exit_status_termination,
3519
0
                                        channel);
3520
0
    if (rc == SSH_ERROR || channel->session->session_state ==
3521
0
        SSH_SESSION_STATE_ERROR) {
3522
0
        return SSH_ERROR;
3523
0
    }
3524
3525
    /* If we don't have any kind of exit state, return SSH_AGAIN */
3526
0
    if (!channel->exit.status) {
3527
0
        return SSH_AGAIN;
3528
0
    }
3529
3530
0
    if (pexit_code != NULL) {
3531
0
        *pexit_code = channel->exit.code;
3532
0
    }
3533
3534
0
    if (pexit_signal != NULL) {
3535
0
        *pexit_signal = NULL;
3536
0
        if (channel->exit.signal != NULL) {
3537
0
            *pexit_signal = strdup(channel->exit.signal);
3538
0
            if (*pexit_signal == NULL) {
3539
0
                ssh_set_error_oom(session);
3540
0
                return SSH_ERROR;
3541
0
            }
3542
0
        }
3543
0
    }
3544
3545
0
    if (pcore_dumped != NULL) {
3546
0
        *pcore_dumped = channel->exit.core_dumped;
3547
0
    }
3548
3549
0
    return SSH_OK;
3550
0
}
3551
3552
/**
3553
 * @brief Get the exit status of the channel (error code from the executed
3554
 *        instruction).
3555
 *
3556
 * @param[in]  channel  The channel to get the status from.
3557
 *
3558
 * @return              The exit status, -1 if no exit status has been returned
3559
 *                      (yet), or `SSH_ERROR` on error.
3560
 * @warning             This function may block until a timeout (or never)
3561
 *                      if the other side is not willing to close the channel.
3562
 *                      When a channel is freed the function returns
3563
 *                      `SSH_ERROR` immediately.
3564
 *
3565
 * If you're looking for an async handling of this register a callback for the
3566
 * exit status.
3567
 *
3568
 * @see ssh_channel_exit_status_callback
3569
 * @deprecated Please use ssh_channel_exit_state()
3570
 */
3571
int ssh_channel_get_exit_status(ssh_channel channel)
3572
0
{
3573
0
    uint32_t exit_status = (uint32_t)-1;
3574
0
    int rc;
3575
3576
0
    rc = ssh_channel_get_exit_state(channel, &exit_status, NULL, NULL);
3577
0
    if (rc != SSH_OK) {
3578
0
        return SSH_ERROR;
3579
0
    }
3580
3581
0
    return exit_status;
3582
0
}
3583
3584
/*
3585
 * This function acts as a meta select.
3586
 *
3587
 * First, channels are analyzed to seek potential can-write or can-read ones,
3588
 * then if no channel has been elected, it goes in a loop with the posix
3589
 * select(2).
3590
 * This is made in two parts: protocol select and network select. The protocol
3591
 * select does not use the network functions at all
3592
 */
3593
static int
3594
channel_protocol_select(ssh_channel *rchans, ssh_channel *wchans,
3595
                        ssh_channel *echans, ssh_channel *rout,
3596
                        ssh_channel *wout, ssh_channel *eout)
3597
0
{
3598
0
    ssh_channel chan = NULL;
3599
0
    int i;
3600
0
    int j = 0;
3601
3602
0
    for (i = 0; rchans[i] != NULL; i++) {
3603
0
        chan = rchans[i];
3604
3605
0
        while (ssh_channel_is_open(chan) &&
3606
0
               ssh_socket_data_available(chan->session->socket)) {
3607
0
            ssh_handle_packets(chan->session, SSH_TIMEOUT_NONBLOCKING);
3608
0
        }
3609
3610
0
        if ((chan->stdout_buffer &&
3611
0
             ssh_buffer_get_len(chan->stdout_buffer) > 0) ||
3612
0
            (chan->stderr_buffer &&
3613
0
             ssh_buffer_get_len(chan->stderr_buffer) > 0) ||
3614
0
            chan->remote_eof) {
3615
0
            rout[j] = chan;
3616
0
            j++;
3617
0
        }
3618
0
    }
3619
0
    rout[j] = NULL;
3620
3621
0
    j = 0;
3622
0
    for (i = 0; wchans[i] != NULL; i++) {
3623
0
        chan = wchans[i];
3624
        /* It's not our business to seek if the file descriptor is writable */
3625
0
        if (ssh_socket_data_writable(chan->session->socket) &&
3626
0
            ssh_channel_is_open(chan) && (chan->remote_window > 0)) {
3627
0
            wout[j] = chan;
3628
0
            j++;
3629
0
        }
3630
0
    }
3631
0
    wout[j] = NULL;
3632
3633
0
    j = 0;
3634
0
    for (i = 0; echans[i] != NULL; i++) {
3635
0
        chan = echans[i];
3636
3637
0
        if (!ssh_socket_is_open(chan->session->socket) ||
3638
0
            ssh_channel_is_closed(chan)) {
3639
0
            eout[j] = chan;
3640
0
            j++;
3641
0
        }
3642
0
    }
3643
0
    eout[j] = NULL;
3644
3645
0
    return 0;
3646
0
}
3647
3648
/* Just count number of pointers in the array */
3649
static size_t count_ptrs(ssh_channel *ptrs)
3650
0
{
3651
0
  size_t c;
3652
0
  for (c = 0; ptrs[c] != NULL; c++)
3653
0
    ;
3654
3655
0
  return c;
3656
0
}
3657
3658
/**
3659
 * @brief Act like the standard select(2) on channels.
3660
 *
3661
 * The list of pointers are then actualized and will only contain pointers to
3662
 * channels that are respectively readable, writable or have an exception to
3663
 * trap.
3664
 *
3665
 * @param[in]  readchans A NULL pointer or an array of channel pointers,
3666
 *                       terminated by a NULL.
3667
 *
3668
 * @param[in]  writechans A NULL pointer or an array of channel pointers,
3669
 *                        terminated by a NULL.
3670
 *
3671
 * @param[in]  exceptchans A NULL pointer or an array of channel pointers,
3672
 *                         terminated by a NULL.
3673
 *
3674
 * @param[in]  timeout  Timeout as defined by select(2).
3675
 *
3676
 * @return             `SSH_OK` on a successful operation, `SSH_EINTR` if the
3677
 *                     select(2) syscall was interrupted, then relaunch the
3678
 *                     function, or `SSH_ERROR` on error.
3679
 */
3680
int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans,
3681
                       ssh_channel *exceptchans, struct timeval * timeout)
3682
0
{
3683
0
    ssh_channel *rchans = NULL, *wchans = NULL, *echans = NULL;
3684
0
    ssh_channel dummy = NULL;
3685
0
    ssh_event event = NULL;
3686
0
    int rc;
3687
0
    int i;
3688
0
    int tm, tm_base;
3689
0
    int firstround = 1;
3690
0
    struct ssh_timestamp ts;
3691
3692
0
    if (timeout != NULL)
3693
0
        tm_base = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
3694
0
    else
3695
0
        tm_base = SSH_TIMEOUT_INFINITE;
3696
0
    ssh_timestamp_init(&ts);
3697
0
    tm = tm_base;
3698
    /* don't allow NULL pointers */
3699
0
    if (readchans == NULL) {
3700
0
        readchans = &dummy;
3701
0
    }
3702
3703
0
    if (writechans == NULL) {
3704
0
        writechans = &dummy;
3705
0
    }
3706
3707
0
    if (exceptchans == NULL) {
3708
0
        exceptchans = &dummy;
3709
0
    }
3710
3711
0
    if (readchans[0] == NULL && writechans[0] == NULL &&
3712
0
        exceptchans[0] == NULL) {
3713
        /* No channel to poll?? Go away! */
3714
0
        return 0;
3715
0
    }
3716
3717
    /* Prepare the outgoing temporary arrays */
3718
0
    rchans = calloc(count_ptrs(readchans) + 1, sizeof(ssh_channel));
3719
0
    if (rchans == NULL) {
3720
0
        return SSH_ERROR;
3721
0
    }
3722
3723
0
    wchans = calloc(count_ptrs(writechans) + 1, sizeof(ssh_channel));
3724
0
    if (wchans == NULL) {
3725
0
        SAFE_FREE(rchans);
3726
0
        return SSH_ERROR;
3727
0
    }
3728
3729
0
    echans = calloc(count_ptrs(exceptchans) + 1, sizeof(ssh_channel));
3730
0
    if (echans == NULL) {
3731
0
        SAFE_FREE(rchans);
3732
0
        SAFE_FREE(wchans);
3733
0
        return SSH_ERROR;
3734
0
    }
3735
3736
    /*
3737
     * First, try without doing network stuff then, use the ssh_poll
3738
     * infrastructure to poll on all sessions.
3739
     */
3740
0
    do {
3741
0
        channel_protocol_select(readchans,
3742
0
                                writechans,
3743
0
                                exceptchans,
3744
0
                                rchans,
3745
0
                                wchans,
3746
0
                                echans);
3747
0
        if (rchans[0] != NULL || wchans[0] != NULL || echans[0] != NULL) {
3748
            /* At least one channel has an event */
3749
0
            break;
3750
0
        }
3751
        /* Add all channels' sessions right into an event object */
3752
0
        if (event == NULL) {
3753
0
            event = ssh_event_new();
3754
0
            if (event == NULL) {
3755
0
                SAFE_FREE(rchans);
3756
0
                SAFE_FREE(wchans);
3757
0
                SAFE_FREE(echans);
3758
3759
0
                return SSH_ERROR;
3760
0
            }
3761
0
            for (i = 0; readchans[i] != NULL; i++) {
3762
0
                ssh_poll_get_default_ctx(readchans[i]->session);
3763
0
                ssh_event_add_session(event, readchans[i]->session);
3764
0
            }
3765
0
            for (i = 0; writechans[i] != NULL; i++) {
3766
0
                ssh_poll_get_default_ctx(writechans[i]->session);
3767
0
                ssh_event_add_session(event, writechans[i]->session);
3768
0
            }
3769
0
            for (i = 0; exceptchans[i] != NULL; i++) {
3770
0
                ssh_poll_get_default_ctx(exceptchans[i]->session);
3771
0
                ssh_event_add_session(event, exceptchans[i]->session);
3772
0
            }
3773
0
        }
3774
        /* Get out if the timeout has elapsed */
3775
0
        if (!firstround && ssh_timeout_elapsed(&ts, tm_base)) {
3776
0
            break;
3777
0
        }
3778
        /* Here we go */
3779
0
        rc = ssh_event_dopoll(event, tm);
3780
0
        if (rc != SSH_OK) {
3781
0
            SAFE_FREE(rchans);
3782
0
            SAFE_FREE(wchans);
3783
0
            SAFE_FREE(echans);
3784
0
            ssh_event_free(event);
3785
0
            return rc;
3786
0
        }
3787
0
        tm = ssh_timeout_update(&ts, tm_base);
3788
0
        firstround = 0;
3789
0
    } while (1);
3790
3791
0
    if (readchans != &dummy) {
3792
0
        memcpy(readchans,
3793
0
               rchans,
3794
0
               (count_ptrs(rchans) + 1) * sizeof(ssh_channel));
3795
0
    }
3796
0
    if (writechans != &dummy) {
3797
0
        memcpy(writechans,
3798
0
               wchans,
3799
0
               (count_ptrs(wchans) + 1) * sizeof(ssh_channel));
3800
0
    }
3801
0
    if (exceptchans != &dummy) {
3802
0
        memcpy(exceptchans,
3803
0
               echans,
3804
0
               (count_ptrs(echans) + 1) * sizeof(ssh_channel));
3805
0
    }
3806
0
    SAFE_FREE(rchans);
3807
0
    SAFE_FREE(wchans);
3808
0
    SAFE_FREE(echans);
3809
0
    if (event)
3810
0
        ssh_event_free(event);
3811
0
    return 0;
3812
0
}
3813
3814
/**
3815
 * @brief Set the channel data counter.
3816
 *
3817
 * @code
3818
 * struct ssh_counter_struct counter = {
3819
 *     .in_bytes = 0,
3820
 *     .out_bytes = 0,
3821
 *     .in_packets = 0,
3822
 *     .out_packets = 0
3823
 * };
3824
 *
3825
 * ssh_channel_set_counter(channel, &counter);
3826
 * @endcode
3827
 *
3828
 * @param[in] channel The SSH channel.
3829
 *
3830
 * @param[in] counter Counter for bytes handled by the channel.
3831
 */
3832
void ssh_channel_set_counter(ssh_channel channel,
3833
                             ssh_counter counter)
3834
0
{
3835
0
    if (channel != NULL) {
3836
0
        channel->counter = counter;
3837
0
    }
3838
0
}
3839
3840
/**
3841
 * @brief Blocking write on a channel stderr.
3842
 *
3843
 * @param[in]  channel  The channel to write to.
3844
 *
3845
 * @param[in]  data     A pointer to the data to write.
3846
 *
3847
 * @param[in]  len      The length of the buffer to write to.
3848
 *
3849
 * @return              The number of bytes written, SSH_ERROR on error.
3850
 *
3851
 * @see ssh_channel_read()
3852
 */
3853
int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len)
3854
0
{
3855
0
    return channel_write_common(channel, data, len, 1);
3856
0
}
3857
3858
#if WITH_SERVER
3859
3860
/**
3861
 * @brief Open a TCP/IP reverse forwarding channel.
3862
 *
3863
 * @param[in]  channel  An allocated channel.
3864
 *
3865
 * @param[in]  remotehost The remote host to connected (host name or IP).
3866
 *
3867
 * @param[in]  remoteport The remote port.
3868
 *
3869
 * @param[in]  sourcehost The source host (your local computer). It's optional
3870
 *                        and for logging purpose.
3871
 *
3872
 * @param[in]  localport  The source port (your local computer). It's optional
3873
 *                        and for logging purpose.
3874
 *
3875
 * @return              `SSH_OK` on success,
3876
 *                      `SSH_ERROR` if an error occurred,
3877
 *                      `SSH_AGAIN` if in nonblocking mode and call has
3878
 *                      to be done again.
3879
 *
3880
 * @warning This function does not bind the local port and does not
3881
 *          automatically forward the content of a socket to the channel. You
3882
 *          still have to use ssh_channel_read and ssh_channel_write for this.
3883
 */
3884
int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost,
3885
                                     int remoteport, const char *sourcehost, int localport)
3886
0
{
3887
0
    ssh_session session = NULL;
3888
0
    ssh_buffer payload = NULL;
3889
0
    int rc = SSH_ERROR;
3890
3891
0
    if (channel == NULL) {
3892
0
        return rc;
3893
0
    }
3894
0
    if (remotehost == NULL || sourcehost == NULL) {
3895
0
        ssh_set_error_invalid(channel->session);
3896
0
        return rc;
3897
0
    }
3898
3899
0
    session = channel->session;
3900
3901
0
    if (channel->state != SSH_CHANNEL_STATE_NOT_OPEN)
3902
0
        goto pending;
3903
0
    payload = ssh_buffer_new();
3904
0
    if (payload == NULL) {
3905
0
        ssh_set_error_oom(session);
3906
0
        goto error;
3907
0
    }
3908
0
    rc = ssh_buffer_pack(payload,
3909
0
                         "sdsd",
3910
0
                         remotehost,
3911
0
                         remoteport,
3912
0
                         sourcehost,
3913
0
                         localport);
3914
0
    if (rc != SSH_OK) {
3915
0
        ssh_set_error_oom(session);
3916
0
        goto error;
3917
0
    }
3918
0
pending:
3919
0
    rc = channel_open(channel,
3920
0
                      "forwarded-tcpip",
3921
0
                      WINDOW_DEFAULT,
3922
0
                      CHANNEL_MAX_PACKET,
3923
0
                      payload);
3924
3925
0
error:
3926
0
    SSH_BUFFER_FREE(payload);
3927
3928
0
    return rc;
3929
0
}
3930
3931
/**
3932
 * @brief Open a X11 channel.
3933
 *
3934
 * @param[in]  channel      An allocated channel.
3935
 *
3936
 * @param[in]  orig_addr    The source host (the local server).
3937
 *
3938
 * @param[in]  orig_port    The source port (the local server).
3939
 *
3940
 * @return              `SSH_OK` on success,
3941
 *                      `SSH_ERROR` if an error occurred,
3942
 *                      `SSH_AGAIN` if in nonblocking mode and call has
3943
 *                      to be done again.
3944
 * @warning This function does not bind the local port and does not
3945
 *          automatically forward the content of a socket to the channel. You
3946
 *          still have to use shh_channel_read and ssh_channel_write for this.
3947
 */
3948
int ssh_channel_open_x11(ssh_channel channel,
3949
                         const char *orig_addr, int orig_port)
3950
0
{
3951
0
    ssh_session session = NULL;
3952
0
    ssh_buffer payload = NULL;
3953
0
    int rc = SSH_ERROR;
3954
3955
0
    if (channel == NULL) {
3956
0
        return rc;
3957
0
    }
3958
0
    if (orig_addr == NULL) {
3959
0
        ssh_set_error_invalid(channel->session);
3960
0
        return rc;
3961
0
    }
3962
0
    session = channel->session;
3963
3964
0
    if (channel->state != SSH_CHANNEL_STATE_NOT_OPEN)
3965
0
        goto pending;
3966
3967
0
    payload = ssh_buffer_new();
3968
0
    if (payload == NULL) {
3969
0
        ssh_set_error_oom(session);
3970
0
        goto error;
3971
0
    }
3972
3973
0
    rc = ssh_buffer_pack(payload, "sd", orig_addr, orig_port);
3974
0
    if (rc != SSH_OK) {
3975
0
        ssh_set_error_oom(session);
3976
0
        goto error;
3977
0
    }
3978
0
pending:
3979
0
    rc = channel_open(channel,
3980
0
                      "x11",
3981
0
                      WINDOW_DEFAULT,
3982
0
                      CHANNEL_MAX_PACKET,
3983
0
                      payload);
3984
3985
0
error:
3986
0
    SSH_BUFFER_FREE(payload);
3987
3988
0
    return rc;
3989
0
}
3990
3991
/**
3992
 * @brief Send the exit status to the remote process
3993
 *
3994
 * Sends the exit status to the remote process (as described in RFC 4254,
3995
 * section 6.10).
3996
 *
3997
 * @param[in]  channel  The channel to send exit status.
3998
 *
3999
 * @param[in]  exit_status  The exit status to send
4000
 *
4001
 * @return     `SSH_OK` on success, `SSH_ERROR` if an error occurred.
4002
 */
4003
int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status)
4004
0
{
4005
0
  ssh_buffer buffer = NULL;
4006
0
  int rc = SSH_ERROR;
4007
4008
0
  if(channel == NULL) {
4009
0
      return SSH_ERROR;
4010
0
  }
4011
4012
0
  buffer = ssh_buffer_new();
4013
0
  if (buffer == NULL) {
4014
0
    ssh_set_error_oom(channel->session);
4015
0
    goto error;
4016
0
  }
4017
4018
0
  rc = ssh_buffer_pack(buffer, "d", exit_status);
4019
0
  if (rc != SSH_OK) {
4020
0
    ssh_set_error_oom(channel->session);
4021
0
    goto error;
4022
0
  }
4023
4024
0
  rc = channel_request(channel, "exit-status", buffer, 0);
4025
0
error:
4026
0
  SSH_BUFFER_FREE(buffer);
4027
0
  return rc;
4028
0
}
4029
4030
/**
4031
 * @brief Send an exit signal to remote process (RFC 4254, section 6.10).
4032
 *
4033
 * This sends the exit status of the remote process.
4034
 * Note, that remote system may not support signals concept.
4035
 * In such a case this request will be silently ignored.
4036
 *
4037
 * @param[in]  channel  The channel to send signal.
4038
 *
4039
 * @param[in]  sig      The signal to send (without SIG prefix)
4040
 *                      (e.g. "TERM" or "KILL").
4041
 * @param[in]  core     A boolean to tell if a core was dumped
4042
 * @param[in]  errmsg   A CRLF explanation text about the error condition
4043
 * @param[in]  lang     The language used in the message (format: RFC 3066)
4044
 *
4045
 * @return              `SSH_OK` on success, `SSH_ERROR` if an error occurred
4046
 */
4047
int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig,
4048
                                         int core, const char *errmsg, const char *lang)
4049
0
{
4050
0
  ssh_buffer buffer = NULL;
4051
0
  int rc = SSH_ERROR;
4052
4053
0
  if(channel == NULL) {
4054
0
      return rc;
4055
0
  }
4056
0
  if(sig == NULL || errmsg == NULL || lang == NULL) {
4057
0
      ssh_set_error_invalid(channel->session);
4058
0
      return rc;
4059
0
  }
4060
4061
0
  buffer = ssh_buffer_new();
4062
0
  if (buffer == NULL) {
4063
0
    ssh_set_error_oom(channel->session);
4064
0
    goto error;
4065
0
  }
4066
4067
0
  rc = ssh_buffer_pack(buffer,
4068
0
                       "sbss",
4069
0
                       sig,
4070
0
                       core ? 1 : 0,
4071
0
                       errmsg,
4072
0
                       lang);
4073
0
  if (rc != SSH_OK) {
4074
0
    ssh_set_error_oom(channel->session);
4075
0
    goto error;
4076
0
  }
4077
4078
0
  rc = channel_request(channel, "exit-signal", buffer, 0);
4079
0
error:
4080
  SSH_BUFFER_FREE(buffer);
4081
0
  return rc;
4082
0
}
4083
4084
#endif
4085
4086
/** @} */