diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | channels.c | 28 | ||||
-rw-r--r-- | channels.h | 14 | ||||
-rw-r--r-- | compat.c | 22 | ||||
-rw-r--r-- | compat.h | 3 | ||||
-rw-r--r-- | nchan.c | 60 |
6 files changed, 84 insertions, 49 deletions
@@ -39,6 +39,10 @@ | |||
39 | - markus@cvs.openbsd.org 2002/03/25 21:04:02 | 39 | - markus@cvs.openbsd.org 2002/03/25 21:04:02 |
40 | [ssh.c] | 40 | [ssh.c] |
41 | simplify num_identity_files handling | 41 | simplify num_identity_files handling |
42 | - markus@cvs.openbsd.org 2002/03/25 21:13:51 | ||
43 | [channels.c channels.h compat.c compat.h nchan.c] | ||
44 | don't send stderr data after EOF, accept this from older known (broken) | ||
45 | sshd servers only, fixes http://bugzilla.mindrot.org/show_bug.cgi?id=179 | ||
42 | 46 | ||
43 | 20020324 | 47 | 20020324 |
44 | - (stevesk) [session.c] disable LOGIN_NEEDS_TERM until we are sure | 48 | - (stevesk) [session.c] disable LOGIN_NEEDS_TERM until we are sure |
@@ -8053,4 +8057,4 @@ | |||
8053 | - Wrote replacements for strlcpy and mkdtemp | 8057 | - Wrote replacements for strlcpy and mkdtemp |
8054 | - Released 1.0pre1 | 8058 | - Released 1.0pre1 |
8055 | 8059 | ||
8056 | $Id: ChangeLog,v 1.1989 2002/03/26 03:23:00 mouring Exp $ | 8060 | $Id: ChangeLog,v 1.1990 2002/03/26 03:26:24 mouring Exp $ |
diff --git a/channels.c b/channels.c index 2b1f33f34..95817624f 100644 --- a/channels.c +++ b/channels.c | |||
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $"); | 42 | RCSID("$OpenBSD: channels.c,v 1.172 2002/03/25 21:13:51 markus Exp $"); |
43 | 43 | ||
44 | #include "ssh.h" | 44 | #include "ssh.h" |
45 | #include "ssh1.h" | 45 | #include "ssh1.h" |
@@ -706,7 +706,11 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
706 | if (buffer_len(&c->output) > 0) { | 706 | if (buffer_len(&c->output) > 0) { |
707 | FD_SET(c->wfd, writeset); | 707 | FD_SET(c->wfd, writeset); |
708 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 708 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
709 | chan_obuf_empty(c); | 709 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
710 | debug2("channel %d: obuf_empty delayed efd %d/(%d)", | ||
711 | c->self, c->efd, buffer_len(&c->extended)); | ||
712 | else | ||
713 | chan_obuf_empty(c); | ||
710 | } | 714 | } |
711 | } | 715 | } |
712 | /** XXX check close conditions, too */ | 716 | /** XXX check close conditions, too */ |
@@ -714,7 +718,8 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset) | |||
714 | if (c->extended_usage == CHAN_EXTENDED_WRITE && | 718 | if (c->extended_usage == CHAN_EXTENDED_WRITE && |
715 | buffer_len(&c->extended) > 0) | 719 | buffer_len(&c->extended) > 0) |
716 | FD_SET(c->efd, writeset); | 720 | FD_SET(c->efd, writeset); |
717 | else if (c->extended_usage == CHAN_EXTENDED_READ && | 721 | else if (!(c->flags & CHAN_EOF_SENT) && |
722 | c->extended_usage == CHAN_EXTENDED_READ && | ||
718 | buffer_len(&c->extended) < c->remote_window) | 723 | buffer_len(&c->extended) < c->remote_window) |
719 | FD_SET(c->efd, readset); | 724 | FD_SET(c->efd, readset); |
720 | } | 725 | } |
@@ -1632,12 +1637,18 @@ channel_output_poll(void) | |||
1632 | fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); | 1637 | fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); |
1633 | /* | 1638 | /* |
1634 | * input-buffer is empty and read-socket shutdown: | 1639 | * input-buffer is empty and read-socket shutdown: |
1635 | * tell peer, that we will not send more data: send IEOF | 1640 | * tell peer, that we will not send more data: send IEOF. |
1641 | * hack for extended data: delay EOF if EFD still in use. | ||
1636 | */ | 1642 | */ |
1637 | chan_ibuf_empty(c); | 1643 | if (CHANNEL_EFD_INPUT_ACTIVE(c)) |
1644 | debug2("channel %d: ibuf_empty delayed efd %d/(%d)", | ||
1645 | c->self, c->efd, buffer_len(&c->extended)); | ||
1646 | else | ||
1647 | chan_ibuf_empty(c); | ||
1638 | } | 1648 | } |
1639 | /* Send extended data, i.e. stderr */ | 1649 | /* Send extended data, i.e. stderr */ |
1640 | if (compat20 && | 1650 | if (compat20 && |
1651 | !(c->flags & CHAN_EOF_SENT) && | ||
1641 | c->remote_window > 0 && | 1652 | c->remote_window > 0 && |
1642 | (len = buffer_len(&c->extended)) > 0 && | 1653 | (len = buffer_len(&c->extended)) > 0 && |
1643 | c->extended_usage == CHAN_EXTENDED_READ) { | 1654 | c->extended_usage == CHAN_EXTENDED_READ) { |
@@ -1726,6 +1737,13 @@ channel_input_extended_data(int type, u_int32_t seq, void *ctxt) | |||
1726 | log("channel %d: ext data for non open", id); | 1737 | log("channel %d: ext data for non open", id); |
1727 | return; | 1738 | return; |
1728 | } | 1739 | } |
1740 | if (c->flags & CHAN_EOF_RCVD) { | ||
1741 | if (datafellows & SSH_BUG_EXTEOF) | ||
1742 | debug("channel %d: accepting ext data after eof", id); | ||
1743 | else | ||
1744 | packet_disconnect("Received extended_data after EOF " | ||
1745 | "on channel %d.", id); | ||
1746 | } | ||
1729 | tcode = packet_get_int(); | 1747 | tcode = packet_get_int(); |
1730 | if (c->efd == -1 || | 1748 | if (c->efd == -1 || |
1731 | c->extended_usage != CHAN_EXTENDED_WRITE || | 1749 | c->extended_usage != CHAN_EXTENDED_WRITE || |
diff --git a/channels.h b/channels.h index 707d9a925..0da2d4e5e 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.65 2002/03/04 17:27:39 stevesk Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.66 2002/03/25 21:13:51 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -135,6 +135,18 @@ struct Channel { | |||
135 | 135 | ||
136 | #define CHAN_CLOSE_SENT 0x01 | 136 | #define CHAN_CLOSE_SENT 0x01 |
137 | #define CHAN_CLOSE_RCVD 0x02 | 137 | #define CHAN_CLOSE_RCVD 0x02 |
138 | #define CHAN_EOF_SENT 0x04 | ||
139 | #define CHAN_EOF_RCVD 0x08 | ||
140 | |||
141 | /* check whether 'efd' is still in use */ | ||
142 | #define CHANNEL_EFD_INPUT_ACTIVE(c) \ | ||
143 | (compat20 && c->extended_usage == CHAN_EXTENDED_READ && \ | ||
144 | (c->efd != -1 || \ | ||
145 | buffer_len(&c->extended) > 0)) | ||
146 | #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ | ||
147 | (compat20 && c->extended_usage == CHAN_EXTENDED_WRITE && \ | ||
148 | ((c->efd != -1 && !(c->flags & CHAN_EOF_RCVD)) || \ | ||
149 | buffer_len(&c->extended) > 0)) | ||
138 | 150 | ||
139 | /* channel management */ | 151 | /* channel management */ |
140 | 152 | ||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $"); | 26 | RCSID("$OpenBSD: compat.c,v 1.62 2002/03/25 21:13:51 markus Exp $"); |
27 | 27 | ||
28 | #include "buffer.h" | 28 | #include "buffer.h" |
29 | #include "packet.h" | 29 | #include "packet.h" |
@@ -61,20 +61,26 @@ compat_datafellows(const char *version) | |||
61 | "OpenSSH-2.1*," | 61 | "OpenSSH-2.1*," |
62 | "OpenSSH_2.1*," | 62 | "OpenSSH_2.1*," |
63 | "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| | 63 | "OpenSSH_2.2*", SSH_OLD_SESSIONID|SSH_BUG_BANNER| |
64 | SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, | 64 | SSH_OLD_DHGEX|SSH_BUG_NOREKEY| |
65 | SSH_BUG_EXTEOF}, | ||
65 | { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| | 66 | { "OpenSSH_2.3.0*", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES| |
66 | SSH_OLD_DHGEX|SSH_BUG_NOREKEY}, | 67 | SSH_OLD_DHGEX|SSH_BUG_NOREKEY| |
68 | SSH_BUG_EXTEOF}, | ||
67 | { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| | 69 | { "OpenSSH_2.3.*", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| |
68 | SSH_BUG_NOREKEY}, | 70 | SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, |
69 | { "OpenSSH_2.5.0p1*," | 71 | { "OpenSSH_2.5.0p1*," |
70 | "OpenSSH_2.5.1p1*", | 72 | "OpenSSH_2.5.1p1*", |
71 | SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| | 73 | SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX| |
72 | SSH_BUG_NOREKEY }, | 74 | SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, |
73 | { "OpenSSH_2.5.0*," | 75 | { "OpenSSH_2.5.0*," |
74 | "OpenSSH_2.5.1*," | 76 | "OpenSSH_2.5.1*," |
75 | "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY }, | 77 | "OpenSSH_2.5.2*", SSH_OLD_DHGEX|SSH_BUG_NOREKEY| |
76 | { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY }, | 78 | SSH_BUG_EXTEOF}, |
77 | { "Sun_SSH_1.0*", SSH_BUG_NOREKEY }, | 79 | { "OpenSSH_2.5.3*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, |
80 | { "OpenSSH_2.*," | ||
81 | "OpenSSH_3.0*," | ||
82 | "OpenSSH_3.1*", SSH_BUG_EXTEOF}, | ||
83 | { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF}, | ||
78 | { "OpenSSH*", 0 }, | 84 | { "OpenSSH*", 0 }, |
79 | { "*MindTerm*", 0 }, | 85 | { "*MindTerm*", 0 }, |
80 | { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| | 86 | { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: compat.h,v 1.30 2002/03/04 17:27:39 stevesk Exp $ */ | 1 | /* $OpenBSD: compat.h,v 1.31 2002/03/25 21:13:51 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. |
@@ -52,6 +52,7 @@ | |||
52 | #define SSH_BUG_OPENFAILURE 0x00020000 | 52 | #define SSH_BUG_OPENFAILURE 0x00020000 |
53 | #define SSH_BUG_DERIVEKEY 0x00040000 | 53 | #define SSH_BUG_DERIVEKEY 0x00040000 |
54 | #define SSH_BUG_DUMMYCHAN 0x00100000 | 54 | #define SSH_BUG_DUMMYCHAN 0x00100000 |
55 | #define SSH_BUG_EXTEOF 0x00200000 | ||
55 | 56 | ||
56 | void enable_compat13(void); | 57 | void enable_compat13(void); |
57 | void enable_compat20(void); | 58 | void enable_compat20(void); |
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: nchan.c,v 1.44 2002/01/21 23:27:10 markus Exp $"); | 26 | RCSID("$OpenBSD: nchan.c,v 1.45 2002/03/25 21:13:51 markus Exp $"); |
27 | 27 | ||
28 | #include "ssh1.h" | 28 | #include "ssh1.h" |
29 | #include "ssh2.h" | 29 | #include "ssh2.h" |
@@ -302,6 +302,7 @@ static void | |||
302 | chan_rcvd_eof2(Channel *c) | 302 | chan_rcvd_eof2(Channel *c) |
303 | { | 303 | { |
304 | debug("channel %d: rcvd eof", c->self); | 304 | debug("channel %d: rcvd eof", c->self); |
305 | c->flags |= CHAN_EOF_RCVD; | ||
305 | if (c->ostate == CHAN_OUTPUT_OPEN) | 306 | if (c->ostate == CHAN_OUTPUT_OPEN) |
306 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | 307 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
307 | } | 308 | } |
@@ -330,6 +331,7 @@ chan_send_eof2(Channel *c) | |||
330 | packet_start(SSH2_MSG_CHANNEL_EOF); | 331 | packet_start(SSH2_MSG_CHANNEL_EOF); |
331 | packet_put_int(c->remote_id); | 332 | packet_put_int(c->remote_id); |
332 | packet_send(); | 333 | packet_send(); |
334 | c->flags |= CHAN_EOF_SENT; | ||
333 | break; | 335 | break; |
334 | default: | 336 | default: |
335 | error("channel %d: cannot send eof for istate %d", | 337 | error("channel %d: cannot send eof for istate %d", |
@@ -365,7 +367,8 @@ chan_rcvd_ieof(Channel *c) | |||
365 | else | 367 | else |
366 | chan_rcvd_ieof1(c); | 368 | chan_rcvd_ieof1(c); |
367 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | 369 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && |
368 | buffer_len(&c->output) == 0) | 370 | buffer_len(&c->output) == 0 && |
371 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | ||
369 | chan_obuf_empty(c); | 372 | chan_obuf_empty(c); |
370 | } | 373 | } |
371 | void | 374 | void |
@@ -404,39 +407,30 @@ chan_is_dead(Channel *c, int send) | |||
404 | debug("channel %d: is dead", c->self); | 407 | debug("channel %d: is dead", c->self); |
405 | return 1; | 408 | return 1; |
406 | } | 409 | } |
407 | /* | 410 | if ((datafellows & SSH_BUG_EXTEOF) && |
408 | * we have to delay the close message if the efd (for stderr) is | 411 | c->extended_usage == CHAN_EXTENDED_WRITE && |
409 | * still active | 412 | c->efd != -1 && |
410 | */ | 413 | buffer_len(&c->extended) > 0) { |
411 | if (((c->extended_usage != CHAN_EXTENDED_IGNORE) && | 414 | debug2("channel %d: active efd: %d len %d", |
412 | buffer_len(&c->extended) > 0) | 415 | c->self, c->efd, buffer_len(&c->extended)); |
413 | #if 0 | 416 | return 0; |
414 | || ((c->extended_usage == CHAN_EXTENDED_READ) && | 417 | } |
415 | c->efd != -1) | 418 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
416 | #endif | 419 | if (send) { |
417 | ) { | 420 | chan_send_close2(c); |
418 | debug2("channel %d: active efd: %d len %d type %s", | 421 | } else { |
419 | c->self, c->efd, buffer_len(&c->extended), | 422 | /* channel would be dead if we sent a close */ |
420 | c->extended_usage==CHAN_EXTENDED_READ ? | 423 | if (c->flags & CHAN_CLOSE_RCVD) { |
421 | "read": "write"); | 424 | debug("channel %d: almost dead", |
422 | } else { | 425 | c->self); |
423 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 426 | return 1; |
424 | if (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 | debug("channel %d: almost dead", | ||
430 | c->self); | ||
431 | return 1; | ||
432 | } | ||
433 | } | 427 | } |
434 | } | 428 | } |
435 | if ((c->flags & CHAN_CLOSE_SENT) && | 429 | } |
436 | (c->flags & CHAN_CLOSE_RCVD)) { | 430 | if ((c->flags & CHAN_CLOSE_SENT) && |
437 | debug("channel %d: is dead", c->self); | 431 | (c->flags & CHAN_CLOSE_RCVD)) { |
438 | return 1; | 432 | debug("channel %d: is dead", c->self); |
439 | } | 433 | return 1; |
440 | } | 434 | } |
441 | return 0; | 435 | return 0; |
442 | } | 436 | } |