|
Packit |
57988d |
#!/usr/bin/perl
|
|
Packit |
57988d |
##########################################################################
|
|
Packit |
57988d |
# $Id$
|
|
Packit |
57988d |
##########################################################################
|
|
Packit |
57988d |
# $Log: spamassassin,v $
|
|
Packit |
57988d |
# Revision 1.2 2008/06/30 20:47:20 kirk
|
|
Packit |
57988d |
# fixed copyright holders for files where I know who they should be
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
# Revision 1.1 2008/05/11 22:00:41 mike
|
|
Packit |
57988d |
# Inital check in of spamassassin files -mgt
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
# Revision 1.3 2007/10/10 16:41:27 whb
|
|
Packit |
57988d |
# Yes, Win does get over 10000 spam messages PER DAY
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
# Revision 1.2 2007/01/20 17:13:56 whb
|
|
Packit |
57988d |
# Lump together child-related errors
|
|
Packit |
57988d |
# - We're experiencing periods of high loads, causing many fork errors
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
# Revision 1.1 2006/09/16 20:02:01 whb
|
|
Packit |
57988d |
# Initial revision
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
#
|
|
Packit |
57988d |
#######################################################
|
|
Packit |
57988d |
### Copyright (c) 2008 Win Bent <whb@haus.org>
|
|
Packit |
57988d |
### Covered under the included MIT/X-Consortium License:
|
|
Packit |
57988d |
### http://www.opensource.org/licenses/mit-license.php
|
|
Packit |
57988d |
### All modifications and contributions by other persons to
|
|
Packit |
57988d |
### this script are assumed to have been donated to the
|
|
Packit |
57988d |
### Logwatch project and thus assume the above copyright
|
|
Packit |
57988d |
### and licensing terms. If you want to make contributions
|
|
Packit |
57988d |
### under your own copyright or a different license this
|
|
Packit |
57988d |
### must be explicitly stated in the contribution an the
|
|
Packit |
57988d |
### Logwatch project reserves the right to not accept such
|
|
Packit |
57988d |
### contributions. If you have made significant
|
|
Packit |
57988d |
### contributions to this script and want to claim
|
|
Packit |
57988d |
### copyright please contact logwatch-devel@lists.sourceforge.net.
|
|
Packit |
57988d |
##########################################################
|
|
Packit |
57988d |
##########################################################################
|
|
Packit |
57988d |
|
|
Packit |
57988d |
use Logwatch ':sort';
|
|
Packit |
57988d |
|
|
Packit |
57988d |
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
|
|
Packit |
57988d |
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
|
|
Packit |
57988d |
my $Ignore_connections = $ENV{'ignore_connections'};
|
|
Packit |
57988d |
|
|
Packit |
57988d |
$StillRoot = 0;
|
|
Packit |
57988d |
$CleanTotal = 0;
|
|
Packit |
57988d |
$SpamTotal = 0;
|
|
Packit |
57988d |
$PyzorTerminated = 0;
|
|
Packit |
57988d |
|
|
Packit |
57988d |
my %Child;
|
|
Packit |
57988d |
my %Clean;
|
|
Packit |
57988d |
my %Spam;
|
|
Packit |
57988d |
my %Users;
|
|
Packit |
57988d |
my %Connections;
|
|
Packit |
57988d |
|
|
Packit |
57988d |
#Todo
|
|
Packit |
57988d |
# meta test DIGEST_MULTIPLE has undefined dependency 'DCC_CHECK' : 2 Time(s)
|
|
Packit |
57988d |
# server started on port 783/tcp (running version 3.1.9) : 2 Time(s)
|
|
Packit |
57988d |
# meta test DIGEST_MULTIPLE has undefined dependency 'RAZOR2_CHECK' : 2 Time(s)
|
|
Packit |
57988d |
# server hit by SIGHUP, restarting : 1 Time(s)
|
|
Packit |
57988d |
# server killed by SIGTERM, shutting down : 1 Time(s)
|
|
Packit |
57988d |
# meta test DIGEST_MULTIPLE has undefined dependency 'PYZOR_CHECK' : 1 Time(s)
|
|
Packit |
57988d |
# meta test SARE_SPEC_PROLEO_M2a has dependency 'MIME_QP_LONG_LINE' with a zero score : 1 Time(s)
|
|
Packit |
57988d |
|
|
Packit |
57988d |
while (defined($ThisLine = <STDIN>)) {
|
|
Packit |
57988d |
if ( # We don't care about these
|
|
Packit |
57988d |
# Note that we DO care about "connection from" non-localhost
|
|
Packit |
57988d |
( $ThisLine =~ m/connection from localhost / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/setuid to / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/processing message / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^spamd: result: .*,mid=\(unknown\)/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^prefork: child states: / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^spamd: alarm *$/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^spamd: handled cleanup of child / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^spamd: server successfully spawned child process, / ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^logger: removing stderr method/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^spamd: server pid:/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^prefork: adjust: \d+ idle children (less|more) than \d+ (min|max)imum idle children/ ) or
|
|
Packit |
57988d |
# Sendmail messages to ignore
|
|
Packit |
57988d |
( $ThisLine =~ m/^AUTH=/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^STARTTLS/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^starting daemon \(/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^ruleset=trust_auth/ ) or
|
|
Packit |
57988d |
( $ThisLine =~ m/^ruleset=check_relay/ ) or
|
|
Packit |
57988d |
0 # Always last in the list, so all above can say "or" at the end
|
|
Packit |
57988d |
) {
|
|
Packit |
57988d |
; # We don't care about these
|
|
Packit |
57988d |
} elsif ( ($User) = ($ThisLine =~ m/clean message .* for (.+?):\d+ / )) {
|
|
Packit |
57988d |
$Clean{ $User}++;
|
|
Packit |
57988d |
$Users{ $User}++;
|
|
Packit |
57988d |
} elsif ( ($User) = ($ThisLine =~ m/identified spam .* for (.+?):\d+ / )) {
|
|
Packit |
57988d |
$Spam{ $User}++;
|
|
Packit |
57988d |
$Users{ $User}++;
|
|
Packit |
57988d |
} elsif ( $ThisLine =~ m/still running as root: / ) {
|
|
Packit |
57988d |
$StillRoot++;
|
|
Packit |
57988d |
} elsif ( $ThisLine =~ m/^spamd: connection from (.*) at port / ) {
|
|
Packit |
57988d |
$Connections{$1}++;
|
|
Packit |
57988d |
# These are caused by pyzor taking too long and being terminated
|
|
Packit |
57988d |
} elsif ( $ThisLine =~ m/^pyzor:.* error: TERMINATED, signal 15/ ) {
|
|
Packit |
57988d |
$PyzorTerminated++;
|
|
Packit |
57988d |
} elsif ( $ThisLine =~ m/\bchild\b/ ) {
|
|
Packit |
57988d |
chomp($ThisLine);
|
|
Packit |
57988d |
# Many perl errors report pseudo-line-numbers, e.g.
|
|
Packit |
57988d |
# ... at /usr/bin/spamd line 1085, <GEN5490> line 212
|
|
Packit |
57988d |
$ThisLine =~ s/\d+/___/g; # Make all numbers "generic"
|
|
Packit |
57988d |
$Child{ $ThisLine }++; # ...and count generic error types
|
|
Packit |
57988d |
} elsif ( ($spam, $score, $msgid) = ($ThisLine =~ m/^spamd: result: (.) (-?\d+).*,mid=<(.*)>/) ) {
|
|
Packit |
57988d |
# Only record the first scan
|
|
Packit |
57988d |
if (!defined($msg{$msgid}->{"score"}) and $spam eq "Y") {
|
|
Packit |
57988d |
$msg{$msgid}->{"score"} = $score;
|
|
Packit |
57988d |
$SpamRelay{$msg{$msgid}->{"relay"}}++;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
} elsif ( $ThisLine =~ m/^\w+:/ ) {
|
|
Packit |
57988d |
# Sendmail lines for statistics
|
|
Packit |
57988d |
if ( ($from, $msgid, $relay) = ($ThisLine =~ m/^\w+: from=<(.*)>, .*, msgid=<(.*)>, .*, relay=(.*)/) ) {
|
|
Packit |
57988d |
$msg{$msgid}->{"from"} = $from;
|
|
Packit |
57988d |
$msg{$msgid}->{"relay"} = $relay;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
# EVERYTHING ELSE, or, Incentive to identify all "We don't care" lines
|
|
Packit |
57988d |
# We on-purpose allow warnings about --max-children to go here
|
|
Packit |
57988d |
} else {
|
|
Packit |
57988d |
chomp($ThisLine);
|
|
Packit |
57988d |
# Report any unmatched entries...
|
|
Packit |
57988d |
$OtherList{$ThisLine}++;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
#######################################################
|
|
Packit |
57988d |
|
|
Packit |
57988d |
#XX print "# Detail:${Detail}\n"; #XX debugging
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if ( keys %Users ) {
|
|
Packit |
57988d |
my ($u, $cl, $sp);
|
|
Packit |
57988d |
print "\nMail Recipients:\n";
|
|
Packit |
57988d |
# Some might want to limit this output based on $Detail, but we want it all!
|
|
Packit |
57988d |
foreach $u (sort {$a cmp $b} keys %Users) {
|
|
Packit |
57988d |
$cl = 0 + $Clean{$u}; # Avoid "undefined" error
|
|
Packit |
57988d |
$sp = 0 + $Spam{$u}; # Avoid "undefined" error
|
|
Packit |
57988d |
$CleanTotal += $cl;
|
|
Packit |
57988d |
$SpamTotal += $sp;
|
|
Packit |
57988d |
#OLD: If one user gets over 9999 messages, you have our sympathies
|
|
Packit |
57988d |
#NOW: If one user gets over 99999 messages, you have our sympathies
|
|
Packit |
57988d |
printf " %-8s : %4d clean, %5d spam\n", $u, $cl, $sp;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if ( $CleanTotal || $SpamTotal ) {
|
|
Packit |
57988d |
my $ttotal = $CleanTotal + $SpamTotal;
|
|
Packit |
57988d |
print "\nSummary:\n";
|
|
Packit |
57988d |
printf "\tTotal Clean: %5d (%3d%%)\n", $CleanTotal,
|
|
Packit |
57988d |
int ((100.0 * $CleanTotal / $ttotal) + 0.5);
|
|
Packit |
57988d |
printf "\tTotal Spam: %5d (%3d%%)\n", $SpamTotal,
|
|
Packit |
57988d |
int ((100.0 * $SpamTotal / $ttotal) + 0.5);
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if (keys %SpamRelay) {
|
|
Packit |
57988d |
print "\nTop 10 Spam Relays:\n";
|
|
Packit |
57988d |
$i = 0;
|
|
Packit |
57988d |
foreach $relay (sort {$SpamRelay{$b}<=>$SpamRelay{$a} } keys %SpamRelay) {
|
|
Packit |
57988d |
print " $relay: $SpamRelay{$relay} Time(s)\n";
|
|
Packit |
57988d |
last if ++$i == 10;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if ( $StillRoot ) {
|
|
Packit |
57988d |
print qq{\n"still running as root" error: $StillRoot time(s)\n};
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if (keys %Child) {
|
|
Packit |
57988d |
print "\nChild-related errors\n";
|
|
Packit |
57988d |
foreach $line (sort {$Child{$b}<=>$Child{$a} } keys %Child) {
|
|
Packit |
57988d |
print " $line: $Child{$line} Time(s)\n";
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if (keys %Connections) {
|
|
Packit |
57988d |
my $header_printed = 0;
|
|
Packit |
57988d |
foreach my $connection ( sort {$a cmp $b} keys %Connections ) {
|
|
Packit |
57988d |
if ($Ignore_connections && $connection =~ /$Ignore_connections/) { next; }
|
|
Packit |
57988d |
if (!$header_printed) {
|
|
Packit |
57988d |
print "\nConnections from:\n";
|
|
Packit |
57988d |
$header_printed = 1;
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
print " $connection : $Connections{$connection} Time(s)\n";
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if ( $PyzorTerminated) {
|
|
Packit |
57988d |
print "\nPyzor TERMINATED errors: $PyzorTerminated time(s)\n";
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
if (keys %OtherList) {
|
|
Packit |
57988d |
print "\n**Unmatched Entries**\n";
|
|
Packit |
57988d |
foreach $line (sort {$OtherList{$b}<=>$OtherList{$a} } keys %OtherList) {
|
|
Packit |
57988d |
print " $line: $OtherList{$line} Time(s)\n";
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
}
|
|
Packit |
57988d |
|
|
Packit |
57988d |
exit(0);
|
|
Packit |
57988d |
|
|
Packit |
57988d |
# vi: shiftwidth=3 tabstop=3 syntax=perl et
|
|
Packit |
57988d |
# Local Variables:
|
|
Packit |
57988d |
# mode: perl
|
|
Packit |
57988d |
# perl-indent-level: 3
|
|
Packit |
57988d |
# indent-tabs-mode: nil
|
|
Packit |
57988d |
# End:
|