Tomato 1.28
[tomato.git] / release / src / router / dropbear / common-channel.c
blob95fce78454b1c19ed489d6bf36475c497fc393f8
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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. */
25 /* Handle the multiplexed channels, such as sessions, x11, agent connections */
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 "ssh.h"
36 #include "listener.h"
37 #include "runopts.h"
39 static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
40 const unsigned char *text, const unsigned char *lang);
41 static void send_msg_channel_open_confirmation(struct Channel* channel,
42 unsigned int recvwindow,
43 unsigned int recvmaxpacket);
44 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
45 static void send_msg_channel_window_adjust(struct Channel *channel,
46 unsigned int incr);
47 static void send_msg_channel_data(struct Channel *channel, int isextended);
48 static void send_msg_channel_eof(struct Channel *channel);
49 static void send_msg_channel_close(struct Channel *channel);
50 static void remove_channel(struct Channel *channel);
51 static void delete_channel(struct Channel *channel);
52 static void check_in_progress(struct Channel *channel);
53 static unsigned int write_pending(struct Channel * channel);
54 static void check_close(struct Channel *channel);
55 static void close_chan_fd(struct Channel *channel, int fd, int how);
57 #define FD_UNINIT (-2)
58 #define FD_CLOSED (-1)
60 #define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
61 #define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
63 /* Initialise all the channels */
64 void chaninitialise(const struct ChanType *chantypes[]) {
66 /* may as well create space for a single channel */
67 ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
68 ses.chansize = 1;
69 ses.channels[0] = NULL;
70 ses.chancount = 0;
72 ses.chantypes = chantypes;
74 #ifdef USING_LISTENERS
75 listeners_initialise();
76 #endif
80 /* Clean up channels, freeing allocated memory */
81 void chancleanup() {
83 unsigned int i;
85 TRACE(("enter chancleanup"))
86 for (i = 0; i < ses.chansize; i++) {
87 if (ses.channels[i] != NULL) {
88 TRACE(("channel %d closing", i))
89 remove_channel(ses.channels[i]);
92 m_free(ses.channels);
93 TRACE(("leave chancleanup"))
96 /* Create a new channel entry, send a reply confirm or failure */
97 /* If remotechan, transwindow and transmaxpacket are not know (for a new
98 * outgoing connection, with them to be filled on confirmation), they should
99 * all be set to 0 */
100 struct Channel* newchannel(unsigned int remotechan,
101 const struct ChanType *type,
102 unsigned int transwindow, unsigned int transmaxpacket) {
104 struct Channel * newchan;
105 unsigned int i, j;
107 TRACE(("enter newchannel"))
109 /* first see if we can use existing channels */
110 for (i = 0; i < ses.chansize; i++) {
111 if (ses.channels[i] == NULL) {
112 break;
116 /* otherwise extend the list */
117 if (i == ses.chansize) {
118 if (ses.chansize >= MAX_CHANNELS) {
119 TRACE(("leave newchannel: max chans reached"))
120 return NULL;
123 /* extend the channels */
124 ses.channels = (struct Channel**)m_realloc(ses.channels,
125 (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
127 ses.chansize += CHAN_EXTEND_SIZE;
129 /* set the new channels to null */
130 for (j = i; j < ses.chansize; j++) {
131 ses.channels[j] = NULL;
136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
137 newchan->type = type;
138 newchan->index = i;
139 newchan->sent_close = newchan->recv_close = 0;
140 newchan->sent_eof = newchan->recv_eof = 0;
142 newchan->remotechan = remotechan;
143 newchan->transwindow = transwindow;
144 newchan->transmaxpacket = transmaxpacket;
146 newchan->typedata = NULL;
147 newchan->writefd = FD_UNINIT;
148 newchan->readfd = FD_UNINIT;
149 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
150 newchan->initconn = 0;
151 newchan->await_open = 0;
152 newchan->flushing = 0;
154 newchan->writebuf = cbuf_new(opts.recv_window);
155 newchan->extrabuf = NULL; /* The user code can set it up */
156 newchan->recvwindow = opts.recv_window;
157 newchan->recvdonelen = 0;
158 newchan->recvmaxpacket = RECV_MAX_PAYLOAD_LEN;
160 ses.channels[i] = newchan;
161 ses.chancount++;
163 TRACE(("leave newchannel"))
165 return newchan;
168 /* Returns the channel structure corresponding to the channel in the current
169 * data packet (ses.payload must be positioned appropriately).
170 * A valid channel is always returns, it will fail fatally with an unknown
171 * channel */
172 static struct Channel* getchannel_msg(const char* kind) {
174 unsigned int chan;
176 chan = buf_getint(ses.payload);
177 if (chan >= ses.chansize || ses.channels[chan] == NULL) {
178 if (kind) {
179 dropbear_exit("%s for unknown channel %d", kind, chan);
180 } else {
181 dropbear_exit("Unknown channel %d", chan);
184 return ses.channels[chan];
187 struct Channel* getchannel() {
188 return getchannel_msg(NULL);
191 /* Iterate through the channels, performing IO if available */
192 void channelio(fd_set *readfds, fd_set *writefds) {
194 struct Channel *channel;
195 unsigned int i;
197 /* foreach channel */
198 for (i = 0; i < ses.chansize; i++) {
200 channel = ses.channels[i];
201 if (channel == NULL) {
202 /* only process in-use channels */
203 continue;
206 /* read data and send it over the wire */
207 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
208 TRACE(("send normal readfd"))
209 send_msg_channel_data(channel, 0);
212 /* read stderr data and send it over the wire */
213 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
214 && FD_ISSET(channel->errfd, readfds)) {
215 TRACE(("send normal errfd"))
216 send_msg_channel_data(channel, 1);
219 /* write to program/pipe stdin */
220 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
221 if (channel->initconn) {
222 /* XXX should this go somewhere cleaner? */
223 check_in_progress(channel);
224 continue; /* Important not to use the channel after
225 check_in_progress(), as it may be NULL */
227 writechannel(channel, channel->writefd, channel->writebuf);
230 /* stderr for client mode */
231 if (ERRFD_IS_WRITE(channel)
232 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
233 writechannel(channel, channel->errfd, channel->extrabuf);
236 /* handle any channel closing etc */
237 check_close(channel);
241 /* Listeners such as TCP, X11, agent-auth */
242 #ifdef USING_LISTENERS
243 handle_listeners(readfds);
244 #endif
248 /* Returns true if there is data remaining to be written to stdin or
249 * stderr of a channel's endpoint. */
250 static unsigned int write_pending(struct Channel * channel) {
252 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
253 return 1;
254 } else if (channel->errfd >= 0 && channel->extrabuf &&
255 cbuf_getused(channel->extrabuf) > 0) {
256 return 1;
258 return 0;
262 /* EOF/close handling */
263 static void check_close(struct Channel *channel) {
264 int close_allowed = 0;
266 TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
267 channel->writefd, channel->readfd,
268 channel->errfd, channel->sent_close, channel->recv_close))
269 TRACE(("writebuf size %d extrabuf size %d",
270 cbuf_getused(channel->writebuf),
271 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
273 if (!channel->flushing && channel->type->check_close
274 && channel->type->check_close(channel))
276 channel->flushing = 1;
279 /* if a type-specific check_close is defined we will only exit
280 once that has been triggered. this is only used for a server "session"
281 channel, to ensure that the shell has exited (and the exit status
282 retrieved) before we close things up. */
283 if (!channel->type->check_close
284 || channel->type->check_close(channel)) {
285 close_allowed = 1;
288 if (channel->recv_close && !write_pending(channel) && close_allowed) {
289 if (!channel->sent_close) {
290 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
291 send_msg_channel_close(channel);
293 remove_channel(channel);
294 return;
297 if (channel->recv_eof && !write_pending(channel)) {
298 close_chan_fd(channel, channel->writefd, SHUT_WR);
301 /* Special handling for flushing read data after an exit. We
302 read regardless of whether the select FD was set,
303 and if there isn't data available, the channel will get closed. */
304 if (channel->flushing) {
305 TRACE(("might send data, flushing"))
306 if (channel->readfd >= 0 && channel->transwindow > 0) {
307 TRACE(("send data readfd"))
308 send_msg_channel_data(channel, 0);
310 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
311 && channel->transwindow > 0) {
312 TRACE(("send data errfd"))
313 send_msg_channel_data(channel, 1);
317 /* If we're not going to send any more data, send EOF */
318 if (!channel->sent_eof
319 && channel->readfd == FD_CLOSED
320 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
321 send_msg_channel_eof(channel);
324 /* And if we can't receive any more data from them either, close up */
325 if (channel->readfd == FD_CLOSED
326 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
327 && !channel->sent_close
328 && close_allowed
329 && !write_pending(channel)) {
330 TRACE(("sending close, readfd is closed"))
331 send_msg_channel_close(channel);
335 /* Check whether a deferred (EINPROGRESS) connect() was successful, and
336 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
337 * it is important that the channel reference isn't used after a call to this
338 * function */
339 static void check_in_progress(struct Channel *channel) {
341 int val;
342 socklen_t vallen = sizeof(val);
344 TRACE(("enter check_in_progress"))
346 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
347 || val != 0) {
348 send_msg_channel_open_failure(channel->remotechan,
349 SSH_OPEN_CONNECT_FAILED, "", "");
350 close(channel->writefd);
351 delete_channel(channel);
352 TRACE(("leave check_in_progress: fail"))
353 } else {
354 send_msg_channel_open_confirmation(channel, channel->recvwindow,
355 channel->recvmaxpacket);
356 channel->readfd = channel->writefd;
357 channel->initconn = 0;
358 TRACE(("leave check_in_progress: success"))
363 /* Send the close message and set the channel as closed */
364 static void send_msg_channel_close(struct Channel *channel) {
366 TRACE(("enter send_msg_channel_close"))
367 if (channel->type->closehandler) {
368 channel->type->closehandler(channel);
371 CHECKCLEARTOWRITE();
373 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
374 buf_putint(ses.writepayload, channel->remotechan);
376 encrypt_packet();
378 channel->sent_eof = 1;
379 channel->sent_close = 1;
380 close_chan_fd(channel, channel->readfd, SHUT_RD);
381 close_chan_fd(channel, channel->errfd, SHUT_RDWR);
382 close_chan_fd(channel, channel->writefd, SHUT_WR);
383 TRACE(("leave send_msg_channel_close"))
386 /* call this when trans/eof channels are closed */
387 static void send_msg_channel_eof(struct Channel *channel) {
389 TRACE(("enter send_msg_channel_eof"))
390 CHECKCLEARTOWRITE();
392 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
393 buf_putint(ses.writepayload, channel->remotechan);
395 encrypt_packet();
397 channel->sent_eof = 1;
399 TRACE(("leave send_msg_channel_eof"))
402 /* Called to write data out to the local side of the channel.
403 * Only called when we know we can write to a channel, writes as much as
404 * possible */
405 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
407 int len, maxlen;
409 TRACE(("enter writechannel fd %d", fd))
411 maxlen = cbuf_readlen(cbuf);
413 /* Write the data out */
414 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
415 if (len <= 0) {
416 TRACE(("errno %d len %d", errno, len))
417 if (len < 0 && errno != EINTR) {
418 close_chan_fd(channel, fd, SHUT_WR);
420 TRACE(("leave writechannel: len <= 0"))
421 return;
423 TRACE(("writechannel wrote %d", len))
425 cbuf_incrread(cbuf, len);
426 channel->recvdonelen += len;
428 /* Window adjust handling */
429 if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
430 /* Set it back to max window */
431 send_msg_channel_window_adjust(channel, channel->recvdonelen);
432 channel->recvwindow += channel->recvdonelen;
433 channel->recvdonelen = 0;
436 dropbear_assert(channel->recvwindow <= opts.recv_window);
437 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
438 dropbear_assert(channel->extrabuf == NULL ||
439 channel->recvwindow <= cbuf_getavail(channel->extrabuf));
441 TRACE(("leave writechannel"))
444 /* Set the file descriptors for the main select in session.c
445 * This avoid channels which don't have any window available, are closed, etc*/
446 void setchannelfds(fd_set *readfds, fd_set *writefds) {
448 unsigned int i;
449 struct Channel * channel;
451 for (i = 0; i < ses.chansize; i++) {
453 channel = ses.channels[i];
454 if (channel == NULL) {
455 continue;
458 /* Stuff to put over the wire */
459 if (channel->transwindow > 0) {
461 if (channel->readfd >= 0) {
462 FD_SET(channel->readfd, readfds);
465 if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
466 FD_SET(channel->errfd, readfds);
470 /* Stuff from the wire */
471 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
472 || channel->initconn) {
473 FD_SET(channel->writefd, writefds);
476 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
477 && cbuf_getused(channel->extrabuf) > 0 ) {
478 FD_SET(channel->errfd, writefds);
481 } /* foreach channel */
483 #ifdef USING_LISTENERS
484 set_listener_fds(readfds);
485 #endif
489 /* handle the channel EOF event, by closing the channel filedescriptor. The
490 * channel isn't closed yet, it is left until the incoming (from the program
491 * etc) FD is also EOF */
492 void recv_msg_channel_eof() {
494 struct Channel * channel;
496 TRACE(("enter recv_msg_channel_eof"))
498 channel = getchannel_msg("EOF");
500 channel->recv_eof = 1;
502 check_close(channel);
503 TRACE(("leave recv_msg_channel_eof"))
507 /* Handle channel closure(), respond in kind and close the channels */
508 void recv_msg_channel_close() {
510 struct Channel * channel;
512 TRACE(("enter recv_msg_channel_close"))
514 channel = getchannel_msg("Close");
516 channel->recv_eof = 1;
517 channel->recv_close = 1;
519 check_close(channel);
520 TRACE(("leave recv_msg_channel_close"))
523 /* Remove a channel entry, this is only executed after both sides have sent
524 * channel close */
525 static void remove_channel(struct Channel * channel) {
527 TRACE(("enter remove_channel"))
528 TRACE(("channel index is %d", channel->index))
530 cbuf_free(channel->writebuf);
531 channel->writebuf = NULL;
533 if (channel->extrabuf) {
534 cbuf_free(channel->extrabuf);
535 channel->extrabuf = NULL;
539 /* close the FDs in case they haven't been done
540 * yet (they might have been shutdown etc) */
541 TRACE(("CLOSE writefd %d", channel->writefd))
542 close(channel->writefd);
543 TRACE(("CLOSE readfd %d", channel->readfd))
544 close(channel->readfd);
545 TRACE(("CLOSE errfd %d", channel->errfd))
546 close(channel->errfd);
548 channel->typedata = NULL;
550 delete_channel(channel);
552 TRACE(("leave remove_channel"))
555 /* Remove a channel entry */
556 static void delete_channel(struct Channel *channel) {
558 ses.channels[channel->index] = NULL;
559 m_free(channel);
560 ses.chancount--;
565 /* Handle channel specific requests, passing off to corresponding handlers
566 * such as chansession or x11fwd */
567 void recv_msg_channel_request() {
569 struct Channel *channel;
571 TRACE(("enter recv_msg_channel_request"))
573 channel = getchannel();
575 if (channel->sent_close) {
576 TRACE(("leave recv_msg_channel_request: already closed channel"))
577 return;
580 if (channel->type->reqhandler) {
581 channel->type->reqhandler(channel);
582 } else {
583 send_msg_channel_failure(channel);
586 TRACE(("leave recv_msg_channel_request"))
590 /* Reads data from the server's program/shell/etc, and puts it in a
591 * channel_data packet to send.
592 * chan is the remote channel, isextended is 0 if it is normal data, 1
593 * if it is extended data. if it is extended, then the type is in
594 * exttype */
595 static void send_msg_channel_data(struct Channel *channel, int isextended) {
597 int len;
598 size_t maxlen, size_pos;
599 int fd;
601 CHECKCLEARTOWRITE();
603 TRACE(("enter send_msg_channel_data"))
604 dropbear_assert(!channel->sent_close);
606 if (isextended) {
607 fd = channel->errfd;
608 } else {
609 fd = channel->readfd;
611 TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
612 dropbear_assert(fd >= 0);
614 maxlen = MIN(channel->transwindow, channel->transmaxpacket);
615 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
616 * exttype if is extended */
617 maxlen = MIN(maxlen,
618 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
619 TRACE(("maxlen %d", maxlen))
620 if (maxlen == 0) {
621 TRACE(("leave send_msg_channel_data: no window"))
622 return;
625 buf_putbyte(ses.writepayload,
626 isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
627 buf_putint(ses.writepayload, channel->remotechan);
628 if (isextended) {
629 buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
631 /* a dummy size first ...*/
632 size_pos = ses.writepayload->pos;
633 buf_putint(ses.writepayload, 0);
635 /* read the data */
636 len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
637 if (len <= 0) {
638 if (len == 0 || errno != EINTR) {
639 /* This will also get hit in the case of EAGAIN. The only
640 time we expect to receive EAGAIN is when we're flushing a FD,
641 in which case it can be treated the same as EOF */
642 close_chan_fd(channel, fd, SHUT_RD);
644 ses.writepayload->len = ses.writepayload->pos = 0;
645 TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
646 len, errno, fd))
647 return;
649 buf_incrwritepos(ses.writepayload, len);
650 /* ... real size here */
651 buf_setpos(ses.writepayload, size_pos);
652 buf_putint(ses.writepayload, len);
654 channel->transwindow -= len;
656 encrypt_packet();
658 /* If we receive less data than we requested when flushing, we've
659 reached the equivalent of EOF */
660 if (channel->flushing && len < (ssize_t)maxlen)
662 TRACE(("closing from channel, flushing out."))
663 close_chan_fd(channel, fd, SHUT_RD);
665 TRACE(("leave send_msg_channel_data"))
668 /* We receive channel data */
669 void recv_msg_channel_data() {
671 struct Channel *channel;
673 channel = getchannel();
675 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
678 /* Shared for data and stderr data - when we receive data, put it in a buffer
679 * for writing to the local file descriptor */
680 void common_recv_msg_channel_data(struct Channel *channel, int fd,
681 circbuffer * cbuf) {
683 unsigned int datalen;
684 unsigned int maxdata;
685 unsigned int buflen;
686 unsigned int len;
688 TRACE(("enter recv_msg_channel_data"))
690 if (channel->recv_eof) {
691 dropbear_exit("received data after eof");
694 if (fd < 0) {
695 /* If we have encountered failed write, the far side might still
696 * be sending data without having yet received our close notification.
697 * We just drop the data. */
698 return;
701 datalen = buf_getint(ses.payload);
702 TRACE(("length %d", datalen))
704 maxdata = cbuf_getavail(cbuf);
706 /* Whilst the spec says we "MAY ignore data past the end" this could
707 * lead to corrupted file transfers etc (chunks missed etc). It's better to
708 * just die horribly */
709 if (datalen > maxdata) {
710 dropbear_exit("Oversized packet");
713 /* We may have to run throught twice, if the buffer wraps around. Can't
714 * just "leave it for next time" like with writechannel, since this
715 * is payload data */
716 len = datalen;
717 while (len > 0) {
718 buflen = cbuf_writelen(cbuf);
719 buflen = MIN(buflen, len);
721 memcpy(cbuf_writeptr(cbuf, buflen),
722 buf_getptr(ses.payload, buflen), buflen);
723 cbuf_incrwrite(cbuf, buflen);
724 buf_incrpos(ses.payload, buflen);
725 len -= buflen;
728 dropbear_assert(channel->recvwindow >= datalen);
729 channel->recvwindow -= datalen;
730 dropbear_assert(channel->recvwindow <= opts.recv_window);
732 TRACE(("leave recv_msg_channel_data"))
735 /* Increment the outgoing data window for a channel - the remote end limits
736 * the amount of data which may be transmitted, this window is decremented
737 * as data is sent, and incremented upon receiving window-adjust messages */
738 void recv_msg_channel_window_adjust() {
740 struct Channel * channel;
741 unsigned int incr;
743 channel = getchannel();
745 incr = buf_getint(ses.payload);
746 TRACE(("received window increment %d", incr))
747 incr = MIN(incr, TRANS_MAX_WIN_INCR);
749 channel->transwindow += incr;
750 channel->transwindow = MIN(channel->transwindow, TRANS_MAX_WINDOW);
754 /* Increment the incoming data window for a channel, and let the remote
755 * end know */
756 static void send_msg_channel_window_adjust(struct Channel* channel,
757 unsigned int incr) {
759 TRACE(("sending window adjust %d", incr))
760 CHECKCLEARTOWRITE();
762 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
763 buf_putint(ses.writepayload, channel->remotechan);
764 buf_putint(ses.writepayload, incr);
766 encrypt_packet();
769 /* Handle a new channel request, performing any channel-type-specific setup */
770 void recv_msg_channel_open() {
772 unsigned char *type;
773 unsigned int typelen;
774 unsigned int remotechan, transwindow, transmaxpacket;
775 struct Channel *channel;
776 const struct ChanType **cp;
777 const struct ChanType *chantype;
778 unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
779 int ret;
782 TRACE(("enter recv_msg_channel_open"))
784 /* get the packet contents */
785 type = buf_getstring(ses.payload, &typelen);
787 remotechan = buf_getint(ses.payload);
788 transwindow = buf_getint(ses.payload);
789 transwindow = MIN(transwindow, TRANS_MAX_WINDOW);
790 transmaxpacket = buf_getint(ses.payload);
791 transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
793 /* figure what type of packet it is */
794 if (typelen > MAX_NAME_LEN) {
795 goto failure;
798 /* Get the channel type. Client and server style invokation will set up a
799 * different list for ses.chantypes at startup. We just iterate through
800 * this list and find the matching name */
801 for (cp = &ses.chantypes[0], chantype = (*cp);
802 chantype != NULL;
803 cp++, chantype = (*cp)) {
804 if (strcmp(type, chantype->name) == 0) {
805 break;
809 if (chantype == NULL) {
810 TRACE(("No matching type for '%s'", type))
811 goto failure;
814 TRACE(("matched type '%s'", type))
816 /* create the channel */
817 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
819 if (channel == NULL) {
820 TRACE(("newchannel returned NULL"))
821 goto failure;
824 if (channel->type->inithandler) {
825 ret = channel->type->inithandler(channel);
826 if (ret == SSH_OPEN_IN_PROGRESS) {
827 /* We'll send the confirmation later */
828 goto cleanup;
830 if (ret > 0) {
831 errtype = ret;
832 delete_channel(channel);
833 TRACE(("inithandler returned failure %d", ret))
834 goto failure;
838 /* success */
839 send_msg_channel_open_confirmation(channel, channel->recvwindow,
840 channel->recvmaxpacket);
841 goto cleanup;
843 failure:
844 TRACE(("recv_msg_channel_open failure"))
845 send_msg_channel_open_failure(remotechan, errtype, "", "");
847 cleanup:
848 m_free(type);
850 TRACE(("leave recv_msg_channel_open"))
853 /* Send a failure message */
854 void send_msg_channel_failure(struct Channel *channel) {
856 TRACE(("enter send_msg_channel_failure"))
857 CHECKCLEARTOWRITE();
859 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
860 buf_putint(ses.writepayload, channel->remotechan);
862 encrypt_packet();
863 TRACE(("leave send_msg_channel_failure"))
866 /* Send a success message */
867 void send_msg_channel_success(struct Channel *channel) {
869 TRACE(("enter send_msg_channel_success"))
870 CHECKCLEARTOWRITE();
872 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
873 buf_putint(ses.writepayload, channel->remotechan);
875 encrypt_packet();
876 TRACE(("leave send_msg_channel_success"))
879 /* Send a channel open failure message, with a corresponding reason
880 * code (usually resource shortage or unknown chan type) */
881 static void send_msg_channel_open_failure(unsigned int remotechan,
882 int reason, const unsigned char *text, const unsigned char *lang) {
884 TRACE(("enter send_msg_channel_open_failure"))
885 CHECKCLEARTOWRITE();
887 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
888 buf_putint(ses.writepayload, remotechan);
889 buf_putint(ses.writepayload, reason);
890 buf_putstring(ses.writepayload, text, strlen((char*)text));
891 buf_putstring(ses.writepayload, lang, strlen((char*)lang));
893 encrypt_packet();
894 TRACE(("leave send_msg_channel_open_failure"))
897 /* Confirm a channel open, and let the remote end know what number we've
898 * allocated and the receive parameters */
899 static void send_msg_channel_open_confirmation(struct Channel* channel,
900 unsigned int recvwindow,
901 unsigned int recvmaxpacket) {
903 TRACE(("enter send_msg_channel_open_confirmation"))
904 CHECKCLEARTOWRITE();
906 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
907 buf_putint(ses.writepayload, channel->remotechan);
908 buf_putint(ses.writepayload, channel->index);
909 buf_putint(ses.writepayload, recvwindow);
910 buf_putint(ses.writepayload, recvmaxpacket);
912 encrypt_packet();
913 TRACE(("leave send_msg_channel_open_confirmation"))
916 /* close a fd, how is SHUT_RD or SHUT_WR */
917 static void close_chan_fd(struct Channel *channel, int fd, int how) {
919 int closein = 0, closeout = 0;
921 if (channel->type->sepfds) {
922 TRACE(("SHUTDOWN(%d, %d)", fd, how))
923 shutdown(fd, how);
924 if (how == 0) {
925 closeout = 1;
926 } else {
927 closein = 1;
929 } else {
930 TRACE(("CLOSE some fd %d", fd))
931 close(fd);
932 closein = closeout = 1;
935 if (closeout && (fd == channel->readfd)) {
936 channel->readfd = FD_CLOSED;
938 if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
939 channel->errfd = FD_CLOSED;
942 if (closein && fd == channel->writefd) {
943 channel->writefd = FD_CLOSED;
945 if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
946 channel->errfd = FD_CLOSED;
949 /* if we called shutdown on it and all references are gone, then we
950 * need to close() it to stop it lingering */
951 if (channel->type->sepfds && channel->readfd == FD_CLOSED
952 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
953 TRACE(("CLOSE (finally) of %d", fd))
954 close(fd);
959 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
960 /* Create a new channel, and start the open request. This is intended
961 * for X11, agent, tcp forwarding, and should be filled with channel-specific
962 * options, with the calling function calling encrypt_packet() after
963 * completion. It is mandatory for the caller to encrypt_packet() if
964 * DROPBEAR_SUCCESS is returned */
965 int send_msg_channel_open_init(int fd, const struct ChanType *type) {
967 struct Channel* chan;
969 TRACE(("enter send_msg_channel_open_init()"))
970 chan = newchannel(0, type, 0, 0);
971 if (!chan) {
972 TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
973 return DROPBEAR_FAILURE;
976 /* set fd non-blocking */
977 setnonblocking(fd);
979 chan->writefd = chan->readfd = fd;
980 ses.maxfd = MAX(ses.maxfd, fd);
982 chan->await_open = 1;
984 /* now open the channel connection */
985 CHECKCLEARTOWRITE();
987 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
988 buf_putstring(ses.writepayload, type->name, strlen(type->name));
989 buf_putint(ses.writepayload, chan->index);
990 buf_putint(ses.writepayload, opts.recv_window);
991 buf_putint(ses.writepayload, RECV_MAX_PAYLOAD_LEN);
993 TRACE(("leave send_msg_channel_open_init()"))
994 return DROPBEAR_SUCCESS;
997 /* Confirmation that our channel open request (for forwardings) was
998 * successful*/
999 void recv_msg_channel_open_confirmation() {
1001 struct Channel * channel;
1002 int ret;
1004 TRACE(("enter recv_msg_channel_open_confirmation"))
1006 channel = getchannel();
1008 if (!channel->await_open) {
1009 dropbear_exit("unexpected channel reply");
1011 channel->await_open = 0;
1013 channel->remotechan = buf_getint(ses.payload);
1014 channel->transwindow = buf_getint(ses.payload);
1015 channel->transmaxpacket = buf_getint(ses.payload);
1017 TRACE(("new chan remote %d local %d",
1018 channel->remotechan, channel->index))
1020 /* Run the inithandler callback */
1021 if (channel->type->inithandler) {
1022 ret = channel->type->inithandler(channel);
1023 if (ret > 0) {
1024 remove_channel(channel);
1025 TRACE(("inithandler returned failure %d", ret))
1030 TRACE(("leave recv_msg_channel_open_confirmation"))
1033 /* Notification that our channel open request failed */
1034 void recv_msg_channel_open_failure() {
1036 struct Channel * channel;
1038 channel = getchannel();
1040 if (!channel->await_open) {
1041 dropbear_exit("unexpected channel reply");
1043 channel->await_open = 0;
1045 remove_channel(channel);
1047 #endif /* USING_LISTENERS */