OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
Bugtraq archives for 1st quarter (Jan-Mar) 1998: Re: Xserver stack smashed -- wrapper

Re: Xserver stack smashed -- wrapper

John Goerzen (jgoerzenSOUTHWIND.NET)
Wed, 21 Jan 1998 12:01:27 -0600

A short time ago, there was some talk about various wrappers around
the X server, and I pointed out that Debian already has one better
than the example posted.  Since then, I have received requests to post
Debian's wrapper source.

This comes from Debian's xfree86 source package.  I do not know who
the original author was (I did not write this code), but a good guess
would be Mark W. Eichin <eichinkitten.gen.ma.us>, Debian's X
maintainer.

I will include the code at the bottom of the message.  First let me
include a sample of the config file that it looks for:

/etc/X11/Xserver:
-- cut --
/usr/X11R6/bin/XF86_S3V
Console

The first line in this file is the full pathname of the default X server.
The second line shows who is allowed to run the X server:
RootOnly
Console      (anyone whose controlling tty is on the console)
Anybody
-- cut --

OK, here is the source to the wrapper itself.  Just compile with gcc
-O2 or some such.

xserver-wrapper.c:
-- cut --
/* X.c - a simple wrapper for X servers that decides whether to let them be
 * run.
 *
 * This program may be distributed under the terms of the GNU public license */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>

#define VT_MAJOR_DEV 4

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

typedef enum {
  RootOnly,
  Console,
  Anybody
} SecurityLevel;

static SecurityLevel getSecLevel(char *security)
{
  char *c;

  for (c=security; *c; c++) *c=toupper(*c);

  if (strncmp(security,"ROOTONLY",8)==0) return RootOnly;
  if (strncmp(security,"CONSOLE",7)==0) return Console;
  if (strncmp(security,"ANYBODY",7)==0) return Anybody;
  return RootOnly;
}

static int checkSecLevel(SecurityLevel level)
{
  struct stat s;

  switch (level) {
  case RootOnly:
    return FALSE;
    break;
  case Console:
    if (fstat(0,&s)!=0) {
      fprintf(stderr,"X: cannot stat stdin\n");
      return FALSE;
    }
    if (S_ISCHR(s.st_mode) && ((s.st_rdev>>8)&0xff)==VT_MAJOR_DEV &&
        (s.st_rdev&0xff)<128) {
      return TRUE;
    }
    break;
  case Anybody:
    return TRUE;
  }
  return FALSE;
}

int main(int argc, char **argv)
{
  FILE *cf;
  char xserver[1024];
  char security[80];
  char *c;

  if (!(cf=fopen("/etc/X11/Xserver","r"))) {
    fprintf(stderr,"X: cannot find configuration file /etc/X11/Xserver\n"
            "\nIf you want to run X clients locally you must install an\n"
            "X server package (eg. xsvga, xs3, xp9000, etc.)\n"
            "Installation of one of these packages should modify the\n"
            "configuration file appropriately.\n");
    exit(1);
  }

  if (!fgets(xserver,1024,cf)) {
    fprintf(stderr,"X: cannot read name of X server from /etc/X11/Xserver\n");
    exit(1);
  }

  /* Strip trailing newline from server name */
  for (c=xserver; *c!=0; c++) if (*c=='\n') *c=0;

  if (!fgets(security,80,cf)) {
    fprintf(stderr,"X: cannot read security setting from /etc/X11/Xserver\n");
    exit(1);
  }

  if (getuid()==0 || checkSecLevel(getSecLevel(security))) {
    /* Run the X server */
    int i;
    for (i = 1; i < argc; i++) {
      if (!strcmp(argv[i], "-config")) {
        if (setuid(getuid())) {
          perror("X couldn't drop setuid privileges for alternate config");
          exit(1);
        }
        break;
      }
    }
    execv(xserver,argv);
    fprintf(stderr,"X: exec of %s failed\n",xserver);
    exit(1);
  } else {
      if (argc == 2 && !strcmp(argv[1], "-showconfig")) {
          if (setuid(getuid())) {
              perror("X couldn't drop setuid privileges");
              exit(1);
          }
          execv(xserver,argv);
          fprintf(stderr,"X: unprivileged exec of %s failed\n",xserver);
          exit(1);
      } else {
          fprintf(stderr,"X: you are not authorised to run the X server\n");
          exit(1);
      }
  }

  exit(1); /* We should never reach this */
}
-- cut --


--
John Goerzen
Southwind Internet Access, Inc,
Business e-mail: jgoerzensouthwind.net

Personal e-mail: jgoerzencomplete.org
Wichita State University e-mail: jgoerzencs.twsu.edu
Developer, Debian GNU/Linux    <http://www.debian.org>