diff options
-rw-r--r-- | usr/src/cmd/ssh/include/channels.h | 9 | ||||
-rw-r--r-- | usr/src/cmd/ssh/libssh/common/channels.c | 29 | ||||
-rw-r--r-- | usr/src/cmd/ssh/ssh/clientloop.c | 25 | ||||
-rw-r--r-- | usr/src/cmd/ssh/sshd/altprivsep.c | 21 |
4 files changed, 54 insertions, 30 deletions
diff --git a/usr/src/cmd/ssh/include/channels.h b/usr/src/cmd/ssh/include/channels.h index 1845845f6a..83b41df0dd 100644 --- a/usr/src/cmd/ssh/include/channels.h +++ b/usr/src/cmd/ssh/include/channels.h @@ -33,8 +33,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. */ /* $OpenBSD: channels.h,v 1.70 2002/06/24 14:33:27 markus Exp $ */ @@ -88,7 +87,11 @@ struct Channel { int isatty; /* rfd is a tty */ int wfd_isatty; /* wfd is a tty */ int force_drain; /* force close on iEOF */ - int delayed; /* fdset hack */ + int delayed; /* post-select handlers for newly created + * channels are delayed until the first call + * to a matching pre-select handler. + * this way post-select handlers are not + * accidenly called if a FD gets reused */ Buffer input; /* data read from socket, to be sent over * encrypted connection */ Buffer output; /* data received over encrypted connection for diff --git a/usr/src/cmd/ssh/libssh/common/channels.c b/usr/src/cmd/ssh/libssh/common/channels.c index 3a0e6bad22..7133758b73 100644 --- a/usr/src/cmd/ssh/libssh/common/channels.c +++ b/usr/src/cmd/ssh/libssh/common/channels.c @@ -38,8 +38,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. */ #include "includes.h" @@ -270,6 +269,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->detach_user = NULL; c->confirm = NULL; c->input_filter = NULL; + c->delayed = 1; /* prevent call to channel_post handler */ debug("channel %d: new [%s]", found, remote_name); return c; } @@ -598,11 +598,11 @@ channel_request_start(int local_id, char *service, int wantconfirm) { Channel *c = channel_lookup(local_id); + debug("channel request %d: %s", local_id, service); if (c == NULL) { log("channel_request_start: %d: unknown channel id", local_id); return; } - debug("channel request %d: %s", local_id, service) ; packet_start(SSH2_MSG_CHANNEL_REQUEST); packet_put_int(c->remote_id); packet_put_cstring(service); @@ -1090,7 +1090,6 @@ channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) int have, ret; have = buffer_len(&c->input); - c->delayed = 0; debug2("channel %d: pre_dynamic: have %d", c->self, have); /* buffer_dump(&c->input); */ /* check if the fixed size part of the packet is in buffer. */ @@ -1283,16 +1282,8 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) nc->host_port = c->host_port; strlcpy(nc->path, c->path, sizeof(nc->path)); - if (nextstate == SSH_CHANNEL_DYNAMIC) { - /* - * do not call the channel_post handler until - * this flag has been reset by a pre-handler. - * otherwise the FD_ISSET calls might overflow - */ - nc->delayed = 1; - } else { + if (nextstate != SSH_CHANNEL_DYNAMIC) port_open_helper(nc, rtype); - } } } @@ -1541,8 +1532,6 @@ channel_check_window(Channel *c) static void channel_post_open(Channel *c, fd_set * readset, fd_set * writeset) { - if (c->delayed) - return; channel_handle_rfd(c, readset, writeset); channel_handle_wfd(c, readset, writeset); if (!compat20) @@ -1672,17 +1661,23 @@ static void channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) { static int did_init = 0; - int i; + int i, oalloc; Channel *c; if (!did_init) { channel_handler_init(); did_init = 1; } - for (i = 0; i < channels_alloc; i++) { + for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { c = channels[i]; if (c == NULL) continue; + if (c->delayed) { + if (ftab == channel_pre) + c->delayed = 0; + else + continue; + } if (ftab[c->type] != NULL) (*ftab[c->type])(c, readset, writeset); channel_garbage_collect(c); diff --git a/usr/src/cmd/ssh/ssh/clientloop.c b/usr/src/cmd/ssh/ssh/clientloop.c index bd94ebaa26..f101c4a6b4 100644 --- a/usr/src/cmd/ssh/ssh/clientloop.c +++ b/usr/src/cmd/ssh/ssh/clientloop.c @@ -59,8 +59,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. */ #include "includes.h" @@ -406,10 +405,30 @@ static void client_check_window_change(void) { struct winsize ws; + Channel *c; if (! received_window_change_signal) return; - /** XXX race */ + + /* + * We want to send a window-change request only when a session is + * already established and alive. + * + * Note: During session handshake we cannot send window-change request, + * because we do not know the remote channel ID yet. We have to store + * the information about signals which have arrived and send the + * window-change request when the channel and the session are fully + * established. + */ + if (compat20) { + if (session_ident == -1 || session_closed) + return; + c = channel_lookup(session_ident); + if (c == NULL || c->type != SSH_CHANNEL_OPEN || + c->remote_id == -1) + return; + } + received_window_change_signal = 0; if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0) diff --git a/usr/src/cmd/ssh/sshd/altprivsep.c b/usr/src/cmd/ssh/sshd/altprivsep.c index a2c437cb6f..6f954feab5 100644 --- a/usr/src/cmd/ssh/sshd/altprivsep.c +++ b/usr/src/cmd/ssh/sshd/altprivsep.c @@ -18,8 +18,7 @@ * * CDDL HEADER END * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <fcntl.h> @@ -331,7 +330,7 @@ altprivsep_rekey(int type, u_int32_t seq, void *ctxt) if (type != SSH2_MSG_NEWKEYS) { debug2("Forwarding re-key packet (%d) to monitor", type); if (!altprivsep_fwd_packet(type)) - fatal("Monitor not responding"); + fatal("altprivsep_rekey: Monitor not responding"); } /* tell server_loop2() that we're re-keying */ @@ -361,7 +360,7 @@ altprivsep_process_input(fd_set *rset) debug2("reading from pipe to monitor (%d)", pipe_fd); if ((type = altprivsep_packet_read()) == -1) - fatal("Monitor not responding"); + fatal("altprivsep_process_input: Monitor not responding"); if (!compat20) return; /* shouldn't happen! but be safe */ @@ -857,6 +856,7 @@ altprivsep_packet_send(void) u_char plen_buf[sizeof (plen)]; u_char padlen; /* padding length */ fd_set *setp; + int err; if (pipe_fd == -1) return (-1); @@ -922,12 +922,15 @@ altprivsep_packet_send(void) return (1); pipe_gone: + + err = errno; (void) close(pipe_fd); pipe_fd = -1; - fatal("Monitor not responding"); + fatal("altprvsep_packet_send: Monitor not responding: %.100s", + strerror(err)); /* NOTREACHED */ return (0); @@ -944,6 +947,7 @@ altprivsep_packet_read(void) u_char plen_buf[sizeof (plen)]; u_char padlen; fd_set *setp; + int err; if (pipe_fd == -1) return (-1); @@ -995,12 +999,15 @@ altprivsep_packet_read(void) pipe_gone: + err = errno; + (void) close(pipe_fd); pipe_fd = -1; if (len < 0) - fatal("Monitor not responding"); + fatal("altpriv_packet_read: Monitor not responding %.100s", + strerror(err)); debug2("Monitor pipe closed by monitor"); return (0); @@ -1014,7 +1021,7 @@ altprivsep_packet_read_expect(int expected) type = altprivsep_packet_read(); if (type <= 0) - fatal("Monitor not responding"); + fatal("altprivsep_packet_read_expect: Monitor not responding"); if (type != expected) fatal("Protocol error in privilege separation; expected " |