Branch data Line data Source code
1 : : /* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
2 : : /*
3 : : * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions
7 : : * are met:
8 : : * 1. Redistributions of source code must retain the above copyright
9 : : * notice, this list of conditions and the following disclaimer.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : *
14 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 : : */
25 : :
26 : : #include "includes.h"
27 : :
28 : : #include <sys/types.h>
29 : : #include <sys/socket.h>
30 : :
31 : : #include <errno.h>
32 : : #include <string.h>
33 : : #include <stdarg.h>
34 : :
35 : : #include "openbsd-compat/sys-queue.h"
36 : : #include "ssh1.h"
37 : : #include "ssh2.h"
38 : : #include "buffer.h"
39 : : #include "packet.h"
40 : : #include "channels.h"
41 : : #include "compat.h"
42 : : #include "log.h"
43 : :
44 : : /*
45 : : * SSH Protocol 1.5 aka New Channel Protocol
46 : : * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
47 : : * Written by Markus Friedl in October 1999
48 : : *
49 : : * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
50 : : * tear down of channels:
51 : : *
52 : : * 1.3: strict request-ack-protocol:
53 : : * CLOSE ->
54 : : * <- CLOSE_CONFIRM
55 : : *
56 : : * 1.5: uses variations of:
57 : : * IEOF ->
58 : : * <- OCLOSE
59 : : * <- IEOF
60 : : * OCLOSE ->
61 : : * i.e. both sides have to close the channel
62 : : *
63 : : * 2.0: the EOF messages are optional
64 : : *
65 : : * See the debugging output from 'ssh -v' and 'sshd -d' of
66 : : * ssh-1.2.27 as an example.
67 : : *
68 : : */
69 : :
70 : : /* functions manipulating channel states */
71 : : /*
72 : : * EVENTS update channel input/output states execute ACTIONS
73 : : */
74 : : /*
75 : : * ACTIONS: should never update the channel states
76 : : */
77 : : static void chan_send_ieof1(Channel *);
78 : : static void chan_send_oclose1(Channel *);
79 : : static void chan_send_close2(Channel *);
80 : : static void chan_send_eof2(Channel *);
81 : : static void chan_send_eow2(Channel *);
82 : :
83 : : /* helper */
84 : : static void chan_shutdown_write(Channel *);
85 : : static void chan_shutdown_read(Channel *);
86 : :
87 : : static char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
88 : : static char *istates[] = { "open", "drain", "wait_oclose", "closed" };
89 : :
90 : : static void
91 : 2148 : chan_set_istate(Channel *c, u_int next)
92 : : {
93 [ + - ][ - + ]: 1074 : if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
94 : 0 : fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
95 : 1074 : debug2("channel %d: input %s -> %s", c->self, istates[c->istate],
96 : : istates[next]);
97 : 1074 : c->istate = next;
98 : 1074 : }
99 : : static void
100 : 3246 : chan_set_ostate(Channel *c, u_int next)
101 : : {
102 [ + - ][ - + ]: 1623 : if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
103 : 0 : fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
104 : 1623 : debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate],
105 : : ostates[next]);
106 : 1623 : c->ostate = next;
107 : 1623 : }
108 : :
109 : : /*
110 : : * SSH1 specific implementation of event functions
111 : : */
112 : :
113 : : static void
114 : 46 : chan_rcvd_oclose1(Channel *c)
115 : : {
116 : 46 : debug2("channel %d: rcvd oclose", c->self);
117 [ + - - - ]: 46 : switch (c->istate) {
118 : : case CHAN_INPUT_WAIT_OCLOSE:
119 : 46 : chan_set_istate(c, CHAN_INPUT_CLOSED);
120 : 46 : break;
121 : : case CHAN_INPUT_OPEN:
122 : 0 : chan_shutdown_read(c);
123 : 0 : chan_send_ieof1(c);
124 : 0 : chan_set_istate(c, CHAN_INPUT_CLOSED);
125 : 0 : break;
126 : : case CHAN_INPUT_WAIT_DRAIN:
127 : : /* both local read_failed and remote write_failed */
128 : 0 : chan_send_ieof1(c);
129 : 0 : chan_set_istate(c, CHAN_INPUT_CLOSED);
130 : 0 : break;
131 : : default:
132 : 0 : error("channel %d: protocol error: rcvd_oclose for istate %d",
133 : : c->self, c->istate);
134 : 0 : return;
135 : : }
136 : : }
137 : : void
138 : 212 : chan_read_failed(Channel *c)
139 : : {
140 : 212 : debug2("channel %d: read failed", c->self);
141 [ + - ]: 212 : switch (c->istate) {
142 : : case CHAN_INPUT_OPEN:
143 : 212 : chan_shutdown_read(c);
144 : 212 : chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
145 : 212 : break;
146 : : default:
147 : 0 : error("channel %d: chan_read_failed for istate %d",
148 : : c->self, c->istate);
149 : 0 : break;
150 : : }
151 : 212 : }
152 : : void
153 : 216 : chan_ibuf_empty(Channel *c)
154 : : {
155 : 216 : debug2("channel %d: ibuf empty", c->self);
156 [ - + ]: 216 : if (buffer_len(&c->input)) {
157 : 0 : error("channel %d: chan_ibuf_empty for non empty buffer",
158 : : c->self);
159 : 0 : return;
160 : : }
161 [ + - ]: 216 : switch (c->istate) {
162 : : case CHAN_INPUT_WAIT_DRAIN:
163 [ + + ]: 216 : if (compat20) {
164 [ + + ]: 170 : if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
165 : 162 : chan_send_eof2(c);
166 : 170 : chan_set_istate(c, CHAN_INPUT_CLOSED);
167 : : } else {
168 : 46 : chan_send_ieof1(c);
169 : 46 : chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
170 : : }
171 : : break;
172 : : default:
173 : 0 : error("channel %d: chan_ibuf_empty for istate %d",
174 : : c->self, c->istate);
175 : 0 : break;
176 : : }
177 : : }
178 : : static void
179 : 46 : chan_rcvd_ieof1(Channel *c)
180 : : {
181 : 46 : debug2("channel %d: rcvd ieof", c->self);
182 [ + - - ]: 46 : switch (c->ostate) {
183 : : case CHAN_OUTPUT_OPEN:
184 : 46 : chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
185 : 46 : break;
186 : : case CHAN_OUTPUT_WAIT_IEOF:
187 : 0 : chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
188 : 0 : break;
189 : : default:
190 : 0 : error("channel %d: protocol error: rcvd_ieof for ostate %d",
191 : : c->self, c->ostate);
192 : 0 : break;
193 : : }
194 : 46 : }
195 : : static void
196 : 0 : chan_write_failed1(Channel *c)
197 : : {
198 : 0 : debug2("channel %d: write failed", c->self);
199 [ # # # ]: 0 : switch (c->ostate) {
200 : : case CHAN_OUTPUT_OPEN:
201 : 0 : chan_shutdown_write(c);
202 : 0 : chan_send_oclose1(c);
203 : 0 : chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
204 : 0 : break;
205 : : case CHAN_OUTPUT_WAIT_DRAIN:
206 : 0 : chan_shutdown_write(c);
207 : 0 : chan_send_oclose1(c);
208 : 0 : chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
209 : 0 : break;
210 : : default:
211 : 0 : error("channel %d: chan_write_failed for ostate %d",
212 : : c->self, c->ostate);
213 : 0 : break;
214 : : }
215 : 0 : }
216 : : void
217 : 807 : chan_obuf_empty(Channel *c)
218 : : {
219 : 807 : debug2("channel %d: obuf empty", c->self);
220 [ - + ]: 807 : if (buffer_len(&c->output)) {
221 : 0 : error("channel %d: chan_obuf_empty for non empty buffer",
222 : : c->self);
223 : 0 : return;
224 : : }
225 [ + - ]: 807 : switch (c->ostate) {
226 : : case CHAN_OUTPUT_WAIT_DRAIN:
227 : 807 : chan_shutdown_write(c);
228 [ + + ]: 807 : if (!compat20)
229 : 46 : chan_send_oclose1(c);
230 : 807 : chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
231 : 807 : break;
232 : : default:
233 : 0 : error("channel %d: internal error: obuf_empty for ostate %d",
234 : : c->self, c->ostate);
235 : 0 : break;
236 : : }
237 : : }
238 : : static void
239 : 46 : chan_send_ieof1(Channel *c)
240 : : {
241 : 46 : debug2("channel %d: send ieof", c->self);
242 [ + - ]: 46 : switch (c->istate) {
243 : : case CHAN_INPUT_OPEN:
244 : : case CHAN_INPUT_WAIT_DRAIN:
245 : 46 : packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
246 : 46 : packet_put_int(c->remote_id);
247 : 46 : packet_send();
248 : 46 : break;
249 : : default:
250 : 0 : error("channel %d: cannot send ieof for istate %d",
251 : : c->self, c->istate);
252 : 0 : break;
253 : : }
254 : 46 : }
255 : : static void
256 : 46 : chan_send_oclose1(Channel *c)
257 : : {
258 : 46 : debug2("channel %d: send oclose", c->self);
259 [ + - ]: 46 : switch (c->ostate) {
260 : : case CHAN_OUTPUT_OPEN:
261 : : case CHAN_OUTPUT_WAIT_DRAIN:
262 : 46 : buffer_clear(&c->output);
263 : 46 : packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
264 : 46 : packet_put_int(c->remote_id);
265 : 46 : packet_send();
266 : 46 : break;
267 : : default:
268 : 0 : error("channel %d: cannot send oclose for ostate %d",
269 : : c->self, c->ostate);
270 : 0 : break;
271 : : }
272 : 46 : }
273 : :
274 : : /*
275 : : * the same for SSH2
276 : : */
277 : : static void
278 : 769 : chan_rcvd_close2(Channel *c)
279 : : {
280 : 769 : debug2("channel %d: rcvd close", c->self);
281 [ + + ]: 769 : if (!(c->flags & CHAN_LOCAL)) {
282 [ - + ]: 745 : if (c->flags & CHAN_CLOSE_RCVD)
283 : 0 : error("channel %d: protocol error: close rcvd twice",
284 : : c->self);
285 : 745 : c->flags |= CHAN_CLOSE_RCVD;
286 : : }
287 [ - + ]: 769 : if (c->type == SSH_CHANNEL_LARVAL) {
288 : : /* tear down larval channels immediately */
289 : 0 : chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
290 : 0 : chan_set_istate(c, CHAN_INPUT_CLOSED);
291 : 0 : return;
292 : : }
293 [ + + ]: 769 : switch (c->ostate) {
294 : : case CHAN_OUTPUT_OPEN:
295 : : /*
296 : : * wait until a data from the channel is consumed if a CLOSE
297 : : * is received
298 : : */
299 : 24 : chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
300 : 24 : break;
301 : : }
302 [ + - + ]: 769 : switch (c->istate) {
303 : : case CHAN_INPUT_OPEN:
304 : 16 : chan_shutdown_read(c);
305 : 16 : chan_set_istate(c, CHAN_INPUT_CLOSED);
306 : 16 : break;
307 : : case CHAN_INPUT_WAIT_DRAIN:
308 [ # # ]: 0 : if (!(c->flags & CHAN_LOCAL))
309 : 0 : chan_send_eof2(c);
310 : 0 : chan_set_istate(c, CHAN_INPUT_CLOSED);
311 : 0 : break;
312 : : }
313 : : }
314 : :
315 : : void
316 : 584 : chan_rcvd_eow(Channel *c)
317 : : {
318 : 584 : debug2("channel %d: rcvd eow", c->self);
319 [ + - ]: 584 : switch (c->istate) {
320 : : case CHAN_INPUT_OPEN:
321 : 584 : chan_shutdown_read(c);
322 : 584 : chan_set_istate(c, CHAN_INPUT_CLOSED);
323 : 584 : break;
324 : : }
325 : 584 : }
326 : : static void
327 : 737 : chan_rcvd_eof2(Channel *c)
328 : : {
329 : 737 : debug2("channel %d: rcvd eof", c->self);
330 : 737 : c->flags |= CHAN_EOF_RCVD;
331 [ + - ]: 737 : if (c->ostate == CHAN_OUTPUT_OPEN)
332 : 737 : chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
333 : 737 : }
334 : : static void
335 : 9 : chan_write_failed2(Channel *c)
336 : : {
337 : 9 : debug2("channel %d: write failed", c->self);
338 [ + - ]: 9 : switch (c->ostate) {
339 : : case CHAN_OUTPUT_OPEN:
340 : : case CHAN_OUTPUT_WAIT_DRAIN:
341 : 9 : chan_shutdown_write(c);
342 [ + - ]: 9 : if (strcmp(c->ctype, "session") == 0)
343 : 9 : chan_send_eow2(c);
344 : 9 : chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
345 : 9 : break;
346 : : default:
347 : 0 : error("channel %d: chan_write_failed for ostate %d",
348 : : c->self, c->ostate);
349 : 0 : break;
350 : : }
351 : 9 : }
352 : : static void
353 : 162 : chan_send_eof2(Channel *c)
354 : : {
355 : 162 : debug2("channel %d: send eof", c->self);
356 [ + - ]: 162 : switch (c->istate) {
357 : : case CHAN_INPUT_WAIT_DRAIN:
358 : 162 : packet_start(SSH2_MSG_CHANNEL_EOF);
359 : 162 : packet_put_int(c->remote_id);
360 : 162 : packet_send();
361 : 162 : c->flags |= CHAN_EOF_SENT;
362 : 162 : break;
363 : : default:
364 : 0 : error("channel %d: cannot send eof for istate %d",
365 : : c->self, c->istate);
366 : 0 : break;
367 : : }
368 : 162 : }
369 : : static void
370 : 746 : chan_send_close2(Channel *c)
371 : : {
372 : 746 : debug2("channel %d: send close", c->self);
373 [ + - ][ - + ]: 746 : if (c->ostate != CHAN_OUTPUT_CLOSED ||
374 : 746 : c->istate != CHAN_INPUT_CLOSED) {
375 : 0 : error("channel %d: cannot send close for istate/ostate %d/%d",
376 : : c->self, c->istate, c->ostate);
377 [ - + ]: 746 : } else if (c->flags & CHAN_CLOSE_SENT) {
378 : 0 : error("channel %d: already sent close", c->self);
379 : : } else {
380 : 746 : packet_start(SSH2_MSG_CHANNEL_CLOSE);
381 : 746 : packet_put_int(c->remote_id);
382 : 746 : packet_send();
383 : 746 : c->flags |= CHAN_CLOSE_SENT;
384 : : }
385 : 746 : }
386 : : static void
387 : 9 : chan_send_eow2(Channel *c)
388 : : {
389 : 9 : debug2("channel %d: send eow", c->self);
390 [ - + ]: 9 : if (c->ostate == CHAN_OUTPUT_CLOSED) {
391 : 0 : error("channel %d: must not sent eow on closed output",
392 : : c->self);
393 : 0 : return;
394 : : }
395 [ + - ]: 9 : if (!(datafellows & SSH_NEW_OPENSSH))
396 : : return;
397 : 9 : packet_start(SSH2_MSG_CHANNEL_REQUEST);
398 : 9 : packet_put_int(c->remote_id);
399 : 9 : packet_put_cstring("eow@openssh.com");
400 : 9 : packet_put_char(0);
401 : 9 : packet_send();
402 : : }
403 : :
404 : : /* shared */
405 : :
406 : : void
407 : 783 : chan_rcvd_ieof(Channel *c)
408 : : {
409 [ + + ]: 783 : if (compat20)
410 : 737 : chan_rcvd_eof2(c);
411 : : else
412 : 46 : chan_rcvd_ieof1(c);
413 [ + - + + ]: 1566 : if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
414 [ + + ]: 1533 : buffer_len(&c->output) == 0 &&
415 [ + + ][ + - ]: 710 : !CHANNEL_EFD_OUTPUT_ACTIVE(c))
[ + - ][ + + ]
416 : 745 : chan_obuf_empty(c);
417 : 783 : }
418 : : void
419 : 815 : chan_rcvd_oclose(Channel *c)
420 : : {
421 [ + + ]: 815 : if (compat20)
422 : 769 : chan_rcvd_close2(c);
423 : : else
424 : 46 : chan_rcvd_oclose1(c);
425 : 815 : }
426 : : void
427 : 9 : chan_write_failed(Channel *c)
428 : : {
429 [ + - ]: 9 : if (compat20)
430 : 9 : chan_write_failed2(c);
431 : : else
432 : 0 : chan_write_failed1(c);
433 : 9 : }
434 : :
435 : : void
436 : 3 : chan_mark_dead(Channel *c)
437 : : {
438 : 3 : c->type = SSH_CHANNEL_ZOMBIE;
439 : 3 : }
440 : :
441 : : int
442 : 254127 : chan_is_dead(Channel *c, int do_send)
443 : : {
444 [ + + ]: 254127 : if (c->type == SSH_CHANNEL_ZOMBIE) {
445 : 3 : debug2("channel %d: zombie", c->self);
446 : 3 : return 1;
447 : : }
448 [ + + ][ + + ]: 254124 : if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
449 : : return 0;
450 [ + + ]: 1698 : if (!compat20) {
451 : 45 : debug2("channel %d: is dead", c->self);
452 : 45 : return 1;
453 : : }
454 [ - + ][ # # ]: 1653 : if ((datafellows & SSH_BUG_EXTEOF) &&
455 [ # # ]: 0 : c->extended_usage == CHAN_EXTENDED_WRITE &&
456 [ # # ]: 0 : c->efd != -1 &&
457 : 0 : buffer_len(&c->extended) > 0) {
458 : 0 : debug2("channel %d: active efd: %d len %d",
459 : : c->self, c->efd, buffer_len(&c->extended));
460 : 0 : return 0;
461 : : }
462 [ + + ]: 1653 : if (c->flags & CHAN_LOCAL) {
463 : 48 : debug2("channel %d: is dead (local)", c->self);
464 : 48 : return 1;
465 : : }
466 [ + + ]: 1605 : if (!(c->flags & CHAN_CLOSE_SENT)) {
467 [ + + ]: 1462 : if (do_send) {
468 : 746 : chan_send_close2(c);
469 : : } else {
470 : : /* channel would be dead if we sent a close */
471 [ + + ]: 716 : if (c->flags & CHAN_CLOSE_RCVD) {
472 : 690 : debug2("channel %d: almost dead",
473 : : c->self);
474 : 690 : return 1;
475 : : }
476 : : }
477 : : }
478 [ + + ]: 915 : if ((c->flags & CHAN_CLOSE_SENT) &&
479 : : (c->flags & CHAN_CLOSE_RCVD)) {
480 : 775 : debug2("channel %d: is dead", c->self);
481 : 775 : return 1;
482 : : }
483 : : return 0;
484 : : }
485 : :
486 : : /* helper */
487 : : static void
488 : 816 : chan_shutdown_write(Channel *c)
489 : : {
490 : 816 : buffer_clear(&c->output);
491 [ + + ][ + - ]: 816 : if (compat20 && c->type == SSH_CHANNEL_LARVAL)
492 : 816 : return;
493 : : /* shutdown failure is allowed if write failed already */
494 : 816 : debug2("channel %d: close_write", c->self);
495 [ + + ]: 816 : if (c->sock != -1) {
496 [ - + ]: 99 : if (shutdown(c->sock, SHUT_WR) < 0)
497 : 0 : debug2("channel %d: chan_shutdown_write: "
498 : : "shutdown() failed for fd %d: %.100s",
499 : 0 : c->self, c->sock, strerror(errno));
500 : : } else {
501 [ - + ]: 717 : if (channel_close_fd(&c->wfd) < 0)
502 : 0 : logit("channel %d: chan_shutdown_write: "
503 : : "close() failed for fd %d: %.100s",
504 : 0 : c->self, c->wfd, strerror(errno));
505 : : }
506 : : }
507 : : static void
508 : 812 : chan_shutdown_read(Channel *c)
509 : : {
510 [ + + ][ + - ]: 812 : if (compat20 && c->type == SSH_CHANNEL_LARVAL)
511 : 812 : return;
512 : 812 : debug2("channel %d: close_read", c->self);
513 [ + + ]: 812 : if (c->sock != -1) {
514 : : /*
515 : : * shutdown(sock, SHUT_READ) may return ENOTCONN if the
516 : : * write side has been closed already. (bug on Linux)
517 : : * HP-UX may return ENOTCONN also.
518 : : */
519 [ + + ]: 95 : if (shutdown(c->sock, SHUT_RD) < 0
520 [ - + ]: 32 : && errno != ENOTCONN)
521 : 0 : error("channel %d: chan_shutdown_read: "
522 : : "shutdown() failed for fd %d [i%d o%d]: %.100s",
523 : : c->self, c->sock, c->istate, c->ostate,
524 : : strerror(errno));
525 : : } else {
526 [ - + ]: 717 : if (channel_close_fd(&c->rfd) < 0)
527 : 0 : logit("channel %d: chan_shutdown_read: "
528 : : "close() failed for fd %d: %.100s",
529 : 0 : c->self, c->rfd, strerror(errno));
530 : : }
531 : : }
|