diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/channels.c b/channels.c index fd6244d48..1cd5004c4 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.308 2010/07/13 23:13:16 djm Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.309 2010/08/05 13:08:42 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -1644,13 +1644,14 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1644 | { | 1644 | { |
1645 | struct termios tio; | 1645 | struct termios tio; |
1646 | u_char *data = NULL, *buf; | 1646 | u_char *data = NULL, *buf; |
1647 | u_int dlen; | 1647 | u_int dlen, olen = 0; |
1648 | int len; | 1648 | int len; |
1649 | 1649 | ||
1650 | /* Send buffered output data to the socket. */ | 1650 | /* Send buffered output data to the socket. */ |
1651 | if (c->wfd != -1 && | 1651 | if (c->wfd != -1 && |
1652 | FD_ISSET(c->wfd, writeset) && | 1652 | FD_ISSET(c->wfd, writeset) && |
1653 | buffer_len(&c->output) > 0) { | 1653 | buffer_len(&c->output) > 0) { |
1654 | olen = buffer_len(&c->output); | ||
1654 | if (c->output_filter != NULL) { | 1655 | if (c->output_filter != NULL) { |
1655 | if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { | 1656 | if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { |
1656 | debug2("channel %d: filter stops", c->self); | 1657 | debug2("channel %d: filter stops", c->self); |
@@ -1669,7 +1670,6 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1669 | 1670 | ||
1670 | if (c->datagram) { | 1671 | if (c->datagram) { |
1671 | /* ignore truncated writes, datagrams might get lost */ | 1672 | /* ignore truncated writes, datagrams might get lost */ |
1672 | c->local_consumed += dlen + 4; | ||
1673 | len = write(c->wfd, buf, dlen); | 1673 | len = write(c->wfd, buf, dlen); |
1674 | xfree(data); | 1674 | xfree(data); |
1675 | if (len < 0 && (errno == EINTR || errno == EAGAIN || | 1675 | if (len < 0 && (errno == EINTR || errno == EAGAIN || |
@@ -1682,7 +1682,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1682 | chan_write_failed(c); | 1682 | chan_write_failed(c); |
1683 | return -1; | 1683 | return -1; |
1684 | } | 1684 | } |
1685 | return 1; | 1685 | goto out; |
1686 | } | 1686 | } |
1687 | #ifdef _AIX | 1687 | #ifdef _AIX |
1688 | /* XXX: Later AIX versions can't push as much data to tty */ | 1688 | /* XXX: Later AIX versions can't push as much data to tty */ |
@@ -1724,10 +1724,10 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | |||
1724 | } | 1724 | } |
1725 | #endif | 1725 | #endif |
1726 | buffer_consume(&c->output, len); | 1726 | buffer_consume(&c->output, len); |
1727 | if (compat20 && len > 0) { | ||
1728 | c->local_consumed += len; | ||
1729 | } | ||
1730 | } | 1727 | } |
1728 | out: | ||
1729 | if (compat20 && olen > 0) | ||
1730 | c->local_consumed += olen - buffer_len(&c->output); | ||
1731 | return 1; | 1731 | return 1; |
1732 | } | 1732 | } |
1733 | 1733 | ||
@@ -2172,6 +2172,14 @@ channel_output_poll(void) | |||
2172 | 2172 | ||
2173 | data = buffer_get_string(&c->input, | 2173 | data = buffer_get_string(&c->input, |
2174 | &dlen); | 2174 | &dlen); |
2175 | if (dlen > c->remote_window || | ||
2176 | dlen > c->remote_maxpacket) { | ||
2177 | debug("channel %d: datagram " | ||
2178 | "too big for channel", | ||
2179 | c->self); | ||
2180 | xfree(data); | ||
2181 | continue; | ||
2182 | } | ||
2175 | packet_start(SSH2_MSG_CHANNEL_DATA); | 2183 | packet_start(SSH2_MSG_CHANNEL_DATA); |
2176 | packet_put_int(c->remote_id); | 2184 | packet_put_int(c->remote_id); |
2177 | packet_put_string(data, dlen); | 2185 | packet_put_string(data, dlen); |
@@ -2257,7 +2265,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) | |||
2257 | { | 2265 | { |
2258 | int id; | 2266 | int id; |
2259 | char *data; | 2267 | char *data; |
2260 | u_int data_len; | 2268 | u_int data_len, win_len; |
2261 | Channel *c; | 2269 | Channel *c; |
2262 | 2270 | ||
2263 | /* Get the channel number and verify it. */ | 2271 | /* Get the channel number and verify it. */ |
@@ -2273,6 +2281,9 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) | |||
2273 | 2281 | ||
2274 | /* Get the data. */ | 2282 | /* Get the data. */ |
2275 | data = packet_get_string_ptr(&data_len); | 2283 | data = packet_get_string_ptr(&data_len); |
2284 | win_len = data_len; | ||
2285 | if (c->datagram) | ||
2286 | win_len += 4; /* string length header */ | ||
2276 | 2287 | ||
2277 | /* | 2288 | /* |
2278 | * Ignore data for protocol > 1.3 if output end is no longer open. | 2289 | * Ignore data for protocol > 1.3 if output end is no longer open. |
@@ -2283,23 +2294,23 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) | |||
2283 | */ | 2294 | */ |
2284 | if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) { | 2295 | if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) { |
2285 | if (compat20) { | 2296 | if (compat20) { |
2286 | c->local_window -= data_len; | 2297 | c->local_window -= win_len; |
2287 | c->local_consumed += data_len; | 2298 | c->local_consumed += win_len; |
2288 | } | 2299 | } |
2289 | return; | 2300 | return; |
2290 | } | 2301 | } |
2291 | 2302 | ||
2292 | if (compat20) { | 2303 | if (compat20) { |
2293 | if (data_len > c->local_maxpacket) { | 2304 | if (win_len > c->local_maxpacket) { |
2294 | logit("channel %d: rcvd big packet %d, maxpack %d", | 2305 | logit("channel %d: rcvd big packet %d, maxpack %d", |
2295 | c->self, data_len, c->local_maxpacket); | 2306 | c->self, win_len, c->local_maxpacket); |
2296 | } | 2307 | } |
2297 | if (data_len > c->local_window) { | 2308 | if (win_len > c->local_window) { |
2298 | logit("channel %d: rcvd too much data %d, win %d", | 2309 | logit("channel %d: rcvd too much data %d, win %d", |
2299 | c->self, data_len, c->local_window); | 2310 | c->self, win_len, c->local_window); |
2300 | return; | 2311 | return; |
2301 | } | 2312 | } |
2302 | c->local_window -= data_len; | 2313 | c->local_window -= win_len; |
2303 | } | 2314 | } |
2304 | if (c->datagram) | 2315 | if (c->datagram) |
2305 | buffer_put_string(&c->output, data, data_len); | 2316 | buffer_put_string(&c->output, data, data_len); |