
#define CONFIG "/site/etc/become.conf"
#define SHELL "/afs/sipb/project/tcsh/tcsh"

#include <stdio.h>
#include <pwd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

char *index();

unlimit()
{
    static struct rlimit no_limit = { RLIM_INFINITY, RLIM_INFINITY };
    int res;
    for (res = 0; res < RLIM_NLIMITS; res++)
	setrlimit (res, &no_limit);
}

main(argc, argv)
     int argc;
     char **argv;
{
  char *who;
  static char *defcmd[] = {SHELL, NULL};
  char **cmd = defcmd;
  FILE *f;
  char line[1024];
  char *c, *e;
  char whoami[9];
  struct passwd *pwd;
  
  if (argc < 2) usage();
  pwd = getpwuid(getuid());
  if (!pwd) {
    fprintf (stderr, "intruder alert\n");
    exit(1);
  }
  strcpy (whoami, pwd->pw_name);
  
  who = argv[1];
  if (argc > 2)
    cmd = argv + 2;

  openlog("become", 0, LOG_LOCAL5);
  if (!geteuid()) goto doit;
  if (!strcmp(whoami, who)) goto doit;
  
  f = fopen(CONFIG, "r");
  if (!f) {
    perror(CONFIG);
    exit(1);
  }
  while (fgets(line, sizeof(line), f)) {
    c = index(line, ':');
    if (!c) continue;
    *c++ = 0;
    if (strcmp(line, who)) continue;
    while (c && *c) {
      e = index(c, ',');
      if (!e) e = index(c, '\n');
      if (e) *e++ = 0;
      if (!strcmp(c, whoami)) {
	fclose(f);
      doit:
	syslog (LOG_NOTICE, "User %s becoming %s running %s", whoami, who, cmd[0]);
	closelog();
	pwd = getpwnam(who);
	if (!pwd) {
	  fprintf (stderr, "%s: no such user\n", line);
	  exit(1);
	}
	setuid(pwd->pw_uid);
	if (!pwd->pw_uid)		/* Let root run with no limits */
	    unlimit();			/* hack hack hack */
	if (execv(cmd[0], cmd)) 
	  perror("execv");
	exit(1);
      }
      c = e;
    }
  }
  syslog (LOG_INFO, "USER %s DENIED becoming %s running %s", whoami, who, cmd[0]);
  closelog();
  fclose(f);
  fprintf (stderr, "permission denied\n");
  exit(1);
}
  

usage()
{
  fprintf(stderr, "usage: become username [argv ...]\n");
}

