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