#!/usr/bin/perl

$|				= 1;

$g_debuglevel	= 3;
$g_maxcnt1		= 5;
$g_maxcnt2		= 3;

$g_cdbfile		= "/etc/tcpserver.d/tcp.ftp.cdb";
$g_rulefile		= "/etc/tcpserver.d/tcp.ftp";
$g_exec			= "/usr/local/bin/tcprules $g_cdbfile $g_cdbfile.tmp < $g_rulefile";
$g_exec_py		= "/opt/python2.4.4/bin/python /var/zope/bin/update_bl_ftp.py";

%g_graylist;
%g_blacklist;

init();
main();
end();

sub main(){

	my ( $ipaddr, @line );
	
	while ( <> ){
		@line = split;
	
		if ( /proftpd/ ){
			if ( /Maximum login attempts/ or /no such user found from/ or /SECURITY VIOLATION/ ){
				$ipaddr = $line[6];
				$ipaddr = splitipaddr( $ipaddr );
				if ( !$g_blacklist{$ipaddr} ){
					if ( countup($ipaddr) > $g_maxcnt1 ){
						addtoblacklist($ipaddr);
						shutout();
						update_python($ipaddr);
					}
				}
			}
		}
	}
}

sub init()
{

	my ( $ipaddr, $access, $addr );

	debugout("----- reading blacklist ($g_rulefile) -----\n", 2);

	open RULEFILE, $g_rulefile or debugout("Can't open $g_rulefile\n", 2);
	while (<RULEFILE>){
		chop;
		( $ipaddr, $access ) = split /:/;
		if( $access eq "deny" ){
			addtoblacklist($ipaddr);
		}
	}
	close RULEFILE;

	debugout("-----\n", 2);

}

sub end()
{
}

sub countup()
{

	my ( $ipaddr ) = @_;

	$g_graylist{$ipaddr}++;
	debugout($ipaddr . " tried " . $g_graylist{$ipaddr} . " times\n", 2);

	return $g_graylist{$ipaddr};

}

sub update_python()
{

	my ( $ipaddr ) = @_;
	my ( $datestr ) = getdatestr();

	debugout("update python $ipaddr\n", 1);
	system( $g_exec_py . ' ' . $ipaddr . ' "' . $datestr . '"');

}

sub addtoblacklist()
{

	my ( $ipaddr ) = @_;

	debugout("adding $ipaddr to blacklist...\n", 1);
	$g_blacklist{$ipaddr} = time;

}

sub shutout()
{

	my ( $ipaddr ) = @_;

	debugout("----- writing blacklist ($g_rulefile) -----\n", 3);

	open RULEFILE, ">$g_rulefile.tmp" or die "Can't open $g_rulefile.tmp";
	foreach $ipaddr (keys %g_blacklist){
		debugout("$ipaddr:deny\n", 3);
		print RULEFILE "$ipaddr:deny\n" or die "Can't print to $g_rulefile.tmp";
	}
	print RULEFILE ":allow\n" or die "Can't print to $g_rulefile.tmp";
	close RULEFILE;

	rename "$g_rulefile.tmp", "$g_rulefile" or die "Can't rename from $g_rulefile.tmp to $g_rulefile";

	debugout("executing $g_exec\n", 3);
#	system "$g_exec\n";
	system($g_exec);

	debugout("-----\n", 3);

}

sub splitipaddr()
{

	my ( $str ) = @_;
	( $s,$tmp ) = split(/\[/, $str );
	( $addr,$s ) = split(/\]/, $tmp );
	return $addr;
}
	

sub debugout()
{

	my ( $message, $level ) = @_;
	my ( $date ) = getdatestr();

	printf "%s %s", $date, $message if $level <= $g_debuglevel;

}

sub getdatestr()
{

	my ( $sec, $min, $hour, $day, $month, $year ) = localtime;
	$str = sprintf( "%04d/%02d/%02d %02d:%02d:%02d", $year + 1900, $month + 1, $day, $hour, $min, $sec );
	return $str;

}

