summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/ssh/include/channels.h9
-rw-r--r--usr/src/cmd/ssh/libssh/common/channels.c29
-rw-r--r--usr/src/cmd/ssh/ssh/clientloop.c25
-rw-r--r--usr/src/cmd/ssh/sshd/altprivsep.c21
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 "