Check imap.pl/code

From Federal Burro of Information
Jump to navigationJump to search
#!/usr/bin/perl -w

use strict;
use Getopt::Long;
use IO::Socket;
use IO::Socket::SSL;
use Pod::Usage;

my $warn = 3; # seconds
my $crit = 5; # seconds
my $user;
my $pwf; #password file
my $host; # imap server
my $port = '993'; # imaps tcp port
my $sock ; # socket
my $timeout = 2;
my $verbose = 0;
my $fr = 0; #full responses
my $help = 0;
my $man = 0;
my $secure = 0;
my $msg = ;
my $rc  = ;
my $start;
my $globalstart;
my $end;
my $globalend;
my $elapse;
my $line;

my $result = GetOptions ( "w=i"     => \$warn,
                          "c=i"     => \$crit,
                          "user=s" => \$user,
                          "pwf=s"   => \$pwf,
                          "host=s"  => \$host,
                          "port=i"  => \$port,
                          'v'      => \$verbose,
                          'h'       => \$help,
                          'm'       => \$man,
                          'S'       => \$secure,
                          'fr'      => \$fr,
                          't=i'     => \$timeout);


pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;

# required parameters
die "warn but be set" unless $warn;
die "critical must be set" unless $crit;
die "user address must be set" unless $user;
die "password file must be set" unless $pwf;
die "host must be set" unless $host;

my $pwfh ; # password file handle

if ( ! open($pwfh, $pwf)) {
    print "CRITICAL Failed to open password file ( $pwf ) :$!\n";
    exit 3;
}

my $password;
read $pwfh,  $password, 64;
chomp $password;

# Expected conversation
my         $opening = "\\* OK IMAP4 ready";
my           $login = "a01 login $user $password\n";
my    $loginsuccess = "LOGIN completed";
my     $selectinbox = "a02 SELECT INBOX\n";
my $selectcompleted = "SELECT completed";
my      $fetchflags = "a03 FETCH 1:* FLAGS\n";
my  $fetchcompleted = "OK FETCH completed";
my       $fetchfull = "a04 FETCH 1 full\n";
#   $fetchcompleted # same as above
my       $fetchbody = "a06 FETCH 1 body\[text\]\n";
#   $fetchcompleted # same as above
my          $logout = "a05 logout\n";

$globalstart = $start = time;
if ( $secure ){
    $sock = new IO::Socket::SSL (
        PeerAddr => $host,
        PeerPort => $port,
        Proto => 'tcp',
        Timeout => $timeout);

} else {

    $sock = new IO::Socket::INET (
        PeerAddr => $host,
        PeerPort => $port,
        Proto => 'tcp',
        Timeout => $timeout);
}

if ( ! $sock ) {
    print "UNKNOWN Failed to create sock ( $host:$port ): $!\n";
    exit 3;
}

$end = time;
$elapse = $end - $start;
$verbose && print "$end socket created ($elapse seconds)\n";


$start = time;
eval { $line = <$sock>; };
if ($@) {
    print "CRITICAL Failed to get opening greeting\n";
    exit 3;
}
$end = time;
$elapse = $end - $start;


if ( ! $line =~ /$opening/ ) {
    chomp $line;
    print "CRITICAL Fist line doesn't match required opening ( expecting $opening , got: $line )\n";
    exit 2;
}  else {
    $verbose && print "$end got opening ($elapse seconds)\n";
    $fr && print "<<< $line";
}

$start = time;
$verbose && print "$start Sending login\n";
$verbose && print ">>> $login";
print $sock $login;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent login and pass ( $elapse seconds)\n";

$verbose && print "$end Reading response\n";
$start = time;
eval { $line = <$sock>; };
if ($@) {
    print "CRITICAL Failed to get login result\n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

if ( ! $line =~ /$loginsuccess/ ) {
    chomp $line;
    print "CRITICAL Failed to get login success ( got: $line )\n";
    exit 2;
} elsif ( $line =~ /NO cleartext logins disabled/ ) {
    print "CRITICAL Failed to get login: cleartext disabled\n";
    exit 2;
} else {
    $verbose && print "$end got login success ( $elapse seconds)\n";
    $fr && print "<<< $line";
}


##########################
# Select inbox
##########################
$start = time;
$verbose && print "$start Selecting inbox\n";
$verbose && print ">>> $selectinbox";
print $sock $selectinbox;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent select inbox\n";

$start = time;

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    while ( $line = <$sock> ) {
        $fr && print "<<< ".$line;
        last if ( $line =~ /$selectcompleted/ );
    }
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
    print "CRITICAL Failed to get select completed (timed out: $timeout seconds)\n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

$verbose && print "$end got select completed\n";
$fr && print "<<< $line";


##########################
# fetch flags
##########################
$start = time;
$verbose && print "$start Fetch Flags\n";
$verbose && print ">>> $fetchflags";
print $sock $fetchflags;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent fetch flags\n";

$start = time;
eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    while ( $line = <$sock> ) {
        $fr && print "<<< ".$line;
        last if ( $line =~ /$fetchcompleted/ );
    }
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
    print "CRITICAL Failed to get fetch flags completed (timed out: $timeout seconds)\n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

$verbose && print "$end got fetch flags completed\n";
$fr && print "<<< $line";


##########################
# fetch Full
##########################
$start = time;
$verbose && print "$start Fetch Full\n";
$verbose && print ">>> $fetchfull";
print $sock $fetchfull;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent fetch full\n";

$start = time;
eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    while ( $line = <$sock> ) {
        $fr && print "<<< ".$line;
        last if ( $line =~ /$fetchcompleted/ );
    }
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
    print "CRITICAL Failed to get fetch full completed (timed out: $timeout seconds)\n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

$verbose && print "$end got fetch full completed\n";
$fr && print "<<< $line";


##########################
# fetch Body
##########################
$start = time;
$verbose && print "$start Fetch Body\n";
$verbose && print ">>> $fetchbody";
print $sock $fetchbody;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent fetch body\n";

$start = time;
eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    while ( $line = <$sock> ) {
        $fr && print "<<< ".$line;
        last if ( $line =~ /$fetchcompleted/ );
    }
    alarm 0;
};
if ($@) {
    die unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
    print "CRITICAL Failed to get fetch body completed (timed out: $timeout seconds)\n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

$verbose && print "$end got fetch body completed\n";
$fr && print "<<< $line";

##########################
# Logout
##########################
$start = time;
$verbose && print "$start logout\n";
print $sock $logout;
$end = time;
$elapse = $end - $start;
$verbose && print "$end Sent logout\n";

$start = time;
eval { $line = <$sock>; };
if ($@) {
    print "CRITICAL Failed to get logout result \n";
    exit 2;
}
$end = time;
$elapse = $end - $start;

if ( ! $line =~ /$fetchcompleted/ ) {
    chomp $line;
    print "CRITICAL Failed to get fetch completed ( got: $line )\n";
    exit 2;
} else {
    $verbose && print "$end got logout completed\n";
    $fr && print "<<< $line";
}


$globalend = time;
$elapse = $globalend - $globalstart;

# 'label'=value[UOM];[warn];[crit];[min];[max]
if ( $elapse > $crit ) {
    print "CRIT IMAP check took too long |'time'=".$elapse."seconds;$warn;$crit;0;100\n";
    exit 2;
}
if ( $elapse > $warn ) {
    print "WARN IMAP check took too long |'time'=".$elapse."seconds;$warn;$crit;0;100\n";
    exit 1;
}
print "OK IMAP check successful |'time'=".$elapse."seconds;$warn;$crit;0;100\n";
exit 0;