Three patches attached.
One implements a 'ControlPersist' option, which when used with
'ControlMaster auto' or 'ControlMaster 'yes' make makes the master
background itself and stick around after its own primary session is
completed.
The second causes control clients to pass X11 display, auth proto and
auth data over the control socket so that appropriate X11 forwarding can
happen for each, instead of using $DISPLAY and $XAUTHORITY of the master
even for all the clients.
The third dispenses with the 'Already forwarding for a different
$DISPLAY' error, to make the second patch actually useful. We delay
opening the connection to the X server until after we've seen an
authentication attempt, and since each set of fake authentication data
is unique, we can use that to work out which server to connect to.
The third patch isn't quite ready yet. Is the way I did the use count on
the X11 forwarding structure the best way to do it? And why does the X11
connection stall after authentication, until after some other traffic
occurs between client and server?
--
dwmw2
--=-N8ul49msogJORhvINV++
Content-Disposition: inline; filename=openssh-4.2p1-controlpersist.patch
Content-Type: text/x-patch; name=openssh-4.2p1-controlpersist.patch;
charset=UTF-8
Content-Transfer-Encoding: 7bit
--- openssh/clientloop.c~ 2005-06-17 03:59:35.000000000 +0100
+++ openssh/clientloop.c 2005-06-23 11:05:11.000000000 +0100
@@ -1271,8 +1271,28 @@ static void
client_channel_closed(int id, void *arg)
{
channel_cancel_cleanup(id);
- session_closed = 1;
leave_raw_mode();
+ if (options.control_persist && options.control_path != NULL && control_fd != -1) {
+ int pid = fork();
+
+ if (pid < 0) {
+ error("fork: %.100s", strerror(errno));
+ /* Just exit */
+ session_closed = 1;
+ return;
+ }
+ if (pid != 0) {
+ /* We are the parent. Exit, leaving the child to continue serving */
+ exit(exit_status);
+ }
+ session_ident = -1;
+ /* We _must_ lose our controlling tty, else subsequent control_client
+ invocations from the same tty will cause us to get -EIO when reading
+ from the tty */
+ setsid();
+ return;
+ }
+ session_closed = 1;
}
/*
--- openssh/readconf.c~ 2005-06-16 04:19:42.000000000 +0100
+++ openssh/readconf.c 2005-06-23 11:05:11.000000000 +0100
@@ -106,7 +106,7 @@ typedef enum {
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
- oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
+ oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts,
oDeprecated, oUnsupported
} OpCodes;
@@ -197,6 +197,7 @@ static struct {
{ "sendenv", oSendEnv },
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
+ { "controlpersist", oControlPersist },
{ "hashknownhosts", oHashKnownHosts },
{ NULL, oBadOption }
};
@@ -818,6 +819,10 @@ parse_int:
*intptr = value;
break;
+ case oControlPersist:
+ intptr = &options->control_persist;
+ goto parse_flag;
+
case oHashKnownHosts:
intptr = &options->hash_known_hosts;
goto parse_flag;
--- openssh/readconf.h~ 2005-06-16 04:19:42.000000000 +0100
+++ openssh/readconf.h 2005-06-23 11:02:01.000000000 +0100
@@ -112,6 +112,7 @@ typedef struct {
char *control_path;
int control_master;
+ int control_persist;
int hash_known_hosts;
} Options;
--=-N8ul49msogJORhvINV++
Content-Disposition: inline; filename=openssh-4.2p1-controldisplay.patch
Content-Type: text/x-patch; name=openssh-4.2p1-controldisplay.patch;
charset=UTF-8
Content-Transfer-Encoding: 7bit
--- openssh-4.2p1/clientloop.c~ 2005-09-04 14:09:30.000000000 +0100
+++ openssh-4.2p1/clientloop.c 2005-09-04 15:00:09.000000000 +0100
@@ -144,6 +144,9 @@ struct confirm_ctx {
int want_agent_fwd;
Buffer cmd;
char *term;
+ char *display;
+ char *x_proto;
+ char *x_data;
struct termios tio;
char **env;
};
@@ -633,7 +636,6 @@ static void
client_extra_session2_setup(int id, void *arg)
{
struct confirm_ctx *cctx = arg;
- const char *display;
Channel *c;
int i;
@@ -642,15 +644,15 @@ client_extra_session2_setup(int id, void
if ((c = channel_lookup(id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
- display = getenv("DISPLAY");
- if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
+ if (cctx->want_x_fwd && options.forward_x11) {
char *proto, *data;
/* Get reasonable local authentication information. */
- client_x11_get_proto(display, options.xauth_location,
+ client_x11_get_proto(cctx->display, options.xauth_location,
options.forward_x11_trusted, &proto, &data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication spoofing.");
- x11_request_forwarding_with_spoofing(id, display, proto, data);
+ x11_request_forwarding_with_spoofing(id, cctx->display,
+ cctx->x_proto, cctx->x_data);
/* XXX wait for reply */
}
@@ -667,6 +670,9 @@ client_extra_session2_setup(int id, void
c->confirm_ctx = NULL;
buffer_free(&cctx->cmd);
xfree(cctx->term);
+ xfree(cctx->display);
+ xfree(cctx->x_proto);
+ xfree(cctx->x_data);
if (cctx->env != NULL) {
for (i = 0; cctx->env[i] != NULL; i++)
xfree(cctx->env[i]);
@@ -813,6 +819,14 @@ client_process_control(fd_set * readset)
cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
+
+ if (cctx->want_x_fwd) {
+ cctx->display = buffer_get_string(&m, &len);
+ cctx->x_proto = buffer_get_string(&m, &len);
+ cctx->x_data = buffer_get_string(&m, &len);
+ debug2("%s: got X11 display %s, auth proto %s, data %s.",
+ __func__, cctx->display, cctx->x_proto, cctx->x_data);
+ }
cctx->term = buffer_get_string(&m, &len);
cmd = buffer_get_string(&m, &len);
@@ -854,11 +866,15 @@ client_process_control(fd_set * readset)
close(new_fd[2]);
buffer_free(&m);
xfree(cctx->term);
+ xfree(cctx->display);
+ xfree(cctx->x_proto);
+ xfree(cctx->x_data);
if (env_len != 0) {
for (i = 0; i < env_len; i++)
xfree(cctx->env[i]);
xfree(cctx->env);
}
+ xfree(cctx);
return;
}
buffer_free(&m);
--- openssh-4.2p1/clientloop.h~ 2005-07-06 00:44:19.000000000 +0100
+++ openssh-4.2p1/clientloop.h 2005-09-04 14:18:31.000000000 +0100
@@ -44,7 +44,7 @@ void client_session2_setup(int, int, in
int, Buffer *, char **, dispatch_fn *);
/* Multiplexing protocol version */
-#define SSHMUX_VER 1
+#define SSHMUX_VER 2
/* Multiplexing control protocol flags */
#define SSHMUX_COMMAND_OPEN 1 /* Open new connection */
--- openssh-4.2p1/ssh.c~ 2005-08-12 13:10:56.000000000 +0100
+++ openssh-4.2p1/ssh.c 2005-09-04 14:45:50.000000000 +0100
@@ -1211,6 +1211,7 @@ control_client(const char *path)
Buffer m;
char *term;
extern char **environ;
+ char *display = NULL, *x_proto, *x_data;
u_int flags;
if (mux_command == 0)
@@ -1270,8 +1271,12 @@ control_client(const char *path)
flags |= SSHMUX_FLAG_TTY;
if (subsystem_flag)
flags |= SSHMUX_FLAG_SUBSYS;
- if (options.forward_x11)
+ if (options.forward_x11 && (display = getenv("DISPLAY")) != NULL) {
+ /* Get reasonable local authentication information. */
+ client_x11_get_proto(display, options.xauth_location,
+ options.forward_x11_trusted, &x_proto, &x_data);
flags |= SSHMUX_FLAG_X11_FWD;
+ }
if (options.forward_agent)
flags |= SSHMUX_FLAG_AGENT_FWD;
@@ -1311,6 +1316,11 @@ control_client(const char *path)
}
/* SSHMUX_COMMAND_OPEN */
+ if (display) {
+ buffer_put_cstring(&m, display);
+ buffer_put_cstring(&m, x_proto);
+ buffer_put_cstring(&m, x_data);
+ }
buffer_put_cstring(&m, term ? term : "");
buffer_append(&command, "\0", 1);
buffer_put_cstring(&m, buffer_ptr(&command));
--=-N8ul49msogJORhvINV++
Content-Disposition: inline; filename=openssh-4.2p1-multidisplay.patch
Content-Type: text/x-patch; name=openssh-4.2p1-multidisplay.patch;
charset=UTF-8
Content-Transfer-Encoding: 7bit
--- openssh-4.2p1/channels.c~ 2005-09-04 15:12:52.000000000 +0100
+++ openssh-4.2p1/channels.c 2005-09-04 17:30:14.000000000 +0100
@@ -111,23 +111,31 @@ static int all_opens_permitted = 0;
/* Maximum number of fake X11 displays to try. */
#define MAX_DISPLAYS 1000
-/* Saved X11 local (client) display. */
-static char *x11_saved_display = NULL;
+struct x11_fwd {
+ /* Saved X11 local (client) display. */
+ char *saved_display;
+
+ /* Saved X11 authentication protocol name. */
+ char *saved_proto;
+
+ /* Saved X11 authentication data. These are the real data. */
+ u_char *saved_data;
+ u_int saved_data_len;
-/* Saved X11 authentication protocol name. */
-static char *x11_saved_proto = NULL;
+ /*
+ * Fake X11 authentication data. This is what the server will be
+ sending us; we should replace any occurrences with the real data.
+ */
+ u_char *fake_data;
+ u_int fake_data_len;
+
+ u_int usecount;
+ struct x11_fwd *next;
+};
-/* Saved X11 authentication data. This is the real data. */
-static char *x11_saved_data = NULL;
-static u_int x11_saved_data_len = 0;
-
-/*
- * Fake X11 authentication data. This is what the server will be sending us;
- * we should replace any occurrences of this by the real data.
- */
-static char *x11_fake_data = NULL;
-static u_int x11_fake_data_len;
+static struct x11_fwd *x11_fwds = NULL;
+static void x11_put_fwd(struct x11_fwd *fwd);
/* -- agent forwarding */
@@ -354,6 +362,8 @@ channel_free(Channel *c)
c->remote_name = NULL;
}
channels[c->self] = NULL;
+ if (c->x11_fwd)
+ x11_put_fwd(c->x11_fwd);
xfree(c);
}
@@ -773,6 +783,54 @@ channel_pre_output_draining(Channel *c,
FD_SET(c->sock, writeset);
}
+static struct x11_fwd *
+x11_lookup_fwd_by_fakedata(unsigned char *proto, u_int protolen, unsigned char *data, u_int datalen)
+{
+ struct x11_fwd *fwd;
+
+ for (fwd = x11_fwds; fwd; fwd = fwd->next) {
+ if (protolen == strlen(fwd->saved_proto) &&
+ !memcmp(fwd->saved_proto, proto, protolen) &&
+ fwd->fake_data_len == datalen &&
+ !memcmp(fwd->fake_data, data, datalen))
+ break;
+ }
+ return fwd;
+}
+
+static struct x11_fwd *
+x11_lookup_fwd_by_realdata(const char *display, const char *proto, const u_char *authdata, u_int datalen)
+{
+ struct x11_fwd *fwd;
+
+ for (fwd = x11_fwds; fwd; fwd = fwd->next) {
+ if (!strcmp(display, fwd->saved_display) &&
+ !strcmp(proto, fwd->saved_proto) &&
+ datalen == fwd->saved_data_len &&
+ !memcmp(authdata, fwd->saved_data, datalen))
+ break;
+ }
+ return fwd;
+}
+
+static void x11_put_fwd(struct x11_fwd *fwd)
+{
+ fwd->usecount--;
+ debug("Decrease usecount on X11 forward data for %s to %d.", fwd->saved_display, fwd->usecount);
+ if (!fwd->usecount) {
+ struct x11_fwd **tmp = &x11_fwds;
+ while (*tmp) {
+ if (*tmp == fwd) {
+ *tmp = fwd->next;
+ xfree(fwd);
+ return;
+ }
+ tmp = &(*tmp)->next;
+ }
+ fatal("X11 forward data not found.");
+ }
+}
+
/*
* This is a special state for X11 authentication spoofing. An opened X11
* connection (when authentication spoofing is being done) remains in this
@@ -783,10 +841,13 @@ channel_pre_output_draining(Channel *c,
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
*/
static int
-x11_open_helper(Buffer *b)
+x11_open_helper(Channel *c)
{
+ Buffer *b = &c->output;
u_char *ucp;
u_int proto_len, data_len;
+ struct x11_fwd *fwd;
+ int sock;
/* Check if the fixed size part of the packet is in buffer. */
if (buffer_len(b) < 12)
@@ -811,50 +872,52 @@ x11_open_helper(Buffer *b)
12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
return 0;
- /* Check if authentication protocol matches. */
- if (proto_len != strlen(x11_saved_proto) ||
- memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) {
- debug2("X11 connection uses different authentication protocol.");
- return -1;
- }
- /* Check if authentication data matches our fake data. */
- if (data_len != x11_fake_data_len ||
- memcmp(ucp + 12 + ((proto_len + 3) & ~3),
- x11_fake_data, x11_fake_data_len) != 0) {
- debug2("X11 auth data does not match fake data.");
- return -1;
- }
- /* Check fake data length */
- if (x11_fake_data_len != x11_saved_data_len) {
- error("X11 fake_data_len %d != saved_data_len %d",
- x11_fake_data_len, x11_saved_data_len);
+ fwd = x11_lookup_fwd_by_fakedata(ucp+12, proto_len,
+ ucp + 12 + ((proto_len + 3) & ~3), data_len);
+
+ if (!fwd) {
+ debug("No matching X11 forward found.");
return -1;
}
+ fwd->usecount++;
+ debug("Increase use count for X11 fwd for display %s to %d.", fwd->saved_display, fwd->usecount);
+ c->x11_fwd = fwd;
/*
- * Received authentication protocol and data match
- * our fake data. Substitute the fake data with real
- * data.
+ * We found a matching X11 forward. Substitute the fake data
+ * with real data.
*/
memcpy(ucp + 12 + ((proto_len + 3) & ~3),
- x11_saved_data, x11_saved_data_len);
+ fwd->saved_data, fwd->saved_data_len);
+
+ sock = x11_connect_display(fwd->saved_display);
+ if (sock == -1)
+ return -2;
+ channel_register_fds(c, sock, sock, -1, 0, 1);
return 1;
}
static void
channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
{
- int ret = x11_open_helper(&c->output);
+ int ret = x11_open_helper(c);
if (ret == 1) {
/* Start normal processing for the channel. */
c->type = SSH_CHANNEL_OPEN;
channel_pre_open_13(c, readset, writeset);
- } else if (ret == -1) {
+ } else if (ret < 0) {
/*
* We have received an X11 connection that has bad
* authentication information.
*/
- logit("X11 connection rejected because of wrong authentication.");
+ switch (ret) {
+ case -1:
+ logit("X11 connection rejected because of wrong authentication.");
+ break;
+ case -2:
+ logit("X11 connection rejected due to failure to connect to local server.");
+ break;
+ }
buffer_clear(&c->input);
buffer_clear(&c->output);
channel_close_fd(&c->sock);
@@ -869,7 +932,7 @@ channel_pre_x11_open_13(Channel *c, fd_s
static void
channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
{
- int ret = x11_open_helper(&c->output);
+ int ret = x11_open_helper(c);
/* c->force_drain = 1; */
@@ -2790,23 +2853,16 @@ connect_local_xsocket(u_int dnr)
}
int
-x11_connect_display(void)
+x11_connect_display(char *display)
{
int display_number, sock = 0;
- const char *display;
char buf[1024], *cp;
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr;
- /* Try to open a socket for the local X server. */
- display = getenv("DISPLAY");
- if (!display) {
- error("DISPLAY not set.");
- return -1;
- }
/*
- * Now we decode the value of the DISPLAY variable and make a
+ * Decode the value of the DISPLAY variable and make a
* connection to the real X server.
*/
@@ -2894,7 +2950,7 @@ void
x11_input_open(int type, u_int32_t seq, void *ctxt)
{
Channel *c = NULL;
- int remote_id, sock = 0;
+ int remote_id;
char *remote_host;
debug("Received X11 open request.");
@@ -2908,27 +2964,20 @@ x11_input_open(int type, u_int32_t seq,
}
packet_check_eom();
- /* Obtain a connection to the real X display. */
- sock = x11_connect_display();
- if (sock != -1) {
- /* Allocate a channel for this connection. */
- c = channel_new("connected x11 socket",
- SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0,
- remote_host, 1);
- c->remote_id = remote_id;
- c->force_drain = 1;
- }
+ /* Allocate a channel for this connection. */
+ c = channel_new("connected x11 socket",
+ SSH_CHANNEL_X11_OPEN, -1, -1, -1, 0, 0, 0,
+ remote_host, 1);
+ c->remote_id = remote_id;
+ c->force_drain = 1;
+
xfree(remote_host);
- if (c == NULL) {
- /* Send refusal to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(remote_id);
- } else {
- /* Send a confirmation to the remote host. */
- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(remote_id);
- packet_put_int(c->self);
- }
+
+ /* Send a confirmation to the remote host. */
+ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+ packet_put_int(remote_id);
+ packet_put_int(c->self);
+
packet_send();
}
@@ -2964,21 +3013,62 @@ void
x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
const char *proto, const char *data)
{
+ Channel *c = NULL;
u_int data_len = (u_int) strlen(data) / 2;
u_int i, value;
char *new_data;
+ u_char *realdata;
int screen_number;
const char *cp;
u_int32_t rnd = 0;
+ struct x11_fwd *fwd;
- if (x11_saved_display == NULL)
- x11_saved_display = xstrdup(disp);
- else if (strcmp(disp, x11_saved_display) != 0) {
- error("x11_request_forwarding_with_spoofing: different "
- "$DISPLAY already forwarded");
- return;
+ if (compat20) {
+ c = channel_lookup(client_session_id);
+ if (!c)
+ error("%s: channel %d: unknown channel", __func__, client_session_id);
+ }
+
+ /* Convert real authentication data to binary */
+ realdata = xmalloc(data_len);
+ for (i = 0; i < data_len; i++) {
+ if (sscanf(data + 2 * i, "%2x", &value) != 1)
+ fatal("x11_request_forwarding: bad "
+ "authentication data: %.100s", data);
+ realdata[i] = value;
+ }
+
+ fwd = x11_lookup_fwd_by_realdata(disp, proto, realdata, data_len);
+ if (fwd) {
+ fwd->usecount++;
+ debug("Increase use count for X11 fwd for display %s to %d.", disp, fwd->usecount);
+ xfree(realdata);
+ } else {
+ /* No existing forward. Create a new one */
+ debug("Create new X11 fake auth data for display %s.", disp);
+ fwd = xmalloc(sizeof(*fwd));
+ fwd->saved_display = xstrdup(disp);
+ fwd->saved_proto = xstrdup(proto);
+ fwd->saved_data = realdata;
+ fwd->saved_data_len = data_len;
+ fwd->fake_data = xmalloc(data_len);
+ fwd->fake_data_len = data_len;
+
+ for (i = 0; i < data_len; i++) {
+ if (i % 4 == 0)
+ rnd = arc4random();
+ fwd->fake_data[i] = rnd & 0xff;
+ rnd >>= 8;
+ }
+
+ fwd->usecount = 1;
+ fwd->next = x11_fwds;
+ x11_fwds = fwd;
}
+ if (c)
+ c->x11_fwd = fwd;
+
cp = disp;
if (disp)
cp = strchr(disp, ':');
@@ -2989,31 +3079,8 @@ x11_request_forwarding_with_spoofing(int
else
screen_number = 0;
- if (x11_saved_proto == NULL) {
- /* Save protocol name. */
- x11_saved_proto = xstrdup(proto);
- /*
- * Extract real authentication data and generate fake data
- * of the same length.
- */
- x11_saved_data = xmalloc(data_len);
- x11_fake_data = xmalloc(data_len);
- for (i = 0; i < data_len; i++) {
- if (sscanf(data + 2 * i, "%2x", &value) != 1)
- fatal("x11_request_forwarding: bad "
- "authentication data: %.100s", data);
- if (i % 4 == 0)
- rnd = arc4random();
- x11_saved_data[i] = value;
- x11_fake_data[i] = rnd & 0xff;
- rnd >>= 8;
- }
- x11_saved_data_len = data_len;
- x11_fake_data_len = data_len;
- }
-
/* Convert the fake data into hex. */
- new_data = tohex(x11_fake_data, data_len);
+ new_data = tohex(fwd->fake_data, data_len);
/* Send the request packet. */
if (compat20) {
--- openssh-4.2p1/channels.h~ 2005-07-17 08:19:25.000000000 +0100
+++ openssh-4.2p1/channels.h 2005-09-04 17:22:47.000000000 +0100
@@ -59,6 +59,7 @@
#define SSH_CHANNEL_PATH_LEN 256
+struct x11_fwd;
struct Channel;
typedef struct Channel Channel;
@@ -111,6 +112,9 @@ struct Channel {
/* filter */
channel_filter_fn *input_filter;
+
+ /* X11 forwarding data */
+ struct x11_fwd *x11_fwd;
};
#define CHAN_EXTENDED_IGNORE 0
@@ -213,7 +217,7 @@ int channel_cancel_rport_listener(const
/* x11 forwarding */
-int x11_connect_display(void);
+int x11_connect_display(char *);
int x11_create_display_inet(int, int, int, u_int *, int **);
void x11_input_open(int, u_int32_t, void *);
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
--- openssh-4.2p1/clientloop.c~ 2005-09-04 15:12:52.000000000 +0100
+++ openssh-4.2p1/clientloop.c 2005-09-04 16:45:58.000000000 +0100
@@ -1730,11 +1730,8 @@ client_request_x11(const char *request_t
debug("client_request_x11: request from %s %d", originator,
originator_port);
xfree(originator);
- sock = x11_connect_display();
- if (sock < 0)
- return NULL;
c = channel_new("x11",
- SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+ SSH_CHANNEL_X11_OPEN, -1, -1, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
c->force_drain = 1;
return c;
--=-N8ul49msogJORhvINV++
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
openssh-unix-dev mailing list
openssh-...@mindrot.org
http://www.mindrot.org/mailman/listinfo/openssh-unix-dev
--=-N8ul49msogJORhvINV++--
To answer my own question... it's because we allocated a new file
descriptor and increased channel_fd_max, but we did so only _after_
channel_prepare_select() had already set *maxfdp and made sure that the
fd_sets were large enough to cope. So we don't get to select on the new
one until the _next_ time round the loop.
Not only that, but when we do FD_SET the new file descriptor in an
existing fd_set, we could be scribbling over random memory because the
fd_set isn't actually large enough.
A quick but dirty workaround is just to have channel_prepare_select()
allow for one or two more file descriptors than we actually need. If we
can get _many_ simultaneous X11 authentication packets, though, all on
different connections, then that won't be sufficient. Better
suggestions...?
--- openssh-4.2p1/channels.c~ 2005-09-05 09:05:21.000000000 +0100
+++ openssh-4.2p1/channels.c 2005-09-05 09:05:56.000000000 +0100
@@ -1779,7 +1779,8 @@ channel_prepare_select(fd_set **readsetp
{
u_int n, sz;
- n = MAX(*maxfdp, channel_max_fd);
+ /* Allow for two more fds to be allocated */
+ n = MAX(*maxfdp, channel_max_fd + 2);
sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
/* perhaps check sz < nalloc/2 and shrink? */
--
dwmw2