xref: /titanic_44/usr/src/cmd/ssh/libssh/common/nchan.c (revision 4d0eb50e691de4c20b1dd9976ad6839fede8a42d)
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 #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 /*
67  * ACTIONS: should never update the channel states
68  */
69 static void	chan_send_ieof1(Channel *);
70 static void	chan_send_oclose1(Channel *);
71 static void	chan_send_close2(Channel *);
72 static void	chan_send_eof2(Channel *);
73 static void	chan_send_eow2(Channel *);
74 
75 /* helper */
76 static void	chan_shutdown_write(Channel *);
77 static void	chan_shutdown_read(Channel *);
78 
79 static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
80 static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
81 
82 static void
83 chan_set_istate(Channel *c, u_int next)
84 {
85 	if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
86 		fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
87 	debug("channel %d: input %s -> %s", c->self, istates[c->istate],
88 	    istates[next]);
89 	c->istate = next;
90 }
91 static void
92 chan_set_ostate(Channel *c, u_int next)
93 {
94 	if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
95 		fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
96 	debug("channel %d: output %s -> %s", c->self, ostates[c->ostate],
97 	    ostates[next]);
98 	c->ostate = next;
99 }
100 
101 /*
102  * SSH1 specific implementation of event functions
103  */
104 
105 static void
106 chan_rcvd_oclose1(Channel *c)
107 {
108 	debug("channel %d: rcvd oclose", c->self);
109 	switch (c->istate) {
110 	case CHAN_INPUT_WAIT_OCLOSE:
111 		chan_set_istate(c, CHAN_INPUT_CLOSED);
112 		break;
113 	case CHAN_INPUT_OPEN:
114 		chan_shutdown_read(c);
115 		chan_send_ieof1(c);
116 		chan_set_istate(c, CHAN_INPUT_CLOSED);
117 		break;
118 	case CHAN_INPUT_WAIT_DRAIN:
119 		/* both local read_failed and remote write_failed  */
120 		chan_send_ieof1(c);
121 		chan_set_istate(c, CHAN_INPUT_CLOSED);
122 		break;
123 	default:
124 		error("channel %d: protocol error: rcvd_oclose for istate %d",
125 		    c->self, c->istate);
126 		return;
127 	}
128 }
129 void
130 chan_read_failed(Channel *c)
131 {
132 	debug("channel %d: read failed", c->self);
133 	switch (c->istate) {
134 	case CHAN_INPUT_OPEN:
135 		chan_shutdown_read(c);
136 		chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
137 		break;
138 	default:
139 		error("channel %d: chan_read_failed for istate %d",
140 		    c->self, c->istate);
141 		break;
142 	}
143 }
144 void
145 chan_ibuf_empty(Channel *c)
146 {
147 	debug("channel %d: ibuf empty", c->self);
148 	if (buffer_len(&c->input)) {
149 		error("channel %d: chan_ibuf_empty for non empty buffer",
150 		    c->self);
151 		return;
152 	}
153 	switch (c->istate) {
154 	case CHAN_INPUT_WAIT_DRAIN:
155 		if (compat20) {
156 			if (!(c->flags & CHAN_CLOSE_SENT))
157 				chan_send_eof2(c);
158 			chan_set_istate(c, CHAN_INPUT_CLOSED);
159 		} else {
160 			chan_send_ieof1(c);
161 			chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
162 		}
163 		break;
164 	default:
165 		error("channel %d: chan_ibuf_empty for istate %d",
166 		    c->self, c->istate);
167 		break;
168 	}
169 }
170 static void
171 chan_rcvd_ieof1(Channel *c)
172 {
173 	debug("channel %d: rcvd ieof", c->self);
174 	switch (c->ostate) {
175 	case CHAN_OUTPUT_OPEN:
176 		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
177 		break;
178 	case CHAN_OUTPUT_WAIT_IEOF:
179 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
180 		break;
181 	default:
182 		error("channel %d: protocol error: rcvd_ieof for ostate %d",
183 		    c->self, c->ostate);
184 		break;
185 	}
186 }
187 static void
188 chan_write_failed1(Channel *c)
189 {
190 	debug("channel %d: write failed", c->self);
191 	switch (c->ostate) {
192 	case CHAN_OUTPUT_OPEN:
193 		chan_shutdown_write(c);
194 		chan_send_oclose1(c);
195 		chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
196 		break;
197 	case CHAN_OUTPUT_WAIT_DRAIN:
198 		chan_shutdown_write(c);
199 		chan_send_oclose1(c);
200 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
201 		break;
202 	default:
203 		error("channel %d: chan_write_failed for ostate %d",
204 		    c->self, c->ostate);
205 		break;
206 	}
207 }
208 void
209 chan_obuf_empty(Channel *c)
210 {
211 	debug("channel %d: obuf empty", c->self);
212 	if (buffer_len(&c->output)) {
213 		error("channel %d: chan_obuf_empty for non empty buffer",
214 		    c->self);
215 		return;
216 	}
217 	switch (c->ostate) {
218 	case CHAN_OUTPUT_WAIT_DRAIN:
219 		chan_shutdown_write(c);
220 		if (!compat20)
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 }
230 static void
231 chan_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 }
247 static void
248 chan_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  */
269 static void
270 chan_rcvd_close2(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 		chan_set_istate(c, CHAN_INPUT_CLOSED);
295 		break;
296 	case CHAN_INPUT_WAIT_DRAIN:
297 		chan_send_eof2(c);
298 		chan_set_istate(c, CHAN_INPUT_CLOSED);
299 		break;
300 	}
301 }
302 void
303 chan_rcvd_eow(Channel *c)
304 {
305 	debug2("channel %d: rcvd eow", c->self);
306 	switch (c->istate) {
307 	case CHAN_INPUT_OPEN:
308 		chan_shutdown_read(c);
309 		chan_set_istate(c, CHAN_INPUT_CLOSED);
310 		break;
311 	}
312 }
313 static void
314 chan_rcvd_eof2(Channel *c)
315 {
316 	debug("channel %d: rcvd eof", c->self);
317 	c->flags |= CHAN_EOF_RCVD;
318 	if (c->ostate == CHAN_OUTPUT_OPEN)
319 		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
320 }
321 static void
322 chan_write_failed2(Channel *c)
323 {
324 	debug("channel %d: write failed", c->self);
325 	switch (c->ostate) {
326 	case CHAN_OUTPUT_OPEN:
327 	case CHAN_OUTPUT_WAIT_DRAIN:
328 		chan_shutdown_write(c);
329 		if (strcmp(c->ctype, "session") == 0)
330 			chan_send_eow2(c);
331 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
332 		break;
333 	default:
334 		error("channel %d: chan_write_failed for ostate %d",
335 		    c->self, c->ostate);
336 		break;
337 	}
338 }
339 static void
340 chan_send_eof2(Channel *c)
341 {
342 	debug("channel %d: send eof", c->self);
343 	switch (c->istate) {
344 	case CHAN_INPUT_WAIT_DRAIN:
345 		packet_start(SSH2_MSG_CHANNEL_EOF);
346 		packet_put_int(c->remote_id);
347 		packet_send();
348 		c->flags |= CHAN_EOF_SENT;
349 		break;
350 	default:
351 		error("channel %d: cannot send eof for istate %d",
352 		    c->self, c->istate);
353 		break;
354 	}
355 }
356 static void
357 chan_send_close2(Channel *c)
358 {
359 	debug("channel %d: send close", c->self);
360 	if (c->ostate != CHAN_OUTPUT_CLOSED ||
361 	    c->istate != CHAN_INPUT_CLOSED) {
362 		error("channel %d: cannot send close for istate/ostate %d/%d",
363 		    c->self, c->istate, c->ostate);
364 	} else if (c->flags & CHAN_CLOSE_SENT) {
365 		error("channel %d: already sent close", c->self);
366 	} else {
367 		packet_start(SSH2_MSG_CHANNEL_CLOSE);
368 		packet_put_int(c->remote_id);
369 		packet_send();
370 		c->flags |= CHAN_CLOSE_SENT;
371 	}
372 }
373 static void
374 chan_send_eow2(Channel *c)
375 {
376        debug2("channel %d: send eow", c->self);
377        if (c->ostate == CHAN_OUTPUT_CLOSED) {
378                error("channel %d: must not sent eow on closed output",
379                    c->self);
380                return;
381        }
382        packet_start(SSH2_MSG_CHANNEL_REQUEST);
383        packet_put_int(c->remote_id);
384        packet_put_cstring("eow@openssh.com");
385        packet_put_char(0);
386        packet_send();
387 }
388 
389 /* shared */
390 
391 void
392 chan_rcvd_ieof(Channel *c)
393 {
394 	if (compat20)
395 		chan_rcvd_eof2(c);
396 	else
397 		chan_rcvd_ieof1(c);
398 	if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
399 	    buffer_len(&c->output) == 0 &&
400 	    !CHANNEL_EFD_OUTPUT_ACTIVE(c))
401 		chan_obuf_empty(c);
402 }
403 void
404 chan_rcvd_oclose(Channel *c)
405 {
406 	if (compat20)
407 		chan_rcvd_close2(c);
408 	else
409 		chan_rcvd_oclose1(c);
410 }
411 void
412 chan_write_failed(Channel *c)
413 {
414 	if (compat20)
415 		chan_write_failed2(c);
416 	else
417 		chan_write_failed1(c);
418 }
419 
420 void
421 chan_mark_dead(Channel *c)
422 {
423 	c->type = SSH_CHANNEL_ZOMBIE;
424 }
425 
426 int
427 chan_is_dead(Channel *c, int send)
428 {
429 	if (c->type == SSH_CHANNEL_ZOMBIE) {
430 		debug("channel %d: zombie", c->self);
431 		return 1;
432 	}
433 	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
434 		return 0;
435 	if (!compat20) {
436 		debug("channel %d: is dead", c->self);
437 		return 1;
438 	}
439 	if ((datafellows & SSH_BUG_EXTEOF) &&
440 	    c->extended_usage == CHAN_EXTENDED_WRITE &&
441 	    c->efd != -1 &&
442 	    buffer_len(&c->extended) > 0) {
443 		debug2("channel %d: active efd: %d len %d",
444 		    c->self, c->efd, buffer_len(&c->extended));
445 		return 0;
446 	}
447 	if (!(c->flags & CHAN_CLOSE_SENT)) {
448 		if (send) {
449 			chan_send_close2(c);
450 		} else {
451 			/* channel would be dead if we sent a close */
452 			if (c->flags & CHAN_CLOSE_RCVD) {
453 				debug("channel %d: almost dead",
454 				    c->self);
455 				return 1;
456 			}
457 		}
458 	}
459 	if ((c->flags & CHAN_CLOSE_SENT) &&
460 	    (c->flags & CHAN_CLOSE_RCVD)) {
461 		debug("channel %d: is dead", c->self);
462 		return 1;
463 	}
464 	return 0;
465 }
466 
467 /* helper */
468 static void
469 chan_shutdown_write(Channel *c)
470 {
471 	buffer_clear(&c->output);
472 	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
473 		return;
474 	/* shutdown failure is allowed if write failed already */
475 	debug("channel %d: close_write", c->self);
476 	if (c->sock != -1) {
477 		if (shutdown(c->sock, SHUT_WR) < 0)
478 			debug("channel %d: chan_shutdown_write: "
479 			    "shutdown() failed for fd%d: %.100s",
480 			    c->self, c->sock, strerror(errno));
481 	} else {
482 		if (channel_close_fd(&c->wfd) < 0)
483 			log("channel %d: chan_shutdown_write: "
484 			    "close() failed for fd%d: %.100s",
485 			    c->self, c->wfd, strerror(errno));
486 	}
487 }
488 static void
489 chan_shutdown_read(Channel *c)
490 {
491 	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
492 		return;
493 	debug("channel %d: close_read", c->self);
494 	if (c->sock != -1) {
495 		/*
496 		 * shutdown(sock, SHUT_READ) may return ENOTCONN if the
497 		 * write side has been closed already. (bug on Linux)
498 		 * HP-UX may return ENOTCONN also.
499 		 */
500 		if (shutdown(c->sock, SHUT_RD) < 0
501 		    && errno != ENOTCONN)
502 			error("channel %d: chan_shutdown_read: "
503 			    "shutdown() failed for fd%d [i%d o%d]: %.100s",
504 			    c->self, c->sock, c->istate, c->ostate,
505 			    strerror(errno));
506 	} else {
507 		if (channel_close_fd(&c->rfd) < 0)
508 			log("channel %d: chan_shutdown_read: "
509 			    "close() failed for fd%d: %.100s",
510 			    c->self, c->rfd, strerror(errno));
511 	}
512 }
513