nchan.c revision 1.1
1/*	$NetBSD: nchan.c,v 1.1 2009/06/07 22:19:14 christos Exp $	*/
2/* $OpenBSD: nchan.c,v 1.62 2008/11/07 18:50:18 stevesk Exp $ */
3/*
4 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/queue.h>
30
31#include <errno.h>
32#include <string.h>
33#include <stdarg.h>
34
35#include "ssh1.h"
36#include "ssh2.h"
37#include "buffer.h"
38#include "packet.h"
39#include "channels.h"
40#include "compat.h"
41#include "log.h"
42
43/*
44 * SSH Protocol 1.5 aka New Channel Protocol
45 * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
46 * Written by Markus Friedl in October 1999
47 *
48 * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
49 * tear down of channels:
50 *
51 * 1.3:	strict request-ack-protocol:
52 *	CLOSE	->
53 *		<-  CLOSE_CONFIRM
54 *
55 * 1.5:	uses variations of:
56 *	IEOF	->
57 *		<-  OCLOSE
58 *		<-  IEOF
59 *	OCLOSE	->
60 *	i.e. both sides have to close the channel
61 *
62 * 2.0: the EOF messages are optional
63 *
64 * See the debugging output from 'ssh -v' and 'sshd -d' of
65 * ssh-1.2.27 as an example.
66 *
67 */
68
69/* functions manipulating channel states */
70/*
71 * EVENTS update channel input/output states execute ACTIONS
72 */
73/*
74 * ACTIONS: should never update the channel states
75 */
76static void	chan_send_ieof1(Channel *);
77static void	chan_send_oclose1(Channel *);
78static void	chan_send_close2(Channel *);
79static void	chan_send_eof2(Channel *);
80static void	chan_send_eow2(Channel *);
81
82/* helper */
83static void	chan_shutdown_write(Channel *);
84static void	chan_shutdown_read(Channel *);
85
86static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
87static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
88
89static void
90chan_set_istate(Channel *c, u_int next)
91{
92	if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
93		fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
94	debug2("channel %d: input %s -> %s", c->self, istates[c->istate],
95	    istates[next]);
96	c->istate = next;
97}
98static void
99chan_set_ostate(Channel *c, u_int next)
100{
101	if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
102		fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
103	debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate],
104	    ostates[next]);
105	c->ostate = next;
106}
107
108/*
109 * SSH1 specific implementation of event functions
110 */
111
112static void
113chan_rcvd_oclose1(Channel *c)
114{
115	debug2("channel %d: rcvd oclose", c->self);
116	switch (c->istate) {
117	case CHAN_INPUT_WAIT_OCLOSE:
118		chan_set_istate(c, CHAN_INPUT_CLOSED);
119		break;
120	case CHAN_INPUT_OPEN:
121		chan_shutdown_read(c);
122		chan_send_ieof1(c);
123		chan_set_istate(c, CHAN_INPUT_CLOSED);
124		break;
125	case CHAN_INPUT_WAIT_DRAIN:
126		/* both local read_failed and remote write_failed  */
127		chan_send_ieof1(c);
128		chan_set_istate(c, CHAN_INPUT_CLOSED);
129		break;
130	default:
131		error("channel %d: protocol error: rcvd_oclose for istate %d",
132		    c->self, c->istate);
133		return;
134	}
135}
136void
137chan_read_failed(Channel *c)
138{
139	debug2("channel %d: read failed", c->self);
140	switch (c->istate) {
141	case CHAN_INPUT_OPEN:
142		chan_shutdown_read(c);
143		chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
144		break;
145	default:
146		error("channel %d: chan_read_failed for istate %d",
147		    c->self, c->istate);
148		break;
149	}
150}
151void
152chan_ibuf_empty(Channel *c)
153{
154	debug2("channel %d: ibuf empty", c->self);
155	if (buffer_len(&c->input)) {
156		error("channel %d: chan_ibuf_empty for non empty buffer",
157		    c->self);
158		return;
159	}
160	switch (c->istate) {
161	case CHAN_INPUT_WAIT_DRAIN:
162		if (compat20) {
163			if (!(c->flags & CHAN_CLOSE_SENT))
164				chan_send_eof2(c);
165			chan_set_istate(c, CHAN_INPUT_CLOSED);
166		} else {
167			chan_send_ieof1(c);
168			chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
169		}
170		break;
171	default:
172		error("channel %d: chan_ibuf_empty for istate %d",
173		    c->self, c->istate);
174		break;
175	}
176}
177static void
178chan_rcvd_ieof1(Channel *c)
179{
180	debug2("channel %d: rcvd ieof", c->self);
181	switch (c->ostate) {
182	case CHAN_OUTPUT_OPEN:
183		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
184		break;
185	case CHAN_OUTPUT_WAIT_IEOF:
186		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
187		break;
188	default:
189		error("channel %d: protocol error: rcvd_ieof for ostate %d",
190		    c->self, c->ostate);
191		break;
192	}
193}
194static void
195chan_write_failed1(Channel *c)
196{
197	debug2("channel %d: write failed", c->self);
198	switch (c->ostate) {
199	case CHAN_OUTPUT_OPEN:
200		chan_shutdown_write(c);
201		chan_send_oclose1(c);
202		chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
203		break;
204	case CHAN_OUTPUT_WAIT_DRAIN:
205		chan_shutdown_write(c);
206		chan_send_oclose1(c);
207		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
208		break;
209	default:
210		error("channel %d: chan_write_failed for ostate %d",
211		    c->self, c->ostate);
212		break;
213	}
214}
215void
216chan_obuf_empty(Channel *c)
217{
218	debug2("channel %d: obuf empty", c->self);
219	if (buffer_len(&c->output)) {
220		error("channel %d: chan_obuf_empty for non empty buffer",
221		    c->self);
222		return;
223	}
224	switch (c->ostate) {
225	case CHAN_OUTPUT_WAIT_DRAIN:
226		chan_shutdown_write(c);
227		if (!compat20)
228			chan_send_oclose1(c);
229		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
230		break;
231	default:
232		error("channel %d: internal error: obuf_empty for ostate %d",
233		    c->self, c->ostate);
234		break;
235	}
236}
237static void
238chan_send_ieof1(Channel *c)
239{
240	debug2("channel %d: send ieof", c->self);
241	switch (c->istate) {
242	case CHAN_INPUT_OPEN:
243	case CHAN_INPUT_WAIT_DRAIN:
244		packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
245		packet_put_int(c->remote_id);
246		packet_send();
247		break;
248	default:
249		error("channel %d: cannot send ieof for istate %d",
250		    c->self, c->istate);
251		break;
252	}
253}
254static void
255chan_send_oclose1(Channel *c)
256{
257	debug2("channel %d: send oclose", c->self);
258	switch (c->ostate) {
259	case CHAN_OUTPUT_OPEN:
260	case CHAN_OUTPUT_WAIT_DRAIN:
261		buffer_clear(&c->output);
262		packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
263		packet_put_int(c->remote_id);
264		packet_send();
265		break;
266	default:
267		error("channel %d: cannot send oclose for ostate %d",
268		    c->self, c->ostate);
269		break;
270	}
271}
272
273/*
274 * the same for SSH2
275 */
276static void
277chan_rcvd_close2(Channel *c)
278{
279	debug2("channel %d: rcvd close", c->self);
280	if (c->flags & CHAN_CLOSE_RCVD)
281		error("channel %d: protocol error: close rcvd twice", c->self);
282	c->flags |= CHAN_CLOSE_RCVD;
283	if (c->type == SSH_CHANNEL_LARVAL) {
284		/* tear down larval channels immediately */
285		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
286		chan_set_istate(c, CHAN_INPUT_CLOSED);
287		return;
288	}
289	switch (c->ostate) {
290	case CHAN_OUTPUT_OPEN:
291		/*
292		 * wait until a data from the channel is consumed if a CLOSE
293		 * is received
294		 */
295		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
296		break;
297	}
298	switch (c->istate) {
299	case CHAN_INPUT_OPEN:
300		chan_shutdown_read(c);
301		chan_set_istate(c, CHAN_INPUT_CLOSED);
302		break;
303	case CHAN_INPUT_WAIT_DRAIN:
304		chan_send_eof2(c);
305		chan_set_istate(c, CHAN_INPUT_CLOSED);
306		break;
307	}
308}
309void
310chan_rcvd_eow(Channel *c)
311{
312	debug2("channel %d: rcvd eow", c->self);
313	switch (c->istate) {
314	case CHAN_INPUT_OPEN:
315		chan_shutdown_read(c);
316		chan_set_istate(c, CHAN_INPUT_CLOSED);
317		break;
318	}
319}
320static void
321chan_rcvd_eof2(Channel *c)
322{
323	debug2("channel %d: rcvd eof", c->self);
324	c->flags |= CHAN_EOF_RCVD;
325	if (c->ostate == CHAN_OUTPUT_OPEN)
326		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
327}
328static void
329chan_write_failed2(Channel *c)
330{
331	debug2("channel %d: write failed", c->self);
332	switch (c->ostate) {
333	case CHAN_OUTPUT_OPEN:
334	case CHAN_OUTPUT_WAIT_DRAIN:
335		chan_shutdown_write(c);
336		if (strcmp(c->ctype, "session") == 0)
337			chan_send_eow2(c);
338		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
339		break;
340	default:
341		error("channel %d: chan_write_failed for ostate %d",
342		    c->self, c->ostate);
343		break;
344	}
345}
346static void
347chan_send_eof2(Channel *c)
348{
349	debug2("channel %d: send eof", c->self);
350	switch (c->istate) {
351	case CHAN_INPUT_WAIT_DRAIN:
352		packet_start(SSH2_MSG_CHANNEL_EOF);
353		packet_put_int(c->remote_id);
354		packet_send();
355		c->flags |= CHAN_EOF_SENT;
356		break;
357	default:
358		error("channel %d: cannot send eof for istate %d",
359		    c->self, c->istate);
360		break;
361	}
362}
363static void
364chan_send_close2(Channel *c)
365{
366	debug2("channel %d: send close", c->self);
367	if (c->ostate != CHAN_OUTPUT_CLOSED ||
368	    c->istate != CHAN_INPUT_CLOSED) {
369		error("channel %d: cannot send close for istate/ostate %d/%d",
370		    c->self, c->istate, c->ostate);
371	} else if (c->flags & CHAN_CLOSE_SENT) {
372		error("channel %d: already sent close", c->self);
373	} else {
374		packet_start(SSH2_MSG_CHANNEL_CLOSE);
375		packet_put_int(c->remote_id);
376		packet_send();
377		c->flags |= CHAN_CLOSE_SENT;
378	}
379}
380static void
381chan_send_eow2(Channel *c)
382{
383	debug2("channel %d: send eow", c->self);
384	if (c->ostate == CHAN_OUTPUT_CLOSED) {
385		error("channel %d: must not sent eow on closed output",
386		    c->self);
387		return;
388	}
389	if (!(datafellows & SSH_NEW_OPENSSH))
390		return;
391	packet_start(SSH2_MSG_CHANNEL_REQUEST);
392	packet_put_int(c->remote_id);
393	packet_put_cstring("eow@openssh.com");
394	packet_put_char(0);
395	packet_send();
396}
397
398/* shared */
399
400void
401chan_rcvd_ieof(Channel *c)
402{
403	if (compat20)
404		chan_rcvd_eof2(c);
405	else
406		chan_rcvd_ieof1(c);
407	if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
408	    buffer_len(&c->output) == 0 &&
409	    !CHANNEL_EFD_OUTPUT_ACTIVE(c))
410		chan_obuf_empty(c);
411}
412void
413chan_rcvd_oclose(Channel *c)
414{
415	if (compat20)
416		chan_rcvd_close2(c);
417	else
418		chan_rcvd_oclose1(c);
419}
420void
421chan_write_failed(Channel *c)
422{
423	if (compat20)
424		chan_write_failed2(c);
425	else
426		chan_write_failed1(c);
427}
428
429void
430chan_mark_dead(Channel *c)
431{
432	c->type = SSH_CHANNEL_ZOMBIE;
433}
434
435int
436chan_is_dead(Channel *c, int do_send)
437{
438	if (c->type == SSH_CHANNEL_ZOMBIE) {
439		debug2("channel %d: zombie", c->self);
440		return 1;
441	}
442	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
443		return 0;
444	if (!compat20) {
445		debug2("channel %d: is dead", c->self);
446		return 1;
447	}
448	if ((datafellows & SSH_BUG_EXTEOF) &&
449	    c->extended_usage == CHAN_EXTENDED_WRITE &&
450	    c->efd != -1 &&
451	    buffer_len(&c->extended) > 0) {
452		debug2("channel %d: active efd: %d len %d",
453		    c->self, c->efd, buffer_len(&c->extended));
454		return 0;
455	}
456	if (!(c->flags & CHAN_CLOSE_SENT)) {
457		if (do_send) {
458			chan_send_close2(c);
459		} else {
460			/* channel would be dead if we sent a close */
461			if (c->flags & CHAN_CLOSE_RCVD) {
462				debug2("channel %d: almost dead",
463				    c->self);
464				return 1;
465			}
466		}
467	}
468	if ((c->flags & CHAN_CLOSE_SENT) &&
469	    (c->flags & CHAN_CLOSE_RCVD)) {
470		debug2("channel %d: is dead", c->self);
471		return 1;
472	}
473	return 0;
474}
475
476/* helper */
477static void
478chan_shutdown_write(Channel *c)
479{
480	buffer_clear(&c->output);
481	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
482		return;
483	/* shutdown failure is allowed if write failed already */
484	debug2("channel %d: close_write", c->self);
485	if (c->sock != -1) {
486		if (shutdown(c->sock, SHUT_WR) < 0)
487			debug2("channel %d: chan_shutdown_write: "
488			    "shutdown() failed for fd %d: %.100s",
489			    c->self, c->sock, strerror(errno));
490	} else {
491		if (channel_close_fd(&c->wfd) < 0)
492			logit("channel %d: chan_shutdown_write: "
493			    "close() failed for fd %d: %.100s",
494			    c->self, c->wfd, strerror(errno));
495	}
496}
497static void
498chan_shutdown_read(Channel *c)
499{
500	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
501		return;
502	debug2("channel %d: close_read", c->self);
503	if (c->sock != -1) {
504		if (shutdown(c->sock, SHUT_RD) < 0)
505			error("channel %d: chan_shutdown_read: "
506			    "shutdown() failed for fd %d [i%d o%d]: %.100s",
507			    c->self, c->sock, c->istate, c->ostate,
508			    strerror(errno));
509	} else {
510		if (channel_close_fd(&c->rfd) < 0)
511			logit("channel %d: chan_shutdown_read: "
512			    "close() failed for fd %d: %.100s",
513			    c->self, c->rfd, strerror(errno));
514	}
515}
516