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