Communication between XDM and the Chooser

XDM is supposed to use the XDMCP protocol to communicate with X servers. If you use xdm to provide the Chooser, it does not. The correct XDMCP protocol interaction is:

  Display    -----  Send indirect query              ----->  Manager

  Manager    -----  Forward query to other machines  ----->  Other Managers

  Other      -----  Send replies giving status       ----->  Display
  Managers

  (The display updates the host list. The user chooses a host.)

  Display    ------ Request session                  ----->  Other Manager

  (etc.)

The protocol actually implemented is closer to:

  Display    -----  Send indirect query              ----->  Manager

  (The manager does not forward the query.)

  Manager    -----  Send willing reply               ----->  Display

  (The display responds to the first willing reply.)

  Display    ------ Request session                  ----->  Manager

  Manager    ------ Accept session                   ----->  Display

  Display    ------ Manage session                   ----->  Manager

  Manager    ------ X connection from the chooser    ----->  Display

  Manager    -----  Forward query to other machines  ----->  Other Managers

  Other      -----  Send replies giving status       ----->  Manager
  Managers

  (The manger updates the host list. The user chooses a host from the 
  list. The chooser tells xdm which host has been chosen.)

  Manager    ------ Closes X connection              ----->  Display

  (The display resets.)

  Display    -----  Send indirect query              ----->  Manager

  (The manager ignores the query and its retransmissions up to 15 secs.)

  Manager    -----  Forward query to other machine   ----->  Other Manager

  Other      -----  Send reply giving status         ----->  Manager
  Manager

  Display    ------ Request session                  ----->  Other Manager

  (etc.)

There are a number of protocol weaknesses in both the specified protocol and the implemented protocol. Some of these weakness render the protocol quite insecure, and unsuitable for use on a network connected to the Internet, however, fixing the protocol means writing and deploying a great many clients and servers for a large number of platforms. Given that we're stuck with the current implementation, we should fix the most easily exploited problems where possible. One of these is the communication between the XDM and the chooser.

In the XDMCP protocol, xdm does not need to know which machine a user has chosen because the choosing is done entirely in the X-server, and a manager will always respond to an indirect query by forwarding the query to other managers. In the implemented protocol, choosing the host is done on the machine running xdm, and the chooser (known as dtchooser by CDE users) has to communicate the user's choice of host back to xdm (dtlogin) so that when the X server resets and sends out an xdmcp indirect query, xdm can return an appropriate response. This communication is done using a tcp connection. The master xdm creates a listener during its initialisation, and the chooser processes connect to the master xdm when they wish to register a user's choice of host. The port that xdm is listening on is given on the chooser's command line.


/usr/dt/bin/dtchooser -xdmaddress 00020401c0a81243 -clientaddress c0a81244 ...
                                   /    |      \
                             Family    Port    IP address
By using a tcp socket, xdm is unable to distinguish the chooser's connections from other connections. Since the the port is not bound to a local address, anyone on the Internet can exploit this weakness to choose which machine you are going to have a session on. The port number used is usually 1024 on Linux 2.0, and 1025 on Linux 2.1, so the exploit is quite easy. If you have a local account, you don't even have to guess the port number, since ps will tell you.

The chooser only makes the connection when the user has chosen a host, so it continues to operate correctly even if xdm was restarted while the chooser was running. Replacing the tcp connection with a pipe or socketpair would break that functionality. Instead, I have replaced the tcp socket with Unix-domain socket.

The socket is placed in a directory because many versions of Unix don't support permissions on sockets. The directory should be created using:


(umask 077 && mkdir /usr/lib/X11/xdm/socketdir)

The following patch was made against XFree86-3.3.2 and should be applied using

cd <Xsourcedir>/xc/programs/xdm && patch -p1 </path/to/xdm-socket.patch

xdm-socket.patch

This is the second version of the patch - the first version only worked on Linux 2.1 systems. You should verify that the patch is working correctly by restarting xdm, starting a display that makes an indirect query, checking that the command line has a pathname instead of an IP address, and selecting a host from the list.

You might also be interested in a patch to make generate better authorization keys:

xdm-genauth.patch


Peter Benie <pjb1008@cam.ac.uk>