xref: /netbsd/crypto/external/bsd/openssh/dist/nchan.c (revision 84f89c72)
1 /*	$NetBSD: nchan.c,v 1.14 2022/02/23 19:07:20 christos Exp $	*/
2 /* $OpenBSD: nchan.c,v 1.74 2022/02/01 23:32:51 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.14 2022/02/23 19:07:20 christos 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 "ssh2.h"
38 #include "sshbuf.h"
39 #include "ssherr.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  */
78 static void	chan_send_eof2(struct ssh *, Channel *);
79 static void	chan_send_eow2(struct ssh *, Channel *);
80 
81 /* helper */
82 static void	chan_shutdown_write(struct ssh *, Channel *);
83 static void	chan_shutdown_read(struct ssh *, Channel *);
84 static void	chan_shutdown_extended_read(struct ssh *, Channel *);
85 
86 static const char * const ostates[] = {
87 	"open", "drain", "wait_ieof", "closed",
88 };
89 static const char * const istates[] = {
90 	"open", "drain", "wait_oclose", "closed",
91 };
92 
93 static void
chan_set_istate(Channel * c,u_int next)94 chan_set_istate(Channel *c, u_int next)
95 {
96 	if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
97 		fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
98 	debug2("channel %d: input %s -> %s", c->self, istates[c->istate],
99 	    istates[next]);
100 	c->istate = next;
101 }
102 
103 static void
chan_set_ostate(Channel * c,u_int next)104 chan_set_ostate(Channel *c, u_int next)
105 {
106 	if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
107 		fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
108 	debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate],
109 	    ostates[next]);
110 	c->ostate = next;
111 }
112 
113 void
chan_read_failed(struct ssh * ssh,Channel * c)114 chan_read_failed(struct ssh *ssh, Channel *c)
115 {
116 	debug2("channel %d: read failed", c->self);
117 	switch (c->istate) {
118 	case CHAN_INPUT_OPEN:
119 		chan_shutdown_read(ssh, c);
120 		chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
121 		break;
122 	default:
123 		error("channel %d: chan_read_failed for istate %d",
124 		    c->self, c->istate);
125 		break;
126 	}
127 }
128 
129 void
chan_ibuf_empty(struct ssh * ssh,Channel * c)130 chan_ibuf_empty(struct ssh *ssh, Channel *c)
131 {
132 	debug2("channel %d: ibuf empty", c->self);
133 	if (sshbuf_len(c->input)) {
134 		error("channel %d: chan_ibuf_empty for non empty buffer",
135 		    c->self);
136 		return;
137 	}
138 	switch (c->istate) {
139 	case CHAN_INPUT_WAIT_DRAIN:
140 		if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
141 			chan_send_eof2(ssh, c);
142 		chan_set_istate(c, CHAN_INPUT_CLOSED);
143 		break;
144 	default:
145 		error("channel %d: chan_ibuf_empty for istate %d",
146 		    c->self, c->istate);
147 		break;
148 	}
149 }
150 
151 void
chan_obuf_empty(struct ssh * ssh,Channel * c)152 chan_obuf_empty(struct ssh *ssh, Channel *c)
153 {
154 	debug2("channel %d: obuf empty", c->self);
155 	if (sshbuf_len(c->output)) {
156 		error("channel %d: chan_obuf_empty for non empty buffer",
157 		    c->self);
158 		return;
159 	}
160 	switch (c->ostate) {
161 	case CHAN_OUTPUT_WAIT_DRAIN:
162 		chan_shutdown_write(ssh, c);
163 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
164 		break;
165 	default:
166 		error("channel %d: internal error: obuf_empty for ostate %d",
167 		    c->self, c->ostate);
168 		break;
169 	}
170 }
171 
172 void
chan_rcvd_eow(struct ssh * ssh,Channel * c)173 chan_rcvd_eow(struct ssh *ssh, Channel *c)
174 {
175 	debug2("channel %d: rcvd eow", c->self);
176 	switch (c->istate) {
177 	case CHAN_INPUT_OPEN:
178 		chan_shutdown_read(ssh, c);
179 		chan_set_istate(c, CHAN_INPUT_CLOSED);
180 		break;
181 	}
182 }
183 
184 static void
chan_send_eof2(struct ssh * ssh,Channel * c)185 chan_send_eof2(struct ssh *ssh, Channel *c)
186 {
187 	int r;
188 
189 	debug2("channel %d: send eof", c->self);
190 	switch (c->istate) {
191 	case CHAN_INPUT_WAIT_DRAIN:
192 		if (!c->have_remote_id)
193 			fatal_f("channel %d: no remote_id", c->self);
194 		if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 ||
195 		    (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
196 		    (r = sshpkt_send(ssh)) != 0)
197 			fatal_fr(r, "send CHANNEL_EOF");
198 		c->flags |= CHAN_EOF_SENT;
199 		break;
200 	default:
201 		error("channel %d: cannot send eof for istate %d",
202 		    c->self, c->istate);
203 		break;
204 	}
205 }
206 
207 static void
chan_send_close2(struct ssh * ssh,Channel * c)208 chan_send_close2(struct ssh *ssh, Channel *c)
209 {
210 	int r;
211 
212 	debug2("channel %d: send close", c->self);
213 	if (c->ostate != CHAN_OUTPUT_CLOSED ||
214 	    c->istate != CHAN_INPUT_CLOSED) {
215 		error("channel %d: cannot send close for istate/ostate %d/%d",
216 		    c->self, c->istate, c->ostate);
217 	} else if (c->flags & CHAN_CLOSE_SENT) {
218 		error("channel %d: already sent close", c->self);
219 	} else {
220 		if (!c->have_remote_id)
221 			fatal_f("channel %d: no remote_id", c->self);
222 		if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 ||
223 		    (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
224 		    (r = sshpkt_send(ssh)) != 0)
225 			fatal_fr(r, "send CHANNEL_EOF");
226 		c->flags |= CHAN_CLOSE_SENT;
227 	}
228 }
229 
230 static void
chan_send_eow2(struct ssh * ssh,Channel * c)231 chan_send_eow2(struct ssh *ssh, Channel *c)
232 {
233 	int r;
234 
235 	debug2("channel %d: send eow", c->self);
236 	if (c->ostate == CHAN_OUTPUT_CLOSED) {
237 		error("channel %d: must not sent eow on closed output",
238 		    c->self);
239 		return;
240 	}
241 	if (!(ssh->compat & SSH_NEW_OPENSSH))
242 		return;
243 	if (!c->have_remote_id)
244 		fatal_f("channel %d: no remote_id", c->self);
245 	if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
246 	    (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
247 	    (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 ||
248 	    (r = sshpkt_put_u8(ssh, 0)) != 0 ||
249 	    (r = sshpkt_send(ssh)) != 0)
250 		fatal_fr(r, "send CHANNEL_EOF");
251 }
252 
253 /* shared */
254 
255 void
chan_rcvd_ieof(struct ssh * ssh,Channel * c)256 chan_rcvd_ieof(struct ssh *ssh, Channel *c)
257 {
258 	debug2("channel %d: rcvd eof", c->self);
259 	c->flags |= CHAN_EOF_RCVD;
260 	if (c->ostate == CHAN_OUTPUT_OPEN)
261 		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
262 	if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
263 	    sshbuf_len(c->output) == 0 &&
264 	    !CHANNEL_EFD_OUTPUT_ACTIVE(c))
265 		chan_obuf_empty(ssh, c);
266 }
267 
268 void
chan_rcvd_oclose(struct ssh * ssh,Channel * c)269 chan_rcvd_oclose(struct ssh *ssh, Channel *c)
270 {
271 	debug2("channel %d: rcvd close", c->self);
272 	if (!(c->flags & CHAN_LOCAL)) {
273 		if (c->flags & CHAN_CLOSE_RCVD)
274 			error("channel %d: protocol error: close rcvd twice",
275 			    c->self);
276 		c->flags |= CHAN_CLOSE_RCVD;
277 	}
278 	if (c->type == SSH_CHANNEL_LARVAL) {
279 		/* tear down larval channels immediately */
280 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
281 		chan_set_istate(c, CHAN_INPUT_CLOSED);
282 		return;
283 	}
284 	switch (c->ostate) {
285 	case CHAN_OUTPUT_OPEN:
286 		/*
287 		 * wait until a data from the channel is consumed if a CLOSE
288 		 * is received
289 		 */
290 		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
291 		break;
292 	}
293 	switch (c->istate) {
294 	case CHAN_INPUT_OPEN:
295 		chan_shutdown_read(ssh, c);
296 		chan_shutdown_extended_read(ssh, c);
297 		chan_set_istate(c, CHAN_INPUT_CLOSED);
298 		break;
299 	case CHAN_INPUT_WAIT_DRAIN:
300 		if (!(c->flags & CHAN_LOCAL))
301 			chan_send_eof2(ssh, c);
302 		chan_shutdown_extended_read(ssh, c);
303 		chan_set_istate(c, CHAN_INPUT_CLOSED);
304 		break;
305 	}
306 }
307 
308 void
chan_write_failed(struct ssh * ssh,Channel * c)309 chan_write_failed(struct ssh *ssh, Channel *c)
310 {
311 	debug2("channel %d: write failed", c->self);
312 	switch (c->ostate) {
313 	case CHAN_OUTPUT_OPEN:
314 	case CHAN_OUTPUT_WAIT_DRAIN:
315 		chan_shutdown_write(ssh, c);
316 		if (strcmp(c->ctype, "session") == 0)
317 			chan_send_eow2(ssh, c);
318 		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
319 		break;
320 	default:
321 		error("channel %d: chan_write_failed for ostate %d",
322 		    c->self, c->ostate);
323 		break;
324 	}
325 }
326 
327 void
chan_mark_dead(struct ssh * ssh,Channel * c)328 chan_mark_dead(struct ssh *ssh, Channel *c)
329 {
330 	c->type = SSH_CHANNEL_ZOMBIE;
331 }
332 
333 int
chan_is_dead(struct ssh * ssh,Channel * c,int do_send)334 chan_is_dead(struct ssh *ssh, Channel *c, int do_send)
335 {
336 	if (c->type == SSH_CHANNEL_ZOMBIE) {
337 		debug2("channel %d: zombie", c->self);
338 		return 1;
339 	}
340 	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
341 		return 0;
342 	if ((ssh->compat & SSH_BUG_EXTEOF) &&
343 	    c->extended_usage == CHAN_EXTENDED_WRITE &&
344 	    c->efd != -1 &&
345 	    sshbuf_len(c->extended) > 0) {
346 		debug2("channel %d: active efd: %d len %zu",
347 		    c->self, c->efd, sshbuf_len(c->extended));
348 		return 0;
349 	}
350 	if (c->flags & CHAN_LOCAL) {
351 		debug2("channel %d: is dead (local)", c->self);
352 		return 1;
353 	}
354 	if (!(c->flags & CHAN_CLOSE_SENT)) {
355 		if (do_send) {
356 			chan_send_close2(ssh, c);
357 		} else {
358 			/* channel would be dead if we sent a close */
359 			if (c->flags & CHAN_CLOSE_RCVD) {
360 				debug2("channel %d: almost dead",
361 				    c->self);
362 				return 1;
363 			}
364 		}
365 	}
366 	if ((c->flags & CHAN_CLOSE_SENT) &&
367 	    (c->flags & CHAN_CLOSE_RCVD)) {
368 		debug2("channel %d: is dead", c->self);
369 		return 1;
370 	}
371 	return 0;
372 }
373 
374 /* helper */
375 static void
chan_shutdown_write(struct ssh * ssh,Channel * c)376 chan_shutdown_write(struct ssh *ssh, Channel *c)
377 {
378 	sshbuf_reset(c->output);
379 	if (c->type == SSH_CHANNEL_LARVAL)
380 		return;
381 	/* shutdown failure is allowed if write failed already */
382 	debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
383 	    c->self, c->istate, c->ostate, c->sock, c->wfd, c->efd,
384 	    channel_format_extended_usage(c));
385 	if (c->sock != -1) {
386 		if (shutdown(c->sock, SHUT_WR) == -1) {
387 			debug2_f("channel %d: shutdown() failed for "
388 			    "fd %d [i%d o%d]: %.100s", c->self, c->sock,
389 			    c->istate, c->ostate, strerror(errno));
390 		}
391 	} else {
392 		if (channel_close_fd(ssh, c, &c->wfd) < 0) {
393 			logit_f("channel %d: close() failed for "
394 			    "fd %d [i%d o%d]: %.100s", c->self, c->wfd,
395 			    c->istate, c->ostate, strerror(errno));
396 		}
397 	}
398 }
399 
400 static void
chan_shutdown_read(struct ssh * ssh,Channel * c)401 chan_shutdown_read(struct ssh *ssh, Channel *c)
402 {
403 	if (c->type == SSH_CHANNEL_LARVAL)
404 		return;
405 	debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
406 	    c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
407 	    channel_format_extended_usage(c));
408 	if (c->sock != -1) {
409 		if (shutdown(c->sock, SHUT_RD) == -1) {
410 			error_f("channel %d: shutdown() failed for "
411 			    "fd %d [i%d o%d]: %.100s", c->self, c->sock,
412 			    c->istate, c->ostate, strerror(errno));
413 		}
414 	} else {
415 		if (channel_close_fd(ssh, c, &c->rfd) < 0) {
416 			logit_f("channel %d: close() failed for "
417 			    "fd %d [i%d o%d]: %.100s", c->self, c->rfd,
418 			    c->istate, c->ostate, strerror(errno));
419 		}
420 	}
421 }
422 
423 static void
chan_shutdown_extended_read(struct ssh * ssh,Channel * c)424 chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
425 {
426 	if (c->type == SSH_CHANNEL_LARVAL || c->efd == -1)
427 		return;
428 	if (c->extended_usage != CHAN_EXTENDED_READ &&
429 	    c->extended_usage != CHAN_EXTENDED_IGNORE)
430 		return;
431 	debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
432 	    c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
433 	    channel_format_extended_usage(c));
434 	if (channel_close_fd(ssh, c, &c->efd) < 0) {
435 		logit_f("channel %d: close() failed for "
436 		    "extended fd %d [i%d o%d]: %.100s", c->self, c->efd,
437 		    c->istate, c->ostate, strerror(errno));
438 	}
439 }
440