Lack of .Xauthority

Have you ever had an issue with running X clients on a firewall protected host where you can’t login directly as the user?  I happens more often than you might think. Here’s an example:

You are user “A” on “hostA”, and hostA is your client machine. Host “hostB” is the host in which you need to run the X application on as user “B”. Furthermore, hostB only allows SSH connections. In addition to the SSH restriction, you need to run an X application as someone other than yourself and you don’t have the password but you can use sudo to become that user. What can you do?

The good new is that it can be done. If you’re interested in the how but not the why, read the end for a one line solution. Otherwise, there are a few road blocks that need to be overcome to get this to work so let’s look at some of those issues:

  1. Since hostA is behind a firewall, the firewall may not be configured to allow X traffic. More than likely this is the case and would prevent the user from simply sudo’ing to the new user and export a display back to hostA.
  2. If you attempted to tunnel the X connection over your SSH connection and then become the user running the X application, you would have found out that once you became the new user and attempted to run the X application you would have been presented with this error similar to this:
    X11 connection rejected because of wrong authentication.
    X connection to localhost:10.0 broken (explicit kill or server shutdown).

So what can you do to get this to work? Actually the answer isn’t all that difficult; it just requires an understanding of how X works. Most users will know that they can export the display to another host by exporting the DISPLAY variable, and that they can use xhost command on the local host to allow access to it. This is called host-based access and is the simplest and least secure access control mechanism available in X.

We already know that X isn’t going to pass through the firewall so any attempt at simply exporting the display isn’t going to work regardless of our initial connect method (SSH or telnet). Some of you who are familiar with SSH will know that it can also tunnel X. SSH creates a “proxy” X server on the remote host and X traffic will be forwarded over the encrypted channel. We can do a simple test to verify this.

A@hostA:~$ ssh -X hostB
Last login: Fri Jan  9 14:23:03 2009 from hostA
/usr/X11R6/bin/xauth:  creating new authority file /home/A/.Xauthority
[~]
A@hostB => xclock

At which point the xclock application will appear on the display of hostA and we now know that X tunneling over SSH works.

xclock_screenshot

But what happens when we become the “B” user? Let’s try again.

A@hostB => sudo su - B
Password:
[~]
B@hostB => xclock
X11 connection rejected because of wrong authentication.
X connection to localhost:10.0 broken (explicit kill or server shutdown).
[~]
B@hostB =>

No luck. The reason this didn’t work is that user “B” doesn’t have the proper authority to display on another user’s display. Remember that X uses an access control mechanism to allow client to write to a display. Unlike the host-based access that we touched on above, X can also use a more secure control mechanism called a “magic cookie”. This cookie allows a user to gain access to a display. By default, these cookies are stored in a file named .Xauthority.

Recall that when we used the X forwarding capabilities of SSH it created a “proxy” X server. Part of the creation of that proxy is the creation of an .Xauthority file to manage the connections to that proxy server. When we created the initial SSH connection with the -X option, “hostB” created a proxy X server with a .Xauthority file in the user’s home directory and added a cookie for the new connection.

One of the good things about cookies is that they can be shared. If I copy the cookie from user “A” and import it into the .Xauthority file of user “B”, user B will be able to use A’s display. There are some caveats to this, but it’s safe to assume that B will be able to display on A for as long as A has the display. Since we are using SSH and it’s providing a proxy X server, it’s very important to remember that we need to copy the cookie from user A on hostB. SSH is doing some translation on the cookies as part of acting as a proxy, so copying user A’s cookie from hostA isn’t going to work.

We can use /usr/X11R6/bin/xauth to manage our .Xauthority file and the cookies contained in it. Let’s validate that we actually have a cookie after logging in with X forwarding turned on.

A@hostB => xauth list
hostB/unix:10  MIT-MAGIC-COOKIE-1  db6b0a2c3f6ef0d52454532e4fb42b93

We know this works as we were able to display the xclock application on our host previously. Notice that we’re looking at user A’s cookie on hostB, NOT hostA. In order to allow user B access to user A’s display, B needs to import A’s cookie. Again, we can use xauth to accomplish this and it’s a quick one-liner.

A@hostB => xauth extract - :`echo $DISPLAY |awk -F: '{print $2}'` | sudo su - B -c "/usr/X11R6/bin/xauth merge -"

This assumes that user A has the ability to sudo su to user B. Once this is done, xclock (or whatever you wish) can be run as user B and will now appear on user A’s display running on hostA. If all of your hosts are internal, this is a relatively secure method of granting access to remote displays. Since the cookies are not encrypted, using this where the connection could be intercepted may not be the best idea and X offers some additional access methods other than host-based and magic cookie.

If you’d like even more info, read the man pages on xauth, and Xsecurity. If a screencast of this would help, let me know.

09. January 2009 by Jason
Categories: Linux | Tags: , | 12 comments

Comments (12)

  1. Hey,

    Thank you mate.
    It’s a wonderful solution.
    It works…

    Best wishes.

  2. The foo is f***ing strong in you. Thanks.

  3. Nice! That’s been very useful, thanks

  4. Thank so much. This really helped me out of a bind.

  5. Thanks! That’s a very useful and very informational article.

  6. Worked like a charm!

  7. the one liner works fine (except that xauth is in /usr/bin/xauth). after executing the command and doing
    sudo su – userB and
    running xcterm produces
    xterm Xt error: Can’t open display:
    xterm: DISPLAY is not set
    So still some more steps needed !

    (userB is on hostB running openSuSE)

  8. Ok, once you set the display like:
    DISPLAY=localhost:10.0 ; export DISPLAY
    then it works.. no problemos.

    The same thing is achieved by another cleaner & easier way:

    ssh -X userA@hostB
    xauth list
    This gives something like :
    hostB/unix:10 MIT-MAGIC-COOKIE-1 db6b0a2c3f6ef0d52454532e4fb42b93

    Then simply:
    sudo su – userB

    xauth add hostB/unix:10 MIT-MAGIC-COOKIE-1 db6b0a2c3f6ef0d52454532e4fb42b93

    (a copy/paste of the above cookie )

    Now, set the DISPLAY and lo, it works !

    DISPLAY=localhost:10.0 ; export DISPLAY
    xterm &
    (and you have it on the screen of hostA )

  9. @nah

    Thanks a lot for your comment. I couldn’t get it to work using the method presented in the article, so this was most helpful.

  10. Worked a treat, plus a great explanation. Thanks!

  11. Like magic, thanks.

Leave a Reply

Required fields are marked *