dropbear: update to 2013.62
[tomato.git] / release / src / router / dropbear / common-channel.c
blob206890461b442344ed1a04cb7f82e8e72df3d701
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 check_in_progress(struct Channel *channel);
52 static unsigned int write_pending(struct Channel * channel);
53 static void check_close(struct Channel *channel);
54 static void close_chan_fd(struct Channel *channel, int fd, int how);
56 #define FD_UNINIT (-2)
57 #define FD_CLOSED (-1)
59 #define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60 #define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
62 /* Initialise all the channels */
63 void chaninitialise(const struct ChanType *chantypes[]) {
65 /* may as well create space for a single channel */
66 ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
67 ses.chansize = 1;
68 ses.channels[0] = NULL;
69 ses.chancount = 0;
71 ses.chantypes = chantypes;
73 #ifdef USING_LISTENERS
74 listeners_initialise();
75 #endif
79 /* Clean up channels, freeing allocated memory */
80 void chancleanup() {
82 unsigned int i;
84 TRACE(("enter chancleanup"))
85 for (i = 0; i < ses.chansize; i++) {
86 if (ses.channels[i] != NULL) {
87 TRACE(("channel %d closing", i))
88 remove_channel(ses.channels[i]);
91 m_free(ses.channels);
92 TRACE(("leave chancleanup"))
95 static void
96 chan_initwritebuf(struct Channel *channel)
98 dropbear_assert(channel->writebuf->size == 0 && channel->recvwindow == 0);
99 cbuf_free(channel->writebuf);
100 channel->writebuf = cbuf_new(opts.recv_window);
101 channel->recvwindow = opts.recv_window;
104 /* Create a new channel entry, send a reply confirm or failure */
105 /* If remotechan, transwindow and transmaxpacket are not know (for a new
106 * outgoing connection, with them to be filled on confirmation), they should
107 * all be set to 0 */
108 static struct Channel* newchannel(unsigned int remotechan,
109 const struct ChanType *type,
110 unsigned int transwindow, unsigned int transmaxpacket) {
112 struct Channel * newchan;
113 unsigned int i, j;
115 TRACE(("enter newchannel"))
117 /* first see if we can use existing channels */
118 for (i = 0; i < ses.chansize; i++) {
119 if (ses.channels[i] == NULL) {
120 break;
124 /* otherwise extend the list */
125 if (i == ses.chansize) {
126 if (ses.chansize >= MAX_CHANNELS) {
127 TRACE(("leave newchannel: max chans reached"))
128 return NULL;
131 /* extend the channels */
132 ses.channels = (struct Channel**)m_realloc(ses.channels,
133 (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
135 ses.chansize += CHAN_EXTEND_SIZE;
137 /* set the new channels to null */
138 for (j = i; j < ses.chansize; j++) {
139 ses.channels[j] = NULL;
144 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
145 newchan->type = type;
146 newchan->index = i;
147 newchan->sent_close = newchan->recv_close = 0;
148 newchan->sent_eof = newchan->recv_eof = 0;
149 newchan->close_handler_done = 0;
151 newchan->remotechan = remotechan;
152 newchan->transwindow = transwindow;
153 newchan->transmaxpacket = transmaxpacket;
155 newchan->typedata = NULL;
156 newchan->writefd = FD_UNINIT;
157 newchan->readfd = FD_UNINIT;
158 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
159 newchan->initconn = 0;
160 newchan->await_open = 0;
161 newchan->flushing = 0;
163 newchan->writebuf = cbuf_new(0); /* resized later by chan_initwritebuf */
164 newchan->recvwindow = 0;
166 newchan->extrabuf = NULL; /* The user code can set it up */
167 newchan->recvdonelen = 0;
168 newchan->recvmaxpacket = RECV_MAX_PAYLOAD_LEN;
170 ses.channels[i] = newchan;
171 ses.chancount++;
173 TRACE(("leave newchannel"))
175 return newchan;
178 /* Returns the channel structure corresponding to the channel in the current
179 * data packet (ses.payload must be positioned appropriately).
180 * A valid channel is always returns, it will fail fatally with an unknown
181 * channel */
182 static struct Channel* getchannel_msg(const char* kind) {
184 unsigned int chan;
186 chan = buf_getint(ses.payload);
187 if (chan >= ses.chansize || ses.channels[chan] == NULL) {
188 if (kind) {
189 dropbear_exit("%s for unknown channel %d", kind, chan);
190 } else {
191 dropbear_exit("Unknown channel %d", chan);
194 return ses.channels[chan];
197 struct Channel* getchannel() {
198 return getchannel_msg(NULL);
201 /* Iterate through the channels, performing IO if available */
202 void channelio(fd_set *readfds, fd_set *writefds) {
204 struct Channel *channel;
205 unsigned int i;
207 /* foreach channel */
208 for (i = 0; i < ses.chansize; i++) {
210 channel = ses.channels[i];
211 if (channel == NULL) {
212 /* only process in-use channels */
213 continue;
216 /* read data and send it over the wire */
217 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
218 TRACE(("send normal readfd"))
219 send_msg_channel_data(channel, 0);
222 /* read stderr data and send it over the wire */
223 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
224 && FD_ISSET(channel->errfd, readfds)) {
225 TRACE(("send normal errfd"))
226 send_msg_channel_data(channel, 1);
229 /* write to program/pipe stdin */
230 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
231 if (channel->initconn) {
232 /* XXX should this go somewhere cleaner? */
233 check_in_progress(channel);
234 continue; /* Important not to use the channel after
235 check_in_progress(), as it may be NULL */
237 writechannel(channel, channel->writefd, channel->writebuf);
240 /* stderr for client mode */
241 if (ERRFD_IS_WRITE(channel)
242 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
243 writechannel(channel, channel->errfd, channel->extrabuf);
246 /* handle any channel closing etc */
247 check_close(channel);
251 /* Listeners such as TCP, X11, agent-auth */
252 #ifdef USING_LISTENERS
253 handle_listeners(readfds);
254 #endif
258 /* Returns true if there is data remaining to be written to stdin or
259 * stderr of a channel's endpoint. */
260 static unsigned int write_pending(struct Channel * channel) {
262 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
263 return 1;
264 } else if (channel->errfd >= 0 && channel->extrabuf &&
265 cbuf_getused(channel->extrabuf) > 0) {
266 return 1;
268 return 0;
272 /* EOF/close handling */
273 static void check_close(struct Channel *channel) {
274 int close_allowed = 0;
276 TRACE2(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
277 channel->writefd, channel->readfd,
278 channel->errfd, channel->sent_close, channel->recv_close))
279 TRACE2(("writebuf size %d extrabuf size %d",
280 channel->writebuf ? cbuf_getused(channel->writebuf) : 0,
281 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
283 if (!channel->flushing
284 && !channel->close_handler_done
285 && channel->type->check_close
286 && channel->type->check_close(channel))
288 channel->flushing = 1;
291 /* if a type-specific check_close is defined we will only exit
292 once that has been triggered. this is only used for a server "session"
293 channel, to ensure that the shell has exited (and the exit status
294 retrieved) before we close things up. */
295 if (!channel->type->check_close
296 || channel->close_handler_done
297 || channel->type->check_close(channel)) {
298 close_allowed = 1;
301 if (channel->recv_close && !write_pending(channel) && close_allowed) {
302 if (!channel->sent_close) {
303 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
304 send_msg_channel_close(channel);
306 remove_channel(channel);
307 return;
310 if ((channel->recv_eof && !write_pending(channel))
311 /* have a server "session" and child has exited */
312 || (channel->type->check_close && close_allowed)) {
313 close_chan_fd(channel, channel->writefd, SHUT_WR);
316 /* Special handling for flushing read data after an exit. We
317 read regardless of whether the select FD was set,
318 and if there isn't data available, the channel will get closed. */
319 if (channel->flushing) {
320 TRACE(("might send data, flushing"))
321 if (channel->readfd >= 0 && channel->transwindow > 0) {
322 TRACE(("send data readfd"))
323 send_msg_channel_data(channel, 0);
325 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
326 && channel->transwindow > 0) {
327 TRACE(("send data errfd"))
328 send_msg_channel_data(channel, 1);
332 /* If we're not going to send any more data, send EOF */
333 if (!channel->sent_eof
334 && channel->readfd == FD_CLOSED
335 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
336 send_msg_channel_eof(channel);
339 /* And if we can't receive any more data from them either, close up */
340 if (channel->readfd == FD_CLOSED
341 && channel->writefd == FD_CLOSED
342 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
343 && !channel->sent_close
344 && close_allowed
345 && !write_pending(channel)) {
346 TRACE(("sending close, readfd is closed"))
347 send_msg_channel_close(channel);
351 /* Check whether a deferred (EINPROGRESS) connect() was successful, and
352 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
353 * it is important that the channel reference isn't used after a call to this
354 * function */
355 static void check_in_progress(struct Channel *channel) {
357 int val;
358 socklen_t vallen = sizeof(val);
360 TRACE(("enter check_in_progress"))
362 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
363 || val != 0) {
364 send_msg_channel_open_failure(channel->remotechan,
365 SSH_OPEN_CONNECT_FAILED, "", "");
366 close(channel->writefd);
367 remove_channel(channel);
368 TRACE(("leave check_in_progress: fail"))
369 } else {
370 chan_initwritebuf(channel);
371 send_msg_channel_open_confirmation(channel, channel->recvwindow,
372 channel->recvmaxpacket);
373 channel->readfd = channel->writefd;
374 channel->initconn = 0;
375 TRACE(("leave check_in_progress: success"))
380 /* Send the close message and set the channel as closed */
381 static void send_msg_channel_close(struct Channel *channel) {
383 TRACE(("enter send_msg_channel_close %p", channel))
384 if (channel->type->closehandler
385 && !channel->close_handler_done) {
386 channel->type->closehandler(channel);
387 channel->close_handler_done = 1;
390 CHECKCLEARTOWRITE();
392 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
393 buf_putint(ses.writepayload, channel->remotechan);
395 encrypt_packet();
397 channel->sent_eof = 1;
398 channel->sent_close = 1;
399 close_chan_fd(channel, channel->readfd, SHUT_RD);
400 close_chan_fd(channel, channel->errfd, SHUT_RDWR);
401 close_chan_fd(channel, channel->writefd, SHUT_WR);
402 TRACE(("leave send_msg_channel_close"))
405 /* call this when trans/eof channels are closed */
406 static void send_msg_channel_eof(struct Channel *channel) {
408 TRACE(("enter send_msg_channel_eof"))
409 CHECKCLEARTOWRITE();
411 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
412 buf_putint(ses.writepayload, channel->remotechan);
414 encrypt_packet();
416 channel->sent_eof = 1;
418 TRACE(("leave send_msg_channel_eof"))
421 /* Called to write data out to the local side of the channel.
422 * Only called when we know we can write to a channel, writes as much as
423 * possible */
424 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
426 int len, maxlen;
428 TRACE(("enter writechannel fd %d", fd))
430 maxlen = cbuf_readlen(cbuf);
432 /* Write the data out */
433 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
434 if (len <= 0) {
435 TRACE(("errno %d len %d", errno, len))
436 if (len < 0 && errno != EINTR) {
437 close_chan_fd(channel, fd, SHUT_WR);
439 TRACE(("leave writechannel: len <= 0"))
440 return;
442 TRACE(("writechannel wrote %d", len))
444 cbuf_incrread(cbuf, len);
445 channel->recvdonelen += len;
447 /* Window adjust handling */
448 if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
449 /* Set it back to max window */
450 send_msg_channel_window_adjust(channel, channel->recvdonelen);
451 channel->recvwindow += channel->recvdonelen;
452 channel->recvdonelen = 0;
455 dropbear_assert(channel->recvwindow <= opts.recv_window);
456 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
457 dropbear_assert(channel->extrabuf == NULL ||
458 channel->recvwindow <= cbuf_getavail(channel->extrabuf));
460 TRACE(("leave writechannel"))
463 /* Set the file descriptors for the main select in session.c
464 * This avoid channels which don't have any window available, are closed, etc*/
465 void setchannelfds(fd_set *readfds, fd_set *writefds) {
467 unsigned int i;
468 struct Channel * channel;
470 for (i = 0; i < ses.chansize; i++) {
472 channel = ses.channels[i];
473 if (channel == NULL) {
474 continue;
477 /* Stuff to put over the wire */
478 if (channel->transwindow > 0) {
480 if (channel->readfd >= 0) {
481 FD_SET(channel->readfd, readfds);
484 if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
485 FD_SET(channel->errfd, readfds);
489 /* Stuff from the wire */
490 if (channel->initconn
491 ||(channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0)) {
492 FD_SET(channel->writefd, writefds);
495 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
496 && cbuf_getused(channel->extrabuf) > 0) {
497 FD_SET(channel->errfd, writefds);
500 } /* foreach channel */
502 #ifdef USING_LISTENERS
503 set_listener_fds(readfds);
504 #endif
508 /* handle the channel EOF event, by closing the channel filedescriptor. The
509 * channel isn't closed yet, it is left until the incoming (from the program
510 * etc) FD is also EOF */
511 void recv_msg_channel_eof() {
513 struct Channel * channel;
515 TRACE(("enter recv_msg_channel_eof"))
517 channel = getchannel_msg("EOF");
519 channel->recv_eof = 1;
521 check_close(channel);
522 TRACE(("leave recv_msg_channel_eof"))
526 /* Handle channel closure(), respond in kind and close the channels */
527 void recv_msg_channel_close() {
529 struct Channel * channel;
531 TRACE(("enter recv_msg_channel_close"))
533 channel = getchannel_msg("Close");
535 channel->recv_eof = 1;
536 channel->recv_close = 1;
538 check_close(channel);
539 TRACE(("leave recv_msg_channel_close"))
542 /* Remove a channel entry, this is only executed after both sides have sent
543 * channel close */
544 static void remove_channel(struct Channel * channel) {
546 TRACE(("enter remove_channel"))
547 TRACE(("channel index is %d", channel->index))
549 cbuf_free(channel->writebuf);
550 channel->writebuf = NULL;
552 if (channel->extrabuf) {
553 cbuf_free(channel->extrabuf);
554 channel->extrabuf = NULL;
558 /* close the FDs in case they haven't been done
559 * yet (they might have been shutdown etc) */
560 TRACE(("CLOSE writefd %d", channel->writefd))
561 close(channel->writefd);
562 TRACE(("CLOSE readfd %d", channel->readfd))
563 close(channel->readfd);
564 TRACE(("CLOSE errfd %d", channel->errfd))
565 close(channel->errfd);
567 if (!channel->close_handler_done
568 && channel->type->closehandler) {
569 channel->type->closehandler(channel);
570 channel->close_handler_done = 1;
573 ses.channels[channel->index] = NULL;
574 m_free(channel);
575 ses.chancount--;
577 TRACE(("leave remove_channel"))
580 /* Handle channel specific requests, passing off to corresponding handlers
581 * such as chansession or x11fwd */
582 void recv_msg_channel_request() {
584 struct Channel *channel;
586 channel = getchannel();
588 TRACE(("enter recv_msg_channel_request %p", channel))
590 if (channel->sent_close) {
591 TRACE(("leave recv_msg_channel_request: already closed channel"))
592 return;
595 if (channel->type->reqhandler
596 && !channel->close_handler_done) {
597 channel->type->reqhandler(channel);
598 } else {
599 send_msg_channel_failure(channel);
602 TRACE(("leave recv_msg_channel_request"))
606 /* Reads data from the server's program/shell/etc, and puts it in a
607 * channel_data packet to send.
608 * chan is the remote channel, isextended is 0 if it is normal data, 1
609 * if it is extended data. if it is extended, then the type is in
610 * exttype */
611 static void send_msg_channel_data(struct Channel *channel, int isextended) {
613 int len;
614 size_t maxlen, size_pos;
615 int fd;
617 CHECKCLEARTOWRITE();
619 TRACE(("enter send_msg_channel_data"))
620 dropbear_assert(!channel->sent_close);
622 if (isextended) {
623 fd = channel->errfd;
624 } else {
625 fd = channel->readfd;
627 TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
628 dropbear_assert(fd >= 0);
630 maxlen = MIN(channel->transwindow, channel->transmaxpacket);
631 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
632 * exttype if is extended */
633 maxlen = MIN(maxlen,
634 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
635 TRACE(("maxlen %zd", maxlen))
636 if (maxlen == 0) {
637 TRACE(("leave send_msg_channel_data: no window"))
638 return;
641 buf_putbyte(ses.writepayload,
642 isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
643 buf_putint(ses.writepayload, channel->remotechan);
644 if (isextended) {
645 buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
647 /* a dummy size first ...*/
648 size_pos = ses.writepayload->pos;
649 buf_putint(ses.writepayload, 0);
651 /* read the data */
652 len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
654 if (len <= 0) {
655 if (len == 0 || errno != EINTR) {
656 /* This will also get hit in the case of EAGAIN. The only
657 time we expect to receive EAGAIN is when we're flushing a FD,
658 in which case it can be treated the same as EOF */
659 close_chan_fd(channel, fd, SHUT_RD);
661 buf_setpos(ses.writepayload, 0);
662 buf_setlen(ses.writepayload, 0);
663 TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
664 len, errno, fd))
665 return;
668 if (channel->read_mangler) {
669 channel->read_mangler(channel, buf_getwriteptr(ses.writepayload, len), &len);
670 if (len == 0) {
671 buf_setpos(ses.writepayload, 0);
672 buf_setlen(ses.writepayload, 0);
673 return;
677 TRACE(("send_msg_channel_data: len %d fd %d", len, fd))
678 buf_incrwritepos(ses.writepayload, len);
679 /* ... real size here */
680 buf_setpos(ses.writepayload, size_pos);
681 buf_putint(ses.writepayload, len);
683 channel->transwindow -= len;
685 encrypt_packet();
687 /* If we receive less data than we requested when flushing, we've
688 reached the equivalent of EOF */
689 if (channel->flushing && len < (ssize_t)maxlen)
691 TRACE(("closing from channel, flushing out."))
692 close_chan_fd(channel, fd, SHUT_RD);
694 TRACE(("leave send_msg_channel_data"))
697 /* We receive channel data */
698 void recv_msg_channel_data() {
700 struct Channel *channel;
702 channel = getchannel();
704 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
707 /* Shared for data and stderr data - when we receive data, put it in a buffer
708 * for writing to the local file descriptor */
709 void common_recv_msg_channel_data(struct Channel *channel, int fd,
710 circbuffer * cbuf) {
712 unsigned int datalen;
713 unsigned int maxdata;
714 unsigned int buflen;
715 unsigned int len;
717 TRACE(("enter recv_msg_channel_data"))
719 if (channel->recv_eof) {
720 dropbear_exit("Received data after eof");
723 if (fd < 0 || !cbuf) {
724 /* If we have encountered failed write, the far side might still
725 * be sending data without having yet received our close notification.
726 * We just drop the data. */
727 return;
730 datalen = buf_getint(ses.payload);
731 TRACE(("length %d", datalen))
733 maxdata = cbuf_getavail(cbuf);
735 /* Whilst the spec says we "MAY ignore data past the end" this could
736 * lead to corrupted file transfers etc (chunks missed etc). It's better to
737 * just die horribly */
738 if (datalen > maxdata) {
739 dropbear_exit("Oversized packet");
742 /* We may have to run throught twice, if the buffer wraps around. Can't
743 * just "leave it for next time" like with writechannel, since this
744 * is payload data */
745 len = datalen;
746 while (len > 0) {
747 buflen = cbuf_writelen(cbuf);
748 buflen = MIN(buflen, len);
750 memcpy(cbuf_writeptr(cbuf, buflen),
751 buf_getptr(ses.payload, buflen), buflen);
752 cbuf_incrwrite(cbuf, buflen);
753 buf_incrpos(ses.payload, buflen);
754 len -= buflen;
757 dropbear_assert(channel->recvwindow >= datalen);
758 channel->recvwindow -= datalen;
759 dropbear_assert(channel->recvwindow <= opts.recv_window);
761 TRACE(("leave recv_msg_channel_data"))
764 /* Increment the outgoing data window for a channel - the remote end limits
765 * the amount of data which may be transmitted, this window is decremented
766 * as data is sent, and incremented upon receiving window-adjust messages */
767 void recv_msg_channel_window_adjust() {
769 struct Channel * channel;
770 unsigned int incr;
772 channel = getchannel();
774 incr = buf_getint(ses.payload);
775 TRACE(("received window increment %d", incr))
776 incr = MIN(incr, TRANS_MAX_WIN_INCR);
778 channel->transwindow += incr;
779 channel->transwindow = MIN(channel->transwindow, TRANS_MAX_WINDOW);
783 /* Increment the incoming data window for a channel, and let the remote
784 * end know */
785 static void send_msg_channel_window_adjust(struct Channel* channel,
786 unsigned int incr) {
788 TRACE(("sending window adjust %d", incr))
789 CHECKCLEARTOWRITE();
791 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
792 buf_putint(ses.writepayload, channel->remotechan);
793 buf_putint(ses.writepayload, incr);
795 encrypt_packet();
798 /* Handle a new channel request, performing any channel-type-specific setup */
799 void recv_msg_channel_open() {
801 unsigned char *type;
802 unsigned int typelen;
803 unsigned int remotechan, transwindow, transmaxpacket;
804 struct Channel *channel;
805 const struct ChanType **cp;
806 const struct ChanType *chantype;
807 unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
808 int ret;
811 TRACE(("enter recv_msg_channel_open"))
813 /* get the packet contents */
814 type = buf_getstring(ses.payload, &typelen);
816 remotechan = buf_getint(ses.payload);
817 transwindow = buf_getint(ses.payload);
818 transwindow = MIN(transwindow, TRANS_MAX_WINDOW);
819 transmaxpacket = buf_getint(ses.payload);
820 transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
822 /* figure what type of packet it is */
823 if (typelen > MAX_NAME_LEN) {
824 goto failure;
827 /* Get the channel type. Client and server style invokation will set up a
828 * different list for ses.chantypes at startup. We just iterate through
829 * this list and find the matching name */
830 for (cp = &ses.chantypes[0], chantype = (*cp);
831 chantype != NULL;
832 cp++, chantype = (*cp)) {
833 if (strcmp(type, chantype->name) == 0) {
834 break;
838 if (chantype == NULL) {
839 TRACE(("No matching type for '%s'", type))
840 goto failure;
843 TRACE(("matched type '%s'", type))
845 /* create the channel */
846 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
848 if (channel == NULL) {
849 TRACE(("newchannel returned NULL"))
850 goto failure;
853 if (channel->type->inithandler) {
854 ret = channel->type->inithandler(channel);
855 if (ret == SSH_OPEN_IN_PROGRESS) {
856 /* We'll send the confirmation later */
857 goto cleanup;
859 if (ret > 0) {
860 errtype = ret;
861 remove_channel(channel);
862 TRACE(("inithandler returned failure %d", ret))
863 goto failure;
867 chan_initwritebuf(channel);
869 /* success */
870 send_msg_channel_open_confirmation(channel, channel->recvwindow,
871 channel->recvmaxpacket);
872 goto cleanup;
874 failure:
875 TRACE(("recv_msg_channel_open failure"))
876 send_msg_channel_open_failure(remotechan, errtype, "", "");
878 cleanup:
879 m_free(type);
881 TRACE(("leave recv_msg_channel_open"))
884 /* Send a failure message */
885 void send_msg_channel_failure(struct Channel *channel) {
887 TRACE(("enter send_msg_channel_failure"))
888 CHECKCLEARTOWRITE();
890 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
891 buf_putint(ses.writepayload, channel->remotechan);
893 encrypt_packet();
894 TRACE(("leave send_msg_channel_failure"))
897 /* Send a success message */
898 void send_msg_channel_success(struct Channel *channel) {
900 TRACE(("enter send_msg_channel_success"))
901 CHECKCLEARTOWRITE();
903 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
904 buf_putint(ses.writepayload, channel->remotechan);
906 encrypt_packet();
907 TRACE(("leave send_msg_channel_success"))
910 /* Send a channel open failure message, with a corresponding reason
911 * code (usually resource shortage or unknown chan type) */
912 static void send_msg_channel_open_failure(unsigned int remotechan,
913 int reason, const unsigned char *text, const unsigned char *lang) {
915 TRACE(("enter send_msg_channel_open_failure"))
916 CHECKCLEARTOWRITE();
918 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
919 buf_putint(ses.writepayload, remotechan);
920 buf_putint(ses.writepayload, reason);
921 buf_putstring(ses.writepayload, text, strlen((char*)text));
922 buf_putstring(ses.writepayload, lang, strlen((char*)lang));
924 encrypt_packet();
925 TRACE(("leave send_msg_channel_open_failure"))
928 /* Confirm a channel open, and let the remote end know what number we've
929 * allocated and the receive parameters */
930 static void send_msg_channel_open_confirmation(struct Channel* channel,
931 unsigned int recvwindow,
932 unsigned int recvmaxpacket) {
934 TRACE(("enter send_msg_channel_open_confirmation"))
935 CHECKCLEARTOWRITE();
937 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
938 buf_putint(ses.writepayload, channel->remotechan);
939 buf_putint(ses.writepayload, channel->index);
940 buf_putint(ses.writepayload, recvwindow);
941 buf_putint(ses.writepayload, recvmaxpacket);
943 encrypt_packet();
944 TRACE(("leave send_msg_channel_open_confirmation"))
947 /* close a fd, how is SHUT_RD or SHUT_WR */
948 static void close_chan_fd(struct Channel *channel, int fd, int how) {
950 int closein = 0, closeout = 0;
952 if (channel->type->sepfds) {
953 TRACE(("SHUTDOWN(%d, %d)", fd, how))
954 shutdown(fd, how);
955 if (how == 0) {
956 closeout = 1;
957 } else {
958 closein = 1;
960 } else {
961 TRACE(("CLOSE some fd %d", fd))
962 close(fd);
963 closein = closeout = 1;
966 if (closeout && (fd == channel->readfd)) {
967 channel->readfd = FD_CLOSED;
969 if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
970 channel->errfd = FD_CLOSED;
973 if (closein && fd == channel->writefd) {
974 channel->writefd = FD_CLOSED;
976 if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
977 channel->errfd = FD_CLOSED;
980 /* if we called shutdown on it and all references are gone, then we
981 * need to close() it to stop it lingering */
982 if (channel->type->sepfds && channel->readfd == FD_CLOSED
983 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
984 TRACE(("CLOSE (finally) of %d", fd))
985 close(fd);
990 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
991 /* Create a new channel, and start the open request. This is intended
992 * for X11, agent, tcp forwarding, and should be filled with channel-specific
993 * options, with the calling function calling encrypt_packet() after
994 * completion. It is mandatory for the caller to encrypt_packet() if
995 * DROPBEAR_SUCCESS is returned */
996 int send_msg_channel_open_init(int fd, const struct ChanType *type) {
998 struct Channel* chan;
1000 TRACE(("enter send_msg_channel_open_init()"))
1001 chan = newchannel(0, type, 0, 0);
1002 if (!chan) {
1003 TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
1004 return DROPBEAR_FAILURE;
1007 /* Outbound opened channels don't make use of in-progress connections,
1008 * we can set it up straight away */
1009 chan_initwritebuf(chan);
1011 /* set fd non-blocking */
1012 setnonblocking(fd);
1014 chan->writefd = chan->readfd = fd;
1015 ses.maxfd = MAX(ses.maxfd, fd);
1017 chan->await_open = 1;
1019 /* now open the channel connection */
1020 CHECKCLEARTOWRITE();
1022 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
1023 buf_putstring(ses.writepayload, type->name, strlen(type->name));
1024 buf_putint(ses.writepayload, chan->index);
1025 buf_putint(ses.writepayload, opts.recv_window);
1026 buf_putint(ses.writepayload, RECV_MAX_PAYLOAD_LEN);
1028 TRACE(("leave send_msg_channel_open_init()"))
1029 return DROPBEAR_SUCCESS;
1032 /* Confirmation that our channel open request (for forwardings) was
1033 * successful*/
1034 void recv_msg_channel_open_confirmation() {
1036 struct Channel * channel;
1037 int ret;
1039 TRACE(("enter recv_msg_channel_open_confirmation"))
1041 channel = getchannel();
1043 if (!channel->await_open) {
1044 dropbear_exit("Unexpected channel reply");
1046 channel->await_open = 0;
1048 channel->remotechan = buf_getint(ses.payload);
1049 channel->transwindow = buf_getint(ses.payload);
1050 channel->transmaxpacket = buf_getint(ses.payload);
1052 TRACE(("new chan remote %d local %d",
1053 channel->remotechan, channel->index))
1055 /* Run the inithandler callback */
1056 if (channel->type->inithandler) {
1057 ret = channel->type->inithandler(channel);
1058 if (ret > 0) {
1059 remove_channel(channel);
1060 TRACE(("inithandler returned failure %d", ret))
1065 TRACE(("leave recv_msg_channel_open_confirmation"))
1068 /* Notification that our channel open request failed */
1069 void recv_msg_channel_open_failure() {
1071 struct Channel * channel;
1073 channel = getchannel();
1075 if (!channel->await_open) {
1076 dropbear_exit("Unexpected channel reply");
1078 channel->await_open = 0;
1080 remove_channel(channel);
1082 #endif /* USING_LISTENERS */