#!/usr/bin/perl
##########################################################################
# $Id: secure,v 1.13 2002/03/28 05:00:00 kirk Exp $
##########################################################################
# $Log: secure,v $
# Revision 1.13  2002/03/28 05:00:00  kirk
# - Implemented several bug fixes and patches that have been sent in
# - Fixed a possible root exploit using a race condition in /tmp
# - Fixed bugs 46371, 56191, 58578, 61202, 61829, 61831, 61832 from bugzilla.redhat.com
#
# Revision 1.12  2000/09/22 15:59:05  kirk
# Prepping for Version 2.0.1
#
# Revision 1.11  2000/09/22 14:47:04  kirk
# *** empty log message ***
#
# Revision 1.10  1999/02/23 14:55:13  kirk
# Prepping for Version 1.6.6
#
# Revision 1.9  1999/02/23 01:24:31  kirk
# Improved LookupIP in named/secure.
# Applied ftp-messages patch from Simon Liddington <sjl96v@ecs.soton.ac.uk>.
#
# Revision 1.8  1999/02/23 00:39:54  kirk
# Added code written by Fabrizio Zeno Cornelli <zeno@filibusta.crema.unimi.it>.
#
# Revision 1.7  1998/09/08 13:08:21  kirk
# Applied patches submitted by Simon Liddington <sjl96v@ecs.soton.ac.uk>.
# Thanks!
#
# Revision 1.6  1998/07/30 19:44:49  kirk
# Prepping for Version 1.4.2
#
# Revision 1.5  1998/06/11 16:37:36  kirk
# Prepping for Version 1.4.1
#
# Revision 1.4  1998/06/01 20:39:55  kirk
# Applied patch submitted by Simon Liddington <sjl96v@ecs.soton.ac.uk>...
#
# Revision 1.3  1998/05/11 13:03:31  kirk
# Applied some wonderful patches sent in by
# Luuk de Boer <luuk_de_boer@pi.net>.
#
# Revision 1.2  1998/04/08 18:32:03  kirk
# Applied changes submitted by Luuk de Boer <luuk_de_boer@pi.net>.. Thanks!
#
# Revision 1.1  1998/03/19 06:43:14  kirk
# Added support for /var/log/secure
#
##########################################################################

########################################################
# This was written and is maintained by:
#    Kirk Bauer <kirk@kaybee.org>
#
# Please send all comments, suggestions, bug reports,
#    etc, to kirk@kaybee.org.
#
########################################################

#$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'};
$DoLookup = $ENV{'secure_ip_lookup'};
$Ignore = $ENV{'ignore_services'};

sub LookupIP {
   my ($name, $a1, $a2,$a3,$a4,$PackedAddr,$Addr);
   $Addr = $_[0];
   ($a1,$a2,$a3,$a4) = split /\./,$Addr;
   $PackedAddr = pack('C4',$a1,$a2,$a3,$a4);
   if ($DoLookup) {
      if ($name = gethostbyaddr ($PackedAddr,2)) {
         return ($name . " (" . $Addr . ")");
      } else {
         return ($Addr);
      }
   }
   else {
      return ($Addr);
   }
}

while (defined($ThisLine = <STDIN>)) {
   chomp($ThisLine);
   $ThisLine =~ s/^... .. ..:..:.. [^ ]+ //;
   my $temp = $ThisLine;
   $temp =~ s/^([^[]+).*/$1/;
   #print "Ignore: $Ignore [temp: $temp]\n";
   if ($Ignore =~ /$temp/) { 
      next;
   }
   if ( ($Host,$User) = ($ThisLine =~ /^login: FAILED LOGIN \d+ FROM ([^ ]+) FOR ([^,]+),/ ) ) {
      $FailedLogins->{$User}->{$Host}++;
   }
   elsif ( ($Service,$IP) = ($ThisLine =~ /^([^ ]+)\[\d+\]: connect from (\d+\.\d+\.\d+\.\d+).*/) ) {
      $Name = LookupIP ($IP);
      $Connections->{$Service}->{$Name}++;
   }
   elsif ( ($Service,$IP) = ($ThisLine =~ /^([^ ]+)\[\d+\]: refused connect from (\d+\.\d+\.\d+\.\d+)$/) ) {
      $Name = LookupIP ($IP);
      $Refused->{$Service}->{$Name}++;
   }
   elsif ( ($Service,$Name) = ($ThisLine =~ /^([^ ]+)\[\d+\]: refused connect from (.*)$/) ) {
      $Refused->{$Service}->{$Name}++;
   }
   elsif ( ($Service,$Name) = ($ThisLine =~ /^([^ ]+)\[\d+\]: connect from ([^ \n]+)$/) ) {
      $Connections->{$Service}->{$Name}++;
   }
   elsif ( ($Service,$Name) = ($ThisLine =~ /^xinetd\[\d+\]: START: ([^ ]+) pid=\d+ from=([^ \n]+)$/) ) {
      $Connections->{$Service}->{$Name}++;
   }
   elsif ( ($Service) = ($ThisLine =~ /^xinetd\[\d+\]: EXIT: ([^ ]+) pid=\d+/) ) {
      #ignore...
   }
   elsif ( $ThisLine =~ s/^([^ ]+)\[\d+\]: warning: can\'t get client address: No route to host$/$1/ ) {
      $NoIP->{$ThisLine}++;
   }
   elsif ( $ThisLine =~ m/^[^ ]+\[\d+\]: connect from localhost$/ ) {
      #ignore...
   }
   elsif ( $ThisLine =~ s/^([^ ]+)\[\d+\]: warning: can\'t get client address: Network is unreachable$/$1/ ) {
      $NoIP->{$ThisLine}++;
   }
   elsif ( $ThisLine =~ s/^([^ ]+)\[\d+\]: warning: can\'t get client address: Connection reset by peer$/$1/ ) {
      $NoIP->{$ThisLine}++;
   }
   elsif ( $ThisLine =~ s/^([^ ]+)\[\d+\]: warning: can\'t get client address: Connection timed out$/$1/ ) {
      $NoIP->{$ThisLine}++;
   }
   elsif ( $ThisLine =~ s/^([^ ]+)\[\d+\]: connect from unknown$/$1/ ) {
      $NoIP->{$ThisLine}++;
   }
   elsif ( ($Service,$Err) = ($ThisLine =~ /^([^ ]+)\[\d+\]: error: (.+)$/) ) {
      $Error{$Service}{$Err}++;
   }
   elsif ( ($Service,$Err) = ($ThisLine =~ /^([^ ]+): (FAILED LOGIN SESSION FROM [^ ]+ FOR , .*)$/ ) ) {
      $Error{$Service}{$Err}++;
   }
   elsif ( $ThisLine =~ /warning: can.t get client address: Connection refused/) {
      # Nothing
   }
   elsif ( $ThisLine =~ /^login: ROOT LOGIN ON tty[0-9]+/) {
      $RootLoginTTY++
   }
   elsif ( $ThisLine =~ /^xinetd\[\d+\]: USERID: ([^ ]+) (.+)$/ ) {
      # This is an inetd lookup... $1 is the service (i.e. ftp), $2 is the response
      # I don't think these are important to log at this time
   }
   else {
      # Unmatched entries...
      push @OtherList,$ThisLine . "\n";
   }
}

if ( (keys %{$Connections}) or
      (keys %{$Refused}) or
      (keys %{$FailedLogins}) or
      (keys %{$NoIP}) or 
      (keys %{$Error}) or
      ($RootLoginTTY) or
      ($#OtherList >= 0)
   ) {

   print "\n\n ---------------- Connections (secure-log) Begin ------------------- \n";

   if (keys %{$Connections}) {
      print "\nConnections:\n";
      foreach $ThisOne (keys %{$Connections}) {
         print "   Service " . $ThisOne . ":\n";
         foreach $OtherOne (keys %{$Connections->{$ThisOne}}) {
            print "      " . $OtherOne . ": " . $Connections->{$ThisOne}->{$OtherOne} . " Time(s)\n";
         }
      }
   }

   if (keys %{$Refused}) {
      print "\nRefused Connections:\n";
      foreach $ThisOne (keys %{$Refused}) {
         print "   Service " . $ThisOne . ":\n";
         foreach $OtherOne (keys %{$Refused->{$ThisOne}}) {
            print "      " . $OtherOne . ": " . $Refused->{$ThisOne}->{$OtherOne} . " Time(s)\n";
         }
      }
   }

   if (keys %{$FailedLogins}) {
      print "\nFailed logins:\n";
      foreach $ThisOne (keys %{$FailedLogins}) {
         print "   User " . $ThisOne . ":\n";
         foreach $OtherOne (keys %{$FailedLogins->{$ThisOne}}) {
            print "      " . $OtherOne . ": " . $FailedLogins->{$ThisOne}->{$OtherOne} . " Time(s)\n";
         }
      }
   }

   if (keys %{$NoIP}) {
      print "\nCouldn't get client IPs for connections to:\n";
      foreach $ThisOne (keys %{$NoIP}) {
         print "   " . $ThisOne . ": " . $NoIP->{$ThisOne} . " Time(s)\n";
      }
   }

   if (keys %{Error}) {
      print "\nErrors:\n";
      foreach $Service (sort {$a cmp $b} keys %{Error}) {
         print "   Service " . $Service . ":\n";
         foreach $Err (sort {$a cmp $b} keys %{$Error{$Service}}) {
            print "      " . $Err . ": " . $Error{$Service}{$Err} . " Time(s)\n";
         }
      }
   }

   if ($RootLoginTTY) {
      print "\nRoot logins on tty\'s: $RootLoginTTY Time(s).\n";
   }

   if ($#OtherList >= 0) {
      print "\n**Unmatched Entries**\n";
      print @OtherList;
   }

   print "\n\n ----------------- Connections (secure-log) End -------------------- \n\n";

}

exit(0);



