[PATCH 5/7] dix: Extend initial connection handshake for forwarding proxies

Adam Jackson ajax at redhat.com
Thu Sep 20 13:56:06 PDT 2012


Forwarding proxies like sshd will appear to be local, even though they
aren't really.  This leads to weird behaviour for extensions that truly
require running under the same OS services as the client, like MIT-SHM
and DRI2.

Add two new legal values for the initial connection's byteOrder field,
'r' and 'R'.  These act like 'l' and 'B' respectively, but have the side
effect of forcing the client to be treated as non-local.  Forwarding
proxies should attempt to munge the first packet of the connection
accordingly; older servers will reject connections thusly munged, so the
proxy should fall back to passthrough if the munged connection attempt
fails.

Reviewed-by: Daniel Stone <daniel at fooishbar.org>
Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 dix/dispatch.c  |   19 ++++++++++++-------
 os/connection.c |   10 +++++-----
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 0ce10c2..2df1a6e 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3499,14 +3499,16 @@ ProcInitialConnection(ClientPtr client)
     REQUEST(xReq);
     xConnClientPrefix *prefix;
     int whichbyte = 1;
+    char order;
 
-    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
-    if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
-        return client->noClientException = -1;
-    if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
-        (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) {
-        client->swapped = TRUE;
-        SwapConnClientPrefix(prefix);
+    prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
+    order = prefix->byteOrder;
+    if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
+	return client->noClientException = -1;
+    if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
+	(!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
+	client->swapped = TRUE;
+	SwapConnClientPrefix(prefix);
     }
     stuff->reqType = 2;
     stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
@@ -3514,6 +3516,9 @@ ProcInitialConnection(ClientPtr client)
     if (client->swapped) {
         swaps(&stuff->length);
     }
+    if (order == 'r' || order == 'R') {
+	client->local = FALSE;
+    }
     ResetCurrentRequest(client);
     return Success;
 }
diff --git a/os/connection.c b/os/connection.c
index d27116a..4561caa 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -894,7 +894,7 @@ ErrorConnMax(XtransConnInfo trans_conn)
     xConnSetupPrefix csp;
     char pad[3] = { 0, 0, 0 };
     struct iovec iov[3];
-    char byteOrder = 0;
+    char order = 0;
     int whichbyte = 1;
     struct timeval waittime;
     fd_set mask;
@@ -907,15 +907,15 @@ ErrorConnMax(XtransConnInfo trans_conn)
     FD_SET(fd, &mask);
     (void) Select(fd + 1, &mask, NULL, NULL, &waittime);
     /* try to read the byte-order of the connection */
-    (void) _XSERVTransRead(trans_conn, &byteOrder, 1);
-    if ((byteOrder == 'l') || (byteOrder == 'B')) {
+    (void) _XSERVTransRead(trans_conn, &order, 1);
+    if (order == 'l' || order == 'B' || order == 'r' || order == 'R') {
         csp.success = xFalse;
         csp.lengthReason = sizeof(NOROOM) - 1;
         csp.length = (sizeof(NOROOM) + 2) >> 2;
         csp.majorVersion = X_PROTOCOL;
         csp.minorVersion = X_PROTOCOL_REVISION;
-        if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
-            (!(*(char *) &whichbyte) && (byteOrder == 'l'))) {
+	if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
+	    (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
             swaps(&csp.majorVersion);
             swaps(&csp.minorVersion);
             swaps(&csp.length);
-- 
1.7.7.6



More information about the xorg-devel mailing list