#!/usr/bin/perl
#
# Log failed logins in the sql database
# Works only with mysql
# It will read the sql parameters from the admin.conf file
#
# Usage:
# log_badlogins <radius.log> [<admin.conf>] [all]
#
# Defaults:
# radius.log: none
# admin.conf: /usr/local/dialup_admin/conf/admin.conf 
# all:        no. Go to the end of the file. Don't read it all.

use Date::Manip qw(ParseDate UnixDate);
$|=1;

$file=shift||'none';
$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
$all_file=shift||'no';
#
#
# CHANGE THESE TO MATCH YOUR SETUP
#
$domain='company.com';
$mysql='/usr/local/mysql/bin/mysql';
$tmpfile='/tmp/mysql.input';
#
#

open CONF, "<$conf"
	or die "Could not open configuration file\n";
while(<CONF>){
	chomp;
	($key,$val)=(split /:\s*/,$_);
	$sql_server = $val if ($key eq 'sql_server');
	$sql_username = $val if ($key eq 'sql_username');
	$sql_password = $val if ($key eq 'sql_password');
	$sql_database = $val if ($key eq 'sql_database');
	$sql_accounting_table = $val if ($key eq 'sql_accounting_table');
	$realm_strip = $val if ($key eq 'general_strip_realms');
	$realm_del = $val if ($key eq 'general_realm_delimiter');
	$realm_for = $val if ($key eq 'general_realm_format');
}
close CONF;
$realm_del = '@' if ($realm_del eq '');
$realm_for = 'suffix' if ($realm_for eq '');
$pass = ($sql_password ne '') ? "-p$sql_password" : '';

open LOG, "<$file"
	or die "Could not open file $file\n";

seek LOG, 0, 2 if ($all_file eq 'no');
for(;;){
	while(<LOG>){
		$do=0;	
		chomp;
		if ($_ ne ''){
			$user = $nas = $port = $caller = '-';
			if (/Login incorrect/){
				if (/Login incorrect \((.+?)\):/){
					$cause = "Login-Incorrect ($1)";
				}else{
					$cause='Login-Incorrect';
				}
				$do=1;
			}
			elsif (/Invalid user/){
				if (/Invalid user \((.+?)\):/){
					$cause = "Invalid-User ($1)";
				}else{
					$cause='Invalid-User';
				}
				$do=1;
			}
			elsif (/Multiple logins/){
				$cause='Multiple-Logins';
				$do=1;
			}
			elsif (/(Outside allowed timespan \(.+?\)):/){
				$cause = "$1";
				$do=1;
			}
			if ($do){
				$date = (split / : /,$_)[0];
				$date2 = ParseDate($date);
				if ($date2){
					($year,$mon,$mday,$hour,$min,$sec)=UnixDate($date2,'%Y','%m','%d','%H','%M','%S');
				}
				$time = "$year-$mon-$mday $hour:$min:$sec";
				if (/\[([\w\-]+?)\]\s+\(from (.+?)\)/){
					$user = $1;
					($nas,$port,$caller) = (split /\s+/,$2)[1,3,5];
				}
				elsif (/\[([\w\-]+?)\/.+?\]\s+\(from (.+?)\)/){
					$user = $1;
					($nas,$port,$caller) = (split /\s+/,$2)[1,3,5];
				}
				$caller='' if (!defined($caller));
				$user =~s/[^\w\-\.]//g;
				$nas =~s/[^\w\.]//g;
				if ($nas ne 'localhost' && $nas !~ /\.$domain$/){
					$nas .= '.$domain';
				}
				$port =~s/[^\d]//g;
				$caller =~s/[^\d]//g;
				$addr = gethostbyname $nas;
				($a,$b,$c,$d)=unpack('C4',$addr);
				$addr = "$a.$b.$c.$d";
				if ($user ne '' && $realm_strip eq 'yes'){
					($one,$two) = (split /$realm_del/, $user)[0,1];
					if ($two ne ''){
						$user = ($realm_for eq 'suffix') ? $one : $two;
					}
				}
				open TMP, ">$tmpfile"
					or die "Could not open temporary file\n";
				print TMP "INSERT INTO $sql_accounting_table (UserName,NASIPAddress,NASPortId,AcctStartTime,AcctStopTime,AcctSessionTime,AcctInputOctets,AcctOutputOctets,CallingStationId,AcctTerminateCause) VALUES ('$user','$addr','$port','$time','$time','0','0','0','$caller','$cause');";
				close TMP;
				`$mysql -h$sql_server -u$sql_username $pass $sql_database <$tmpfile`;
			}
		}
	}
	sleep 2;
	seek LOG,0,1;
}
