Re: Xserver stack smashed -- wrapper

From: John Goerzen (jgoerzenat_private)
Date: Wed Jan 21 1998 - 10:01:27 PST

  • Next message: Pavel Kankovsky: "Re: Xserver stack smashed -- wrapper"

    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 <eichinat_private>, 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: jgoerzenat_private
    
    Personal e-mail: jgoerzenat_private
    Wichita State University e-mail: jgoerzenat_private
    Developer, Debian GNU/Linux    <http://www.debian.org>
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:40:53 PDT