On Sun, Nov 01, 2009 at 07:57:34AM -0500, Nathan Gibbs wrote:
> * Ed Ravin wrote:
> > We use a similar monitor for SpamAssassin that uses the corresponding
> > "fake spam signature" to test whether spamd is checking messages - if
> > anyone's interested, let me know.
> > 
> >     -- Ed
> 
> Sure, I could use that.

See attached.

#!/usr/bin/perl -w
#
# test spamd by sending a test spam string.  Will alarm if socket doesn
# not answer or if spamd fails to recognize the test string as spam.

# copyright(2004) by Ed Ravin <era...@panix.com>.  License is GPL
# this software is made available courtesy of PANIX, http://www.panix.com
# based on code snatched from nntp.monitor by Jim Trocki and
# http.monitor by Jon Meek.
#
#
my $usage=
  "spamd.monitor [-d] [-p port] [-t timeout] host [host...]\n";
#  -d for debug
#

use strict;
use Getopt::Std;
use English;

use vars qw($opt_p $opt_t $opt_d);

getopts ("m:p:t:d") || die $usage;
my $PORT = $opt_p || 783;
my $TIMEOUT = $opt_t || 30;
my $DEBUG = $opt_d || "";

my @failures = ();
my @details=   ();

# WARNING - this spam test string is broken up to avoid getting trapped by
# spam filters if the program is sent via mail.
my $GTUBE= 
        "XJS*C4JDBQADN1.NSBN3*2IDNEN*" . 
        "GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X";


foreach my $host (@ARGV) {

    if (! &spamdTEST($host, $PORT)) {
        push (@failures, $host);
    }
}

if (@failures == 0) {
    exit 0;
}

print join (" ", sort @failures), "\n";
print sort @details if (scalar @details) > 0;

exit 1;


sub spamdTEST {
    use Socket;
    use Sys::Hostname;

    my($Server, $Port) = @_;
    my($ServerOK, $TheContent);

    $ServerOK = 0;

    $TheContent = '';

###############################################################
my $TransactionOK= eval {

        local $SIG{ALRM} = sub { die "Timeout Alarm" };
        alarm $TIMEOUT;
        my $result = &OpenSocket($Server, $Port); # Open a connection to the 
server
        if (!$result) { # Failure to open the socket
            print "$Server: Unable to open socket\n" if $DEBUG;
            return '';
        }

        my $now= time;
        my $testmessage="Subject: Mon test of spamd at $now\r\n\r\n$GTUBE";
        my $testlength= length($testmessage) + 2;


#  52 45 50 4f 52 54 20 53    50 41 4d 43 2f 31 2e 33    REPORT SPAMC/1.3
#  0d 0a 55 73 65 72 3a 20    72 6f 6f 74 0d 0a 43 6f    ..User: root..Co
#  6e 74 65 6e 74 2d 6c 65    6e 67 74 68 3a 20 31 31    ntent-length: 11
#  31 0d 0a 0d 0a                                        1....           

        transact("REPORT SPAMC/1.3\r\nUser: netmon\r\nContent-length: 
$testlength\r\n", '', "$Server: failed sending REPORT request") || return 0;

#  Expected reply to test message:
#  53 50 41 4d 44 2f 31 2e    31 20 30 20 45 58 5f 4f    SPAMD/1.1 0 EX_O
#  4b 0d 0a                                              K..             

        transact("$testmessage", '^SPAMD/.*\b0\b', "$Server: no response (or 
incorrect response) to test message") || return 0;
        my $inputline="";

        my @spamcresults= <S>;

        if (grep /^1000\s+GTUBE\b/, @spamcresults)
        {
                push @details, "$Server: spamd OK, found test spam\n" if $DEBUG;
                return 1;
        }
        else
        {
                push @details, "$Server: spamd responded but didn't find test 
spam\n";
                map {push @details, "$Server: $_" } @spamcresults;
                return 0;
        }
};

        close(S);
        alarm 0; # Cancel the alarm

    if ($EVAL_ERROR and ($EVAL_ERROR =~ /^Timeout Alarm/)) {
                push(@details, "$Server: timeout($TIMEOUT)\n");
                return 0;
    }

        return 0 unless $TransactionOK;

        $ServerOK = 1;
    return $ServerOK;

}

sub OpenSocket {
#
# Make a Berkeley socket connection between this program and a TCP port
#  on another (or this) host. Port can be a number or a named service
#
    my($OtherHostname, $Port) = @_;
    my($OurHostname, $sockaddr, $proto, $type, $len,
          $ThisAddr, $that, $OtherHostAddr, $result);
    $OurHostname = &hostname;

    $proto = getprotobyname('tcp');
    $Port = getservbyname($Port, 'tcp') unless $Port =~ /^\d+$/;
    $ThisAddr = gethostbyname($OurHostname);
    $OtherHostAddr = gethostbyname($OtherHostname);
        if (!defined $OtherHostAddr)
        {
                push (@details, "$OtherHostname: cannot resolve hostname\n");
                return undef
        }

    $that = sockaddr_in ($Port, $OtherHostAddr);

    if (! ($result = socket(S, PF_INET, SOCK_STREAM, $proto)) ||
       (! ($result = connect(S, $that))) )
        {
         push (@details, "$OtherHostname: $!\n");  return undef;
        }

    select(S); $| = 1; select(STDOUT);      # set S to be un-buffered
    return 1;                               # success
}

sub transact # "string to send", "pattern to expect", "error message"
{
    my($sendstr, $rxpattern, $errormsg) = @_;
    my($rxstr);

        warn "DEBUG: sending data: $sendstr<CR LF>\n" if $DEBUG;
    print S $sendstr . "\r\n" unless $sendstr eq "";
        return 1 if $rxpattern eq "";

    $rxstr = <S> || "";
        warn "DEBUG: received data (" . length($rxstr) . " bytes): $rxstr\n"
                if $DEBUG;
    if ($rxstr !~ $rxpattern) {
                alarm 0;
                push(@details, $errormsg . "\n");
                return 0;
    }
    return 1;
}
_______________________________________________
mon mailing list
mon@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/mon

Reply via email to