nchan.c revision 1.38
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.38 2002/01/14 13:22:35 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
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	debug("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	debug("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	debug("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}
136static void
137chan_read_failed_12(Channel *c)
138{
139	debug("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}
151static void
152chan_ibuf_empty1(Channel *c)
153{
154	debug("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		chan_send_ieof1(c);
163		chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
164		break;
165	default:
166		error("channel %d: chan_ibuf_empty for istate %d",
167		    c->self, c->istate);
168		break;
169	}
170}
171static void
172chan_rcvd_ieof1(Channel *c)
173{
174	debug("channel %d: rcvd ieof", c->self);
175	switch (c->ostate) {
176	case CHAN_OUTPUT_OPEN:
177		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
178		break;
179	case CHAN_OUTPUT_WAIT_IEOF:
180		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
181		break;
182	default:
183		error("channel %d: protocol error: rcvd_ieof for ostate %d",
184		    c->self, c->ostate);
185		break;
186	}
187}
188static void
189chan_write_failed1(Channel *c)
190{
191	debug("channel %d: write failed", c->self);
192	switch (c->ostate) {
193	case CHAN_OUTPUT_OPEN:
194		chan_shutdown_write(c);
195		chan_send_oclose1(c);
196		chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
197		break;
198	case CHAN_OUTPUT_WAIT_DRAIN:
199		chan_shutdown_write(c);
200		chan_send_oclose1(c);
201		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
202		break;
203	default:
204		error("channel %d: chan_write_failed for ostate %d",
205		    c->self, c->ostate);
206		break;
207	}
208}
209static void
210chan_obuf_empty1(Channel *c)
211{
212	debug("channel %d: obuf empty", c->self);
213	if (buffer_len(&c->output)) {
214		error("channel %d: chan_obuf_empty for non empty buffer",
215		    c->self);
216		return;
217	}
218	switch (c->ostate) {
219	case CHAN_OUTPUT_WAIT_DRAIN:
220		chan_shutdown_write(c);
221		chan_send_oclose1(c);
222		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
223		break;
224	default:
225		error("channel %d: internal error: obuf_empty for ostate %d",
226		    c->self, c->ostate);
227		break;
228	}
229}
230static void
231chan_send_ieof1(Channel *c)
232{
233	debug("channel %d: send ieof", c->self);
234	switch (c->istate) {
235	case CHAN_INPUT_OPEN:
236	case CHAN_INPUT_WAIT_DRAIN:
237		packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
238		packet_put_int(c->remote_id);
239		packet_send();
240		break;
241	default:
242		error("channel %d: cannot send ieof for istate %d",
243		    c->self, c->istate);
244		break;
245	}
246}
247static void
248chan_send_oclose1(Channel *c)
249{
250	debug("channel %d: send oclose", c->self);
251	switch (c->ostate) {
252	case CHAN_OUTPUT_OPEN:
253	case CHAN_OUTPUT_WAIT_DRAIN:
254		buffer_clear(&c->output);
255		packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
256		packet_put_int(c->remote_id);
257		packet_send();
258		break;
259	default:
260		error("channel %d: cannot send oclose for ostate %d",
261		    c->self, c->ostate);
262		break;
263	}
264}
265
266/*
267 * the same for SSH2
268 */
269static void
270chan_rcvd_oclose2(Channel *c)
271{
272	debug("channel %d: rcvd close", c->self);
273	if (c->flags & CHAN_CLOSE_RCVD)
274		error("channel %d: protocol error: close rcvd twice", c->self);
275	c->flags |= CHAN_CLOSE_RCVD;
276	if (c->type == SSH_CHANNEL_LARVAL) {
277		/* tear down larval channels immediately */
278		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
279		chan_set_istate(c, CHAN_INPUT_CLOSED);
280		return;
281	}
282	switch (c->ostate) {
283	case CHAN_OUTPUT_OPEN:
284		/*
285		 * wait until a data from the channel is consumed if a CLOSE
286		 * is received
287		 */
288		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
289		break;
290	}
291	switch (c->istate) {
292	case CHAN_INPUT_OPEN:
293		chan_shutdown_read(c);
294		break;
295	case CHAN_INPUT_WAIT_DRAIN:
296		chan_send_eof2(c);
297		break;
298	}
299	chan_set_istate(c, CHAN_INPUT_CLOSED);
300}
301static void
302chan_ibuf_empty2(Channel *c)
303{
304	debug("channel %d: ibuf empty", c->self);
305	if (buffer_len(&c->input)) {
306		error("channel %d: chan_ibuf_empty for non empty buffer",
307		    c->self);
308		return;
309	}
310	switch (c->istate) {
311	case CHAN_INPUT_WAIT_DRAIN:
312		if (!(c->flags & CHAN_CLOSE_SENT))
313			chan_send_eof2(c);
314		chan_set_istate(c, CHAN_INPUT_CLOSED);
315		break;
316	default:
317		error("channel %d: chan_ibuf_empty for istate %d",
318		    c->self, c->istate);
319		break;
320	}
321}
322static void
323chan_rcvd_ieof2(Channel *c)
324{
325	debug("channel %d: rcvd eof", c->self);
326	if (c->ostate == CHAN_OUTPUT_OPEN)
327		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
328}
329static void
330chan_write_failed2(Channel *c)
331{
332	debug("channel %d: write failed", c->self);
333	switch (c->ostate) {
334	case CHAN_OUTPUT_OPEN:
335		chan_shutdown_write(c); /* ?? */
336		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
337		break;
338	case CHAN_OUTPUT_WAIT_DRAIN:
339		chan_shutdown_write(c);
340		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
341		break;
342	default:
343		error("channel %d: chan_write_failed for ostate %d",
344		    c->self, c->ostate);
345		break;
346	}
347}
348static void
349chan_obuf_empty2(Channel *c)
350{
351	debug("channel %d: obuf empty", c->self);
352	if (buffer_len(&c->output)) {
353		error("channel %d: chan_obuf_empty for non empty buffer",
354		    c->self);
355		return;
356	}
357	switch (c->ostate) {
358	case CHAN_OUTPUT_WAIT_DRAIN:
359		chan_shutdown_write(c);
360		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
361		break;
362	default:
363		error("channel %d: chan_obuf_empty for ostate %d",
364		    c->self, c->ostate);
365		break;
366	}
367}
368static void
369chan_send_eof2(Channel *c)
370{
371	debug("channel %d: send eof", c->self);
372	switch (c->istate) {
373	case CHAN_INPUT_WAIT_DRAIN:
374		packet_start(SSH2_MSG_CHANNEL_EOF);
375		packet_put_int(c->remote_id);
376		packet_send();
377		break;
378	default:
379		error("channel %d: cannot send eof for istate %d",
380		    c->self, c->istate);
381		break;
382	}
383}
384static void
385chan_send_close2(Channel *c)
386{
387	debug("channel %d: send close", c->self);
388	if (c->ostate != CHAN_OUTPUT_CLOSED ||
389	    c->istate != CHAN_INPUT_CLOSED) {
390		error("channel %d: cannot send close for istate/ostate %d/%d",
391		    c->self, c->istate, c->ostate);
392	} else if (c->flags & CHAN_CLOSE_SENT) {
393		error("channel %d: already sent close", c->self);
394	} else {
395		packet_start(SSH2_MSG_CHANNEL_CLOSE);
396		packet_put_int(c->remote_id);
397		packet_send();
398		c->flags |= CHAN_CLOSE_SENT;
399	}
400}
401
402/* shared */
403
404void
405chan_mark_dead(Channel *c)
406{
407	c->type = SSH_CHANNEL_ZOMBIE;
408}
409
410int
411chan_is_dead(Channel *c, int send)
412{
413	if (c->type == SSH_CHANNEL_ZOMBIE) {
414		debug("channel %d: zombie", c->self);
415		return 1;
416	}
417	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
418		return 0;
419	if (!compat20) {
420		debug("channel %d: is dead", c->self);
421		return 1;
422	}
423	/*
424	 * we have to delay the close message if the efd (for stderr) is
425	 * still active
426	 */
427	if (((c->extended_usage != CHAN_EXTENDED_IGNORE) &&
428	    buffer_len(&c->extended) > 0)
429#if 0
430	    || ((c->extended_usage == CHAN_EXTENDED_READ) &&
431	    c->efd != -1)
432#endif
433	    ) {
434		debug2("channel %d: active efd: %d len %d type %s",
435		    c->self, c->efd, buffer_len(&c->extended),
436		    c->extended_usage==CHAN_EXTENDED_READ ?
437		    "read": "write");
438	} else {
439		if (!(c->flags & CHAN_CLOSE_SENT)) {
440			if (send) {
441				chan_send_close2(c);
442			} else {
443				/* channel would be dead if we sent a close */
444				if (c->flags & CHAN_CLOSE_RCVD) {
445					debug("channel %d: almost dead",
446					    c->self);
447					return 1;
448				}
449			}
450		}
451		if ((c->flags & CHAN_CLOSE_SENT) &&
452		    (c->flags & CHAN_CLOSE_RCVD)) {
453			debug("channel %d: is dead", c->self);
454			return 1;
455		}
456	}
457	return 0;
458}
459
460void
461chan_init_iostates(Channel *c)
462{
463	c->ostate = CHAN_OUTPUT_OPEN;
464	c->istate = CHAN_INPUT_OPEN;
465	c->flags = 0;
466}
467
468/* init */
469void
470chan_init(void)
471{
472	if (compat20) {
473		chan_rcvd_oclose		= chan_rcvd_oclose2;
474		chan_read_failed		= chan_read_failed_12;
475		chan_ibuf_empty			= chan_ibuf_empty2;
476
477		chan_rcvd_ieof			= chan_rcvd_ieof2;
478		chan_write_failed		= chan_write_failed2;
479		chan_obuf_empty			= chan_obuf_empty2;
480	} else {
481		chan_rcvd_oclose		= chan_rcvd_oclose1;
482		chan_read_failed		= chan_read_failed_12;
483		chan_ibuf_empty			= chan_ibuf_empty1;
484
485		chan_rcvd_ieof			= chan_rcvd_ieof1;
486		chan_write_failed		= chan_write_failed1;
487		chan_obuf_empty			= chan_obuf_empty1;
488	}
489}
490
491/* helper */
492static void
493chan_shutdown_write(Channel *c)
494{
495	buffer_clear(&c->output);
496	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
497		return;
498	/* shutdown failure is allowed if write failed already */
499	debug("channel %d: close_write", c->self);
500	if (c->sock != -1) {
501		if (shutdown(c->sock, SHUT_WR) < 0)
502			debug("channel %d: chan_shutdown_write: "
503			    "shutdown() failed for fd%d: %.100s",
504			    c->self, c->sock, strerror(errno));
505	} else {
506		if (channel_close_fd(&c->wfd) < 0)
507			log("channel %d: chan_shutdown_write: "
508			    "close() failed for fd%d: %.100s",
509			    c->self, c->wfd, strerror(errno));
510	}
511}
512static void
513chan_shutdown_read(Channel *c)
514{
515	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
516		return;
517	debug("channel %d: close_read", c->self);
518	if (c->sock != -1) {
519		if (shutdown(c->sock, SHUT_RD) < 0)
520			error("channel %d: chan_shutdown_read: "
521			    "shutdown() failed for fd%d [i%d o%d]: %.100s",
522			    c->self, c->sock, c->istate, c->ostate,
523			    strerror(errno));
524	} else {
525		if (channel_close_fd(&c->rfd) < 0)
526			log("channel %d: chan_shutdown_read: "
527			    "close() failed for fd%d: %.100s",
528			    c->self, c->rfd, strerror(errno));
529	}
530}
531