I'm trying to write an application that runs as a daemon and monitors
running X sessions. Right now I'm struggling to find documentation
regarding the X security model. Specifically, I'm attempting to
connect to running X displays from my daemon process. Calling
XOpenDisplay(dispName)
doesn't work, I guess because my process
doesn't have permission to connect to this display. After a bit of
research, it looks like I need to do something with xauth.
In my test environment, the X server is started like this:
/usr/bin/X -br -nolisten tcp :0 vt7 -auth /var/run/xauth/A:0-QBEVDj
That file contains a single entry, that looks like this:
#ffff##: MIT-MAGIC-COOKIE-1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
by adding an entry to ~/.Xauthority
with the same hex key, I can
connect to the X server. However, this is difficult because I need to
programmatically find the auth file the X server is using (the
location of which I guess will change from distro to distro, and
probably from one boot to the next), then query it, then write a new
auth file. If the process is running as a daemon, it might not have a
home directory, so how do I know where to write the new entries to?
Ideally, what I'm looking for is a way to bypass the need to have the
xauth cookie in ~/.Xauthority
, or even to know what the cookie is at
all. I realise that this is unlikely - what good is a security model
if it's easily bypassed? but I'm hoping someone on this list may have
a few good ideas. Is there a way to specify that my process is
privileged and thus should automatically be given access to any
display on the local machine?
You don't have to use a home directory if you specify an XAUTHORITY
environment variable, which specifies the location of the .Xauthority
file. Read the xauth
man page.
But, in general, it's hard to locate the auth file, for the reasons you mentioned; also, this "fishing for auth tokens" approach would only work for local displays.
With regard to letting root (or some other user) connect to an X server willy-nilly, you'd probably have to patch the source code to do this, and you'd have to use something like getpeereid
to obtain the connecting user's uid/gid (this only works on Unix-domain sockets, which I presume would be the type used for local connections, anyway).