README FOR XTERM SETUID WRAPPER
-------------------------------

xterm is setuid root in order for it to manipulate utmp, wtmp, lastlog
and to allocate a pty securely. xterm is also linked against the X
libraries, which were not written with security in mind, and there are
bugs which in the X libraries which can be exploited via xterm to get
superuser priviledge.

xterm-wrapper is a program that handles logfiles and pty allocation,
and then calls the real xterm program. xterm-wrapper has the following
structure.
_______________________________________________________________________________

Init:
Block all signals.
Get username from password file entry.
Parse the command line looking for +ut, -ut, and -display.
Allocate a pty, chown and chmod corresponding tty.
Fill in utmp (if required).
Fill in wtmp (always).
Fill in lastlog (always).
Fork
[Parent]				[Child]
Set signal handler			Drop priviledge.
Allow selected signals			Allow signals.
					Compose command line, putting 
					-Mptyfd at start.
					Exec xterm
Run:
Forward selected signals to the child process
Wait for child to exit

Done:
Remove utmp entry (if required)
Remove wtmp entry
Restore owner/permissions of tty device.
_______________________________________________________________________________

The command line is parsed to get the display name - the is used for
the host entry in the logs. It's also used to get +ut/-ut to turn
on/off utmp handling. (wtmp is always handled so that it provides an
audit trail.)

When a pty is opened, the tty is chmoded and chowned to the correct
permissions and user. utmp is handled by the libc functions. wtmp and
lastlog are done manaully. wtmp handling is such that the file can
become corrupt.

Signals are forwarded to the child process so they affect the real
xterm process and not the wrapper. All blockable signals are either
forwarded or blocked. SIGTSTP is handled by forwarding it then calling
SIGSTOP.
_______________________________________________________________________________

Files
-----
main.c		Main program, pty allocation, dropping priviledge, 
		calling xterm, signal handling and forwarding

parse.c		Extracting arguments from original argument list, setting
		display and utmp-inhibit variables

sessreg.c	utmp/wtmp/lastlog handling
_______________________________________________________________________________

main.c:

static int get_pty(int *ptyfd, const char **ptyname, const char **ttyname, 
	const char **line);
Search the ptys for a free pty.
On success, set ptyfd to the open pty, set ptyname, ttyname and line to static
buffers for the pty ('/dev/pty??'), tty ('/dev/tty??') and line ('tty??').
Return 0 on success, 1 otherwise.

void xterm(int argc, const char *argv[], int fd, const char *line);
Exec the modified xterm as a child process.
Returns only on error.

void sigforward(int signal);
Signal handler - forward signal to child application. If signal is SIGTSTP,
forward signal then send self SIGSTOP.

int main(int argc, const char *argv[]);
Block signals, get pty, register session, run xterm and deregister session.
Returns 0 on success, non-zero otherwise.

parse.c:

void parse(int argc, const char *argv[], int *noutmp, const char **display);
Parse the command line to extract utmp-inhibit and display.

sessreg.c:

static int dowrite(int fd, const void *buf, size_t len);
Reliable write(). Returns 0 on success, 1 otherwise.

static void make_utmp(struct utmp *u, const char *line, const char *host, 
	const char *name, time_t time, int add);
Create a utmp structure in memory.

static void utmp(struct utmp *u);
Write a utmp entry.

static int wtmp(struct utmp *u, int silent);
Write a wtmp entry.

static void make_llog(struct lastlog *l, const char *line, const char *host, 
	time_t time);
Create a lastlog structure in memory.

static int llog(struct lastlog *l, uid_t uid, int silent)
Write a lastlog entry.

int sessreg(const struct passwd *pwd, const char *line, const char *host, 
	int noutmp, int add, int silent);
Write utmp, wtmp and lastlog entries.
pwd is a non-NULL pointer to a struct passwd for the current user.
host is a non-NULL pointer to the name of the host.
noutmp inhibits utmp handling.
The utmp entry is added if add is true, and removed otherwise.
Errors are not reported to stderr if silent is true.
Returns 0 for success, 1 otherwise.
_______________________________________________________________________________

The xterm patch turns of utmp handling and gives an extra option, '-M', to
enable users to pass an open filedescriptor to a pty for the xterm to use.

Peter Benie
