#!/usr/bin/perl
##########################################################################
# $Id: proftpd-messages,v 1.13 2003/11/26 14:36:30 kirk Exp $
##########################################################################

########################################################
# This was written and is maintained by:
#    Simon Liddington <sjl96v@ecs.soton.ac.uk>
#
# for use with Logwatch
#
# Logwatch was written and is maintained by:
#    Kirk Bauer <kirk@kaybee.org>
########################################################

$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
$IgnoreUnmatched = $ENV{'ftpd_ignore_unmatched'};

while (defined($ThisLine = <STDIN>)) {
	if ( ( $ThisLine =~ /^FTP session closed./ ) or
		( $ThisLine =~ /^(ANONYMOUS )?FTP login as \'.*\' from [^ ]+ \[.*\] to .*/ ) or
		( $ThisLine =~ /^FTP no transfer time out, disconnected\./ ) or
		( $ThisLine =~ /PAM\(.*\): Authentication failure/ ) or
		( $ThisLine =~ /^data_sendfile/ ) or
		( $ThisLine =~ / - FTP session opened/ ) or
		( $ThisLine =~ / - FTP session closed/ ) or
		( $ThisLine =~ / - No certificate files found/ ) or
		( $ThisLine =~ /FTP no transfer timeout, disconnected\./ ) or
		( $ThisLine =~ /FTP login timed out, disconnected\./ )   ) {
		#We don't care about these
	} elsif ( ($Host,$IP,$Email,) = ( $ThisLine =~ /^FTP session opened: ftp\/ftp (.*)\[(.*)\] (.*)$/ ) ) {
		$Temp = "   " . $Host . " (" . $IP . "): " . $Email . " - ";
		$AnonLogins{$Temp}++;
	} elsif ( ($Host, $IP) = ( $ThisLine =~ /\((.*)\[(.*)\]\) - ANON .+: Login successful\./ ) ) {
		$Temp = "   " . $Host . " (" . $IP . ")";
		$AnonLogins{$Temp}++;
	} elsif ( ($User,$Host,$IP) = ( $ThisLine =~ /^FTP session opened: (.*\/.*) (.*)\[(.*)\] (.*)$/ ) ) {
		$Temp = "   " . $Host .  ": " . $User . " - ";
		$UserLogins{$Temp}++;
	} elsif ( ($Host,$IP,$User) = ( $ThisLine =~ /\((.*)\[(.*)\]\) - USER (.+): Login successful/ ) ) {
		$Temp = "   " . $Host . ": " . $User . " - ";
	   $UserLogins{$Temp}++;
   } elsif ( ($User) = ( $ThisLine =~ /^failed login, can\'t find user \'(.*)\' $/ ) ) {
	   $Temp = "   " . "Unknown" . " (" . "Unknown.IP" . "): " . $User . " - ";
	   $BadUsers{$Temp}++;
   } elsif ( ($User,$Host,$IP) = ( $ThisLine =~ /USER (.*): no such user found from (.*) \[(.*)\] to/ ) ) {
	   $Temp = "   " . $Host . ": " . $User . " - ";
	   $BadUsers{$Temp}++;
   } elsif ( ($Host,$Ip,$User) = ( $ThisLine =~ /\((.*)\[(.*)\]\) - no such user '(.*)'.$/ ) ) {
	   #$Temp = "$Host($Ip)";
	   $BadUsers{$User}{$Host}++;
   } elsif ( ($Host,$User) = ( $ThisLine =~ /\[(.*)\]\) - USER (.*) \(Login failed\): Incorrect password/ ) ) {
	   $Temp = "   " . $Host . ": " . $User . " - ";
	   $BadPasswds{$Temp}++;
   } elsif ( ($Host,$User) = ( $ThisLine =~ /\[(.*)\]\) - USER (.*) \(Login failed\): Invalid shell/ ) ) {
	   $Temp = "   " . $Host . ": " . $User . " - ";
	   $BadShell{$Temp}++;
   } elsif ( ($Host,$Ip) = ( $ThisLine =~ /\((.*)\[(.*)\]\) - SECURITY VIOLATION: root login attempted./ ) ) {
	   $RootLoginAttempt{$Host}++;
   }elsif ( ($Host,$Reason) = ( $ThisLine =~ /\[(.*)\]\) - Refused PORT [\d,]+ \((.*)\)/ ) ) {
	   $Temp = "   " . $Host . ": " . $Reason . " - ";
	   $RefusedPorts{$Temp}++;
   } else {
	   # Report any unmatched entries...
	   push @OtherList,$ThisLine;
   }
}

##############################################

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

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

if (keys %UserLogins) {
	print "\nUser FTP Logins:\n";
	foreach $ThisOne (sort {$a cmp $b} keys %UserLogins) {
		print $ThisOne . $UserLogins{$ThisOne} . " Time(s)\n";
	}
}

if (keys %RootLoginAttempt) {
	print "\nSECURITY VIOLATION!!!!\n";
	print "Root login attempt from:\n";
	foreach $Host (sort {$a cmp $b} keys %RootLoginAttempt) {
		print "  $Host : $RootLoginAttempt{$Host} Time(s)\n";
	}
}

if ( ( (keys %BadUsers) or (keys %BadPasswds) ) and ($Detail >= 5) ) {
	print "\nFailed FTP Logins:\n";
	
	if ( (keys %BadUsers) and ($Detail >= 5) ) {
		print "\n  Invalid Username:\n";
		foreach $User (sort {$a cmp $b} keys %BadUsers) {
			print "    $User:\n";
			foreach $Host (sort {$a cmp $b} keys %{$BadUsers{$User}}) {
				print "      $Host : $BadUsers{$User}{$Host} Time(s)\n";
			}
		}
	}
	
	if ( (keys %BadPasswds) and ($Detail >= 5) ) {
		print "\n  Incorrect Password:\n";
		foreach $ThisOne (sort {$a cmp $b} keys %BadPasswds) {
			print $ThisOne . $BadPasswds{$ThisOne} . " Time(s)\n";
		}
	}
	
	if ( (keys %BadPasswds) and ($Detail >= 5) ) {
		print "\n  Invalid Shell:\n";
		foreach $ThisOne (sort {$a cmp $b} keys %BadShell) {
			print $ThisOne . $BadShell{$ThisOne} . " Time(s)\n";
		}
	}
}

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

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

exit(0);

# vi: shiftwidth=4 tabstop=4
