##########################################################################
# freeradius logwatch filter
# written by Jonas Marczona 28.12.2011
#
## Covered under the included MIT/X-Consortium License:
## http://www.opensource.org/licenses/mit-license.php
## All modifications and contributions by other persons to
## this script are assumed to have been donated to the
## Logwatch project and thus assume the above copyright
## and licensing terms.
##########################################################################
$^W=1;
use strict;
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
my $DebugCounter = 0;
if ( $Debug >= 5 ) {
print STDERR "\n\nDEBUG: Inside freeradius Filter \n\n";
$DebugCounter = 1;
}
my %OtherList = ();
my %loginsOk = ();
my %wrongPassword = ();
my %wrongUser = ();
my %wrong_ip = ();
my %invalidUser = ();
my %discards = ();
my %warnings = ();
my %givingUps = ();
my $killedChilds = 0;
my $requests = 0;
my $requests_duration = 0;
my $ThisLine;
while (defined($ThisLine = <STDIN>)) {
if ( $Debug >= 5 ) {
print STDERR "DEBUG($DebugCounter): $ThisLine";
$DebugCounter++;
}
chomp($ThisLine);
if ( ( $ThisLine =~ /^F-TICKS/ ) ||
( $ThisLine =~ /^Access-Request from/ ) ||
( $ThisLine =~ /^ \.\.\. (?:closing|adding new) socket/ ) ||
( $ThisLine =~ /^(?:SSL|TLS|rlm_(?:unix|eap|sql|radutmp)| TLS_accept| \[ldap\])/ ) ||
( $ThisLine =~ /^Ready to process requests\.$/ ) ||
( $ThisLine =~ /^Exiting normally\.$/ ) ||
( $ThisLine =~ /^Loaded virtual server/ ) ||
( $ThisLine =~ /^HUP - / ) ||
( $ThisLine =~ /^Received HUP signal\.$/ ) ||
( $ThisLine =~ /^ ?Module: Reloaded module/ )
) {
# ignore
}
# TD: Login OK: [user@example.com] (from client radius port 0)
# TD: Login OK: [user@example.com] (from client radius port 9 cli 00-11-22-33-44-AA;eduroam via TLS tunnel)
elsif ( my ($user) = ($ThisLine =~ m/^(?:Auth: )?Login OK: \[(.+)\] \(from client [^ ]* port \d{1,10}(?: cli [-0-9a-fA-F.:]+)?(?:;\w+)?(?: via TLS tunnel)?\)/) ) {
$loginsOk{$user}++;
}
# TD: Login incorrect ( [ldap] User not found): [user@example.com] (from client radius port 13 cli 38-16-dd-aa-bb-cc via TLS tunnel)
# TD: Login incorrect (mschap: External script says Logon failure (0xc000006d)): [user@example.com] (from client radius port 13 cli aa-bb-cc-11-22-33 via TLS tunnel)
# TD: Login incorrect (TLS Alert write:fatal:handshake failure): [user@example.com] (from client radius port 13 cli aa-bb-cc-11-22-33)
# TD:
elsif ( my ($user, $ip) = ( $ThisLine =~ m/^(?:Auth: )?Login incorrect(?: \(.+\))?: \[(.*)\] \(from client [^ ]* port \d{1,10}(?: cli ([-0-9a-fA-F.:]+)(?:;\w+)?)?(?: via TLS tunnel)?\)/) ) {
if (! $ip) { $ip = "*not named*"; }
$wrongUser{$ip}{$user}++;
$wrong_ip{$ip}++;
}
# TD: Login incorrect: [user@example.com] (from client radius port 175143 cli cc08.e051.a240)
# TD: Login incorrect: [user@example.com] (from client radius1 port 0)
elsif ( my ($user, $ip) = ($ThisLine =~ m/^(?:Auth: )?Login incorrect: \[(.+)\] \(from client [^ ]* port \d{1,10}(?: cli ([-0-9a-fA-F.:]+))?(?: via TLS tunnel)?\)/) ) {
if (! $ip) { $ip = "*not named*"; }
$wrongPassword{$ip}{$user}++;
$wrong_ip{$ip}++;
}
# TD: Invalid user ( [ldap] Access Attribute denies access): [user@example.com] (from client radius port 13 cli aa-bb-cc-dd-ee-11 via TLS tunnel)
# TD: Invalid user: [user@example.com] (from client <host> port 13 cli aa-bb-cc-dd-ee-11)
elsif ( my ($reason, $user, $ip) = ($ThisLine =~ m/^(?:Auth: )?Invalid user(?: \(\s*(.+)\))?: \[(.+)\] \(from client [^ ]* port \d{1,10}(?: cli ([-0-9a-fA-F.:]+))?(?: via TLS tunnel)?\)/) ) {
if (! $ip) { $ip = "*not named*"; }
if (! $reason) { $reason = "*no reason*"; }
$invalidUser{$reason}{$user}++;
}
# TD: Discarding duplicate request from client <host> port 47609 - ID: 182 due to unfinished request 12713766
# TD: Discarding conflicting packet from client <host> port 42221 - ID: 85 due to recent request 9008535.
elsif ( my ($reason, $client) = ($ThisLine =~ /Discarding (duplicate request|conflicting packet) from client (\S+) port \d+ - ID: \d+ due to (unfinished|recent) request/) ) {
$discards{$reason}{$client}++;
}
# TD: Received conflicting packet from client radius2 port 60612 - ID: 30 due to unfinished request 1136681. Giving up on old request.
elsif ( my ($client) = ($ThisLine =~ /Received conflicting packet from client ([^ ]+) port \d{1,10} - ID: \d+ due to unfinished request \d+/) ) {
$givingUps{$client}++;
}
# TD: Child PID 57436 is taking too much time: forcing failure and killing child.
elsif ( $ThisLine =~ m/Child PID \d+ is taking too much time: forcing failure and killing child/ ) {
$killedChilds++;
}
# TD: Request 67678577 has been waiting in the processing queue for 378 seconds. Check that all databases are running properly!
elsif ($ThisLine =~ m/^Request \d+ has been waiting in the processing queue for (\d+) seconds/) {
$requests++;
$requests_duration += $1;
}
# TD: WARNING: Unresponsive child for request 4737598, in component accounting module unix
# TD: WARNING: Child is hung for request 4737598 in component accounting module unix.
elsif ( $ThisLine =~ m/^WARNING: (Unresponsive child|Child is hung) for request \d+,? in component ([<>\w]+) module ?([<>\w]*)/ ) {
$warnings{"$1 in component:"}{"$2 [module: $3]"}++;
}
# TD: WARNING: Allowing fast client radius2 port 60612 - ID: 102 for recent request 9035637.
elsif ( $ThisLine =~ m/^WARNING: (Allowing fast client) ([^ ]+) port \d{1,10} - ID: \d+/ ) {
$warnings{"${1}s:"}{$2}++;
}
else {
# Report any unmatched entries...
$OtherList{$ThisLine}++;
}
}
#################################
# Output section
################################
if ($requests > 0) {
printf "Long running requests: Check that all databases are running properly!\n";
printf " %-40s : %5d\n", 'Long running requests', $requests;
printf " %-40s : %5d s\n", 'avg queue time per long running request', $requests_duration / $requests;
print "\n";
}
sub compPerIp {
return $wrong_ip{$b} <=> $wrong_ip{$a};
}
if (keys %loginsOk) {
if ($Detail >= 10) {
print "\nSuccessful logins:\n";
foreach my $user (sort {$loginsOk{$b} <=> $loginsOk{$a}} keys %loginsOk) {
printf " %-40s : %5d time(s)\n", $user, $loginsOk{$user};
}
} elsif ($Detail >= 6) {
my $loginsOkSum = 0;
foreach my $user (keys %loginsOk) {
$loginsOkSum += $loginsOk{$user};
}
printf "\n%-42s : %5d time(s)\n", "Successful logins", $loginsOkSum;
}
}
if ($Detail >= 8) {
if (keys %wrong_ip) {
print "\nSum of failed logins per ip (wrong password or user)\n";
foreach my $ip (sort compPerIp keys %wrong_ip) {
printf " %-40s : %5d time(s)\n", $ip, $wrong_ip{$ip};
}
}
}
if (keys %wrongUser) {
if ($Detail >= 6) {
print "\nFailed logins - wrong user name:\n";
foreach my $ip (sort compPerIp keys %wrongUser) {
printf " %-40s\n", $ip;
my $users = $wrongUser{$ip};
foreach my $user (sort {$users->{$b} <=> $users->{$a}} keys %$users) {
printf " %-38s : %5d time(s)\n", $user, $users->{$user};
}
}
} else {
my $userSum = 0;
foreach my $ip (keys %wrongUser) {
my $users = $wrongUser{$ip};
foreach my $user (keys %$users) {
$userSum += $users->{$user};
}
}
printf "\n%-42s : %5d time(s)\n", "Failed logins - wrong user name", $userSum;
}
}
if (keys %wrongPassword) {
if ($Detail >= 6) {
print "\nFailed logins - wrong password:\n";
foreach my $ip (sort compPerIp keys %wrongPassword) {
my $users = $wrongPassword{$ip};
printf " %-40s\n", $ip ;
foreach my $user (sort {$users->{$b} <=> $users->{$a}} keys %$users) {
#print " $user ", $users->{$user}, " time(s)\n";
printf " %-38s : %5d time(s)\n", $user, $users->{$user};
}
}
} else {
my $wrongPasswordSum = 0;
foreach my $ip (%wrongPassword) {
my $users = $wrongPassword{$ip};
foreach my $user (keys %$users) {
$wrongPasswordSum += $users->{$user};
}
}
printf "\n%-42s : %5d time(s)\n", "Failed logins - wrong password", $wrongPasswordSum;
}
}
if (keys %invalidUser) {
if ($Detail >= 6) {
print "\nInvalid User:\n";
foreach my $reason (keys %invalidUser) {
my $users = $invalidUser{$reason};
printf " %-40s\n", $reason;
foreach my $user (sort {$users->{$b} <=> $users->{$a}} keys %$users) {
printf " %-38s : %5d time(s)\n", $user, $users->{$user};
}
}
} else {
my $invalidUserSum = 0;
foreach my $reason (keys %invalidUser) {
my $users = $invalidUser{$reason};
foreach my $user (keys %$users) {
$invalidUserSum += $users->{$user};
}
}
printf "\n%-42s : %5d time(s)\n", "Invalid Users", $invalidUserSum;
}
}
if (keys %discards) {
print "\nDiscards:\n";
foreach my $reason (keys %discards) {
my $clients = $discards{$reason};
printf " %-40s\n", $reason;
foreach my $client (keys %$clients) {
printf " %-38s : %5d time(s)\n", $client, $clients->{$client};
}
}
}
if (keys %givingUps) {
print "\nGiving up on old requests:\n";
foreach my $client (keys %givingUps) {
printf " %-40s : %5d time(s)\n", $client, $givingUps{$client};
}
}
if ($killedChilds) {
printf "\n%-42s : %5d time(s)\n", "Killed Childs (taking too much time)", $killedChilds;
}
if (%warnings) {
print "\nWarnings:\n";
foreach my $warning (keys %warnings) {
my $components = $warnings{$warning};
printf " %-40s\n", $warning;
foreach my $component (keys %$components) {
printf " %-38s : %5d time(s)\n", $component, $components->{$component};
}
}
}
if (keys %OtherList) {
print "\n**** Unmatched entries ****\n";
foreach (keys %OtherList) {
print " $_ : $OtherList{$_} Time(s)\n";
}
}
exit(0);
# vi: shiftwidth=3 tabstop=3 syntax=perl et