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