X authorization problems in a mobile environment

Egbert Eich eich at pdx.freedesktop.org
Fri Aug 5 14:43:27 EST 2005


When authorization is enabled and host based authorization is
disabled clients search an authorization file (normaly ~/.Xautority)
for a credential to pass to the server before connetion setup.

remote hosts are identified by their IP. Local hosts are identified
by their hostname which is obtained simply by calling gethostname().

The reason that this is done (and it is not only looked for an entry
tagged with ':0' ) is that a user might want to log into several 
different X sessions simultaniously each one local to the machine 
it's running on with the home directory imported over NFS.

There is a disadvantage however: If the user uses a mobile device
that he carries from one network to another without taking down
his X session the hostname will change. 
The result: the X clients cannot find their credentials any more 
and their connection requests are denied by the server.
The usual workaround here is to fall back to host based authentication
- doing 'xhost +' (before changing the network environment!).
This however is suboptimal.
Another approach may be to have a process running that checks for
hostname changes and updates the authority file. This however relies
on such a process being started and such a process wacking the 
authority file in the background may produce undesireable side 
effects which are confusing for the user and hard to debug.

I've looked for a different solution and came up with two which I
implemented simultaniously as they don't exclude each other:

   1. Approach:

   Introduce a new environment variable XAUTHLOCALHOSTNAME which
   if set takes precedence over gethostname(). It holds the 
   local hostname that was set at the time the X session was started
   and thus is used and thus identifies the credential for this session
   in the authority file.
   This variable can be set by the display manager for the 
   entire X session. I've fixed xdm and startx to do this, fixes for
   kdm and gdm are on their way.
   I've also made a fix for ssh which sets up a local socket for 
   tunneling remote connections.

   2. Approach:

   For local connection the DISPLAY variable is usually :<n> where n
   denotes the display or display.screen combo.	
   However a DISPLAY variable of the form: unix/<localhostname>:0 (*)
   is also valid. So far <localhostname> has just been ignored. I've
   modified Xlib to no longer ignore this.
   I ran into a problems with this approach which I've also fixed:
   X clients that themselves create an environment for sub processes
   (like xterm) pull the information what to pass in the DISPLAY 
   environment variable down to the child process from 'display_name'
   entry of their Display structure.
   The value there however has the 'unix/' part stripped even if it
   was specified in their own environment. I assume that this happend 
   by negligance rather than by intend so I fixed this in Xlib.
   
   There is still another issue invloved here:
   Display managers obtain the display string to use from the first
   entry in each line of the Xservers file. In order to have the 
   DISPLAY environment variable set to unix/<localhostname>:n
   it would require to add the local hostname to the Xserver file
   - something that we want to avoid in a mobile environment.

   Still this apporach may be useful as xinit rc-scripts could
   wack the DISPLAY environment variable in any way they like.

I've also fixed xauth to support both methods so removal of entries
to the authority file should work at session closing time even though
the local hostname of the system has changed.

The patches are attached below.

----------------------
(*) While I was looking at this I came accross a flaw in xauth:
while Xlib accepts the display name as 
           [<protocol>/][<hostname>]:dpy[.screen]
xauth expects (and prints) the protocol and hostname in reverse order:
           [<hostname>/][<protocol>]:dpy[.screen]
although its man page claims it uses the same format as Xlib.
There are three solutions to this:
1. Fix the behavior
2. Make xauth support both the old and the fixed version.
3. Document the flaw in the man page.
I've decided to go with 3: There may be numerous scripts calling
xauth which rely on the broken ordering and thus will break if we
fix it. 2 can be ruled out as there is no unambiguous way to support
both orders.

Cheers,
	Egbert.

-------------- next part --------------
Index: lib/X11/ConnDis.c
===================================================================
RCS file: /home/eich/cvs/xc/lib/X11/ConnDis.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 ConnDis.c
--- lib/X11/ConnDis.c	25 Nov 2004 16:47:38 -0000	1.1.1.13
+++ lib/X11/ConnDis.c	5 Aug 2005 09:34:58 -0000
@@ -137,6 +137,7 @@
     char *pdpynum = NULL;		/* start of dpynum of display */
     char *pscrnum = NULL;		/* start of screen of display */
     Bool dnet = False;			/* if true, then DECnet format */
+    Bool protocol_specified = False;		/* add protocol to fullname */
     int idisplay = 0;			/* required display number */
     int iscreen = 0;			/* optional screen number */
     /*  int (*connfunc)(); */		/* method to create connection */
@@ -167,6 +168,7 @@
     if (!*p) return NULL;		/* must have a colon */
 
     if (p != lastp && *p != ':') {	/* protocol given? */
+	protocol_specified = True;
 	pprotocol = copystring (lastp, p - lastp);
 	if (!pprotocol) goto bad;	/* no memory */
 	p++;				/* skip the '/' */
@@ -199,11 +201,13 @@
 #ifndef DNETCONN
 	goto bad;
 #else
-	dnet = True;
-	/* override the protocol specified */
-	if (pprotocol)
-	    Xfree (pprotocol);
-	pprotocol = copystring ("dnet", 4);
+	if (!pprotocol || strcmp(pprotocol,"dnet")) {
+	    /* override the protocol specified */
+	    if (pprotocol) Xfree(pprotocol);
+	    pprotocol = copystring("dnet",4);
+	    protocol_specified = False;
+	}
+    	dnet = True;
 	hostlen = lastc - 1 - lastp;
 #endif
     }
@@ -286,20 +290,20 @@
 #if defined(TCPCONN) || defined(UNIXCONN) || defined(LOCALCONN) || defined(MNX_TCPCONN) || defined(OS2PIPECONN)
     if (!pprotocol) {
 	if (!phostname) {
-#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+# if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
 	    pprotocol = copystring ("local", 5);
-#if defined(TCPCONN)
+#  if defined(TCPCONN)
 	    tcphostname = copystring("localhost", 9);
-#endif
+#  endif
 	}
 	else
 	{
-#endif
+# endif
 	    pprotocol = copystring ("tcp", 3);
 	}
     }
 #endif
-
+    
 #if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
     /*
      * Now that the defaults have been established, see if we have any 
@@ -313,19 +317,21 @@
      * transport connection function set above.
      */
 
-    if (!phostname) {
-#ifdef apollo
-	;   /* Unix domain sockets are *really* bad on apollos */
+#ifndef apollo     /* Unix domain sockets are *really* bad on apollos */
+    if (!phostname || (strcmp (phostname, "unix") == 0))
 #else
-	if( pprotocol ) Xfree(pprotocol);
-	pprotocol = copystring ("local", 5);
+    if (phostname && (strcmp (phostname, "unix") == 0))
 #endif
-    }
-    else if (strcmp (phostname, "unix") == 0) {
-	if( pprotocol ) Xfree(pprotocol);
-	pprotocol = copystring ("local", 5);
-    }
+    {
+	if (pprotocol && strcmp(pprotocol,"unix")
+	    && strcmp(pprotocol,"local")) {
+	    Xfree(pprotocol);
+	    pprotocol = NULL;
+	    protocol_specified = False;
+	}
+	if (!pprotocol) pprotocol = copystring ("local", 5);
 #endif
+    }
 
 #if defined(TCPCONN)
   connect:
@@ -343,11 +349,19 @@
     }
     if (!address) goto bad;
 
-    sprintf(address,"%s/%s:%d",
-	pprotocol ? pprotocol : "",
-	phostname ? phostname : "",
-	idisplay );
-
+    if (pprotocol
+	&& (!strcmp(pprotocol,"unix") || !strcmp(pprotocol, "local"))) {
+	sprintf(address,"%s/%s:%d",
+		pprotocol ? pprotocol : "",
+		"unix",
+		idisplay );
+    } else {
+	sprintf(address,"%s/%s:%d",
+		pprotocol ? pprotocol : "",
+		phostname ? phostname : "",
+		idisplay );
+    }
+	
     /*
      * Make the connection, also need to get the auth address info for
      * the connection.  Do retries in case server host has hit its
@@ -395,7 +409,7 @@
 	    }
 	    continue;
 	    }
-
+	
 	break;
 	}
 
@@ -416,28 +430,50 @@
      *
      *     [host] : [:] dpy . scr \0
      */
-    len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
+    len = ((protocol_specified && pprotocol ? (strlen(pprotocol) + 1) : 0) +
+	(phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
 	   strlen(pdpynum) + 1 + (pscrnum ? strlen(pscrnum) : 1) + 1);
     *fullnamep = (char *) Xmalloc (len);
     if (!*fullnamep) goto bad;
 
-    sprintf (*fullnamep, "%s%s%d.%d",
-	     (phostname ? phostname : ""),
-	     (dnet ? "::" : ":"),
-	     idisplay, iscreen);
+    if (protocol_specified && pprotocol)
+	sprintf (*fullnamep, "%s/%s%s%d.%d",
+		 pprotocol,
+		 (phostname ? phostname : ""),
+		 (dnet ? "::" : ":"),
+		 idisplay, iscreen);
+    else
+	sprintf (*fullnamep, "%s%s%d.%d",
+		 (phostname ? phostname : ""),
+		 (dnet ? "::" : ":"),
+		 idisplay, iscreen);
 
     *dpynump = idisplay;
     *screenp = iscreen;
     if (pprotocol) Xfree (pprotocol);
-    if (phostname) Xfree (phostname);
     if (pdpynum) Xfree (pdpynum);
     if (pscrnum) Xfree (pscrnum);
 #ifdef TCPCONN
     if (tcphostname) Xfree (tcphostname);
 #endif
-
     GetAuthorization(trans_conn, family, (char *) saddr, saddrlen, idisplay,
 		     auth_namep, auth_namelenp, auth_datap, auth_datalenp);
+    if (!(*auth_datalenp) && family == FamilyLocal) {
+	char *addr = NULL;
+	if (phostname)
+	    addr = strdup(phostname);
+	 else {
+	    char *env;
+	    if ((env = getenv("XAUTHLOCALHOSTNAME")) != NULL) 
+		addr = strdup(env);
+	}
+	if (addr)
+	    GetAuthorization(trans_conn, family, addr, strlen(addr),
+			     idisplay, auth_namep, auth_namelenp,
+			     auth_datap, auth_datalenp);
+    }
+    if (phostname) Xfree (phostname);
+	
     return trans_conn;
 
 
@@ -1226,5 +1262,6 @@
     }
     else
 	*auth_datap = NULL;
+
     if (authptr) XauDisposeAuth (authptr);
 }
Index: programs/xauth/gethost.c
===================================================================
RCS file: /home/eich/cvs/xc/programs/xauth/gethost.c,v
retrieving revision 1.1.1.7
diff -u -r1.1.1.7 gethost.c
--- programs/xauth/gethost.c	8 Sep 2003 09:32:24 -0000	1.1.1.7
+++ programs/xauth/gethost.c	5 Aug 2005 09:35:26 -0000
@@ -279,12 +279,17 @@
 	if (prefix == 0 && (strncmp (fulldpyname, "unix:", 5) == 0 ||
 			    fulldpyname[0] == ':')) {
 
-	    if (!get_local_hostname (buf, sizeof buf)) {
-		len = 0;
-	    } else {
+	    if ((host
+#if defined(UNIXCONN) || defined(LOCALCONN)
+		 && strncmp (host, UNIX_CONNECTION, UNIX_CONNECTION_LENGTH)
+#endif
+		 && strncpy(buf, host, sizeof buf))
+		|| get_local_hostname (buf, sizeof buf)) {
 		src = buf;
 		len = strlen (buf);
-	    }
+	    } else 
+		len = 0;
+
 	} else {
 	    src = fulldpyname;
 	    len = prefix;
Index: programs/xauth/parsedpy.c
===================================================================
RCS file: /home/eich/cvs/xc/programs/xauth/parsedpy.c,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 parsedpy.c
--- programs/xauth/parsedpy.c	8 Sep 2003 09:32:24 -0000	1.1.1.6
+++ programs/xauth/parsedpy.c	5 Aug 2005 09:35:26 -0000
@@ -41,11 +41,6 @@
 #include <X11/Xauth.h>			/* for FamilyLocal */
 #include <X11/Xmu/SysUtil.h>
 
-#if defined(UNIXCONN) || defined(LOCALCONN)
-#define UNIX_CONNECTION "unix"
-#define UNIX_CONNECTION_LENGTH 4
-#endif
-
 #include <stdlib.h>
 #include "xauth.h"
 
@@ -91,12 +86,14 @@
  * parse_displayname - display a display string up into its component parts
  */
 Bool 
-parse_displayname (char *displayname, 
+parse_displayname (char *displayname,
+		   char *localhost,
 		   int *familyp,	/* return */
 		   char **hostp,	/* return */
 		   int *dpynump,	/* return */
 		   int *scrnump,	/* return */
-		   char **restp)	/* return */
+		   char **restp,	/* return */
+		   int *prelen)         /* return */
 {
     char *ptr;				/* work variables */
     int len;				/* work variable */
@@ -106,10 +103,21 @@
     int scrnum = 0;			/* value to be returned */
     char *rest = NULL;			/* must free if set and error return */
     Bool dnet = False;			/* if true then using DECnet */
-
+    char *myhost = NULL;		/* address of localhost if specified */
+    char *cp;
 					/* check the name */
     if (!displayname || !displayname[0]) return False;
-
+    /*
+     * check to see if the display name is of the form "host/unix:"
+     * which is how the list routine prints out local connections
+     */
+    cp = strchr(displayname, '/');
+    if (cp && strncmp (cp, "/unix:", 6) == 0) {
+	*prelen = (cp - displayname);
+	myhost = strndup(displayname,*prelen);
+	displayname = displayname + *prelen + 1;
+    }
+    
 					/* must have at least :number */
     ptr = strrchr(displayname, ':');
     if (!ptr || !ptr[1]) return False;
@@ -126,13 +134,20 @@
     len = (ptr - displayname);	/* length of host name */
     if (len == 0) {			/* choose most efficient path */
 #if defined(UNIXCONN) || defined(LOCALCONN)
-	host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
+	if (localhost)
+	    host = strdup(localhost);
+	else
+	    host = copystring (UNIX_CONNECTION, UNIX_CONNECTION_LENGTH);
 	family = FamilyLocal;
 #else
 	if (dnet) {
 	    host = copystring ("0", 1);
 	    family = FamilyDECnet;
 	} else {
+	    /*
+	     * use the current local host name as the IP
+	     * is matched for FamilyInternet
+	     */
 	    host = copyhostname ();
 	    family = FamilyInternet;
 	}
@@ -147,14 +162,23 @@
 	    family = dnet;
 	} else {
 #if defined(UNIXCONN) || defined(LOCALCONN)
-	    if (host && strcmp (host, UNIX_CONNECTION) == 0)
+	    if (host && strcmp (host, UNIX_CONNECTION) == 0) {
 	      family = FamilyLocal;
-	    else
+	      if (myhost) {
+		  free(host);
+		  host = strdup(myhost);
+	      } else if (localhost) {
+		  free(host);
+		  host = strdup(localhost);
+	      }
+	    } else
 #endif
 	      family = FamilyInternet;
 	}
     }
 
+    if (myhost) free(myhost);
+    
     if (!host) return False;
 
 
Index: programs/xauth/process.c
===================================================================
RCS file: /home/eich/cvs/xc/programs/xauth/process.c,v
retrieving revision 1.1.1.17
diff -u -r1.1.1.17 process.c
--- programs/xauth/process.c	6 Jul 2004 15:11:16 -0000	1.1.1.17
+++ programs/xauth/process.c	5 Aug 2005 09:35:26 -0000
@@ -462,27 +462,19 @@
 }
 
 static Bool 
-get_displayname_auth(char *displayname, AuthList **authl)
+get_displayname_auth(char *displayname, AuthList **authl, char *localhost)
 {
     int family;
     char *host = NULL, *rest = NULL;
     int dpynum, scrnum;
-    char *cp;
     int prelen = 0;
     struct addrlist *addrlist_head, *addrlist_cur;
     AuthList *authl_cur = NULL;
 
     *authl = NULL;
-    /*
-     * check to see if the display name is of the form "host/unix:"
-     * which is how the list routine prints out local connections
-     */
-    cp = strchr(displayname, '/');
-    if (cp && strncmp (cp, "/unix:", 6) == 0)
-      prelen = (cp - displayname);
 
-    if (!parse_displayname (displayname + ((prelen > 0) ? prelen + 1 : 0),
-			    &family, &host, &dpynum, &scrnum, &rest)) {
+    if (!parse_displayname (displayname, localhost, &family, &host,
+			    &dpynum, &scrnum, &rest, &prelen)) {
 	return False;
     }
 
@@ -1221,13 +1213,39 @@
     Xauth *tmp_auth;
     AuthList *proto_head, *proto;
     AuthList *l, *next;
+    char *localhostname = NULL;
+    
+    /*
+     * get saved local address from environment in case the host
+     * name has changed after the credential was added.
+     */
 
+    /* get the environment variable */
+    localhostname = getenv("XAUTHLOCALHOSTNAME");
+    /*
+     * if it doesn't exist check if the DISPLAY variable is of the form
+     * unix/<hostname>:n and extract <hostname> from there.
+     */
+    if (!localhostname) {
+	char *dsp = getenv("DISPLAY");
+	char *dsp_delim;
+	
+	if (dsp && !strncmp(dsp,"unix/", 5)) {
+	    dsp = strchr(dsp, '/');
+	    dsp ++;
+	    if ((dsp_delim = strchr(dsp,':')))
+		localhostname = strndup (dsp, dsp_delim - dsp);
+	}
+    } else
+	localhostname = strdup(localhostname);
+	    
     /*
      * iterate
      */
     for (i = start; i < argc; i++) {
 	char *displayname = argv[i];
-	if (!get_displayname_auth (displayname, &proto_head)) {
+
+	if (!get_displayname_auth (displayname, &proto_head, localhostname)) {
 	    prefix (inputfilename, lineno);
 	    baddisplayname (displayname, argv[0]);
 	    errors++;
@@ -1271,7 +1289,8 @@
 	    break;
 	}
     }
-
+    if (localhostname) free(localhostname);
+    
     return errors;
 }
 
@@ -1566,7 +1585,7 @@
 	}
     }
 
-    if (!get_displayname_auth (dpyname, &list)) {
+    if (!get_displayname_auth (dpyname, &list, NULL)) {
 	prefix (inputfilename, lineno);
 	baddisplayname (dpyname, argv[0]);
 	free (key);
Index: programs/xauth/xauth.h
===================================================================
RCS file: /home/eich/cvs/xc/programs/xauth/xauth.h,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 xauth.h
--- programs/xauth/xauth.h	8 Sep 2003 09:32:24 -0000	1.1.1.6
+++ programs/xauth/xauth.h	5 Aug 2005 09:35:26 -0000
@@ -39,6 +39,11 @@
 #define True 1
 #endif
 
+#if defined(UNIXCONN) || defined(LOCALCONN)
+#define UNIX_CONNECTION "unix"
+#define UNIX_CONNECTION_LENGTH 4
+#endif
+
 extern char *ProgramName;
 
 #include <stdlib.h>
@@ -53,8 +58,8 @@
 extern char *get_hostname ( Xauth *auth );
 extern struct addrlist *get_address_info ( int family, char *fulldpyname, int prefix, char *host);
 extern char *copystring ( char *src, int len );
-extern char *get_local_hostname ( char *buf, int maxlen );
-extern Bool parse_displayname ( char *displayname, int *familyp, char **hostp, int *dpynump, int *scrnump, char **restp );
+extern char *get_local_hostname ( char *buf, int maxlen);
+extern Bool parse_displayname ( char *displayname, char *localhost, int *familyp, char **hostp, int *dpynump, int *scrnump, char **restp, int *prelen );
 extern int auth_initialize ( char *authfilename );
 extern int auth_finalize ( void );
 extern int process_command ( char *inputfilename, int lineno, int argc, char **argv );
Index: programs/xauth/xauth.man
===================================================================
RCS file: /home/eich/cvs/xc/programs/xauth/xauth.man,v
retrieving revision 1.1.1.6
diff -u -r1.1.1.6 xauth.man
--- programs/xauth/xauth.man	8 Sep 2003 09:32:24 -0000	1.1.1.6
+++ programs/xauth/xauth.man	5 Aug 2005 09:35:26 -0000
@@ -191,8 +191,10 @@
 Display names for the \fIadd\fP, \fI[n]extract\fP, \fI[n]list\fP,
 \fI[n]merge\fP, and \fIremove\fP commands use the same format as the
 DISPLAY environment variable and the common \fI\-display\fP command line
-argument.  Display-specific information (such as the screen number)
-is unnecessary and will be ignored.
+argument with the protocol/hostname order switched (ie. the DISPLAY
+environment variable uses [protocol/]hostname.displaynumber while here
+the order is hostname[/protocol].displaynumber.  Display-specific 
+information (such as the screen number) is unnecessary and will be ignored.
 Same-machine connections (such as local-host sockets,
 shared memory, and the Internet Protocol hostname \fIlocalhost\fP) are 
 referred to as \fIhostname\fP/unix:\fIdisplaynumber\fP so that
Index: programs/xinit/startx.cpp
===================================================================
RCS file: /home/eich/cvs/xc/programs/xinit/startx.cpp,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 startx.cpp
--- programs/xinit/startx.cpp	2 Dec 2003 18:47:07 -0000	1.1.1.13
+++ programs/xinit/startx.cpp	5 Aug 2005 09:35:33 -0000
@@ -192,6 +192,8 @@
 
 #endif
 
+export XAUTHLOCALHOSTNAME=`hostname`
+
 xinit $client $clientargs -- $server $display $serverargs
 
 if [ x"$removelist" != x ]; then
Index: programs/xdm/auth.c
===================================================================
RCS file: /home/eich/cvs/xc/programs/xdm/auth.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 auth.c
--- programs/xdm/auth.c	6 Jul 2004 15:10:22 -0000	1.1.1.11
+++ programs/xdm/auth.c	5 Aug 2005 09:35:37 -0000
@@ -678,7 +678,7 @@
 }
 
 static void
-DefineLocal (FILE *file, Xauth *auth)
+DefineLocal (FILE *file, Xauth *auth, char **pLocalAddress)
 {
 	char	displayname[100];
 	char	tmp_displayname[100];
@@ -735,6 +735,8 @@
 	    writeAddr (FamilyLocal, strlen (displayname), displayname, 
 		       file, auth);
 #endif
+	if (pLocalAddress && displayname)
+	    *pLocalAddress = strdup(displayname);
 }
 
 #ifdef HAS_GETIFADDRS
@@ -1167,7 +1169,7 @@
 }
 
 static void
-writeLocalAuth (FILE *file, Xauth *auth, char *name)
+writeLocalAuth (FILE *file, Xauth *auth, char *name, char **pLocalAddress)
 {
     int	fd;
 
@@ -1194,13 +1196,13 @@
     DefineSelf (fd, file, auth);
     close (fd);
 #endif
-    DefineLocal (file, auth);
+    DefineLocal (file, auth, pLocalAddress);
 }
 
 #ifdef XDMCP
 
 static void
-writeRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name)
+writeRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name, char **pLocalAddress)
 {
     int	    family = FamilyLocal;
     char    *addr;
@@ -1219,7 +1221,7 @@
     }
     else
     {
-	writeLocalAuth (file, auth, name);
+	writeLocalAuth (file, auth, name, pLocalAddress);
     }
 }
 
@@ -1243,7 +1245,8 @@
 #ifdef HAS_MKSTEMP
     int		fd;
 #endif
-
+    char	*localAddress = NULL;
+    
     Debug ("SetUserAuthorization\n");
     auths = d->authorizations;
     if (auths) {
@@ -1335,10 +1338,10 @@
 	    {
 		magicCookie = i;
 	    	if (d->displayType.location == Local)
-	    	    writeLocalAuth (new, auths[i], d->name);
+	    	    writeLocalAuth (new, auths[i], d->name,&localAddress);
 #ifdef XDMCP
 	    	else
-	    	    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
+	    	    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name, &localAddress);
 #endif
 		break;
 	    }
@@ -1356,10 +1359,10 @@
 		    !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14))
 		    auths[i]->data_length = 0;
 	    	if (d->displayType.location == Local)
-	    	    writeLocalAuth (new, auths[i], d->name);
+	    	    writeLocalAuth (new, auths[i], d->name, &localAddress);
 #ifdef XDMCP
 	    	else
-	    	    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
+	    	    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name, &localAddress);
 #endif
 		auths[i]->data_length = data_len;
 	    }
@@ -1398,6 +1401,12 @@
 	    verify->systemEnviron = setEnv (verify->systemEnviron,
 				    "XAUTHORITY", envname);
 	}
+	if (localAddress) {
+	    verify->userEnviron = setEnv (verify->userEnviron,
+				    "XAUTHLOCALHOSTNAME",localAddress);
+	    free(localAddress);
+	}
+	
 	XauUnlockAuth (name);
 	if (envname)
 	    chown (envname, verify->uid, verify->gid);
@@ -1436,10 +1445,10 @@
 	for (i = 0; i < d->authNum; i++)
 	{
 	    if (d->displayType.location == Local)
-	    	writeLocalAuth (new, auths[i], d->name);
+	    	writeLocalAuth (new, auths[i], d->name, NULL);
 #ifdef XDMCP
 	    else
-	    	writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
+	    	writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name,NULL);
 #endif
 	}
 	doWrite = 1;


More information about the xorg-arch mailing list