Bugzilla – Attachment 1316 Details for
Bug 1328
Support multiple X11 forwarding in multiplexing
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Handle multiple $DISPLAYs
openssh-4.5p1-multidisplay.patch (text/plain), 15.30 KB, created by
David Woodhouse
on 2007-07-06 01:15:52 AEST
(
hide
)
Description:
Handle multiple $DISPLAYs
Filename:
MIME Type:
Creator:
David Woodhouse
Created:
2007-07-06 01:15:52 AEST
Size:
15.30 KB
patch
obsolete
>diff -ur openssh-4.5p1/channels.c openssh-4.5p1-multidisplay/channels.c >--- openssh-4.5p1/channels.c 2006-08-30 02:07:40.000000000 +0100 >+++ openssh-4.5p1-multidisplay/channels.c 2007-03-24 16:22:37.000000000 +0000 >@@ -96,6 +96,11 @@ > */ > static int channel_max_fd = 0; > >+/* >+ * Flag indicating that channel fds have been modified, used to restart >+ * preparations for select if necessary >+ */ >+static int channel_fds_changed = 0; > > /* -- tcp forwarding */ > >@@ -136,23 +141,31 @@ > /* Maximum number of fake X11 displays to try. */ > #define MAX_DISPLAYS 1000 > >-/* Saved X11 local (client) display. */ >-static char *x11_saved_display = NULL; >- >-/* Saved X11 authentication protocol name. */ >-static char *x11_saved_proto = 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 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 with the real data. >+ */ >+ u_char *fake_data; >+ u_int fake_data_len; >+ >+ u_int usecount; >+ struct x11_fwd *next; >+}; > >-/* >- * 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 u_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 */ > >@@ -218,6 +231,16 @@ > channel_register_fds(Channel *c, int rfd, int wfd, int efd, > int extusage, int nonblock) > { >+ c->rfd = rfd; >+ c->wfd = wfd; >+ c->sock = (rfd == wfd) ? rfd : -1; >+ c->ctl_fd = -1; /* XXX: set elsewhere */ >+ c->efd = efd; >+ channel_fds_changed = 1; >+ >+ if (rfd == -1 && wfd == -1 && efd == -1) >+ return; >+ > /* Update the maximum file descriptor value. */ > channel_max_fd = MAX(channel_max_fd, rfd); > channel_max_fd = MAX(channel_max_fd, wfd); >@@ -225,11 +248,6 @@ > > /* XXX set close-on-exec -markus */ > >- c->rfd = rfd; >- c->wfd = wfd; >- c->sock = (rfd == wfd) ? rfd : -1; >- c->ctl_fd = -1; /* XXX: set elsewhere */ >- c->efd = efd; > c->extended_usage = extusage; > > /* XXX ugly hack: nonblock is only set by the server */ >@@ -403,6 +421,8 @@ > c->remote_name = NULL; > } > channels[c->self] = NULL; >+ if (c->x11_fwd) >+ x11_put_fwd(c->x11_fwd); > xfree(c); > } > >@@ -826,6 +846,54 @@ > 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 >@@ -836,10 +904,13 @@ > * 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) >@@ -864,50 +935,54 @@ > 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); >- return 1; >+ 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); >+ c->type = SSH_CHANNEL_OPEN; >+ >+ /* Because we registered a new fd, the channel_pre handlers will be >+ called again immediately. And because we changed the channel type >+ to SSH_CHANNEL_OPEN, the x11 function won't be called next time. >+ It's just a normal channel now */ >+ return 0; > } > > 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) { >+ 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); >@@ -922,15 +997,17 @@ > static void > channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) > { >- int ret = x11_open_helper(&c->output); >- >- /* c->force_drain = 1; */ >+ int ret = x11_open_helper(c); > >- if (ret == 1) { >- c->type = SSH_CHANNEL_OPEN; >- channel_pre_open(c, readset, writeset); >- } else if (ret == -1) { >- logit("X11 connection rejected because of wrong authentication."); >+ if (ret < 0) { >+ 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; >+ } > debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); > chan_read_failed(c); > buffer_clear(&c->input); >@@ -1834,26 +1911,30 @@ > { > u_int n, sz, nfdset; > >- n = MAX(*maxfdp, channel_max_fd); >+ for (channel_fds_changed = 1; channel_fds_changed;) { >+ channel_fds_changed = 0; >+ n = MAX(*maxfdp, channel_max_fd); >+ >+ nfdset = howmany(n+1, NFDBITS); >+ /* Explicitly test here, because xrealloc isn't always called */ >+ if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask)) >+ fatal("channel_prepare_select: max_fd (%d) is too large", n); >+ sz = nfdset * sizeof(fd_mask); >+ >+ /* perhaps check sz < nalloc/2 and shrink? */ >+ if (*readsetp == NULL || sz > *nallocp) { >+ *readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask)); >+ *writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask)); >+ *nallocp = sz; >+ } >+ *maxfdp = n; >+ memset(*readsetp, 0, sz); >+ memset(*writesetp, 0, sz); > >- nfdset = howmany(n+1, NFDBITS); >- /* Explicitly test here, because xrealloc isn't always called */ >- if (nfdset && SIZE_T_MAX / nfdset < sizeof(fd_mask)) >- fatal("channel_prepare_select: max_fd (%d) is too large", n); >- sz = nfdset * sizeof(fd_mask); >- >- /* perhaps check sz < nalloc/2 and shrink? */ >- if (*readsetp == NULL || sz > *nallocp) { >- *readsetp = xrealloc(*readsetp, nfdset, sizeof(fd_mask)); >- *writesetp = xrealloc(*writesetp, nfdset, sizeof(fd_mask)); >- *nallocp = sz; >- } >- *maxfdp = n; >- memset(*readsetp, 0, sz); >- memset(*writesetp, 0, sz); >+ if (!rekeying) >+ channel_handler(channel_pre, *readsetp, *writesetp); >+ } > >- if (!rekeying) >- channel_handler(channel_pre, *readsetp, *writesetp); > } > > /* >@@ -2973,23 +3054,16 @@ > } > > int >-x11_connect_display(void) >+x11_connect_display(char *display) > { > u_int display_number; >- const char *display; > char buf[1024], *cp; > struct addrinfo hints, *ai, *aitop; > char strport[NI_MAXSERV]; > int gaierr, sock = 0; > >- /* 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. > */ > >@@ -3078,7 +3152,7 @@ > 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."); >@@ -3092,27 +3166,20 @@ > } > 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(); > } > >@@ -3149,21 +3216,62 @@ > 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 = strchr(disp, ':'); > if (cp) > cp = strchr(cp, '.'); >@@ -3172,31 +3280,8 @@ > 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) { >diff -ur openssh-4.5p1/channels.h openssh-4.5p1-multidisplay/channels.h >--- openssh-4.5p1/channels.h 2006-08-05 03:39:39.000000000 +0100 >+++ openssh-4.5p1-multidisplay/channels.h 2007-03-24 16:18:19.000000000 +0000 >@@ -57,6 +57,7 @@ > > #define SSH_CHANNEL_PATH_LEN 256 > >+struct x11_fwd; > struct Channel; > typedef struct Channel Channel; > >@@ -114,6 +115,9 @@ > channel_outfilter_fn *output_filter; > > int datagram; /* keep boundaries */ >+ >+ /* X11 forwarding data */ >+ struct x11_fwd *x11_fwd; > }; > > #define CHAN_EXTENDED_IGNORE 0 >@@ -221,7 +225,7 @@ > > /* 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 *, >Only in openssh-4.5p1: cipher.c.orig >diff -ur openssh-4.5p1/clientloop.c openssh-4.5p1-multidisplay/clientloop.c >--- openssh-4.5p1/clientloop.c 2006-10-23 18:02:41.000000000 +0100 >+++ openssh-4.5p1-multidisplay/clientloop.c 2007-03-24 16:18:19.000000000 +0000 >@@ -1736,11 +1736,8 @@ > 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;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1328
:
1316
|
1317
|
1856
|
1857