xref: /freebsd/crypto/openssh/nchan.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*
2  * Copyright (c) 1999 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.19 2000/09/07 20:27:52 deraadt Exp $");
27 
28 #include "ssh.h"
29 
30 #include "buffer.h"
31 #include "packet.h"
32 #include "channels.h"
33 #include "nchan.h"
34 
35 #include "ssh2.h"
36 #include "compat.h"
37 
38 /* functions manipulating channel states */
39 /*
40  * EVENTS update channel input/output states execute ACTIONS
41  */
42 /* events concerning the INPUT from socket for channel (istate) */
43 chan_event_fn *chan_rcvd_oclose			= NULL;
44 chan_event_fn *chan_read_failed			= NULL;
45 chan_event_fn *chan_ibuf_empty			= NULL;
46 /* events concerning the OUTPUT from channel for socket (ostate) */
47 chan_event_fn *chan_rcvd_ieof			= NULL;
48 chan_event_fn *chan_write_failed		= NULL;
49 chan_event_fn *chan_obuf_empty			= NULL;
50 /*
51  * ACTIONS: should never update the channel states
52  */
53 static void	chan_send_ieof1(Channel *c);
54 static void	chan_send_oclose1(Channel *c);
55 static void	chan_send_close2(Channel *c);
56 static void	chan_send_eof2(Channel *c);
57 
58 /* channel cleanup */
59 chan_event_fn *chan_delete_if_full_closed	= NULL;
60 
61 /* helper */
62 static void	chan_shutdown_write(Channel *c);
63 static void	chan_shutdown_read(Channel *c);
64 
65 /*
66  * SSH1 specific implementation of event functions
67  */
68 
69 static void
70 chan_rcvd_oclose1(Channel *c)
71 {
72 	debug("channel %d: rcvd oclose", c->self);
73 	switch (c->istate) {
74 	case CHAN_INPUT_WAIT_OCLOSE:
75 		debug("channel %d: input wait_oclose -> closed", c->self);
76 		c->istate = CHAN_INPUT_CLOSED;
77 		break;
78 	case CHAN_INPUT_OPEN:
79 		debug("channel %d: input open -> closed", c->self);
80 		chan_shutdown_read(c);
81 		chan_send_ieof1(c);
82 		c->istate = CHAN_INPUT_CLOSED;
83 		break;
84 	case CHAN_INPUT_WAIT_DRAIN:
85 		/* both local read_failed and remote write_failed  */
86 		log("channel %d: input drain -> closed", c->self);
87 		chan_send_ieof1(c);
88 		c->istate = CHAN_INPUT_CLOSED;
89 		break;
90 	default:
91 		error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
92 		    c->self, c->istate);
93 		return;
94 	}
95 }
96 static void
97 chan_read_failed_12(Channel *c)
98 {
99 	debug("channel %d: read failed", c->self);
100 	switch (c->istate) {
101 	case CHAN_INPUT_OPEN:
102 		debug("channel %d: input open -> drain", c->self);
103 		chan_shutdown_read(c);
104 		c->istate = CHAN_INPUT_WAIT_DRAIN;
105 		if (buffer_len(&c->input) == 0) {
106 			debug("channel %d: input: no drain shortcut", c->self);
107 			chan_ibuf_empty(c);
108 		}
109 		break;
110 	default:
111 		error("channel %d: internal error: we do not read, but chan_read_failed for istate %d",
112 		    c->self, c->istate);
113 		break;
114 	}
115 }
116 static void
117 chan_ibuf_empty1(Channel *c)
118 {
119 	debug("channel %d: ibuf empty", c->self);
120 	if (buffer_len(&c->input)) {
121 		error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
122 		    c->self);
123 		return;
124 	}
125 	switch (c->istate) {
126 	case CHAN_INPUT_WAIT_DRAIN:
127 		debug("channel %d: input drain -> wait_oclose", c->self);
128 		chan_send_ieof1(c);
129 		c->istate = CHAN_INPUT_WAIT_OCLOSE;
130 		break;
131 	default:
132 		error("channel %d: internal error: chan_ibuf_empty for istate %d",
133 		    c->self, c->istate);
134 		break;
135 	}
136 }
137 static void
138 chan_rcvd_ieof1(Channel *c)
139 {
140 	debug("channel %d: rcvd ieof", c->self);
141 	if (c->type != SSH_CHANNEL_OPEN) {
142 		debug("channel %d: non-open", c->self);
143 		if (c->istate == CHAN_INPUT_OPEN) {
144 			debug("channel %d: non-open: input open -> wait_oclose", c->self);
145 			chan_shutdown_read(c);
146 			chan_send_ieof1(c);
147 			c->istate = CHAN_INPUT_WAIT_OCLOSE;
148 		} else {
149 			error("channel %d: istate %d != open", c->self, c->istate);
150 		}
151 		if (c->ostate == CHAN_OUTPUT_OPEN) {
152 			debug("channel %d: non-open: output open -> closed", c->self);
153 			chan_send_oclose1(c);
154 			c->ostate = CHAN_OUTPUT_CLOSED;
155 		} else {
156 			error("channel %d: ostate %d != open", c->self, c->ostate);
157 		}
158 		return;
159 	}
160 	switch (c->ostate) {
161 	case CHAN_OUTPUT_OPEN:
162 		debug("channel %d: output open -> drain", c->self);
163 		c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
164 		break;
165 	case CHAN_OUTPUT_WAIT_IEOF:
166 		debug("channel %d: output wait_ieof -> closed", c->self);
167 		c->ostate = CHAN_OUTPUT_CLOSED;
168 		break;
169 	default:
170 		error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
171 		    c->self, c->ostate);
172 		break;
173 	}
174 }
175 static void
176 chan_write_failed1(Channel *c)
177 {
178 	debug("channel %d: write failed", c->self);
179 	switch (c->ostate) {
180 	case CHAN_OUTPUT_OPEN:
181 		debug("channel %d: output open -> wait_ieof", c->self);
182 		chan_send_oclose1(c);
183 		c->ostate = CHAN_OUTPUT_WAIT_IEOF;
184 		break;
185 	case CHAN_OUTPUT_WAIT_DRAIN:
186 		debug("channel %d: output wait_drain -> closed", c->self);
187 		chan_send_oclose1(c);
188 		c->ostate = CHAN_OUTPUT_CLOSED;
189 		break;
190 	default:
191 		error("channel %d: internal error: chan_write_failed for ostate %d",
192 		    c->self, c->ostate);
193 		break;
194 	}
195 }
196 static void
197 chan_obuf_empty1(Channel *c)
198 {
199 	debug("channel %d: obuf empty", c->self);
200 	if (buffer_len(&c->output)) {
201 		error("channel %d: internal error: chan_obuf_empty for non empty buffer",
202 		    c->self);
203 		return;
204 	}
205 	switch (c->ostate) {
206 	case CHAN_OUTPUT_WAIT_DRAIN:
207 		debug("channel %d: output drain -> closed", c->self);
208 		chan_send_oclose1(c);
209 		c->ostate = CHAN_OUTPUT_CLOSED;
210 		break;
211 	default:
212 		error("channel %d: internal error: chan_obuf_empty for ostate %d",
213 		    c->self, c->ostate);
214 		break;
215 	}
216 }
217 static void
218 chan_send_ieof1(Channel *c)
219 {
220 	debug("channel %d: send ieof", c->self);
221 	switch (c->istate) {
222 	case CHAN_INPUT_OPEN:
223 	case CHAN_INPUT_WAIT_DRAIN:
224 		packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
225 		packet_put_int(c->remote_id);
226 		packet_send();
227 		break;
228 	default:
229 		error("channel %d: internal error: cannot send ieof for istate %d",
230 		    c->self, c->istate);
231 		break;
232 	}
233 }
234 static void
235 chan_send_oclose1(Channel *c)
236 {
237 	debug("channel %d: send oclose", c->self);
238 	switch (c->ostate) {
239 	case CHAN_OUTPUT_OPEN:
240 	case CHAN_OUTPUT_WAIT_DRAIN:
241 		chan_shutdown_write(c);
242 		buffer_consume(&c->output, buffer_len(&c->output));
243 		packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
244 		packet_put_int(c->remote_id);
245 		packet_send();
246 		break;
247 	default:
248 		error("channel %d: internal error: cannot send oclose for ostate %d",
249 		     c->self, c->ostate);
250 		break;
251 	}
252 }
253 static void
254 chan_delete_if_full_closed1(Channel *c)
255 {
256 	if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
257 		debug("channel %d: full closed", c->self);
258 		channel_free(c->self);
259 	}
260 }
261 
262 /*
263  * the same for SSH2
264  */
265 static void
266 chan_rcvd_oclose2(Channel *c)
267 {
268 	debug("channel %d: rcvd close", c->self);
269 	if (c->flags & CHAN_CLOSE_RCVD)
270 		error("channel %d: protocol error: close rcvd twice", c->self);
271 	c->flags |= CHAN_CLOSE_RCVD;
272 	if (c->type == SSH_CHANNEL_LARVAL) {
273 		/* tear down larval channels immediately */
274 		c->ostate = CHAN_OUTPUT_CLOSED;
275 		c->istate = CHAN_INPUT_CLOSED;
276 		return;
277 	}
278 	switch (c->ostate) {
279 	case CHAN_OUTPUT_OPEN:
280 		/* wait until a data from the channel is consumed if a CLOSE is received */
281 		debug("channel %d: output open -> drain", c->self);
282 		c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
283 		break;
284 	}
285 	switch (c->istate) {
286 	case CHAN_INPUT_OPEN:
287 		debug("channel %d: input open -> closed", c->self);
288 		chan_shutdown_read(c);
289 		break;
290 	case CHAN_INPUT_WAIT_DRAIN:
291 		debug("channel %d: input drain -> closed", c->self);
292 		chan_send_eof2(c);
293 		break;
294 	}
295 	c->istate = CHAN_INPUT_CLOSED;
296 }
297 static void
298 chan_ibuf_empty2(Channel *c)
299 {
300 	debug("channel %d: ibuf empty", c->self);
301 	if (buffer_len(&c->input)) {
302 		error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
303 		     c->self);
304 		return;
305 	}
306 	switch (c->istate) {
307 	case CHAN_INPUT_WAIT_DRAIN:
308 		debug("channel %d: input drain -> closed", c->self);
309 		if (!(c->flags & CHAN_CLOSE_SENT))
310 			chan_send_eof2(c);
311 		c->istate = CHAN_INPUT_CLOSED;
312 		break;
313 	default:
314 		error("channel %d: internal error: chan_ibuf_empty for istate %d",
315 		     c->self, c->istate);
316 		break;
317 	}
318 }
319 static void
320 chan_rcvd_ieof2(Channel *c)
321 {
322 	debug("channel %d: rcvd eof", c->self);
323 	if (c->ostate == CHAN_OUTPUT_OPEN) {
324 		debug("channel %d: output open -> drain", c->self);
325 		c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
326 	}
327 }
328 static void
329 chan_write_failed2(Channel *c)
330 {
331 	debug("channel %d: write failed", c->self);
332 	switch (c->ostate) {
333 	case CHAN_OUTPUT_OPEN:
334 		debug("channel %d: output open -> closed", c->self);
335 		chan_shutdown_write(c); /* ?? */
336 		c->ostate = CHAN_OUTPUT_CLOSED;
337 		break;
338 	case CHAN_OUTPUT_WAIT_DRAIN:
339 		debug("channel %d: output drain -> closed", c->self);
340 		chan_shutdown_write(c);
341 		c->ostate = CHAN_OUTPUT_CLOSED;
342 		break;
343 	default:
344 		error("channel %d: internal error: chan_write_failed for ostate %d",
345 		    c->self, c->ostate);
346 		break;
347 	}
348 }
349 static void
350 chan_obuf_empty2(Channel *c)
351 {
352 	debug("channel %d: obuf empty", c->self);
353 	if (buffer_len(&c->output)) {
354 		error("internal error: chan_obuf_empty %d for non empty buffer",
355 		    c->self);
356 		return;
357 	}
358 	switch (c->ostate) {
359 	case CHAN_OUTPUT_WAIT_DRAIN:
360 		debug("channel %d: output drain -> closed", c->self);
361 		chan_shutdown_write(c);
362 		c->ostate = CHAN_OUTPUT_CLOSED;
363 		break;
364 	default:
365 		error("channel %d: internal error: chan_obuf_empty for ostate %d",
366 		    c->self, c->ostate);
367 		break;
368 	}
369 }
370 static void
371 chan_send_eof2(Channel *c)
372 {
373 	debug("channel %d: send eof", c->self);
374 	switch (c->istate) {
375 	case CHAN_INPUT_WAIT_DRAIN:
376 		packet_start(SSH2_MSG_CHANNEL_EOF);
377 		packet_put_int(c->remote_id);
378 		packet_send();
379 		break;
380 	default:
381 		error("channel %d: internal error: cannot send eof for istate %d",
382 		    c->self, c->istate);
383 		break;
384 	}
385 }
386 static void
387 chan_send_close2(Channel *c)
388 {
389 	debug("channel %d: send close", c->self);
390 	if (c->ostate != CHAN_OUTPUT_CLOSED ||
391 	    c->istate != CHAN_INPUT_CLOSED) {
392 		error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
393 		    c->self, c->istate, c->ostate);
394 	} else if (c->flags & CHAN_CLOSE_SENT) {
395 		error("channel %d: internal error: already sent close", c->self);
396 	} else {
397 		packet_start(SSH2_MSG_CHANNEL_CLOSE);
398 		packet_put_int(c->remote_id);
399 		packet_send();
400 		c->flags |= CHAN_CLOSE_SENT;
401 	}
402 }
403 static void
404 chan_delete_if_full_closed2(Channel *c)
405 {
406 	if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
407 		if (!(c->flags & CHAN_CLOSE_SENT)) {
408 			chan_send_close2(c);
409 		}
410 		if ((c->flags & CHAN_CLOSE_SENT) &&
411 		    (c->flags & CHAN_CLOSE_RCVD)) {
412 			debug("channel %d: full closed2", c->self);
413 			channel_free(c->self);
414 		}
415 	}
416 }
417 
418 /* shared */
419 void
420 chan_init_iostates(Channel *c)
421 {
422 	c->ostate = CHAN_OUTPUT_OPEN;
423 	c->istate = CHAN_INPUT_OPEN;
424 	c->flags = 0;
425 }
426 
427 /* init */
428 void
429 chan_init(void)
430 {
431 	if (compat20) {
432 		chan_rcvd_oclose		= chan_rcvd_oclose2;
433 		chan_read_failed		= chan_read_failed_12;
434 		chan_ibuf_empty			= chan_ibuf_empty2;
435 
436 		chan_rcvd_ieof			= chan_rcvd_ieof2;
437 		chan_write_failed		= chan_write_failed2;
438 		chan_obuf_empty			= chan_obuf_empty2;
439 
440 		chan_delete_if_full_closed	= chan_delete_if_full_closed2;
441 	} else {
442 		chan_rcvd_oclose		= chan_rcvd_oclose1;
443 		chan_read_failed		= chan_read_failed_12;
444 		chan_ibuf_empty			= chan_ibuf_empty1;
445 
446 		chan_rcvd_ieof			= chan_rcvd_ieof1;
447 		chan_write_failed		= chan_write_failed1;
448 		chan_obuf_empty			= chan_obuf_empty1;
449 
450 		chan_delete_if_full_closed	= chan_delete_if_full_closed1;
451 	}
452 }
453 
454 /* helper */
455 static void
456 chan_shutdown_write(Channel *c)
457 {
458 	buffer_consume(&c->output, buffer_len(&c->output));
459 	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
460 		return;
461 	/* shutdown failure is allowed if write failed already */
462 	debug("channel %d: close_write", c->self);
463 	if (c->sock != -1) {
464 		if (shutdown(c->sock, SHUT_WR) < 0)
465 			debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
466 			    c->self, c->sock, strerror(errno));
467 	} else {
468 		if (close(c->wfd) < 0)
469 			log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
470 			    c->self, c->wfd, strerror(errno));
471 		c->wfd = -1;
472 	}
473 }
474 static void
475 chan_shutdown_read(Channel *c)
476 {
477 	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
478 		return;
479 	debug("channel %d: close_read", c->self);
480 	if (c->sock != -1) {
481 		if (shutdown(c->sock, SHUT_RD) < 0)
482 			error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
483 			    c->self, c->sock, c->istate, c->ostate, strerror(errno));
484 	} else {
485 		if (close(c->rfd) < 0)
486 			log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
487 			    c->self, c->rfd, strerror(errno));
488 		c->rfd = -1;
489 	}
490 }
491