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