summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2002-03-26 03:26:24 +0000
committerBen Lindstrom <mouring@eviladmin.org>2002-03-26 03:26:24 +0000
commitcf15944c2355f61116d7fb5e793c097dd347284f (patch)
tree15203eed8ed647b7f11f7e5347e8a9bc0f18f2b5
parent4f054607f05f18a705579a2475f490ed47e31028 (diff)
- markus@cvs.openbsd.org 2002/03/25 21:13:51
[channels.c channels.h compat.c compat.h nchan.c] don't send stderr data after EOF, accept this from older known (broken) sshd servers only, fixes http://bugzilla.mindrot.org/show_bug.cgi?id=179
-rw-r--r--ChangeLog6
-rw-r--r--channels.c28
-rw-r--r--channels.h14
-rw-r--r--compat.c22
-rw-r--r--compat.h3
-rw-r--r--nchan.c60
6 files changed, 84 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 87039872c..a3a918b72 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
4320020324 4720020324
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"
42RCSID("$OpenBSD: channels.c,v 1.171 2002/03/04 19:37:58 markus Exp $"); 42RCSID("$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
diff --git a/compat.c b/compat.c
index 74d5ed85e..8671e641b 100644
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: compat.c,v 1.61 2002/03/06 00:24:39 markus Exp $"); 26RCSID("$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|
diff --git a/compat.h b/compat.h
index 0eeb782e8..3fb0f9799 100644
--- a/compat.h
+++ b/compat.h
@@ -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
56void enable_compat13(void); 57void enable_compat13(void);
57void enable_compat20(void); 58void enable_compat20(void);
diff --git a/nchan.c b/nchan.c
index fc8e7f18d..db38de6ac 100644
--- a/nchan.c
+++ b/nchan.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: nchan.c,v 1.44 2002/01/21 23:27:10 markus Exp $"); 26RCSID("$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
302chan_rcvd_eof2(Channel *c) 302chan_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}
371void 374void
@@ -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}