Coverage Report

Created: 2023-09-25 06:08

/src/dropbear/src/common-channel.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Dropbear SSH
3
 * 
4
 * Copyright (c) 2002-2004 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
/* Handle the multiplexed channels, such as sessions, x11, agent connections */
26
27
#include "includes.h"
28
#include "session.h"
29
#include "packet.h"
30
#include "ssh.h"
31
#include "buffer.h"
32
#include "circbuffer.h"
33
#include "dbutil.h"
34
#include "channel.h"
35
#include "listener.h"
36
#include "runopts.h"
37
#include "netio.h"
38
39
static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
40
    const char *text, const char *lang);
41
static void send_msg_channel_open_confirmation(const struct Channel* channel,
42
    unsigned int recvwindow, 
43
    unsigned int recvmaxpacket);
44
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
45
  const unsigned char *moredata, unsigned int *morelen);
46
static void send_msg_channel_window_adjust(const struct Channel *channel,
47
    unsigned int incr);
48
static void send_msg_channel_data(struct Channel *channel, int isextended);
49
static void send_msg_channel_eof(struct Channel *channel);
50
static void send_msg_channel_close(struct Channel *channel);
51
static void remove_channel(struct Channel *channel);
52
static unsigned int write_pending(const struct Channel * channel);
53
static void check_close(struct Channel *channel);
54
static void close_chan_fd(struct Channel *channel, int fd, int how);
55
56
788
#define FD_UNINIT (-2)
57
394
#define FD_CLOSED (-1)
58
59
0
#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60
0
#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
61
62
/* allow space for:
63
 * 1 byte  byte      SSH_MSG_CHANNEL_DATA
64
 * 4 bytes uint32    recipient channel
65
 * 4 bytes string    data
66
 */
67
394
#define RECV_MAX_CHANNEL_DATA_LEN (RECV_MAX_PAYLOAD_LEN-(1+4+4))
68
69
/* Initialise all the channels */
70
2.93k
void chaninitialise(const struct ChanType *chantypes[]) {
71
72
  /* may as well create space for a single channel */
73
2.93k
  ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
74
2.93k
  ses.chansize = 1;
75
2.93k
  ses.channels[0] = NULL;
76
2.93k
  ses.chancount = 0;
77
78
2.93k
  ses.chantypes = chantypes;
79
80
2.93k
#if DROPBEAR_LISTENERS
81
2.93k
  listeners_initialise();
82
2.93k
#endif
83
84
2.93k
}
85
86
/* Clean up channels, freeing allocated memory */
87
2.93k
void chancleanup() {
88
89
2.93k
  unsigned int i;
90
91
2.93k
  TRACE(("enter chancleanup"))
92
5.86k
  for (i = 0; i < ses.chansize; i++) {
93
2.93k
    if (ses.channels[i] != NULL) {
94
2
      TRACE(("channel %d closing", i))
95
2
      remove_channel(ses.channels[i]);
96
2
    }
97
2.93k
  }
98
2.93k
  m_free(ses.channels);
99
2.93k
  TRACE(("leave chancleanup"))
100
2.93k
}
101
102
/* Create a new channel entry, send a reply confirm or failure */
103
/* If remotechan, transwindow and transmaxpacket are not know (for a new
104
 * outgoing connection, with them to be filled on confirmation), they should
105
 * all be set to 0 */
106
static struct Channel* newchannel(unsigned int remotechan, 
107
    const struct ChanType *type, 
108
394
    unsigned int transwindow, unsigned int transmaxpacket) {
109
110
394
  struct Channel * newchan;
111
394
  unsigned int i, j;
112
113
394
  TRACE(("enter newchannel"))
114
  
115
  /* first see if we can use existing channels */
116
394
  for (i = 0; i < ses.chansize; i++) {
117
394
    if (ses.channels[i] == NULL) {
118
394
      break;
119
394
    }
120
394
  }
121
122
  /* otherwise extend the list */
123
394
  if (i == ses.chansize) {
124
0
    if (ses.chansize >= MAX_CHANNELS) {
125
0
      TRACE(("leave newchannel: max chans reached"))
126
0
      return NULL;
127
0
    }
128
129
    /* extend the channels */
130
0
    ses.channels = (struct Channel**)m_realloc(ses.channels,
131
0
        (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
132
133
0
    ses.chansize += CHAN_EXTEND_SIZE;
134
135
    /* set the new channels to null */
136
0
    for (j = i; j < ses.chansize; j++) {
137
0
      ses.channels[j] = NULL;
138
0
    }
139
140
0
  }
141
  
142
394
  newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
143
394
  newchan->type = type;
144
394
  newchan->index = i;
145
394
  newchan->sent_close = newchan->recv_close = 0;
146
394
  newchan->sent_eof = newchan->recv_eof = 0;
147
148
394
  newchan->remotechan = remotechan;
149
394
  newchan->transwindow = transwindow;
150
394
  newchan->transmaxpacket = transmaxpacket;
151
  
152
394
  newchan->typedata = NULL;
153
394
  newchan->writefd = FD_UNINIT;
154
394
  newchan->readfd = FD_UNINIT;
155
394
  newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
156
394
  newchan->await_open = 0;
157
158
394
  newchan->writebuf = cbuf_new(opts.recv_window);
159
394
  newchan->recvwindow = opts.recv_window;
160
161
394
  newchan->extrabuf = NULL; /* The user code can set it up */
162
394
  newchan->recvdonelen = 0;
163
394
  newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
164
165
394
  newchan->prio = DROPBEAR_PRIO_NORMAL;
166
167
394
  ses.channels[i] = newchan;
168
394
  ses.chancount++;
169
170
394
  TRACE(("leave newchannel"))
171
172
394
  return newchan;
173
394
}
174
175
/* Returns the channel structure corresponding to the channel in the current
176
 * data packet (ses.payload must be positioned appropriately).
177
 * A valid channel is always returns, it will fail fatally with an unknown
178
 * channel */
179
427
static struct Channel* getchannel_msg(const char* kind) {
180
181
427
  unsigned int chan;
182
183
427
  chan = buf_getint(ses.payload);
184
427
  if (chan >= ses.chansize || ses.channels[chan] == NULL) {
185
419
    if (kind) {
186
105
      dropbear_exit("%s for unknown channel %d", kind, chan);
187
314
    } else {
188
314
      dropbear_exit("Unknown channel %d", chan);
189
314
    }
190
419
  }
191
8
  return ses.channels[chan];
192
427
}
193
194
320
struct Channel* getchannel() {
195
320
  return getchannel_msg(NULL);
196
320
}
197
198
/* Iterate through the channels, performing IO if available */
199
142k
void channelio(const fd_set *readfds, const fd_set *writefds) {
200
201
  /* Listeners such as TCP, X11, agent-auth */
202
142k
  struct Channel *channel;
203
142k
  unsigned int i;
204
205
  /* foreach channel */
206
285k
  for (i = 0; i < ses.chansize; i++) {
207
    /* Close checking only needs to occur for channels that had IO events */
208
142k
    int do_check_close = 0;
209
210
142k
    channel = ses.channels[i];
211
142k
    if (channel == NULL) {
212
      /* only process in-use channels */
213
142k
      continue;
214
142k
    }
215
216
    /* read data and send it over the wire */
217
0
    if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
218
0
      TRACE(("send normal readfd"))
219
0
      send_msg_channel_data(channel, 0);
220
0
      do_check_close = 1;
221
0
    }
222
223
    /* read stderr data and send it over the wire */
224
0
    if (ERRFD_IS_READ(channel) && channel->errfd >= 0 
225
0
      && FD_ISSET(channel->errfd, readfds)) {
226
0
        TRACE(("send normal errfd"))
227
0
        send_msg_channel_data(channel, 1);
228
0
      do_check_close = 1;
229
0
    }
230
231
    /* write to program/pipe stdin */
232
0
    if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
233
0
      writechannel(channel, channel->writefd, channel->writebuf, NULL, NULL);
234
0
      do_check_close = 1;
235
0
    }
236
    
237
    /* stderr for client mode */
238
0
    if (ERRFD_IS_WRITE(channel)
239
0
        && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
240
0
      writechannel(channel, channel->errfd, channel->extrabuf, NULL, NULL);
241
0
      do_check_close = 1;
242
0
    }
243
244
0
    if (ses.channel_signal_pending) {
245
      /* SIGCHLD can change channel state for server sessions */
246
0
      do_check_close = 1;
247
0
    }
248
  
249
    /* handle any channel closing etc */
250
0
    if (do_check_close) {
251
0
      check_close(channel);
252
0
    }
253
0
  }
254
255
142k
#if DROPBEAR_LISTENERS
256
142k
  handle_listeners(readfds);
257
142k
#endif
258
142k
}
259
260
261
/* Returns true if there is data remaining to be written to stdin or
262
 * stderr of a channel's endpoint. */
263
0
static unsigned int write_pending(const struct Channel * channel) {
264
265
0
  if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
266
0
    return 1;
267
0
  } else if (channel->errfd >= 0 && channel->extrabuf && 
268
0
      cbuf_getused(channel->extrabuf) > 0) {
269
0
    return 1;
270
0
  }
271
0
  return 0;
272
0
}
273
274
275
/* EOF/close handling */
276
0
static void check_close(struct Channel *channel) {
277
0
  int close_allowed = 0;
278
279
0
  TRACE2(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
280
0
        channel->writefd, channel->readfd,
281
0
        channel->errfd, channel->sent_close, channel->recv_close))
282
0
  TRACE2(("writebuf size %d extrabuf size %d",
283
0
        channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
284
0
        channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
285
286
  /* if a type-specific check_close is defined we will only exit
287
     once that has been triggered. this is only used for a server "session"
288
     channel, to ensure that the shell has exited (and the exit status
289
     retrieved) before we close things up. */
290
0
  if (!channel->type->check_close
291
0
    || channel->sent_close
292
0
    || channel->type->check_close(channel)) {
293
0
    close_allowed = 1;
294
0
  }
295
296
  /* In flushing mode we close FDs as soon as pipes are empty.
297
  This is used to drain out FDs when the process exits, in the case
298
  where the FD doesn't have EOF - "sleep 10&echo hello" case */
299
0
  if (channel->flushing) {
300
0
    if (channel->readfd >= 0 && !fd_read_pending(channel->readfd)) {
301
0
      close_chan_fd(channel, channel->readfd, SHUT_RD);
302
0
    }
303
0
    if (ERRFD_IS_READ(channel)
304
0
      && channel->errfd >= 0 && !fd_read_pending(channel->errfd)) {
305
0
      close_chan_fd(channel, channel->errfd, SHUT_RD);
306
0
    }
307
0
  }
308
309
0
  if (channel->recv_close && !write_pending(channel) && close_allowed) {
310
0
    if (!channel->sent_close) {
311
0
      TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
312
0
      send_msg_channel_close(channel);
313
0
    }
314
0
    remove_channel(channel);
315
0
    return;
316
0
  }
317
318
0
  if ((channel->recv_eof && !write_pending(channel))
319
    /* have a server "session" and child has exited */
320
0
    || (channel->type->check_close && close_allowed)) {
321
0
    close_chan_fd(channel, channel->writefd, SHUT_WR);
322
0
  }
323
324
  /* If we're not going to send any more data, send EOF */
325
0
  if (!channel->sent_eof
326
0
      && channel->readfd == FD_CLOSED 
327
0
      && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
328
0
    send_msg_channel_eof(channel);
329
0
  }
330
331
  /* And if we can't receive any more data from them either, close up */
332
0
  if (channel->readfd == FD_CLOSED
333
0
      && channel->writefd == FD_CLOSED
334
0
      && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
335
0
      && !channel->sent_close
336
0
      && close_allowed
337
0
      && !write_pending(channel)) {
338
0
    TRACE(("sending close, readfd is closed"))
339
0
    send_msg_channel_close(channel);
340
0
  }
341
0
}
342
343
/* Check whether a deferred (EINPROGRESS) connect() was successful, and
344
 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
345
 * it is important that the channel reference isn't used after a call to this
346
 * function */
347
0
void channel_connect_done(int result, int sock, void* user_data, const char* errstring) {
348
0
  struct Channel *channel = user_data;
349
350
0
  TRACE(("enter channel_connect_done"))
351
352
0
  if (result == DROPBEAR_SUCCESS)
353
0
  {
354
0
    channel->readfd = channel->writefd = sock;
355
0
    channel->bidir_fd = 1;
356
0
    channel->conn_pending = NULL;
357
0
    send_msg_channel_open_confirmation(channel, channel->recvwindow,
358
0
        channel->recvmaxpacket);
359
0
    TRACE(("leave channel_connect_done: success"))
360
0
  }
361
0
  else
362
0
  {
363
0
    send_msg_channel_open_failure(channel->remotechan,
364
0
        SSH_OPEN_CONNECT_FAILED, errstring, "");
365
0
    remove_channel(channel);
366
0
    TRACE(("leave check_in_progress: fail. internal errstring: %s", errstring))
367
0
  }
368
0
}
369
370
371
/* Send the close message and set the channel as closed */
372
0
static void send_msg_channel_close(struct Channel *channel) {
373
374
0
  TRACE(("enter send_msg_channel_close %p", (void*)channel))
375
0
  if (channel->type->closehandler) {
376
0
    channel->type->closehandler(channel);
377
0
  }
378
  
379
0
  CHECKCLEARTOWRITE();
380
381
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
382
0
  buf_putint(ses.writepayload, channel->remotechan);
383
384
0
  encrypt_packet();
385
386
0
  channel->sent_eof = 1;
387
0
  channel->sent_close = 1;
388
0
  close_chan_fd(channel, channel->readfd, SHUT_RD);
389
0
  close_chan_fd(channel, channel->errfd, SHUT_RDWR);
390
0
  close_chan_fd(channel, channel->writefd, SHUT_WR);
391
0
  TRACE(("leave send_msg_channel_close"))
392
0
}
393
394
/* call this when trans/eof channels are closed */
395
0
static void send_msg_channel_eof(struct Channel *channel) {
396
397
0
  TRACE(("enter send_msg_channel_eof"))
398
0
  CHECKCLEARTOWRITE();
399
400
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
401
0
  buf_putint(ses.writepayload, channel->remotechan);
402
403
0
  encrypt_packet();
404
405
0
  channel->sent_eof = 1;
406
407
0
  TRACE(("leave send_msg_channel_eof"))
408
0
}
409
410
#ifndef HAVE_WRITEV
411
static int writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf,
412
  const unsigned char *UNUSED(moredata), unsigned int *morelen) {
413
414
  unsigned char *circ_p1, *circ_p2;
415
  unsigned int circ_len1, circ_len2;
416
  ssize_t written;
417
418
  if (morelen) {
419
    /* fallback doesn't consume moredata */
420
    *morelen = 0;
421
  }
422
423
  /* Write the first portion of the circular buffer */
424
  cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
425
  written = write(fd, circ_p1, circ_len1);
426
  if (written < 0) {
427
    if (errno != EINTR && errno != EAGAIN) {
428
      TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
429
      close_chan_fd(channel, fd, SHUT_WR);
430
      return DROPBEAR_FAILURE;
431
    }
432
  } else {
433
    cbuf_incrread(cbuf, written);
434
    channel->recvdonelen += written;
435
  }
436
  return DROPBEAR_SUCCESS;
437
}
438
#endif /* !HAVE_WRITEV */
439
440
#ifdef HAVE_WRITEV
441
static int writechannel_writev(struct Channel* channel, int fd, circbuffer *cbuf,
442
0
  const unsigned char *moredata, unsigned int *morelen) {
443
444
0
  struct iovec iov[3];
445
0
  unsigned char *circ_p1, *circ_p2;
446
0
  unsigned int circ_len1, circ_len2;
447
0
  int io_count = 0;
448
449
0
  ssize_t written;
450
451
0
  cbuf_readptrs(cbuf, &circ_p1, &circ_len1, &circ_p2, &circ_len2);
452
453
0
  if (circ_len1 > 0) {
454
0
    TRACE(("circ1 %d", circ_len1))
455
0
    iov[io_count].iov_base = circ_p1;
456
0
    iov[io_count].iov_len = circ_len1;
457
0
    io_count++;
458
0
  }
459
460
0
  if (circ_len2 > 0) {
461
0
    TRACE(("circ2 %d", circ_len2))
462
0
    iov[io_count].iov_base = circ_p2;
463
0
    iov[io_count].iov_len = circ_len2;
464
0
    io_count++;
465
0
  }
466
467
0
  if (morelen) {
468
0
    assert(moredata);
469
0
    TRACE(("more %d", *morelen))
470
0
    iov[io_count].iov_base = (void*)moredata;
471
0
    iov[io_count].iov_len  = *morelen;
472
0
    io_count++;
473
0
  }
474
475
0
  if (io_count == 0) {
476
    /* writechannel may sometimes be called twice in a main loop iteration.
477
    From common_recv_msg_channel_data() then channelio().
478
    The second call may not have any data to write, so we just return. */
479
0
    TRACE(("leave writechannel, no data"))
480
0
    return DROPBEAR_SUCCESS;
481
0
  }
482
483
0
  if (morelen) {
484
    /* Default return value, none consumed */
485
0
    *morelen = 0;
486
0
  }
487
488
0
  written = writev(fd, iov, io_count);
489
490
0
  if (written < 0) {
491
0
    if (errno != EINTR && errno != EAGAIN) {
492
0
      TRACE(("channel IO write error fd %d %s", fd, strerror(errno)))
493
0
      close_chan_fd(channel, fd, SHUT_WR);
494
0
      return DROPBEAR_FAILURE;
495
0
    }
496
0
  } else {
497
0
    int cbuf_written = MIN(circ_len1+circ_len2, (unsigned int)written);
498
0
    cbuf_incrread(cbuf, cbuf_written);
499
0
    if (morelen) {
500
0
      *morelen = written - cbuf_written;
501
0
    }
502
0
    channel->recvdonelen += written;
503
0
  }
504
0
  return DROPBEAR_SUCCESS;
505
0
}
506
#endif /* HAVE_WRITEV */
507
508
/* Called to write data out to the local side of the channel. 
509
   Writes the circular buffer contents and also the "moredata" buffer
510
   if not null. Will ignore EAGAIN.
511
   Returns DROPBEAR_FAILURE if writing to fd had an error and the channel is being closed, DROPBEAR_SUCCESS otherwise */
512
static int writechannel(struct Channel* channel, int fd, circbuffer *cbuf,
513
0
  const unsigned char *moredata, unsigned int *morelen) {
514
0
  int ret = DROPBEAR_SUCCESS;
515
0
  TRACE(("enter writechannel fd %d", fd))
516
0
#ifdef HAVE_WRITEV
517
0
  ret = writechannel_writev(channel, fd, cbuf, moredata, morelen);
518
#else
519
  ret = writechannel_fallback(channel, fd, cbuf, moredata, morelen);
520
#endif
521
522
  /* Window adjust handling */
523
0
  if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
524
0
    send_msg_channel_window_adjust(channel, channel->recvdonelen);
525
0
    channel->recvwindow += channel->recvdonelen;
526
0
    channel->recvdonelen = 0;
527
0
  }
528
529
0
  dropbear_assert(channel->recvwindow <= opts.recv_window);
530
0
  dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
531
0
  dropbear_assert(channel->extrabuf == NULL ||
532
0
      channel->recvwindow <= cbuf_getavail(channel->extrabuf));
533
  
534
0
  TRACE(("leave writechannel"))
535
0
  return ret;
536
0
}
537
538
539
/* Set the file descriptors for the main select in session.c
540
 * This avoid channels which don't have any window available, are closed, etc*/
541
145k
void setchannelfds(fd_set *readfds, fd_set *writefds, int allow_reads) {
542
  
543
145k
  unsigned int i;
544
145k
  struct Channel * channel;
545
  
546
291k
  for (i = 0; i < ses.chansize; i++) {
547
548
145k
    channel = ses.channels[i];
549
145k
    if (channel == NULL) {
550
145k
      continue;
551
145k
    }
552
553
    /* Stuff to put over the wire. 
554
    Avoid queueing data to send if we're in the middle of a 
555
    key re-exchange (!dataallowed), but still read from the 
556
    FD if there's the possibility of "~."" to kill an 
557
    interactive session (the read_mangler) */
558
0
    if (channel->transwindow > 0
559
0
       && ((ses.dataallowed && allow_reads) || channel->read_mangler)) {
560
561
0
      if (channel->readfd >= 0) {
562
0
        FD_SET(channel->readfd, readfds);
563
0
      }
564
      
565
0
      if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
566
0
          FD_SET(channel->errfd, readfds);
567
0
      }
568
0
    }
569
570
    /* Stuff from the wire */
571
0
    if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
572
0
        FD_SET(channel->writefd, writefds);
573
0
    }
574
575
0
    if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0 
576
0
        && cbuf_getused(channel->extrabuf) > 0) {
577
0
        FD_SET(channel->errfd, writefds);
578
0
    }
579
580
0
  } /* foreach channel */
581
582
145k
#if DROPBEAR_LISTENERS
583
145k
  set_listener_fds(readfds);
584
145k
#endif
585
586
145k
}
587
588
/* handle the channel EOF event, by closing the channel filedescriptor. The
589
 * channel isn't closed yet, it is left until the incoming (from the program
590
 * etc) FD is also EOF */
591
53
void recv_msg_channel_eof() {
592
593
53
  struct Channel * channel;
594
595
53
  TRACE(("enter recv_msg_channel_eof"))
596
597
53
  channel = getchannel_msg("EOF");
598
599
53
  channel->recv_eof = 1;
600
601
53
  check_close(channel);
602
53
  TRACE(("leave recv_msg_channel_eof"))
603
53
}
604
605
606
/* Handle channel closure(), respond in kind and close the channels */
607
54
void recv_msg_channel_close() {
608
609
54
  struct Channel * channel;
610
611
54
  TRACE(("enter recv_msg_channel_close"))
612
613
54
  channel = getchannel_msg("Close");
614
615
54
  channel->recv_eof = 1;
616
54
  channel->recv_close = 1;
617
618
54
  check_close(channel);
619
54
  TRACE(("leave recv_msg_channel_close"))
620
54
}
621
622
/* Remove a channel entry, this is only executed after both sides have sent
623
 * channel close */
624
394
static void remove_channel(struct Channel * channel) {
625
626
394
  TRACE(("enter remove_channel"))
627
394
  TRACE(("channel index is %d", channel->index))
628
629
394
  cbuf_free(channel->writebuf);
630
394
  channel->writebuf = NULL;
631
632
394
  if (channel->extrabuf) {
633
0
    cbuf_free(channel->extrabuf);
634
0
    channel->extrabuf = NULL;
635
0
  }
636
637
638
394
  if (IS_DROPBEAR_SERVER || (channel->writefd != STDOUT_FILENO)) {
639
    /* close the FDs in case they haven't been done
640
     * yet (they might have been shutdown etc) */
641
394
    TRACE(("CLOSE writefd %d", channel->writefd))
642
394
    m_close(channel->writefd);
643
394
    TRACE(("CLOSE readfd %d", channel->readfd))
644
394
    m_close(channel->readfd);
645
394
    TRACE(("CLOSE errfd %d", channel->errfd))
646
394
    m_close(channel->errfd);
647
394
  }
648
649
394
  if (channel->type->cleanup) {
650
0
    channel->type->cleanup(channel);
651
0
  }
652
653
394
  if (channel->conn_pending) {
654
0
    cancel_connect(channel->conn_pending);
655
0
  }
656
657
394
  ses.channels[channel->index] = NULL;
658
394
  m_free(channel);
659
394
  ses.chancount--;
660
661
394
  update_channel_prio();
662
663
394
  TRACE(("leave remove_channel"))
664
394
}
665
666
/* Handle channel specific requests, passing off to corresponding handlers
667
 * such as chansession or x11fwd */
668
53
void recv_msg_channel_request() {
669
670
53
  struct Channel *channel;
671
672
53
  channel = getchannel();
673
674
53
  TRACE(("enter recv_msg_channel_request %p", (void*)channel))
675
676
53
  if (channel->type->reqhandler) {
677
0
    channel->type->reqhandler(channel);
678
53
  } else {
679
53
    int wantreply;
680
53
    buf_eatstring(ses.payload);
681
53
    wantreply = buf_getbool(ses.payload);
682
53
    if (wantreply) {
683
0
      send_msg_channel_failure(channel);
684
0
    }
685
53
  }
686
687
53
  TRACE(("leave recv_msg_channel_request"))
688
689
53
}
690
691
/* Reads data from the server's program/shell/etc, and puts it in a
692
 * channel_data packet to send.
693
 * chan is the remote channel, isextended is 0 if it is normal data, 1
694
 * if it is extended data. if it is extended, then the type is in
695
 * exttype */
696
0
static void send_msg_channel_data(struct Channel *channel, int isextended) {
697
698
0
  int len;
699
0
  size_t maxlen, size_pos;
700
0
  int fd;
701
702
0
  CHECKCLEARTOWRITE();
703
704
0
  TRACE(("enter send_msg_channel_data"))
705
0
  dropbear_assert(!channel->sent_close);
706
707
0
  if (isextended) {
708
0
    fd = channel->errfd;
709
0
  } else {
710
0
    fd = channel->readfd;
711
0
  }
712
0
  TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
713
0
  dropbear_assert(fd >= 0);
714
715
0
  maxlen = MIN(channel->transwindow, channel->transmaxpacket);
716
  /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and 
717
   * exttype if is extended */
718
0
  maxlen = MIN(maxlen, 
719
0
      ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
720
0
  TRACE(("maxlen %zd", maxlen))
721
0
  if (maxlen == 0) {
722
0
    TRACE(("leave send_msg_channel_data: no window"))
723
0
    return;
724
0
  }
725
726
0
  buf_putbyte(ses.writepayload, 
727
0
      isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
728
0
  buf_putint(ses.writepayload, channel->remotechan);
729
0
  if (isextended) {
730
0
    buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
731
0
  }
732
  /* a dummy size first ...*/
733
0
  size_pos = ses.writepayload->pos;
734
0
  buf_putint(ses.writepayload, 0);
735
736
  /* read the data */
737
0
  len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
738
739
0
  if (len <= 0) {
740
0
    if (len == 0 || errno != EINTR) {
741
      /* This will also get hit in the case of EAGAIN. The only
742
      time we expect to receive EAGAIN is when we're flushing a FD,
743
      in which case it can be treated the same as EOF */
744
0
      close_chan_fd(channel, fd, SHUT_RD);
745
0
    }
746
0
    buf_setpos(ses.writepayload, 0);
747
0
    buf_setlen(ses.writepayload, 0);
748
0
    TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d", 
749
0
          len, errno, fd))
750
0
    return;
751
0
  }
752
753
0
  if (channel->read_mangler) {
754
0
    channel->read_mangler(channel, buf_getwriteptr(ses.writepayload, len), &len);
755
0
    if (len == 0) {
756
0
      buf_setpos(ses.writepayload, 0);
757
0
      buf_setlen(ses.writepayload, 0);
758
0
      return;
759
0
    }
760
0
  }
761
762
0
  TRACE(("send_msg_channel_data: len %d fd %d", len, fd))
763
0
  buf_incrwritepos(ses.writepayload, len);
764
  /* ... real size here */
765
0
  buf_setpos(ses.writepayload, size_pos);
766
0
  buf_putint(ses.writepayload, len);
767
768
0
  channel->transwindow -= len;
769
770
0
  encrypt_packet();
771
0
  TRACE(("leave send_msg_channel_data"))
772
0
}
773
774
/* We receive channel data */
775
53
void recv_msg_channel_data() {
776
777
53
  struct Channel *channel;
778
779
53
  channel = getchannel();
780
781
53
  common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
782
53
}
783
784
/* Shared for data and stderr data - when we receive data, put it in a buffer
785
 * for writing to the local file descriptor */
786
void common_recv_msg_channel_data(struct Channel *channel, int fd, 
787
0
    circbuffer * cbuf) {
788
789
0
  unsigned int datalen;
790
0
  unsigned int maxdata;
791
0
  unsigned int buflen;
792
0
  unsigned int len;
793
0
  unsigned int consumed;
794
0
  int res;
795
796
0
  TRACE(("enter recv_msg_channel_data"))
797
798
0
  if (channel->recv_eof) {
799
0
    dropbear_exit("Received data after eof");
800
0
  }
801
802
0
  if (fd < 0 || !cbuf) {
803
    /* If we have encountered failed write, the far side might still
804
     * be sending data without having yet received our close notification.
805
     * We just drop the data. */
806
0
    return;
807
0
  }
808
809
0
  datalen = buf_getint(ses.payload);
810
0
  TRACE(("length %d", datalen))
811
812
0
  maxdata = cbuf_getavail(cbuf);
813
814
  /* Whilst the spec says we "MAY ignore data past the end" this could
815
   * lead to corrupted file transfers etc (chunks missed etc). It's better to
816
   * just die horribly */
817
0
  if (datalen > maxdata) {
818
0
    dropbear_exit("Oversized packet");
819
0
  }
820
821
0
  dropbear_assert(channel->recvwindow >= datalen);
822
0
  channel->recvwindow -= datalen;
823
0
  dropbear_assert(channel->recvwindow <= opts.recv_window);
824
825
  /* Attempt to write the data immediately without having to put it in the circular buffer */
826
0
  consumed = datalen;
827
0
  res = writechannel(channel, fd, cbuf, buf_getptr(ses.payload, datalen), &consumed);
828
829
0
  datalen -= consumed;
830
0
  buf_incrpos(ses.payload, consumed);
831
832
833
  /* We may have to run throught twice, if the buffer wraps around. Can't
834
   * just "leave it for next time" like with writechannel, since this
835
   * is payload data.
836
   * If the writechannel() failed then remaining data is discarded */
837
0
  if (res == DROPBEAR_SUCCESS) {
838
0
    len = datalen;
839
0
    while (len > 0) {
840
0
      buflen = cbuf_writelen(cbuf);
841
0
      buflen = MIN(buflen, len);
842
843
0
      memcpy(cbuf_writeptr(cbuf, buflen), 
844
0
          buf_getptr(ses.payload, buflen), buflen);
845
0
      cbuf_incrwrite(cbuf, buflen);
846
0
      buf_incrpos(ses.payload, buflen);
847
0
      len -= buflen;
848
0
    }
849
0
  }
850
851
0
  TRACE(("leave recv_msg_channel_data"))
852
0
}
853
854
/* Increment the outgoing data window for a channel - the remote end limits
855
 * the amount of data which may be transmitted, this window is decremented
856
 * as data is sent, and incremented upon receiving window-adjust messages */
857
53
void recv_msg_channel_window_adjust() {
858
859
53
  struct Channel * channel;
860
53
  unsigned int incr;
861
  
862
53
  channel = getchannel();
863
  
864
53
  incr = buf_getint(ses.payload);
865
53
  TRACE(("received window increment %d", incr))
866
53
  incr = MIN(incr, TRANS_MAX_WIN_INCR);
867
  
868
53
  channel->transwindow += incr;
869
53
  channel->transwindow = MIN(channel->transwindow, TRANS_MAX_WINDOW);
870
871
53
}
872
873
/* Increment the incoming data window for a channel, and let the remote
874
 * end know */
875
static void send_msg_channel_window_adjust(const struct Channel* channel,
876
0
    unsigned int incr) {
877
878
0
  TRACE(("sending window adjust %d", incr))
879
0
  CHECKCLEARTOWRITE();
880
881
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
882
0
  buf_putint(ses.writepayload, channel->remotechan);
883
0
  buf_putint(ses.writepayload, incr);
884
885
0
  encrypt_packet();
886
0
}
887
  
888
/* Handle a new channel request, performing any channel-type-specific setup */
889
1.78k
void recv_msg_channel_open() {
890
891
1.78k
  char *type;
892
1.78k
  unsigned int typelen;
893
1.78k
  unsigned int remotechan, transwindow, transmaxpacket;
894
1.78k
  struct Channel *channel;
895
1.78k
  const struct ChanType **cp;
896
1.78k
  const struct ChanType *chantype;
897
1.78k
  unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
898
1.78k
  int ret;
899
900
901
1.78k
  TRACE(("enter recv_msg_channel_open"))
902
903
  /* get the packet contents */
904
1.78k
  type = buf_getstring(ses.payload, &typelen);
905
906
1.78k
  remotechan = buf_getint(ses.payload);
907
1.78k
  transwindow = buf_getint(ses.payload);
908
1.78k
  transwindow = MIN(transwindow, TRANS_MAX_WINDOW);
909
1.78k
  transmaxpacket = buf_getint(ses.payload);
910
1.78k
  transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
911
912
  /* figure what type of packet it is */
913
1.78k
  if (typelen > MAX_NAME_LEN) {
914
200
    goto failure;
915
200
  }
916
917
  /* Get the channel type. Client and server style invokation will set up a
918
   * different list for ses.chantypes at startup. We just iterate through
919
   * this list and find the matching name */
920
1.58k
  for (cp = &ses.chantypes[0], chantype = (*cp); 
921
4.07k
      chantype != NULL;
922
2.88k
      cp++, chantype = (*cp)) {
923
2.88k
    if (strcmp(type, chantype->name) == 0) {
924
394
      break;
925
394
    }
926
2.88k
  }
927
928
1.58k
  if (chantype == NULL) {
929
1.14k
    TRACE(("No matching type for '%s'", type))
930
1.14k
    goto failure;
931
1.14k
  }
932
933
436
  TRACE(("matched type '%s'", type))
934
935
  /* create the channel */
936
436
  channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
937
938
436
  if (channel == NULL) {
939
0
    TRACE(("newchannel returned NULL"))
940
0
    errtype = SSH_OPEN_RESOURCE_SHORTAGE;
941
0
    goto failure;
942
0
  }
943
944
436
  if (channel->type->inithandler) {
945
394
    ret = channel->type->inithandler(channel);
946
394
    if (ret == SSH_OPEN_IN_PROGRESS) {
947
      /* We'll send the confirmation later */
948
0
      goto cleanup;
949
0
    }
950
394
    if (ret > 0) {
951
392
      errtype = ret;
952
392
      remove_channel(channel);
953
392
      TRACE(("inithandler returned failure %d", ret))
954
392
      goto failure;
955
392
    }
956
394
  }
957
958
44
  update_channel_prio();
959
960
  /* success */
961
44
  send_msg_channel_open_confirmation(channel, channel->recvwindow,
962
44
      channel->recvmaxpacket);
963
44
  goto cleanup;
964
965
1.73k
failure:
966
1.73k
  TRACE(("recv_msg_channel_open failure"))
967
1.73k
  send_msg_channel_open_failure(remotechan, errtype, "", "");
968
969
1.73k
cleanup:
970
1.73k
  m_free(type);
971
972
1.73k
  TRACE(("leave recv_msg_channel_open"))
973
1.73k
}
974
975
/* Send a failure message */
976
0
void send_msg_channel_failure(const struct Channel *channel) {
977
978
0
  TRACE(("enter send_msg_channel_failure"))
979
980
0
  if (channel->sent_close) {
981
0
    TRACE(("Skipping sending msg_channel_failure for closed channel"))
982
0
    return;
983
0
  }
984
0
  CHECKCLEARTOWRITE();
985
986
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
987
0
  buf_putint(ses.writepayload, channel->remotechan);
988
989
0
  encrypt_packet();
990
0
  TRACE(("leave send_msg_channel_failure"))
991
0
}
992
993
/* Send a success message */
994
0
void send_msg_channel_success(const struct Channel *channel) {
995
996
0
  TRACE(("enter send_msg_channel_success"))
997
0
  if (channel->sent_close) {
998
0
    TRACE(("Skipping sending msg_channel_success for closed channel"))
999
0
    return;
1000
0
  }
1001
0
  CHECKCLEARTOWRITE();
1002
1003
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
1004
0
  buf_putint(ses.writepayload, channel->remotechan);
1005
1006
0
  encrypt_packet();
1007
0
  TRACE(("leave send_msg_channel_success"))
1008
0
}
1009
1010
/* Send a channel open failure message, with a corresponding reason
1011
 * code (usually resource shortage or unknown chan type) */
1012
static void send_msg_channel_open_failure(unsigned int remotechan, 
1013
1.73k
    int reason, const char *text, const char *lang) {
1014
1015
1.73k
  TRACE(("enter send_msg_channel_open_failure"))
1016
1.73k
  CHECKCLEARTOWRITE();
1017
  
1018
1.73k
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
1019
1.73k
  buf_putint(ses.writepayload, remotechan);
1020
1.73k
  buf_putint(ses.writepayload, reason);
1021
1.73k
  buf_putstring(ses.writepayload, text, strlen(text));
1022
1.73k
  buf_putstring(ses.writepayload, lang, strlen(lang));
1023
1024
1.73k
  encrypt_packet();
1025
1.73k
  TRACE(("leave send_msg_channel_open_failure"))
1026
1.73k
}
1027
1028
/* Confirm a channel open, and let the remote end know what number we've
1029
 * allocated and the receive parameters */
1030
static void send_msg_channel_open_confirmation(const struct Channel* channel,
1031
    unsigned int recvwindow, 
1032
0
    unsigned int recvmaxpacket) {
1033
1034
0
  TRACE(("enter send_msg_channel_open_confirmation"))
1035
0
  CHECKCLEARTOWRITE();
1036
1037
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
1038
0
  buf_putint(ses.writepayload, channel->remotechan);
1039
0
  buf_putint(ses.writepayload, channel->index);
1040
0
  buf_putint(ses.writepayload, recvwindow);
1041
0
  buf_putint(ses.writepayload, recvmaxpacket);
1042
1043
0
  encrypt_packet();
1044
0
  TRACE(("leave send_msg_channel_open_confirmation"))
1045
0
}
1046
1047
/* close a fd, how is SHUT_RD or SHUT_WR */
1048
0
static void close_chan_fd(struct Channel *channel, int fd, int how) {
1049
1050
0
  int closein = 0, closeout = 0;
1051
1052
0
  if (channel->bidir_fd) {
1053
0
    TRACE(("SHUTDOWN(%d, %d)", fd, how))
1054
0
    shutdown(fd, how);
1055
0
    if (how == 0) {
1056
0
      closeout = 1;
1057
0
    } else {
1058
0
      closein = 1;
1059
0
    }
1060
0
  } else {
1061
0
    TRACE(("CLOSE some fd %d", fd))
1062
0
    m_close(fd);
1063
0
    closein = closeout = 1;
1064
0
  }
1065
1066
0
  if (closeout && (fd == channel->readfd)) {
1067
0
    channel->readfd = FD_CLOSED;
1068
0
  }
1069
0
  if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
1070
0
    channel->errfd = FD_CLOSED;
1071
0
  }
1072
1073
0
  if (closein && fd == channel->writefd) {
1074
0
    channel->writefd = FD_CLOSED;
1075
0
  }
1076
0
  if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
1077
0
    channel->errfd = FD_CLOSED;
1078
0
  }
1079
1080
  /* if we called shutdown on it and all references are gone, then we 
1081
   * need to close() it to stop it lingering */
1082
0
  if (channel->bidir_fd && channel->readfd == FD_CLOSED 
1083
0
    && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
1084
0
    TRACE(("CLOSE (finally) of %d", fd))
1085
0
    m_close(fd);
1086
0
  }
1087
0
}
1088
1089
1090
#if (DROPBEAR_LISTENERS) || (DROPBEAR_CLIENT)
1091
/* Create a new channel, and start the open request. This is intended
1092
 * for X11, agent, tcp forwarding, and should be filled with channel-specific
1093
 * options, with the calling function calling encrypt_packet() after
1094
 * completion. It is mandatory for the caller to encrypt_packet() if
1095
 * a channel is returned. NULL is returned on failure. */
1096
0
int send_msg_channel_open_init(int fd, const struct ChanType *type) {
1097
1098
0
  struct Channel* chan;
1099
1100
0
  TRACE(("enter send_msg_channel_open_init()"))
1101
0
  chan = newchannel(0, type, 0, 0);
1102
0
  if (!chan) {
1103
0
    TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
1104
0
    return DROPBEAR_FAILURE;
1105
0
  }
1106
1107
  /* Outbound opened channels don't make use of in-progress connections,
1108
   * we can set it up straight away */
1109
1110
  /* set fd non-blocking */
1111
0
  setnonblocking(fd);
1112
1113
0
  chan->writefd = chan->readfd = fd;
1114
0
  ses.maxfd = MAX(ses.maxfd, fd);
1115
0
  chan->bidir_fd = 1;
1116
1117
0
  chan->await_open = 1;
1118
1119
  /* now open the channel connection */
1120
0
  CHECKCLEARTOWRITE();
1121
1122
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
1123
0
  buf_putstring(ses.writepayload, type->name, strlen(type->name));
1124
0
  buf_putint(ses.writepayload, chan->index);
1125
0
  buf_putint(ses.writepayload, opts.recv_window);
1126
0
  buf_putint(ses.writepayload, RECV_MAX_CHANNEL_DATA_LEN);
1127
1128
0
  TRACE(("leave send_msg_channel_open_init()"))
1129
0
  return DROPBEAR_SUCCESS;
1130
0
}
1131
1132
/* Confirmation that our channel open request was 
1133
 * successful*/
1134
54
void recv_msg_channel_open_confirmation() {
1135
1136
54
  struct Channel * channel;
1137
54
  int ret;
1138
1139
54
  TRACE(("enter recv_msg_channel_open_confirmation"))
1140
1141
54
  channel = getchannel();
1142
1143
54
  if (!channel->await_open) {
1144
0
    dropbear_exit("Unexpected channel reply");
1145
0
  }
1146
54
  channel->await_open = 0;
1147
1148
54
  channel->remotechan =  buf_getint(ses.payload);
1149
54
  channel->transwindow = buf_getint(ses.payload);
1150
54
  channel->transmaxpacket = buf_getint(ses.payload);
1151
  
1152
54
  TRACE(("new chan remote %d local %d", 
1153
54
        channel->remotechan, channel->index))
1154
1155
  /* Run the inithandler callback */
1156
54
  if (channel->type->inithandler) {
1157
0
    ret = channel->type->inithandler(channel);
1158
0
    if (ret > 0) {
1159
0
      remove_channel(channel);
1160
0
      TRACE(("inithandler returned failure %d", ret))
1161
0
      return;
1162
0
    }
1163
0
  }
1164
1165
54
  update_channel_prio();
1166
1167
54
  TRACE(("leave recv_msg_channel_open_confirmation"))
1168
54
}
1169
1170
/* Notification that our channel open request failed */
1171
53
void recv_msg_channel_open_failure() {
1172
1173
53
  struct Channel * channel;
1174
1175
53
  channel = getchannel();
1176
1177
53
  if (!channel->await_open) {
1178
0
    dropbear_exit("Unexpected channel reply");
1179
0
  }
1180
53
  channel->await_open = 0;
1181
1182
53
  remove_channel(channel);
1183
53
}
1184
#endif /* DROPBEAR_LISTENERS */
1185
1186
0
void send_msg_request_success() {
1187
0
  CHECKCLEARTOWRITE();
1188
0
  buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
1189
0
  encrypt_packet();
1190
0
}
1191
1192
791
void send_msg_request_failure() {
1193
791
  CHECKCLEARTOWRITE();
1194
791
  buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
1195
791
  encrypt_packet();
1196
791
}
1197
1198
0
struct Channel* get_any_ready_channel() {
1199
0
  size_t i;
1200
0
  if (ses.chancount == 0) {
1201
0
    return NULL;
1202
0
  }
1203
0
  for (i = 0; i < ses.chansize; i++) {
1204
0
    struct Channel *chan = ses.channels[i];
1205
0
    if (chan
1206
0
        && !(chan->sent_eof || chan->recv_eof)
1207
0
        && !(chan->await_open)) {
1208
0
      return chan;
1209
0
    }
1210
0
  }
1211
0
  return NULL;
1212
0
}
1213
1214
void start_send_channel_request(const struct Channel *channel,
1215
0
    const char *type) {
1216
1217
0
  CHECKCLEARTOWRITE();
1218
0
  buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_REQUEST);
1219
0
  buf_putint(ses.writepayload, channel->remotechan);
1220
1221
0
  buf_putstring(ses.writepayload, type, strlen(type));
1222
1223
0
}