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