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