#!/usr/bin/perl
##########################################################################
# $Id: ftpd-messages,v 1.20 2003/01/13 14:12:36 kirk Exp $
##########################################################################

########################################################
# 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'};
$IgnoreUnmatched = $ENV{'ftpd_ignore_unmatched'};

while (defined($ThisLine = <STDIN>)) {
   if ( ( $ThisLine =~ /FTP session closed$/ ) or
         ( $ThisLine =~ /^getpeername \(in.ftpd\): Transport endpoint is not connected$/ ) or
         ( $ThisLine =~ /QUIT/ ) or
         ( $ThisLine =~ /IDLE/ ) or
         ( $ThisLine =~ /TLS connection using cipher/ ) or
         ( $ThisLine =~ /wu-ftpd - loading TLS config file/ ) or
         ( $ThisLine =~ /lost connection to / ) or
         ( $ThisLine =~ /^VirtualFTP Connect to: / ) or
         ( $ThisLine =~ /ACCESS DENIED \(not in any class\) TO / ) or
         ( $ThisLine =~ /data connect from/ ) or
         ( $ThisLine =~ /wu-ftpd - TLS settings/ ) or
         ( $ThisLine =~ /User .* timed out after .* seconds at .*$/ )   ) {
      # We don't care about these
   } elsif ( ($Host,$IP,$Email) = ( $ThisLine =~ /^ANONYMOUS FTP LOGIN FROM ([^ ]+) \[(.*)\], (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $Email . " - ";
      $AnonLogins{$Temp}++;
   } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /FTP LOGIN FROM ([^ ]+) \[(.*)\], (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $User . " - ";
      $UserLogins{$Temp}++;
   } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /^FTP LOGIN REFUSED \(.+\) FROM ([^ ]+) \[(.*)\], (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $User . " - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /REFUSED .+ from ([^ ]+) \[(.*)\], (.*)$/i ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $User . " - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /^failed login from ([^ ]+) \[(.*)\], (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $User . " - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($Limit,$Class,$Host,$IP) = ( $ThisLine =~ /^ACCESS DENIED \(user limit (.*)\; class (.*)\) TO (.*) \[(.*)\]/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): class " . $Class . " (Limit: " . $Limit . ") - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($Host,$IP) = ( $ThisLine =~ /^FTP ACCESS REFUSED \(anonymous password not rfc822\) from (.*) \[(.*)\]/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . ") - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /failed login from ([^ ]+) \[(.*)\]$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . ") - ";
      $FailedLogins{$Temp}++;
   } elsif ( ($IP,$Host) = ( $ThisLine =~ /^refused PORT ([0123456789.]+),[0123456789]+ from (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . ") - ";
      $RefusedPorts{$Temp}++;
   } elsif ( $ThisLine =~ /^exiting on signal 11: Segmentation fault$/ ) {
      $SegFault++;
   } elsif ( ($User,$Host,$IP,$File) = ( $ThisLine =~ /^([^ ]+) of ([^ ]*) \[(.*)\] deleted (.*)$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): " . $User . "\n";
      $Temp2 = "      " . $File . "\n";
      push @{$DeletedFiles{$Temp}}, $Temp2;
   } elsif ( ($User,$Pass,$Host,$IP) = ( $ThisLine =~ /(.*)\((.*)\) of (.*) \[(.*)\] tried to/) ) {
      $Temp = "   " . $Host . " ($IP): " . $User . " ($Pass) - ";
      $SecurityViolations{$Temp}++;
   } elsif ( ($Host,$User,$IP) = ( $ThisLine =~ /(.*)\: (.*)\: SITE .* \[(.*)\] tried to/) ) {
      $Temp = "   " . $Host . " ($IP): " . $User . " - ";
      $SecurityViolations{$Temp}++;
   } elsif ( ($Host,$IP) = ( $ThisLine =~ /^FTP LOGIN FAILED \(cannot set guest privileges\) for ([^ ]+) \[(.*)\], ftp$/ ) ) {
      $Temp = "   " . $Host . " (" . $IP . "): - ";
      $RefusedAnonLogins{$Temp}++;
   } else {
      # Report any unmatched entries...
      push @OtherList,$ThisLine;
   }
}

if ( (keys %AnonLogins) and ($Detail >= 10) ) {
   print "\nAnonymous FTP Logins:\n";
   foreach $ThisOne (keys %AnonLogins) {
      print $ThisOne . $AnonLogins{$ThisOne} . " Time(s)\n";
   }
}

if ((keys %DeletedFiles) and ($Detail >= 5)) {
   print "\nFiles deleted through FTP:\n";
   foreach $ThisOne (keys %DeletedFiles) {
      print $ThisOne;
      print @{$DeletedFiles{$ThisOne}};
   }
}

if ((keys %UserLogins) and ($Details >= 5)) {
   print "\nUser FTP Logins:\n";
   foreach $ThisOne (keys %UserLogins) {
      print $ThisOne . $UserLogins{$ThisOne} . " Time(s)\n";
   }
}

if (keys %FailedLogins) {
   print "\nFailed FTP Logins:\n";
   foreach $ThisOne (keys %FailedLogins) {
      print $ThisOne . $FailedLogins{$ThisOne} . " Time(s)\n";
   }
}

if ( (keys %RefusedPorts) and ($Detail >= 10) ) {
   print "\nRefused PORTs:\n";
   foreach $ThisOne (keys %RefusedPorts) {
      print $ThisOne . $RefusedPorts{$ThisOne} . " Time(s)\n";
   }
}

if ( (keys %SecurityViolations) and ($Detail >= 5) ) {
   print "\nFailed filesystem violations:\n";
   foreach $ThisOne (keys %SecurityViolations) {
      print $ThisOne . $SecurityViolations{$ThisOne} . " Time(s)\n";
   }
}

if (keys %RefusedAnonLogins) {
   print "\nRefused anonymous FTP Logins:\n";
   foreach $ThisOne (keys %RefusedAnonLogins) {
      print $ThisOne . $RefusedAnonLogins{$ThisOne} . " Time(s)\n";
   }
}

if ($SegFault > 0) {
   print "\nexiting on signal 11: Segmentation fault: $SegFault Time(s)\n";
}

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

exit(0);

