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 "ssh.h"
36#include "listener.h"
37
38static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
39		const unsigned char *text, const unsigned char *lang);
40static void send_msg_channel_open_confirmation(struct Channel* channel,
41		unsigned int recvwindow,
42		unsigned int recvmaxpacket);
43static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
44static void send_msg_channel_window_adjust(struct Channel *channel,
45		unsigned int incr);
46static void send_msg_channel_data(struct Channel *channel, int isextended);
47static void send_msg_channel_eof(struct Channel *channel);
48static void send_msg_channel_close(struct Channel *channel);
49static void remove_channel(struct Channel *channel);
50static void delete_channel(struct Channel *channel);
51static void check_in_progress(struct Channel *channel);
52static unsigned int write_pending(struct Channel * channel);
53static void check_close(struct Channel *channel);
54static void close_chan_fd(struct Channel *channel, int fd, int how);
55
56#define FD_UNINIT (-2)
57#define FD_CLOSED (-1)
58
59#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
61
62/* Initialise all the channels */
63void chaninitialise(const struct ChanType *chantypes[]) {
64
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;
70
71	ses.chantypes = chantypes;
72
73#ifdef USING_LISTENERS
74	listeners_initialise();
75#endif
76
77}
78
79/* Clean up channels, freeing allocated memory */
80void chancleanup() {
81
82	unsigned int i;
83
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]);
89		}
90	}
91	m_free(ses.channels);
92	TRACE(("leave chancleanup"))
93}
94
95/* Create a new channel entry, send a reply confirm or failure */
96/* If remotechan, transwindow and transmaxpacket are not know (for a new
97 * outgoing connection, with them to be filled on confirmation), they should
98 * all be set to 0 */
99struct Channel* newchannel(unsigned int remotechan,
100		const struct ChanType *type,
101		unsigned int transwindow, unsigned int transmaxpacket) {
102
103	struct Channel * newchan;
104	unsigned int i, j;
105
106	TRACE(("enter newchannel"))
107
108	/* first see if we can use existing channels */
109	for (i = 0; i < ses.chansize; i++) {
110		if (ses.channels[i] == NULL) {
111			break;
112		}
113	}
114
115	/* otherwise extend the list */
116	if (i == ses.chansize) {
117		if (ses.chansize >= MAX_CHANNELS) {
118			TRACE(("leave newchannel: max chans reached"))
119			return NULL;
120		}
121
122		/* extend the channels */
123		ses.channels = (struct Channel**)m_realloc(ses.channels,
124				(ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
125
126		ses.chansize += CHAN_EXTEND_SIZE;
127
128		/* set the new channels to null */
129		for (j = i; j < ses.chansize; j++) {
130			ses.channels[j] = NULL;
131		}
132
133	}
134
135	newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
136	newchan->type = type;
137	newchan->index = i;
138	newchan->sent_close = newchan->recv_close = 0;
139	newchan->sent_eof = newchan->recv_eof = 0;
140
141	newchan->remotechan = remotechan;
142	newchan->transwindow = transwindow;
143	newchan->transmaxpacket = transmaxpacket;
144
145	newchan->typedata = NULL;
146	newchan->writefd = FD_UNINIT;
147	newchan->readfd = FD_UNINIT;
148	newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
149	newchan->initconn = 0;
150	newchan->await_open = 0;
151	newchan->flushing = 0;
152
153	newchan->writebuf = cbuf_new(RECV_MAXWINDOW);
154	newchan->extrabuf = NULL; /* The user code can set it up */
155	newchan->recvwindow = RECV_MAXWINDOW;
156	newchan->recvdonelen = 0;
157	newchan->recvmaxpacket = RECV_MAXPACKET;
158
159	ses.channels[i] = newchan;
160	ses.chancount++;
161
162	TRACE(("leave newchannel"))
163
164	return newchan;
165}
166
167/* Returns the channel structure corresponding to the channel in the current
168 * data packet (ses.payload must be positioned appropriately).
169 * A valid channel is always returns, it will fail fatally with an unknown
170 * channel */
171static struct Channel* getchannel_msg(const char* kind) {
172
173	unsigned int chan;
174
175	chan = buf_getint(ses.payload);
176	if (chan >= ses.chansize || ses.channels[chan] == NULL) {
177		if (kind) {
178			dropbear_exit("%s for unknown channel %d", kind, chan);
179		} else {
180			dropbear_exit("Unknown channel %d", chan);
181		}
182	}
183	return ses.channels[chan];
184}
185
186struct Channel* getchannel() {
187	return getchannel_msg(NULL);
188}
189
190/* Iterate through the channels, performing IO if available */
191void channelio(fd_set *readfds, fd_set *writefds) {
192
193	struct Channel *channel;
194	unsigned int i;
195
196	/* foreach channel */
197	for (i = 0; i < ses.chansize; i++) {
198
199		channel = ses.channels[i];
200		if (channel == NULL) {
201			/* only process in-use channels */
202			continue;
203		}
204
205		/* read data and send it over the wire */
206		if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
207			TRACE(("send normal readfd"))
208			send_msg_channel_data(channel, 0);
209		}
210
211		/* read stderr data and send it over the wire */
212		if (ERRFD_IS_READ(channel) && channel->errfd >= 0
213			&& FD_ISSET(channel->errfd, readfds)) {
214				TRACE(("send normal errfd"))
215				send_msg_channel_data(channel, 1);
216		}
217
218		/* write to program/pipe stdin */
219		if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
220			if (channel->initconn) {
221				/* XXX should this go somewhere cleaner? */
222				check_in_progress(channel);
223				continue; /* Important not to use the channel after
224							 check_in_progress(), as it may be NULL */
225			}
226			writechannel(channel, channel->writefd, channel->writebuf);
227		}
228
229		/* stderr for client mode */
230		if (ERRFD_IS_WRITE(channel)
231				&& channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
232			writechannel(channel, channel->errfd, channel->extrabuf);
233		}
234
235		/* handle any channel closing etc */
236		check_close(channel);
237
238	}
239
240	/* Listeners such as TCP, X11, agent-auth */
241#ifdef USING_LISTENERS
242	handle_listeners(readfds);
243#endif
244}
245
246
247/* Returns true if there is data remaining to be written to stdin or
248 * stderr of a channel's endpoint. */
249static unsigned int write_pending(struct Channel * channel) {
250
251	if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
252		return 1;
253	} else if (channel->errfd >= 0 && channel->extrabuf &&
254			cbuf_getused(channel->extrabuf) > 0) {
255		return 1;
256	}
257	return 0;
258}
259
260
261/* EOF/close handling */
262static void check_close(struct Channel *channel) {
263
264	TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
265				channel->writefd, channel->readfd,
266				channel->errfd, channel->sent_close, channel->recv_close))
267	TRACE(("writebuf size %d extrabuf size %d",
268				cbuf_getused(channel->writebuf),
269				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
270
271	if (!channel->flushing && channel->type->check_close
272		&& channel->type->check_close(channel))
273	{
274		channel->flushing = 1;
275	}
276
277	if (channel->recv_close && !write_pending(channel)) {
278		if (!channel->sent_close) {
279			TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
280			send_msg_channel_close(channel);
281		}
282		remove_channel(channel);
283		return;
284	}
285
286	if (channel->recv_eof && !write_pending(channel)) {
287		close_chan_fd(channel, channel->writefd, SHUT_WR);
288	}
289
290	/* Special handling for flushing read data after an exit. We
291	   read regardless of whether the select FD was set,
292	   and if there isn't data available, the channel will get closed. */
293	if (channel->flushing) {
294		TRACE(("might send data, flushing"))
295		if (channel->readfd >= 0 && channel->transwindow > 0) {
296			TRACE(("send data readfd"))
297			send_msg_channel_data(channel, 0);
298		}
299		if (ERRFD_IS_READ(channel) && channel->errfd >= 0
300			&& channel->transwindow > 0) {
301			TRACE(("send data errfd"))
302			send_msg_channel_data(channel, 1);
303		}
304	}
305
306	/* If we're not going to send any more data, send EOF */
307	if (!channel->sent_eof
308			&& channel->readfd == FD_CLOSED
309			&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
310		send_msg_channel_eof(channel);
311	}
312
313	/* And if we can't receive any more data from them either, close up */
314	if (!channel->sent_close
315			&& channel->readfd == FD_CLOSED
316			&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
317			&& !write_pending(channel)) {
318		TRACE(("sending close, readfd is closed"))
319		send_msg_channel_close(channel);
320	}
321}
322
323/* Check whether a deferred (EINPROGRESS) connect() was successful, and
324 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
325 * it is important that the channel reference isn't used after a call to this
326 * function */
327static void check_in_progress(struct Channel *channel) {
328
329	int val;
330	socklen_t vallen = sizeof(val);
331
332	TRACE(("enter check_in_progress"))
333
334	if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
335			|| val != 0) {
336		send_msg_channel_open_failure(channel->remotechan,
337				SSH_OPEN_CONNECT_FAILED, "", "");
338		close(channel->writefd);
339		delete_channel(channel);
340		TRACE(("leave check_in_progress: fail"))
341	} else {
342		send_msg_channel_open_confirmation(channel, channel->recvwindow,
343				channel->recvmaxpacket);
344		channel->readfd = channel->writefd;
345		channel->initconn = 0;
346		TRACE(("leave check_in_progress: success"))
347	}
348}
349
350
351/* Send the close message and set the channel as closed */
352static void send_msg_channel_close(struct Channel *channel) {
353
354	TRACE(("enter send_msg_channel_close"))
355	if (channel->type->closehandler) {
356		channel->type->closehandler(channel);
357	}
358
359	CHECKCLEARTOWRITE();
360
361	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
362	buf_putint(ses.writepayload, channel->remotechan);
363
364	encrypt_packet();
365
366	channel->sent_eof = 1;
367	channel->sent_close = 1;
368	close_chan_fd(channel, channel->readfd, SHUT_RD);
369	close_chan_fd(channel, channel->errfd, SHUT_RDWR);
370	close_chan_fd(channel, channel->writefd, SHUT_WR);
371	TRACE(("leave send_msg_channel_close"))
372}
373
374/* call this when trans/eof channels are closed */
375static void send_msg_channel_eof(struct Channel *channel) {
376
377	TRACE(("enter send_msg_channel_eof"))
378	CHECKCLEARTOWRITE();
379
380	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
381	buf_putint(ses.writepayload, channel->remotechan);
382
383	encrypt_packet();
384
385	channel->sent_eof = 1;
386
387	TRACE(("leave send_msg_channel_eof"))
388}
389
390/* Called to write data out to the local side of the channel.
391 * Only called when we know we can write to a channel, writes as much as
392 * possible */
393static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
394
395	int len, maxlen;
396
397	TRACE(("enter writechannel fd %d", fd))
398
399	maxlen = cbuf_readlen(cbuf);
400
401	/* Write the data out */
402	len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
403	if (len <= 0) {
404		TRACE(("errno %d len %d", errno, len))
405		if (len < 0 && errno != EINTR) {
406			close_chan_fd(channel, fd, SHUT_WR);
407		}
408		TRACE(("leave writechannel: len <= 0"))
409		return;
410	}
411	TRACE(("writechannel wrote %d", len))
412
413	cbuf_incrread(cbuf, len);
414	channel->recvdonelen += len;
415
416	/* Window adjust handling */
417	if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
418		/* Set it back to max window */
419		send_msg_channel_window_adjust(channel, channel->recvdonelen);
420		channel->recvwindow += channel->recvdonelen;
421		channel->recvdonelen = 0;
422	}
423
424	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
425	dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
426	dropbear_assert(channel->extrabuf == NULL ||
427			channel->recvwindow <= cbuf_getavail(channel->extrabuf));
428
429	TRACE(("leave writechannel"))
430}
431
432/* Set the file descriptors for the main select in session.c
433 * This avoid channels which don't have any window available, are closed, etc*/
434void setchannelfds(fd_set *readfds, fd_set *writefds) {
435
436	unsigned int i;
437	struct Channel * channel;
438
439	for (i = 0; i < ses.chansize; i++) {
440
441		channel = ses.channels[i];
442		if (channel == NULL) {
443			continue;
444		}
445
446		/* Stuff to put over the wire */
447		if (channel->transwindow > 0) {
448
449			if (channel->readfd >= 0) {
450				FD_SET(channel->readfd, readfds);
451			}
452
453			if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
454					FD_SET(channel->errfd, readfds);
455			}
456		}
457
458		/* Stuff from the wire */
459		if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
460				|| channel->initconn) {
461				FD_SET(channel->writefd, writefds);
462		}
463
464		if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
465				&& cbuf_getused(channel->extrabuf) > 0 ) {
466				FD_SET(channel->errfd, writefds);
467		}
468
469	} /* foreach channel */
470
471#ifdef USING_LISTENERS
472	set_listener_fds(readfds);
473#endif
474
475}
476
477/* handle the channel EOF event, by closing the channel filedescriptor. The
478 * channel isn't closed yet, it is left until the incoming (from the program
479 * etc) FD is also EOF */
480void recv_msg_channel_eof() {
481
482	struct Channel * channel;
483
484	TRACE(("enter recv_msg_channel_eof"))
485
486	channel = getchannel_msg("EOF");
487
488	channel->recv_eof = 1;
489
490	check_close(channel);
491	TRACE(("leave recv_msg_channel_eof"))
492}
493
494
495/* Handle channel closure(), respond in kind and close the channels */
496void recv_msg_channel_close() {
497
498	struct Channel * channel;
499
500	TRACE(("enter recv_msg_channel_close"))
501
502	channel = getchannel_msg("Close");
503
504	channel->recv_eof = 1;
505	channel->recv_close = 1;
506
507	check_close(channel);
508	TRACE(("leave recv_msg_channel_close"))
509}
510
511/* Remove a channel entry, this is only executed after both sides have sent
512 * channel close */
513static void remove_channel(struct Channel * channel) {
514
515	TRACE(("enter remove_channel"))
516	TRACE(("channel index is %d", channel->index))
517
518	cbuf_free(channel->writebuf);
519	channel->writebuf = NULL;
520
521	if (channel->extrabuf) {
522		cbuf_free(channel->extrabuf);
523		channel->extrabuf = NULL;
524	}
525
526
527	/* close the FDs in case they haven't been done
528	 * yet (they might have been shutdown etc) */
529	TRACE(("CLOSE writefd %d", channel->writefd))
530	close(channel->writefd);
531	TRACE(("CLOSE readfd %d", channel->readfd))
532	close(channel->readfd);
533	TRACE(("CLOSE errfd %d", channel->errfd))
534	close(channel->errfd);
535
536	channel->typedata = NULL;
537
538	delete_channel(channel);
539
540	TRACE(("leave remove_channel"))
541}
542
543/* Remove a channel entry */
544static void delete_channel(struct Channel *channel) {
545
546	ses.channels[channel->index] = NULL;
547	m_free(channel);
548	ses.chancount--;
549
550}
551
552
553/* Handle channel specific requests, passing off to corresponding handlers
554 * such as chansession or x11fwd */
555void recv_msg_channel_request() {
556
557	struct Channel *channel;
558
559	TRACE(("enter recv_msg_channel_request"))
560
561	channel = getchannel();
562
563	if (channel->type->reqhandler) {
564		channel->type->reqhandler(channel);
565	} else {
566		send_msg_channel_failure(channel);
567	}
568
569	TRACE(("leave recv_msg_channel_request"))
570
571}
572
573/* Reads data from the server's program/shell/etc, and puts it in a
574 * channel_data packet to send.
575 * chan is the remote channel, isextended is 0 if it is normal data, 1
576 * if it is extended data. if it is extended, then the type is in
577 * exttype */
578static void send_msg_channel_data(struct Channel *channel, int isextended) {
579
580	int len;
581	size_t maxlen, size_pos;
582	int fd;
583
584	CHECKCLEARTOWRITE();
585
586	TRACE(("enter send_msg_channel_data"))
587	dropbear_assert(!channel->sent_close);
588
589	if (isextended) {
590		fd = channel->errfd;
591	} else {
592		fd = channel->readfd;
593	}
594	TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
595	dropbear_assert(fd >= 0);
596
597	maxlen = MIN(channel->transwindow, channel->transmaxpacket);
598	/* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
599	 * exttype if is extended */
600	maxlen = MIN(maxlen,
601			ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
602	TRACE(("maxlen %d", maxlen))
603	if (maxlen == 0) {
604		TRACE(("leave send_msg_channel_data: no window"))
605		return;
606	}
607
608	buf_putbyte(ses.writepayload,
609			isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
610	buf_putint(ses.writepayload, channel->remotechan);
611	if (isextended) {
612		buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
613	}
614	/* a dummy size first ...*/
615	size_pos = ses.writepayload->pos;
616	buf_putint(ses.writepayload, 0);
617
618	/* read the data */
619	len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
620	if (len <= 0) {
621		if (len == 0 || errno != EINTR) {
622			/* This will also get hit in the case of EAGAIN. The only
623			time we expect to receive EAGAIN is when we're flushing a FD,
624			in which case it can be treated the same as EOF */
625			close_chan_fd(channel, fd, SHUT_RD);
626		}
627		ses.writepayload->len = ses.writepayload->pos = 0;
628		TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
629					len, errno, fd))
630		return;
631	}
632	buf_incrwritepos(ses.writepayload, len);
633	/* ... real size here */
634	buf_setpos(ses.writepayload, size_pos);
635	buf_putint(ses.writepayload, len);
636
637	channel->transwindow -= len;
638
639	encrypt_packet();
640
641	/* If we receive less data than we requested when flushing, we've
642	   reached the equivalent of EOF */
643	if (channel->flushing && len < (ssize_t)maxlen)
644	{
645		TRACE(("closing from channel, flushing out."))
646		close_chan_fd(channel, fd, SHUT_RD);
647	}
648	TRACE(("leave send_msg_channel_data"))
649}
650
651/* We receive channel data */
652void recv_msg_channel_data() {
653
654	struct Channel *channel;
655
656	channel = getchannel();
657
658	common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
659}
660
661/* Shared for data and stderr data - when we receive data, put it in a buffer
662 * for writing to the local file descriptor */
663void common_recv_msg_channel_data(struct Channel *channel, int fd,
664		circbuffer * cbuf) {
665
666	unsigned int datalen;
667	unsigned int maxdata;
668	unsigned int buflen;
669	unsigned int len;
670
671	TRACE(("enter recv_msg_channel_data"))
672
673	if (channel->recv_eof) {
674		dropbear_exit("received data after eof");
675	}
676
677 	if (fd < 0) {
678		/* If we have encountered failed write, the far side might still
679		 * be sending data without having yet received our close notification.
680		 * We just drop the data. */
681		return;
682	}
683
684	datalen = buf_getint(ses.payload);
685	TRACE(("length %d", datalen))
686
687	maxdata = cbuf_getavail(cbuf);
688
689	/* Whilst the spec says we "MAY ignore data past the end" this could
690	 * lead to corrupted file transfers etc (chunks missed etc). It's better to
691	 * just die horribly */
692	if (datalen > maxdata) {
693		dropbear_exit("Oversized packet");
694	}
695
696	/* We may have to run throught twice, if the buffer wraps around. Can't
697	 * just "leave it for next time" like with writechannel, since this
698	 * is payload data */
699	len = datalen;
700	while (len > 0) {
701		buflen = cbuf_writelen(cbuf);
702		buflen = MIN(buflen, len);
703
704		memcpy(cbuf_writeptr(cbuf, buflen),
705				buf_getptr(ses.payload, buflen), buflen);
706		cbuf_incrwrite(cbuf, buflen);
707		buf_incrpos(ses.payload, buflen);
708		len -= buflen;
709	}
710
711	dropbear_assert(channel->recvwindow >= datalen);
712	channel->recvwindow -= datalen;
713	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
714
715	TRACE(("leave recv_msg_channel_data"))
716}
717
718/* Increment the outgoing data window for a channel - the remote end limits
719 * the amount of data which may be transmitted, this window is decremented
720 * as data is sent, and incremented upon receiving window-adjust messages */
721void recv_msg_channel_window_adjust() {
722
723	struct Channel * channel;
724	unsigned int incr;
725
726	channel = getchannel();
727
728	incr = buf_getint(ses.payload);
729	TRACE(("received window increment %d", incr))
730	incr = MIN(incr, MAX_TRANS_WIN_INCR);
731
732	channel->transwindow += incr;
733	channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW);
734
735}
736
737/* Increment the incoming data window for a channel, and let the remote
738 * end know */
739static void send_msg_channel_window_adjust(struct Channel* channel,
740		unsigned int incr) {
741
742	TRACE(("sending window adjust %d", incr))
743	CHECKCLEARTOWRITE();
744
745	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
746	buf_putint(ses.writepayload, channel->remotechan);
747	buf_putint(ses.writepayload, incr);
748
749	encrypt_packet();
750}
751
752/* Handle a new channel request, performing any channel-type-specific setup */
753void recv_msg_channel_open() {
754
755	unsigned char *type;
756	unsigned int typelen;
757	unsigned int remotechan, transwindow, transmaxpacket;
758	struct Channel *channel;
759	const struct ChanType **cp;
760	const struct ChanType *chantype;
761	unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
762	int ret;
763
764
765	TRACE(("enter recv_msg_channel_open"))
766
767	/* get the packet contents */
768	type = buf_getstring(ses.payload, &typelen);
769
770	remotechan = buf_getint(ses.payload);
771	transwindow = buf_getint(ses.payload);
772	transwindow = MIN(transwindow, MAX_TRANS_WINDOW);
773	transmaxpacket = buf_getint(ses.payload);
774	transmaxpacket = MIN(transmaxpacket, MAX_TRANS_PAYLOAD_LEN);
775
776	/* figure what type of packet it is */
777	if (typelen > MAX_NAME_LEN) {
778		goto failure;
779	}
780
781	/* Get the channel type. Client and server style invokation will set up a
782	 * different list for ses.chantypes at startup. We just iterate through
783	 * this list and find the matching name */
784	for (cp = &ses.chantypes[0], chantype = (*cp);
785			chantype != NULL;
786			cp++, chantype = (*cp)) {
787		if (strcmp(type, chantype->name) == 0) {
788			break;
789		}
790	}
791
792	if (chantype == NULL) {
793		TRACE(("No matching type for '%s'", type))
794		goto failure;
795	}
796
797	TRACE(("matched type '%s'", type))
798
799	/* create the channel */
800	channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
801
802	if (channel == NULL) {
803		TRACE(("newchannel returned NULL"))
804		goto failure;
805	}
806
807	if (channel->type->inithandler) {
808		ret = channel->type->inithandler(channel);
809		if (ret == SSH_OPEN_IN_PROGRESS) {
810			/* We'll send the confirmation later */
811			goto cleanup;
812		}
813		if (ret > 0) {
814			errtype = ret;
815			delete_channel(channel);
816			TRACE(("inithandler returned failure %d", ret))
817			goto failure;
818		}
819	}
820
821	/* success */
822	send_msg_channel_open_confirmation(channel, channel->recvwindow,
823			channel->recvmaxpacket);
824	goto cleanup;
825
826failure:
827	TRACE(("recv_msg_channel_open failure"))
828	send_msg_channel_open_failure(remotechan, errtype, "", "");
829
830cleanup:
831	m_free(type);
832
833	TRACE(("leave recv_msg_channel_open"))
834}
835
836/* Send a failure message */
837void send_msg_channel_failure(struct Channel *channel) {
838
839	TRACE(("enter send_msg_channel_failure"))
840	CHECKCLEARTOWRITE();
841
842	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
843	buf_putint(ses.writepayload, channel->remotechan);
844
845	encrypt_packet();
846	TRACE(("leave send_msg_channel_failure"))
847}
848
849/* Send a success message */
850void send_msg_channel_success(struct Channel *channel) {
851
852	TRACE(("enter send_msg_channel_success"))
853	CHECKCLEARTOWRITE();
854
855	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
856	buf_putint(ses.writepayload, channel->remotechan);
857
858	encrypt_packet();
859	TRACE(("leave send_msg_channel_success"))
860}
861
862/* Send a channel open failure message, with a corresponding reason
863 * code (usually resource shortage or unknown chan type) */
864static void send_msg_channel_open_failure(unsigned int remotechan,
865		int reason, const unsigned char *text, const unsigned char *lang) {
866
867	TRACE(("enter send_msg_channel_open_failure"))
868	CHECKCLEARTOWRITE();
869
870	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
871	buf_putint(ses.writepayload, remotechan);
872	buf_putint(ses.writepayload, reason);
873	buf_putstring(ses.writepayload, text, strlen((char*)text));
874	buf_putstring(ses.writepayload, lang, strlen((char*)lang));
875
876	encrypt_packet();
877	TRACE(("leave send_msg_channel_open_failure"))
878}
879
880/* Confirm a channel open, and let the remote end know what number we've
881 * allocated and the receive parameters */
882static void send_msg_channel_open_confirmation(struct Channel* channel,
883		unsigned int recvwindow,
884		unsigned int recvmaxpacket) {
885
886	TRACE(("enter send_msg_channel_open_confirmation"))
887	CHECKCLEARTOWRITE();
888
889	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
890	buf_putint(ses.writepayload, channel->remotechan);
891	buf_putint(ses.writepayload, channel->index);
892	buf_putint(ses.writepayload, recvwindow);
893	buf_putint(ses.writepayload, recvmaxpacket);
894
895	encrypt_packet();
896	TRACE(("leave send_msg_channel_open_confirmation"))
897}
898
899/* close a fd, how is SHUT_RD or SHUT_WR */
900static void close_chan_fd(struct Channel *channel, int fd, int how) {
901
902	int closein = 0, closeout = 0;
903
904	if (channel->type->sepfds) {
905		TRACE(("SHUTDOWN(%d, %d)", fd, how))
906		shutdown(fd, how);
907		if (how == 0) {
908			closeout = 1;
909		} else {
910			closein = 1;
911		}
912	} else {
913		TRACE(("CLOSE some fd %d", fd))
914		close(fd);
915		closein = closeout = 1;
916	}
917
918	if (closeout && (fd == channel->readfd)) {
919		channel->readfd = FD_CLOSED;
920	}
921	if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
922		channel->errfd = FD_CLOSED;
923	}
924
925	if (closein && fd == channel->writefd) {
926		channel->writefd = FD_CLOSED;
927	}
928	if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
929		channel->errfd = FD_CLOSED;
930	}
931
932	/* if we called shutdown on it and all references are gone, then we
933	 * need to close() it to stop it lingering */
934	if (channel->type->sepfds && channel->readfd == FD_CLOSED
935		&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
936		TRACE(("CLOSE (finally) of %d", fd))
937		close(fd);
938	}
939}
940
941
942#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
943/* Create a new channel, and start the open request. This is intended
944 * for X11, agent, tcp forwarding, and should be filled with channel-specific
945 * options, with the calling function calling encrypt_packet() after
946 * completion. It is mandatory for the caller to encrypt_packet() if
947 * DROPBEAR_SUCCESS is returned */
948int send_msg_channel_open_init(int fd, const struct ChanType *type) {
949
950	struct Channel* chan;
951
952	TRACE(("enter send_msg_channel_open_init()"))
953	chan = newchannel(0, type, 0, 0);
954	if (!chan) {
955		TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
956		return DROPBEAR_FAILURE;
957	}
958
959	/* set fd non-blocking */
960	setnonblocking(fd);
961
962	chan->writefd = chan->readfd = fd;
963	ses.maxfd = MAX(ses.maxfd, fd);
964
965	chan->await_open = 1;
966
967	/* now open the channel connection */
968	CHECKCLEARTOWRITE();
969
970	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
971	buf_putstring(ses.writepayload, type->name, strlen(type->name));
972	buf_putint(ses.writepayload, chan->index);
973	buf_putint(ses.writepayload, RECV_MAXWINDOW);
974	buf_putint(ses.writepayload, RECV_MAXPACKET);
975
976	TRACE(("leave send_msg_channel_open_init()"))
977	return DROPBEAR_SUCCESS;
978}
979
980/* Confirmation that our channel open request (for forwardings) was
981 * successful*/
982void recv_msg_channel_open_confirmation() {
983
984	struct Channel * channel;
985	int ret;
986
987	TRACE(("enter recv_msg_channel_open_confirmation"))
988
989	channel = getchannel();
990
991	if (!channel->await_open) {
992		dropbear_exit("unexpected channel reply");
993	}
994	channel->await_open = 0;
995
996	channel->remotechan =  buf_getint(ses.payload);
997	channel->transwindow = buf_getint(ses.payload);
998	channel->transmaxpacket = buf_getint(ses.payload);
999
1000	TRACE(("new chan remote %d local %d",
1001				channel->remotechan, channel->index))
1002
1003	/* Run the inithandler callback */
1004	if (channel->type->inithandler) {
1005		ret = channel->type->inithandler(channel);
1006		if (ret > 0) {
1007			remove_channel(channel);
1008			TRACE(("inithandler returned failure %d", ret))
1009		}
1010	}
1011
1012
1013	TRACE(("leave recv_msg_channel_open_confirmation"))
1014}
1015
1016/* Notification that our channel open request failed */
1017void recv_msg_channel_open_failure() {
1018
1019	struct Channel * channel;
1020
1021	channel = getchannel();
1022
1023	if (!channel->await_open) {
1024		dropbear_exit("unexpected channel reply");
1025	}
1026	channel->await_open = 0;
1027
1028	remove_channel(channel);
1029}
1030#endif /* USING_LISTENERS */
1031