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