*BSD News Article 18808


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!haven.umd.edu!uunet!news!demon!pizzabox.demon.co.uk!gtoal
Newsgroups: comp.os.386bsd.questions
From: gtoal@pizzabox.demon.co.uk ("gtoal)
Reply-To: Graham Toal <gtoal@gtoal.com>
Subject: Restricted root shells: termcap problem?
Date: Tue, 20 Jul 1993 22:35:40 +0000
Message-ID: <9307202235.AA10295@pizzabox.demon.co.uk>
Sender: usenet@demon.co.uk
Lines: 143

I've been experimenting with creating a shell that runs in a restricted
root. (No special reason, just wanted to learn more unix stuff)

I've got it set up pretty well, but there's one *strange* problem...
when I run programs (say irc for example) that need termcap information,
they say things like 'No termcap entry for vt100.'  There clearly *is*
a termcap entry - I can see it in /etc/termcap by grepping for it.

Any ideas what's afoot?

Below is the program that I've set to be the shell on the guest account.
I've created a /fakeroot directory which pretends to be /, and inside
it I've created dirs /etc /usr/local/bin etc etc - inside those dirs
I've done ln /etc/* . (from su) to create copies of all the real files.

I create the whole of /dev on the fly each time I enter, plus a couple
of .db files are relinked to make sure they're up to date to provide
info for 'who' etc.  See for yourself:

/* su; cc -o csh csh.c; chmod 4755 csh */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define GUEST_UID 314
#define GUEST_GID 314
int main(int argc, char **argv)
{
  FILE *cshrc, *fcshrc;
  FILE *login, *flogin;
  char *margv[2];
  int i, c;
  
  int tty;
  char *ttypx;
  char fakettypx[128];

  unlink("/fakeroot/var/run/utmp");
  link("/var/run/utmp", "/fakeroot/var/run/utmp");
  unlink("/fakeroot/var/run/dev.db");
  link("/var/run/dev.db", "/fakeroot/var/run/dev.db");
  
  tty = fileno(stdin);
  ttypx = ttyname(tty);
  if (ttypx == NULL) exit(1);
  if (*ttypx != '/') exit(1);
  sprintf(fakettypx, "/fakeroot%s", ttypx);
  unlink(fakettypx);
  for (i = '0'; i <= '9'; i++) {
    sprintf(fakettypx, "/fakeroot/dev/ttyp%c", i);
    unlink(fakettypx);
  }
  for (i = 'a'; i <= 'f'; i++) {
    sprintf(fakettypx, "/fakeroot/dev/ttyp%c", i);
    unlink(fakettypx);
  }
  unlink("/fakeroot/dev/console");
  unlink("/fakeroot/dev/cua0");
  unlink("/fakeroot/dev/cua1");
  unlink("/fakeroot/dev/drum");
  unlink("/fakeroot/dev/fd0a");
  unlink("/fakeroot/dev/fd1a");
  unlink("/fakeroot/dev/klog");
  unlink("/fakeroot/dev/kmem");
  unlink("/fakeroot/dev/log");
  unlink("/fakeroot/dev/lp");
  unlink("/fakeroot/dev/lpt1");
  unlink("/fakeroot/dev/mem");
  unlink("/fakeroot/dev/null");
  unlink("/fakeroot/dev/stderr");
  unlink("/fakeroot/dev/stdin");
  unlink("/fakeroot/dev/stdout");
  unlink("/fakeroot/dev/tty");
  unlink("/fakeroot/dev/ttyd0");
  unlink("/fakeroot/dev/ttyd1");

  sprintf(fakettypx, "/fakeroot%s", ttypx);
  link(ttypx, fakettypx);
  link("/dev/console", "/fakeroot/dev/console");
  link("/dev/cua0", "/fakeroot/dev/cua0");
  link("/dev/cua1", "/fakeroot/dev/cua1");
  link("/dev/drum", "/fakeroot/dev/drum");
  link("/dev/fd0a", "/fakeroot/dev/fd0a");
  link("/dev/fd1a", "/fakeroot/dev/fd1a");
  link("/dev/klog", "/fakeroot/dev/klog");
  link("/dev/kmem", "/fakeroot/dev/kmem");
  link("/dev/log", "/fakeroot/dev/log");
  link("/dev/lp", "/fakeroot/dev/lp");
  link("/dev/lpt1", "/fakeroot/dev/lpt1");
  link("/dev/mem", "/fakeroot/dev/mem");
  link("/dev/null", "/fakeroot/dev/null");
  link("/dev/stderr", "/fakeroot/dev/stderr");
  link("/dev/stdin", "/fakeroot/dev/stdin");
  link("/dev/stdout", "/fakeroot/dev/stdout");
  link("/dev/tty", "/fakeroot/dev/tty");
  link("/dev/ttyd0", "/fakeroot/dev/ttyd0");
  link("/dev/ttyd1", "/fakeroot/dev/ttyd1");


  margv[0] = "-"; /* exec .login */
  margv[1] = NULL;
  cshrc = fopen("/home/guest/.cshrc", "rb");
  if (cshrc == NULL) exit(1);
  (void)remove("/fakeroot/home/guest/.cshrc");
  login = fopen("/home/guest/.login", "rb");
  if (login == NULL) exit(1);
  (void)remove("/fakeroot/home/guest/.login");
  i = chdir("/fakeroot/home/guest");
  if (i != 0) exit(1);
  i = chroot("/fakeroot");
  if (i != 0) exit(1);
  i = setgid(GUEST_GID);
  if (i != 0) exit(1);
  i = setuid(GUEST_UID);
  if (i != 0) exit(1);
  i = chdir("/home/guest");
  if (i != 0) exit(1);
    fcshrc = fopen("/home/guest/.cshrc", "wb");
    if (fcshrc == NULL) exit(1);
    for (;;) {
      c = fgetc(cshrc);
      if (c == EOF) break;
      fputc(c, fcshrc);
    }
    fclose(cshrc); fclose(fcshrc);
    flogin = fopen("/home/guest/.login", "wb");
    if (flogin == NULL) exit(1);
    for (;;) {
      c = fgetc(login);
      if (c == EOF) break;
      fputc(c, flogin);
    }
    fclose(login); fclose(flogin);
  setenv("HOME", "/home/guest", 1);
  i = execv("/bin/csh", margv);
  /* Shouldn't return */
  exit(1);
  return(1);
}

PS I've also set the guest account withboth user/gid 314, and done the
thing with /etc/shells and /etc/ftpusers to ensure that it gets a
restricted root when it logs in on ftp too.  If there's anything else
I can usefully do, please tell me.