Thursday, March 25, 2010

SSH, XAuth and X11 Forward after user switch at remote site

Problem

User A connects to server S using ssh. X11 forward is enabled using –Y option. Then X11 should work smoothly.
User A connects to server S using ssh. X11 forward is enabled. Then user A switches to another User B (using command su B or ssh localhost –l B). After that, X11 forward won't work. The error should look like
"SSH gateway: X11 authentication failed. Error: Can't open display:" or
"Error: Can't open display:".
Readers may ask why user A does not directly connect to server S as user B given user A knows password of user B. The reason is that sometimes user B is a restricted user account so that he cannot log in remotely.

Solution

  1. Run command
        echo ${DISPLAY}
    Sample result:
        localhost:11.0
  2. Command: xauth list
    The output should be like:   
    your_host_name/unix:11  MIT-MAGIC-COOKIE-1  d1e63de6fd7bc3800d868c3b64ca4531
    your_host_name/unix:0  MIT-MAGIC-COOKIE-1  e044d47b672dcade1362cd632236f919
    your_host_name/unix:10  MIT-MAGIC-COOKIE-1  2aa3bc47d1c209fd06577f4b45f83383
    Pick the entry with the same display number as the output in step 1)
    In this example, display number is 11, so the entry we pick is
    your_host_name/unix:11  MIT-MAGIC-COOKIE-1  d1e63de6fd7bc3800d868c3b64ca4531
  3. switch to another user using either of the following ways
    1) su user_name
    or su – user_name
    read "man su" for difference between these two commands.
    2) ssh localhost –l user_name
  4. In step 3), if you ran command "su – user_name" or "ssh localhost –l user_name", you should run command
        export DISPLAY=localhost:11.0
    Value of DISPLAY should be the same as the output in step 1).

    add the entry obtained in step 2) to the .Xauthority file. You can either add it manually to the file or use tool xauth to do it. The way to use xauth to add an entry:
        xauth add :11 . d1e63de6fd7bc3800d868c3b64ca4531
    The cookie string (long string) must match the one in step 2). The display number (:11) must match the result in step 1)
  5. Try command
        xclock

Or you can combine step 1), 2), 3) and 4) into one long command:

    (tmpfile=/tmp/xauth_tmp_entry; \
    xauth extract ${tmpfile} :$(echo $DISPLAY|cut -d : -f 2 ); \
    chmod a+r ${tmpfile}; \
    su user_name -c "xauth merge ${tmpfile}"; \
    rm ${tmpfile} )

Note: replace user_name with the real target user name.

Disadvantage

Each time the user reconnects the remote machine using ssh, the whole process described above must be redone :-( The reason is that sshd may choose another display number and cookie value.

How SSH X authorization works?

From ssh manual:

"ssh will also automatically set up Xauthority data on the server machine.  For this purpose, it
will generate a random authorization cookie, store it in Xauthority on the server, and verify
that any forwarded connections carry this cookie and replace it by the real cookie when the
connection is opened.  The real authentication cookie is never sent to the server machine (and
no cookies are sent in the plain)."

http://blogs.gnome.org/markmc/2005/02/25/ssh-x-forwarding-and-xauth/

Every time a user connects to a remote server using ssh, a proxy X server is created. And that X server is used by the sshd process (a new process is forked each time a new connection comes in). The process is like:

  user ---> server ---> fork a new process, 
create a proxy X server
create pseudo terminal, etc. |
                                       |
                                       V
                        a program that needs X is used
                                       |
                                       |
                                       V
  local display <--- verify <--- the X output is forwarded by sshd to client

It seems that after a user connects to a remote server using ssh, another proxy X server is not created when the user ssh to localhost or 127.0.0.1.

1 comment:

Eric said...

Hi - very nice code! Thanks and here goes a switchuser-script:

#bin/sh
tmpfile=/tmp/xauth_tmp_entry
xauth extract ${tmpfile} :$(echo $DISPLAY|cut -d : -f 2 )
chmod a+r ${tmpfile}
su $1 -c "xauth merge ${tmpfile}"
rm ${tmpfile}
sudo login $1 DISPLAY=$DISPLAY