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