Skip to content

X authentication with cookies and xhost ("No protocol specified" error)

Martin Viereck edited this page Jul 22, 2022 · 27 revisions

X authentication

X servers normally run with enabled cookie authentication (X option -auth).

  • Only clients providing the cookie can access the X server.
  • Exceptions from mandatory cookie authentication can be declared with xhost.
  • If an X client is not allowed to access the X server, it throws errors like No protocol specified. Unable to init server: Could not connect: Connection refused or Couldn't connect to XServer.
    • This is different from error Cannot open display that indicates that either variable DISPLAY is not set correctly or the X server is not accessible for other reasons, e.g. not running at all.

XAUTHORITY

The path to the cookie is stored in environment variable XAUTHORITY.

  • Normally the file is ~/.Xauthority or $XDG_RUNTIME_DIR/Xauthority.
  • The file can contain more than one cookie and for more than one X server.
  • X clients read this variable and authenticate themselves at the X server with the cookie.
  • Stored cookies can be seen with xauth list.

xhost

Exceptions to cookie authentication can be specified with xhost.

  • xhost weakens the X security setup. Prefer to work with cookies.
  • Check current xhost access rules with plain xhost command.
  • X authentication can be disabled entirely with xhost +. Don't do that. No access protection is left, and X can be abused horribly.
  • X access for single local users can be specified with:
    • xhost +SI:localuser:username (Replace username with desired user name).
    • xhost "+SI:localuser:#uid" (Replace uid with desired user uid).
    • This can be revoked with - instead of +, e.g. xhost -SI:localuser:username.
    • Often seen use case: Allow root access to X: xhost +SI:localuser:root

Cookie baking

If you want to run your own X server, provide it a cookie generated with xauth:

Cookiefile=~/mycookie
Displaynumber=100
touch $Cookiefile
xauth -f $Cookiefile add :$Displaynumber . $(mcookie)

Run an X server with this cookie:

# $Displaynumber must not be in use in ~/tmp/.X11-unix
Xephyr :$Displaynumber -auth $Cookiefile

Run an application (here a window manager) on the new X server:

env DISPLAY=:$Displaynumber XAUTHORITY=$Cookiefile fluxbox

Additional note: If you want to provide the X server to a container, add option -extension MIT-SHM to the X server command. That avoids some memory access errors and graphical glitches. Otherwise you would need insecure docker run option --ipc=host.

Special case: Request cookie from X server

You can ask a running X server to generate a cookie for you:

touch $Cookiefile
xauth -f $Cookiefile generate :$Displaynumber . trusted timeout 3600
  • An interesting use case is to replace trusted with untrusted. That generates a cookie that can be used for untrusted applications. The X server will deny some security sensitive features to applications that use this cookie.
  • timeout 3600 means that the cookie must be used from a client within 3600 seconds, otherwise it will be discarded as invalid.
  • This X feature needs X extension SECURITY. Normally it is enabled by default. You can check this with xdpyinfo | grep SECURITY.

Special case: Start X server with empty cookie

It is possible to start the X server with an empty cookie file and to generate the cookie afterwards. The X server will have no access restriction until the cookie is created:

Cookiefile=~/mycookie
Displaynumber=100
rm $Cookiefile
Xephyr :$Displaynumber -auth $Cookiefile
Cookiefile=~/mycookie
Displaynumber=100
touch $Cookiefile
xauth -f $Cookiefile generate :$Displaynumber . trusted timeout 3600

Cookies in a container

Access to the X server can be done sharing the X unix socket in /tmp/.X11-unix, e.g. with --volume /tmp/.X11-unix/X0:/tmp/.X11-unix/X0. The cookie from XAUTHORITY cannot be shared immediately but needs some preparation.

  • Cookies contain a server adress family code. That must be overwritten. A way to go:
  • Choose a new cookie file name, e.g. ~/mycookie.
  • Read the cookie from XAUTHORITY, adjust it, and store the result in ~/mycookie.
    Cookiefile=~/containercookie
    Cookie="$(xauth nlist $DISPLAY | sed -e 's/^..../ffff/')" 
    echo "$Cookie" | xauth -f "$Cookiefile" nmerge -
    
  • Share the new cookie with the container and set XAUTHORITY accordingly
    docker run --env XAUTHORITY=/cookie \
               --volume $Cookiefile:/cookie \
               --env DISPLAY=$DISPLAY \
               --volume /tmp/.X11-unix/X0:/tmp/.X11-unix/X0 \
               --ipc=host \
               [...]
    
    Additional note: --ipc=host is added to avoid MIT-SHM issues. Note that this also reduces container isolation. This is not needed if the X server runs without extension MIT-SHM. You can check that with xdpyinfo | grep MIT-SHM. Further info at MIT-SHM error solutions.

Untrusted cookie for container applications

Consider to use untrusted cookies for container applications. Cookie generation changes to:

Cookiefile=~/containercookie
:> $Cookiefile
xauth -f $Cookiefile generate $DISPLAY . untrusted timeout 3600
Cookie="$(xauth -f $Cookiefile nlist $DISPLAY | sed -e 's/^..../ffff/')" 
echo "$Cookie" | xauth -f "$Cookiefile" nmerge -
  • A few applications do not work well with untrusted cookies but expect to have all X features available. That case is an application bug.
  • A nice bonus: With untrusted cookies the X clients are not allowed to use MIT-SHM. You can omit insecure docker run option --ipc=host.
Clone this wiki locally