Overview

Introduction

GDM is a replacement for XDM, the X Display Manager. Unlike its competitors (X3DM, KDM, WDM) GDM was written from scratch and does not contain any original XDM / X Consortium code.

For further information about GDM, see the the GDM website.

The GDM Daemon

GDM was written with simplicity and security in mind. The overall design concept is this:

Upon startup the gdm daemon parses its config file gdm.conf. For each of the local displays gdm forks an Xserver and a slave process. The main gdm process will then listen to XDMCP requests, if so configured, from remote displays and monitor the local display sessions. The main daemon process will also allow starting of on new local Xservers on demand using the gdmflexiserver command.

The gdm slave process opens the display and starts gdmlogin, the graphical login program. gdmlogin runs as a dedicated user and communicates asynchronously with the slave process through a pipe. Alternatively gdmgreeter command can be used which is the same as gdmlogin but allows greater themability. gdmgreeter is referred to as the Graphical Greeter, while gdmlogin is refereed to as the Standard Greeter.

GDM relies heavily on the presence of PAM, Pluggable Authentication Modules, but supports regular crypt() and shadow passwords on legacy systems.

Remote displays can connect to the XDMCP port on the GDM host. gdm will grant access to hosts specified in the gdm service section in your TCP Wrappers configuration file. GDM does not support remote display access control on systems without TCP Wrappers. XDMCP support can be turned off completely, however.

GDM includes several measures making it more resistant to denial of service attacks on the XDMCP service. A lot of the protocol parameters, handshaking timeouts etc. can be fine tuned. The defaults should work for most systems, however. Don't change them unless you know what you're doing.

In general GDM is very reluctant regarding reading/writing of user files. For instance it refuses to touch anything but regular files. Links, sockets and devices are ignored. The value of the RelaxPermissions parameter determines whether GDM should accept files writable by the user's group or others. These are ignored by default.

All operations on user files are done with the effective user id of the user. If the sanity check fails on the user's .Xauthority file, a fallback cookie is created in /tmp.

Note that normally it is assumed that the home directory is only readable by the user. However NFS traffic really goes "over the wire" and thus can be snooped. For setups with NFS directories you should really use the UserAuthDir and set it to some local directory such as /tmp. GDM will try to open the normal authorization file for reading as root, and if it fails, then it will conclude that it is on an NFS mount and it will automatically use UserAuthFBDir, which is usually /tmp. This can be changed by setting NeverPlaceCookiesOnNFS in the [security] section to false.

GDM implements only the MIT-MAGIC-COOKIE-1 authorization scheme, see the XDMCP section for more information about this, especially relating to using X over the network.

Finally, the sysadmin can specify the maximum file size GDM should accept, and, if the face browser is enabled, a tunable maximum icon size is also enforced. On large systems it is still advised to turn off the face browser for performance reasons. Looking up icons in homedirs, scaling and rendering face icons can take quite a long time. YMMV.

GDM also has a unix domain socket which can be used to control certain aspects of behavior, or to query information about running servers or logged in users. This is the /tmp/.gdm_socket and the protocol is described in the sources in the daemon/gdm.h header file. The gdmflexiserver command uses this for example to launch on demand X servers for the user.

Different Display Types

GDM allows 3 different display types. First local static X servers. These are always run, and when they die or are killed, they are restarted. GDM can run as many of these as needed. GDM can also manage servers on which it does not manage a login itself, thus allowing GDM to be used when building X terminals.

Next GDM supports flexible or on demand servers. These are run by requesting one using the socket protocol. There is a command, gdmflexiserver, which can do this for the user. For standard X servers the user must be logged in from a console, on one of the servers that GDM has run. This command can however also launch nested Xnest servers which can be started even from non-console logins. This is generally done by running gdmflexiserver -n. These servers are not restarted when the user session ends. gdmflexiserver normally also locks the users screen before running a new server with xscreensaver.

Last display type is the XDMCP remote displays that are described in the next section. Remote hosts can connect to GDM and present the login screen if this is enabled. Some things may be different for these sessions, such as the Actions menu which allows you to shut down, reboot, or configure GDM will not be shown.

XDMCP

GDM also supports the X Display Manager Protocol (XDMCP) for managing remote displays.

GDM listens to UDP port 177 and will respond to QUERY and BROADCAST_QUERY requests by sending a WILLING packet to the originator.

GDM can also be configured to honor INDIRECT queries and present a host chooser to the remote display. GDM will remember the user's choice and forward subsequent requests to the chosen manager. GDM also supports an extension to the protocol which will make it forget the redirection once the user's connection succeeds. This extension is only supported if both daemons are GDM. It is transparent and will be ignored by XDM or other daemons that implement XDMCP.

GDM only supports the MIT-MAGIC-COOKIE-1 authentication system. Normally little is gained from the other schemes, and no effort has been made to implement them so far. Because of this the cookies go over the wire as clear text, and thus you should be careful about what network you use this on. That is, you should be careful about through where your XDMCP connection is going. Note that obviously if snooping is possible, then the attacker could just snoop your password as you log in, so a better XDMCP authentication wouldn't help you much anyway. If snooping is possible and undesirable, then you had better use ssh for tunneling an X connection anyway rather then using GDM's XDMCP. You could think of XDMCP as a sort of graphical telnet, having the same security issues.

On the upside, GDM's random number generation is very anal and GDM goes to extraordinary measures to truly get a 128 bit random number, using hardware random number generators if available, plus the current time (in microsecond precision), a 20 byte array of pseudorandom numbers, process pid's, plus other random information (possibly using /dev/audio or /dev/mem if hardware random generators are not available) to create a large buffer and then run MD5 digest on this. Obviously, all this work is wasted if you send this cookie over an open network or store it on an NFS directory (see UserAuthDir configuration key). So be careful about where you use remote X display.

Since it is fairly easy to do denial of service attacks on the XDMCP service, GDM incorporates a few features to guard against attacks. Please read the XDMCP reference section below for more information.

Even though GDM tries to outsmart potential attackers, it is still advised that you block UDP port 177 on your firewall unless you really need it. GDM guards against DoS attacks, but the X protocol is still inherently insecure and should only be used in controlled environments. Also each remote connection takes up lots of resources, so it is much easier to to DoS an XDMCP server then say a webserver.

In addition to UDP port 177, you should also block all the X server ports (TCP ports 6000 + display number) on the firewall as well. Do note that various places in GDM will use display numbers 20 and higher (for example the on demand server stuff). X is not a very safe protocol for leaving on the net, and XDMCP is even less safe.

Even though your display is protected by cookies the XEvents and thus the keystrokes typed when entering passwords will still go over the wire in clear text. It is trivial to capture these. You should also be aware that cookies, if placed on an NFS mounted directory, are prone to eavesdropping too. In case of NFS home directories you should really use the UserAuthDir and set it to some local temporary directory.

XDMCP is primarily useful for running thin clients such as in terminal labs. Those thin clients will only ever need the network to access the server, and so it seems like the best policy securitywise to have those thin clients on a separate network that cannot be accessed by the outside world, and can only connect to the server. The only point from which you need to access outside is the server.

XDMCP Access Control

XDMCP access control is done using TCP wrappers. It is possible to compile GDM without TCP wrappers however, so you should test your configuration to see if they work.

You should use the daemon name gdm in the /etc/hosts.allow and /etc/hosts.deny files. For example to deny computers from .evil.domain from logging in, then add


    gdm: .evil.domain
to /etc/hosts.deny. You may also need to add

    gdm: .your.domain
to your /etc/hosts.allow if you normally disallow all services from all hosts. See the hosts.allow(5) man page for details.

Even though GDM now tries very hard to ignore things coming from banned hosts you should not rely on the TCP Wrappers for complete protection. It is really best to block UDP port 177 (and all the X ports which are TCP ports 6000 + the display number of course) on your firewall.

The Standard Greeter

The Standard Greeter is the default graphical user interface that is presented to the user. The greeter contains a menu at the top, an optional face browser, an optional logo and a text entry widget.

The text entry field is used for entering logins, passwords, passphrases etc. gdmlogin is controlled by the underlying daemon and is basically stateless. The daemon controls the greeter through a simple protocol where it can ask the greeter for a text string with echo turned on or off. Similarly, the daemon can change the label above the text entry widget to correspond to the value the authentication system wants the user to enter.

The menu bar in the top of the greeter enables the user to select the requested session type/desktop environment, select an appropriate locale/language and optionally shutdown/reboot/suspend the machine, configure GDM (given the user knows the root password) or start an XDMCP chooser.

Optionally the greeter can provide a face browser containing icons for all the users on a system. The icons can be installed globally by the sysadmin or in the users' home directories. If installed globally they should be in the <share>/faces/ directory (though this can be configured with the GlobalFaceDir configuration option) and the filename should be the name of the user, optionally with a .png appended.

The users can place their icons in a file called ~/.face, and they can use the program gdmphotosetup to graphically configure this.

Face icons placed in the global face directory must be readable to the gdm user. However, the daemon, proxies user pictures to the greeter and thus those don't have be be readable by the gdm user, but root.

Please note that loading and scaling face icons located in user home directories can be a very time consuming task. Especially on large systems or systems running NIS. The browser feature is only intended for systems with relatively few users. Also if home directories are on an on demand mounted filesystem like AFS, then GDM may mount all the home directories just to check for pictures if the face browser is on. GDM will try to give up after 5 seconds of activity however and only display the users whoose pictures it has gotten so far.

To filter out unwanted user names in the browser, an exclude option is implemented. The greeter will automatically ignore usernames listed in the Exclude statement in the config file, and furthermore exclude users whose UIDs are lower then MinimalUID.

When the browser is turned on, valid usernames on the machine are inherently exposed to a potential intruder. This may be a bad idea if you don't know who can get to a login screen. This is especially true if you run XDMCP. However you should never run XDMCP on an open network anyway.

The greeter can optionally display a logo in the login window. The image must be in a format readable to the gdk-pixbuf library (GIF, JPG, PNG, TIFF, XPM and possibly others), and it must be readable to the gdm user. See the Logo option in the reference section below for details.

The Graphical Greeter

The Graphical Greeter is a greeter interface that takes up the whole screen and is very themable. Themes can be selected and new themes can be installed by the Configuration program or by setting the GraphicalTheme configuration key.

The look and feel of this greeter is really controlled by the theme and so the user interface elements that are present may be different. The only thing that must always be present is the text entry field as described above in the Standard Greeter.

You can always get a menu of available actions by pressing the F10 key. This can be useful if the theme doesn't provide certain buttons when you really wish to do some action.

Logging

GDM itself will use syslog to log errors or status. It can also log debugging information, but this is not generally useful unless something is very wrong, and this must be enabled in the configuration file.

Output from the various X servers is stored in the GDM log directory, which is configurable, but is usually <var>/log/gdm/. The output from the session can be found in a file called <display>.log. Four older files are also stored with .1 through .4 appended. These will be rotated as new sessions on that display are started. You can use these logs to view what the X server said when it started up.

The output from the user session is redirected to ~/.xsession-errors before even the PreSession script is started. So it is not really necessary to redirect this again in the session setup script. As is usually done. If the user session lasted less then 10 seconds, GDM assumes that the session crashed and allows the user to view this file in a dialog before returning to the login screen. This way the user can view the session errors from the last session and correct the problem this way.

The session output is piped through the GDM daemon and so the ~/.xsession-errors file is capped at about 200 kilobytes by GDM to prevent a possible denial of service attack on the session. An app could perhaps on reading some wrong data print out warnings or errors on the stderr or stdout. This could perhaps fill up the users home directory who would then have to log out and log back in to clear this. This could be especially nasty if quotas are set. GDM also correctly traps the XFSZ signal and stops writing the file, which would lead to killed sessions if the file was redirected in the old fashioned way from the script.

Note that some distributors seem to override the ~/.xsession-errors redirection and do it themselves in their own Xsession script (set by the BaseXsession configuration key) which means that GDM will not be able to trap the output and cap this file. You also lose output from the PreSession script which can make debugging things harder to figure out as perhaps useful output of what is wrong will not be printed out. See the description of the BaseXsession configuration key for more information, especially on how to handle multiple display managers using the same script.

Note that if the session is a failsafe session, or if GDM can't open this file for some reason, then a fallback file will be created in the /tmp directory named /tmp/xses-<user>.XXXXXX where the XXXXXX are some random characters.

If you run a system with quotas set, it would be good to delete the ~/.xsession-errors in the PostSession script. Such that this log file doesn't unneccesairly stay around.

Security and the GDM User

The GDM daemon normally runs as root, as does the slave. However GDM should also have a dedicated user id and a group id which it uses for its graphical interfaces such as gdmgreeter and gdmlogin. You can choose the name of this user and group in the [daemon] section of the configuration file.

The GDM user, and group, which are normally just gdm should not be user or group of any particular privilage. The reason for using them is to have the user interface run as a user without privilages so that in the unlikely case that someone finds a weakness in the GUI, they cannot access root on the machine.

It should however be noted that the GDM user and group have some privilages that make them somewhat dangerous. For one they have access to the server authorization directory (the ServAuthDir), which contains all the X server authorization files and other private information. This means that someone who gains the GDM user/group privilages can then connect to any session. So you should not, under any circumstances, make this some user/group which may be easy to get access to, such as the user nobody.

The server authorization directory (the ServAuthDir) is used for a host of random internal data in addition to the X server authorization files, and the naming is really a relic of history. GDM daemon enforces this dirctory to be owned by root.gdm with the permissions of 1770. This way, only root and the GDM group have write access to this directory, but the GDM group cannot remove the root owned files from this directory, such as the X server authorization files.

GDM by default doesn't trust the server authorization directory and treats it in the same way as the temporary directory with respect to creating files. This way someone breaking the GDM user cannot mount attacks by creating links in this directory. Similarly the X server log directory is treated safely, but that directory should really be owned and writable only by root.

Anybody found not using a dedicated user for GDM should be whacked over the head with a large, blunt, heavy and rusty object, although the rusty requirement may be dropped if there is not enough time to have the object develop rust.