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