Have you ever needed to run an X11 based program like emacs or firefox in a sudo session and received one of the following errors?
1 2 3 4 |
% firefox X11 connection rejected because of wrong authentication. Error: cannot open display: localhost:10.0 |
This blog describes how to fix the problem.
I needed to solve this problem because there are a number of hosts on my network that do not allow root logins for security reasons. As a result I have to log into these hosts as a non-root user and then create a sudo session to perform administrative functions. Furthermore, I often do this remotely via XRDP, VNC or FreeNX through an ssh tunnel (or VPN) so there can be multiple credentials set.
To run an X11 based tool, I need to set the proper X credentials in the sudo session. I used to do this manually by manually looking up the xauth list
for the original login and then adding them using xauth add
in the sudo session but I recently figured out how to make it work with a single command.
1 Steps
The basic steps are:
- Login into the remote host. Make sure that X11 forwarding is enabled. I tend to use trusted forwarding which is why you see -Y instead of -X.
ssh -Y user@host
- Create the sudo session by logging in with
sudo user -
- Grab the X credentials for the original user. There can be many of them which is why the next step filters out the one we want.
su - user -c "xauth list"
- Filter out the credential that we want using grep by looking for matches based on the DISPLAY environment variable. The extracted string used in the grep pattern match will be something like
:10
.grep `echo $DISPLAY |\
cut -d ':' -f 2 |\
cut -d '.' -f 1 |\
sed -e s/^/:/` - Enable the credentials for this session using the xauth add command. The xargs command says to take the first 3 arguments and pass them to the xauth add command.
xargs -n 3 xauth add
Another option suggested by “scott e” on 2013-10-28 is to use the command “xauth -f ~user/.Xauthority
” command which simplifies things. Here are the steps based on the new idiom:
- Login into the remote host. Make sure that X11 forwarding is enabled. I tend to use trusted forwarding which is why you see -Y instead of -X.
ssh -Y user@host
- Create the sudo session by logging in with
sudo user -
- Enable the credentials for this session using the “x
auth -f ~user/.Xauthority
” command.
2 Example
Here is an example that shows how it works.
1 2 3 4 5 6 7 8 9 10 11 12 |
% ssh -Y -A -t -C -o CompressionLevel=9 admin@thehost admin@thehost's password: <admin-password> [admin@thehost ~]$ sudo su - [sudo] password for admin: <admin-password> [root@thehost ~]$ su - admin -c 'xauth list' |\ grep `echo $DISPLAY |\ cut -d ':' -f 2 |\ cut -d '.' -f 1 |\ sed -e s/^/:/` |\ xargs -n 3 xauth add [root@thehost ~]$ emacs & |
Note that I used compression level 7 because this example was taken from a remote session where I experimentally determined that it improved performance. Before setting a compression level, you should verify that it really does improve performance. Often it doesn’t help.
Enjoy!
7 or 9 ?
The example shows compression 9, but your note says 7.
In either case, the intent is clear.
Thanks,
dt
nice!
smart and simple, i like it
thx for that
You saved me an evening man..
Thank you.
I improved the command a bit to allow cut-and-paste without the need to adapt the user name by using the SUDO_USER environment variable:
su - $SUDO_USER -c 'xauth list' |\
grep
echo $DISPLAY |\
|\cut -d ':' -f 2 |\
cut -d '.' -f 1 |\
sed -e s/^/:/
xargs -n 3 xauth add
Tested on Debian/Ubuntu installations.
Emh…
sudo -E firefox
should do it…
Ow waa!
The parameter “-E”:
It was sufficient for the work.
Works fine on Debian Wheezy !
Thank you very much.
This works if sudoing to “root” (the default), but it will definitely not work if using for example
% sudo -u -E xeyes
No protocol specified
Error: Can't open display: :0
Thank you Daniel, but you forgotten the
sign; I correct it:
su - $SUDO_USER -c 'xauth list' |\
grep
echo $DISPLAY |\
cut -d ':' -f 2 |\
cut -d '.' -f 1 |\
sed -e s/^/:/
|\
xargs -n 3 xauth add
Or if you like a single line command:
su - $SUDO_USER -c 'xauth list' |grep echo $DISPLAY |cut -d ‘:’ -f 2 |cut -d ‘.’ -f 1 |sed -e s/^/:/` | xargs -n 3 xauth add
Thank you all for the valuable help!
Thank you Daniel, but you forgotten the sign:
disappears if you do not enter it in a “code box”
Here is the command again:
Or if you like a single line command:
Thank you all for the valuable help!
$SUDO_USER is not present on my system. instead, I use:
su -
logname
-c 'xauth list' |\grep
echo $DISPLAY |\
|\cut -d ':' -f 2 |\
cut -d '.' -f 1 |\
sed -e s/^/:/
xargs -n 3 xauth add
Thank you, that is a very helpful tip.
Put this in root’s .bash_functions, .bashrc, or .bash_profile:
Then just use
Thanks, I really like your suggestion.
whats wrong with:
1) sudo su –
2) xauth add $(xauth -f <home directory of regular user>/.Xauthority list)
I like that. I have updated the blog and credited you. Thank you for the suggestion.
Dude.. That was all I needed… a frikken little ‘-E’
sudo -E firefox
Thank You !
similar to scott e’s solution i was hoping to just run a single sudo command rather than create a root shell.
what i ran across in the xauth man page is that it uses an environment variable XAUTHORITY to trump which authority file to use. tried out the following, and my app launched as root
Interesting, thank you.
This page was great with all the ideas. I was looking for something I could script for multiple users, and it seems with the combination of your ideas one could do this:
export XAUTHORITY=$(eval echo ~$(logname)/.Xauthority)
The only problem is it would only work if you sudo to root, unless you want to make your .Xauthority file readable by any user.
Thanks everyone!