nchan.c revision 181110
1212795Sdim/* $OpenBSD: nchan.c,v 1.57 2006/08/03 03:34:42 deraadt Exp $ */
2212795Sdim/*
3212795Sdim * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
4212795Sdim *
5212795Sdim * Redistribution and use in source and binary forms, with or without
6212795Sdim * modification, are permitted provided that the following conditions
7212795Sdim * are met:
8212795Sdim * 1. Redistributions of source code must retain the above copyright
9212795Sdim *    notice, this list of conditions and the following disclaimer.
10212795Sdim * 2. Redistributions in binary form must reproduce the above copyright
11212795Sdim *    notice, this list of conditions and the following disclaimer in the
12212795Sdim *    documentation and/or other materials provided with the distribution.
13212795Sdim *
14212795Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15212795Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16249423Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17218893Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18218893Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19212795Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20212795Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21212795Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22212795Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23263508Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24212795Sdim */
25212795Sdim
26234353Sdim#include "includes.h"
27212795Sdim
28212795Sdim#include <sys/types.h>
29212795Sdim#include <sys/socket.h>
30212795Sdim
31212795Sdim#include <errno.h>
32212795Sdim#include <string.h>
33212795Sdim#include <stdarg.h>
34212795Sdim
35212795Sdim#include "ssh1.h"
36212795Sdim#include "ssh2.h"
37212795Sdim#include "buffer.h"
38212795Sdim#include "packet.h"
39239462Sdim#include "channels.h"
40239462Sdim#include "compat.h"
41239462Sdim#include "log.h"
42234353Sdim
43218893Sdim/*
44226633Sdim * SSH Protocol 1.5 aka New Channel Protocol
45234353Sdim * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
46243830Sdim * Written by Markus Friedl in October 1999
47243830Sdim *
48212795Sdim * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
49212795Sdim * tear down of channels:
50243830Sdim *
51249423Sdim * 1.3:	strict request-ack-protocol:
52212795Sdim *	CLOSE	->
53212795Sdim *		<-  CLOSE_CONFIRM
54221345Sdim *
55212795Sdim * 1.5:	uses variations of:
56212795Sdim *	IEOF	->
57212795Sdim *		<-  OCLOSE
58212795Sdim *		<-  IEOF
59212795Sdim *	OCLOSE	->
60212795Sdim *	i.e. both sides have to close the channel
61212795Sdim *
62212795Sdim * 2.0: the EOF messages are optional
63212795Sdim *
64212795Sdim * See the debugging output from 'ssh -v' and 'sshd -d' of
65212795Sdim * ssh-1.2.27 as an example.
66239462Sdim *
67239462Sdim */
68239462Sdim
69239462Sdim/* functions manipulating channel states */
70239462Sdim/*
71239462Sdim * EVENTS update channel input/output states execute ACTIONS
72239462Sdim */
73239462Sdim/*
74239462Sdim * ACTIONS: should never update the channel states
75212795Sdim */
76212795Sdimstatic void	chan_send_ieof1(Channel *);
77212795Sdimstatic void	chan_send_oclose1(Channel *);
78212795Sdimstatic void	chan_send_close2(Channel *);
79212795Sdimstatic void	chan_send_eof2(Channel *);
80212795Sdim
81239462Sdim/* helper */
82239462Sdimstatic void	chan_shutdown_write(Channel *);
83239462Sdimstatic void	chan_shutdown_read(Channel *);
84239462Sdim
85239462Sdimstatic char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
86239462Sdimstatic char *istates[] = { "open", "drain", "wait_oclose", "closed" };
87239462Sdim
88239462Sdimstatic void
89239462Sdimchan_set_istate(Channel *c, u_int next)
90239462Sdim{
91239462Sdim	if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
92239462Sdim		fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
93239462Sdim	debug2("channel %d: input %s -> %s", c->self, istates[c->istate],
94239462Sdim	    istates[next]);
95239462Sdim	c->istate = next;
96239462Sdim}
97239462Sdimstatic void
98234353Sdimchan_set_ostate(Channel *c, u_int next)
99234353Sdim{
100239462Sdim	if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
101239462Sdim		fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
102239462Sdim	debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate],
103239462Sdim	    ostates[next]);
104239462Sdim	c->ostate = next;
105239462Sdim}
106218893Sdim
107234353Sdim/*
108218893Sdim * SSH1 specific implementation of event functions
109234353Sdim */
110218893Sdim
111234353Sdimstatic void
112218893Sdimchan_rcvd_oclose1(Channel *c)
113218893Sdim{
114218893Sdim	debug2("channel %d: rcvd oclose", c->self);
115234353Sdim	switch (c->istate) {
116218893Sdim	case CHAN_INPUT_WAIT_OCLOSE:
117218893Sdim		chan_set_istate(c, CHAN_INPUT_CLOSED);
118218893Sdim		break;
119234353Sdim	case CHAN_INPUT_OPEN:
120212795Sdim		chan_shutdown_read(c);
121212795Sdim		chan_send_ieof1(c);
122212795Sdim		chan_set_istate(c, CHAN_INPUT_CLOSED);
123212795Sdim		break;
124212795Sdim	case CHAN_INPUT_WAIT_DRAIN:
125212795Sdim		/* both local read_failed and remote write_failed  */
126212795Sdim		chan_send_ieof1(c);
127212795Sdim		chan_set_istate(c, CHAN_INPUT_CLOSED);
128212795Sdim		break;
129212795Sdim	default:
130212795Sdim		error("channel %d: protocol error: rcvd_oclose for istate %d",
131212795Sdim		    c->self, c->istate);
132212795Sdim		return;
133212795Sdim	}
134212795Sdim}
135212795Sdimvoid
136212795Sdimchan_read_failed(Channel *c)
137212795Sdim{
138212795Sdim	debug2("channel %d: read failed", c->self);
139212795Sdim	switch (c->istate) {
140212795Sdim	case CHAN_INPUT_OPEN:
141212795Sdim		chan_shutdown_read(c);
142212795Sdim		chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
143212795Sdim		break;
144212795Sdim	default:
145249423Sdim		error("channel %d: chan_read_failed for istate %d",
146249423Sdim		    c->self, c->istate);
147212795Sdim		break;
148212795Sdim	}
149212795Sdim}
150212795Sdimvoid
151212795Sdimchan_ibuf_empty(Channel *c)
152249423Sdim{
153249423Sdim	debug2("channel %d: ibuf empty", c->self);
154249423Sdim	if (buffer_len(&c->input)) {
155212795Sdim		error("channel %d: chan_ibuf_empty for non empty buffer",
156212795Sdim		    c->self);
157249423Sdim		return;
158249423Sdim	}
159249423Sdim	switch (c->istate) {
160249423Sdim	case CHAN_INPUT_WAIT_DRAIN:
161251662Sdim		if (compat20) {
162251662Sdim			if (!(c->flags & CHAN_CLOSE_SENT))
163249423Sdim				chan_send_eof2(c);
164212795Sdim			chan_set_istate(c, CHAN_INPUT_CLOSED);
165212795Sdim		} else {
166263508Sdim			chan_send_ieof1(c);
167212795Sdim			chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
168263508Sdim		}
169263508Sdim		break;
170263508Sdim	default:
171263508Sdim		error("channel %d: chan_ibuf_empty for istate %d",
172263508Sdim		    c->self, c->istate);
173263508Sdim		break;
174263508Sdim	}
175263508Sdim}
176263508Sdimstatic void
177263508Sdimchan_rcvd_ieof1(Channel *c)
178263508Sdim{
179263508Sdim	debug2("channel %d: rcvd ieof", c->self);
180263508Sdim	switch (c->ostate) {
181263508Sdim	case CHAN_OUTPUT_OPEN:
182263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
183263508Sdim		break;
184263508Sdim	case CHAN_OUTPUT_WAIT_IEOF:
185263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
186263508Sdim		break;
187263508Sdim	default:
188263508Sdim		error("channel %d: protocol error: rcvd_ieof for ostate %d",
189263508Sdim		    c->self, c->ostate);
190263508Sdim		break;
191263508Sdim	}
192263508Sdim}
193263508Sdimstatic void
194263508Sdimchan_write_failed1(Channel *c)
195263508Sdim{
196263508Sdim	debug2("channel %d: write failed", c->self);
197263508Sdim	switch (c->ostate) {
198263508Sdim	case CHAN_OUTPUT_OPEN:
199263508Sdim		chan_shutdown_write(c);
200263508Sdim		chan_send_oclose1(c);
201263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
202263508Sdim		break;
203263508Sdim	case CHAN_OUTPUT_WAIT_DRAIN:
204263508Sdim		chan_shutdown_write(c);
205263508Sdim		chan_send_oclose1(c);
206263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
207263508Sdim		break;
208263508Sdim	default:
209263508Sdim		error("channel %d: chan_write_failed for ostate %d",
210263508Sdim		    c->self, c->ostate);
211263508Sdim		break;
212263508Sdim	}
213263508Sdim}
214263508Sdimvoid
215263508Sdimchan_obuf_empty(Channel *c)
216263508Sdim{
217263508Sdim	debug2("channel %d: obuf empty", c->self);
218263508Sdim	if (buffer_len(&c->output)) {
219263508Sdim		error("channel %d: chan_obuf_empty for non empty buffer",
220263508Sdim		    c->self);
221263508Sdim		return;
222263508Sdim	}
223263508Sdim	switch (c->ostate) {
224263508Sdim	case CHAN_OUTPUT_WAIT_DRAIN:
225263508Sdim		chan_shutdown_write(c);
226263508Sdim		if (!compat20)
227263508Sdim			chan_send_oclose1(c);
228263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
229263508Sdim		break;
230263508Sdim	default:
231263508Sdim		error("channel %d: internal error: obuf_empty for ostate %d",
232263508Sdim		    c->self, c->ostate);
233263508Sdim		break;
234263508Sdim	}
235263508Sdim}
236263508Sdimstatic void
237263508Sdimchan_send_ieof1(Channel *c)
238263508Sdim{
239263508Sdim	debug2("channel %d: send ieof", c->self);
240263508Sdim	switch (c->istate) {
241263508Sdim	case CHAN_INPUT_OPEN:
242263508Sdim	case CHAN_INPUT_WAIT_DRAIN:
243263508Sdim		packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
244263508Sdim		packet_put_int(c->remote_id);
245263508Sdim		packet_send();
246263508Sdim		break;
247263508Sdim	default:
248263508Sdim		error("channel %d: cannot send ieof for istate %d",
249263508Sdim		    c->self, c->istate);
250263508Sdim		break;
251263508Sdim	}
252263508Sdim}
253263508Sdimstatic void
254263508Sdimchan_send_oclose1(Channel *c)
255263508Sdim{
256263508Sdim	debug2("channel %d: send oclose", c->self);
257263508Sdim	switch (c->ostate) {
258263508Sdim	case CHAN_OUTPUT_OPEN:
259263508Sdim	case CHAN_OUTPUT_WAIT_DRAIN:
260263508Sdim		buffer_clear(&c->output);
261263508Sdim		packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
262263508Sdim		packet_put_int(c->remote_id);
263263508Sdim		packet_send();
264263508Sdim		break;
265263508Sdim	default:
266263508Sdim		error("channel %d: cannot send oclose for ostate %d",
267263508Sdim		    c->self, c->ostate);
268263508Sdim		break;
269263508Sdim	}
270263508Sdim}
271263508Sdim
272263508Sdim/*
273263508Sdim * the same for SSH2
274263508Sdim */
275263508Sdimstatic void
276263508Sdimchan_rcvd_close2(Channel *c)
277263508Sdim{
278263508Sdim	debug2("channel %d: rcvd close", c->self);
279263508Sdim	if (c->flags & CHAN_CLOSE_RCVD)
280263508Sdim		error("channel %d: protocol error: close rcvd twice", c->self);
281263508Sdim	c->flags |= CHAN_CLOSE_RCVD;
282263508Sdim	if (c->type == SSH_CHANNEL_LARVAL) {
283263508Sdim		/* tear down larval channels immediately */
284263508Sdim		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
285263508Sdim		chan_set_istate(c, CHAN_INPUT_CLOSED);
286212795Sdim		return;
287	}
288	switch (c->ostate) {
289	case CHAN_OUTPUT_OPEN:
290		/*
291		 * wait until a data from the channel is consumed if a CLOSE
292		 * is received
293		 */
294		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
295		break;
296	}
297	switch (c->istate) {
298	case CHAN_INPUT_OPEN:
299		chan_shutdown_read(c);
300		chan_set_istate(c, CHAN_INPUT_CLOSED);
301		break;
302	case CHAN_INPUT_WAIT_DRAIN:
303		chan_send_eof2(c);
304		chan_set_istate(c, CHAN_INPUT_CLOSED);
305		break;
306	}
307}
308static void
309chan_rcvd_eof2(Channel *c)
310{
311	debug2("channel %d: rcvd eof", c->self);
312	c->flags |= CHAN_EOF_RCVD;
313	if (c->ostate == CHAN_OUTPUT_OPEN)
314		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
315}
316static void
317chan_write_failed2(Channel *c)
318{
319	debug2("channel %d: write failed", c->self);
320	switch (c->ostate) {
321	case CHAN_OUTPUT_OPEN:
322	case CHAN_OUTPUT_WAIT_DRAIN:
323		chan_shutdown_write(c);
324		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
325		break;
326	default:
327		error("channel %d: chan_write_failed for ostate %d",
328		    c->self, c->ostate);
329		break;
330	}
331}
332static void
333chan_send_eof2(Channel *c)
334{
335	debug2("channel %d: send eof", c->self);
336	switch (c->istate) {
337	case CHAN_INPUT_WAIT_DRAIN:
338		packet_start(SSH2_MSG_CHANNEL_EOF);
339		packet_put_int(c->remote_id);
340		packet_send();
341		c->flags |= CHAN_EOF_SENT;
342		break;
343	default:
344		error("channel %d: cannot send eof for istate %d",
345		    c->self, c->istate);
346		break;
347	}
348}
349static void
350chan_send_close2(Channel *c)
351{
352	debug2("channel %d: send close", c->self);
353	if (c->ostate != CHAN_OUTPUT_CLOSED ||
354	    c->istate != CHAN_INPUT_CLOSED) {
355		error("channel %d: cannot send close for istate/ostate %d/%d",
356		    c->self, c->istate, c->ostate);
357	} else if (c->flags & CHAN_CLOSE_SENT) {
358		error("channel %d: already sent close", c->self);
359	} else {
360		packet_start(SSH2_MSG_CHANNEL_CLOSE);
361		packet_put_int(c->remote_id);
362		packet_send();
363		c->flags |= CHAN_CLOSE_SENT;
364	}
365}
366
367/* shared */
368
369void
370chan_rcvd_ieof(Channel *c)
371{
372	if (compat20)
373		chan_rcvd_eof2(c);
374	else
375		chan_rcvd_ieof1(c);
376	if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
377	    buffer_len(&c->output) == 0 &&
378	    !CHANNEL_EFD_OUTPUT_ACTIVE(c))
379		chan_obuf_empty(c);
380}
381void
382chan_rcvd_oclose(Channel *c)
383{
384	if (compat20)
385		chan_rcvd_close2(c);
386	else
387		chan_rcvd_oclose1(c);
388}
389void
390chan_write_failed(Channel *c)
391{
392	if (compat20)
393		chan_write_failed2(c);
394	else
395		chan_write_failed1(c);
396}
397
398void
399chan_mark_dead(Channel *c)
400{
401	c->type = SSH_CHANNEL_ZOMBIE;
402}
403
404int
405chan_is_dead(Channel *c, int do_send)
406{
407	if (c->type == SSH_CHANNEL_ZOMBIE) {
408		debug2("channel %d: zombie", c->self);
409		return 1;
410	}
411	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
412		return 0;
413	if (!compat20) {
414		debug2("channel %d: is dead", c->self);
415		return 1;
416	}
417	if ((datafellows & SSH_BUG_EXTEOF) &&
418	    c->extended_usage == CHAN_EXTENDED_WRITE &&
419	    c->efd != -1 &&
420	    buffer_len(&c->extended) > 0) {
421		debug2("channel %d: active efd: %d len %d",
422		    c->self, c->efd, buffer_len(&c->extended));
423		return 0;
424	}
425	if (!(c->flags & CHAN_CLOSE_SENT)) {
426		if (do_send) {
427			chan_send_close2(c);
428		} else {
429			/* channel would be dead if we sent a close */
430			if (c->flags & CHAN_CLOSE_RCVD) {
431				debug2("channel %d: almost dead",
432				    c->self);
433				return 1;
434			}
435		}
436	}
437	if ((c->flags & CHAN_CLOSE_SENT) &&
438	    (c->flags & CHAN_CLOSE_RCVD)) {
439		debug2("channel %d: is dead", c->self);
440		return 1;
441	}
442	return 0;
443}
444
445/* helper */
446static void
447chan_shutdown_write(Channel *c)
448{
449	buffer_clear(&c->output);
450	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
451		return;
452	/* shutdown failure is allowed if write failed already */
453	debug2("channel %d: close_write", c->self);
454	if (c->sock != -1) {
455		if (shutdown(c->sock, SHUT_WR) < 0)
456			debug2("channel %d: chan_shutdown_write: "
457			    "shutdown() failed for fd%d: %.100s",
458			    c->self, c->sock, strerror(errno));
459	} else {
460		if (channel_close_fd(&c->wfd) < 0)
461			logit("channel %d: chan_shutdown_write: "
462			    "close() failed for fd%d: %.100s",
463			    c->self, c->wfd, strerror(errno));
464	}
465}
466static void
467chan_shutdown_read(Channel *c)
468{
469	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
470		return;
471	debug2("channel %d: close_read", c->self);
472	if (c->sock != -1) {
473		/*
474		 * shutdown(sock, SHUT_READ) may return ENOTCONN if the
475		 * write side has been closed already. (bug on Linux)
476		 * HP-UX may return ENOTCONN also.
477		 */
478		if (shutdown(c->sock, SHUT_RD) < 0
479		    && errno != ENOTCONN)
480			error("channel %d: chan_shutdown_read: "
481			    "shutdown() failed for fd%d [i%d o%d]: %.100s",
482			    c->self, c->sock, c->istate, c->ostate,
483			    strerror(errno));
484	} else {
485		if (channel_close_fd(&c->rfd) < 0)
486			logit("channel %d: chan_shutdown_read: "
487			    "close() failed for fd%d: %.100s",
488			    c->self, c->rfd, strerror(errno));
489	}
490}
491