From:	SMTP%"everhart@mail09.mitre.org" 22-JAN-1998 17:25:25.11
To:	everhart@gce.com (everhart@gce.com)
CC:	
Subj:	FWD: Re: Xserver stack smashed -- wrapper

--===_tgate3_44691_96625535_===
Content-Type: text/plain; charset="us-ascii"

----- Forwarded message follows -----
Approved-By: aleph1@UNDERGROUND.ORG
References: <Pine.LNX.3.96.980116100237.21536I-100000@lacrosse.redhat.com>
Lines: 163
Date: Wed, 21 Jan 98 13:01:27 -0500
Reply-To: John Goerzen <jgoerzen@SOUTHWIND.NET>
From: John Goerzen <jgoerzen@SOUTHWIND.NET>
Subject: Re: Xserver stack smashed -- wrapper
To: <BUGTRAQ@NETSPACE.ORG>
In-Reply-To: Erik Troan's message of "Fri, 16 Jan 1998 10:03:02 -0500 (EST)"

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 <eichin@kitten.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: jgoerzen@southwind.net

Personal e-mail: jgoerzen@complete.org
Wichita State University e-mail: jgoerzen@cs.twsu.edu
Developer, Debian GNU/Linux    <http://www.debian.org>


----- End of forwarded message -----

--===_tgate3_44691_96625535_===--

================== RFC 822 Headers ==================
Return-Path: everhart@mail09.mitre.org
Received: by norlmn.gce.com (UCX X4.2-14, OpenVMS E7.1-1H1 Alpha);
	Thu, 22 Jan 1998 17:16:27 -0500
Received: from mbunix.mitre.org (mbunix.mitre.org [129.83.20.100]) by mercury.mv.net (8.8.8/mem-971025) with ESMTP id IAA25360 for <everhart@gce.com>; Thu, 22 Jan 1998 08:22:03 -0500 (EST)
Received: from TGATE3 (tgate3.mitre.org [129.83.20.27])
	by mbunix.mitre.org (8.8.8/8.8.8/mitre.0) with ESMTP id IAA02415
	for <everhart@gce.com>; Thu, 22 Jan 1998 08:25:37 -0500 (EST)
Received: from mail09.mitre.org (unverified [129.83.20.43]) by tgate3.mitre.org (EMWAC SMTPRS 0.83) with SMTP id <B0005765447@tgate3.mitre.org>; Thu, 22 Jan 1998 08:25:36 -0500
Received: by mail09.mitre.org; (5.65v3.2/1.1.8.2/22Jun94-0628PM) id AA16341; Thu, 22 Jan 1998 08:25:32 -0500
Subject: FWD: Re: Xserver stack smashed -- wrapper
From: everhart@mail09.mitre.org (Glenn C. Everhart)
To: everhart@gce.com (everhart@gce.com)
Message-Id: <980122082530.31233@mail09.mitre.org.0>
Date: Thu, 22 Jan 98 08:25:31 -0500
X-Mailer: MailWorks 2.0-4
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="===_tgate3_44691_96625535_==="
