There was some interest from MON users at LISA for me to post my version
of https.monitor which does SSL certification expiration detection.

I've attached it to this message.  The contrib maintainer can drop it into
the repository if they choose.

I recommend running this a a separate service, as it probably isn't worth
waking someone up at 3am about a certificate that will expire in a few
days.

It also has a few other minor changes:
- It handles connection timeouts a bit better
- It handles http result codes other than 200 (301, 302, and 401)
- It only outputs hostnames in the summary line.

-David

David Nolan                    <*>                    [EMAIL PROTECTED]
curses: May you be forced to grep the termcap of an unclean yacc while
      a herd of rogue emacs fsck your troff and vgrind your pathalias!
#!/usr/bin/perl
#
# $Id: https.monitor,v 1.7 2003/10/06 13:13:39 vitroth Exp $
#
# An extremely simple https monitor for mon.
#
# Code structure based on Jon Meek & Jim Trocki's http.monitor program.
#
# https code taken from the get_page.pl function from the 
# Net::SSLeay distribution by Sampo Kellomaki <[EMAIL PROTECTED]>
#
# It makes use of the Net::SSLeay library and the OpenSSL package
# (www.openssl.org).
#
# To get around the problem that Net::SSLeay carps to STDERR 
# uncontrollably about a number of things (e.g. connection refused),
# we get around this by running the actual ssl get as an escaped 
# perl program and dropping the stderr of that instance. Gross, but
# strangely effective.
#
# Use the -v option if you actually want to see the full result and
# all headers. You'd never use this from mon, since it provides 
# non-mon-compliant output, but it can be interesting from the command
# line.
#
# Use the -w option if you want to be warned about SSL certificats which
# are about to expire, or already have expired.  '-w 10' would give you ten 
# days notice about a certificate expiration, which should be plenty of time
# to get a replacement certificate.
# 
#
#     Distribution and use of this program is under the same terms
#     as the OpenSSL package itself (i.e. free, but mandatory
#     attribution; NO WARRANTY). Please consult COPYRIGHT file in
#     the root of the SSLeay distribution.
# 

use strict; 

use Socket;
use Net::SSLeay qw(die_now die_if_ssl_error) ;
use Getopt::Std;   
use Time::ParseDate;
#
use English;


#Net::SSLeay::load_error_strings();
#Net::SSLeay::SSLeay_add_ssl_algorithms();

# Comment this out since on systems without a /dev/[u]random this
# line causes an unneccesary carp which will confuse mon.
# If you use Linux or BSD or other OS which supports a random device,
# feel free to uncomment this line.
#Net::SSLeay::randomize();

use vars qw($opt_p $opt_t $opt_u $opt_v $opt_w);
getopts ("vp:t:u:w:");
my $PORT = $opt_p || 443;
my $TIMEOUT = $opt_t || 30;
my $URL = $opt_u || "/";
my $EXPIREWARN = $opt_w ;       # How long in advance to warn about cert expiration.  
0 means don't warn
$EXPIREWARN = 0 if (!defined $EXPIREWARN); # Don't warn by default

my @failures = ();
my @detail = ();

$PORT = getservbyname($PORT, 'tcp') unless $PORT =~ /^\d+$/;

my ($host, $OK);

foreach $host (@ARGV) {

    $OK = &httpsGET($host, $PORT, $URL);

    if (!defined ($OK) || $OK == 0) {
        push (@failures, $host);
    }
}

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

print "@failures\n";
print join("\n",@detail);

exit 1;



#  Main function begins here
sub httpsGET {
    my ($site, $port, $path) = (@_);
    my $total_bytes = 0;       #set total bytes transferred to 0
    my ($headers,$cert, $res, $reply, $ServerOK);

    print "attempting to contact site $site on port $port with path $path\n" if $opt_v;

    $ServerOK = 1;
    eval {    
        local $SIG{ALRM} = sub { print STDERR "$site: Timeout\n" if $opt_v; die 
"Timeout Alarm" };
        alarm $TIMEOUT;

        ($reply, $res, $headers, $cert) = Net::SSLeay::get_https3($site, $port, $path);
        print STDERR 
"XXXXX\nreply\nXXXXX\n$reply\nXXXXX\nres\nXXXXX\n$res\nXXXXX\nheaders\nXXXXX\n$headers\nXXXXX\ncert\nXXXXX\n$cert\n"
 if $opt_v;
        if (!($res =~ /^HTTP\/([\d\.]+)\s+(?:200|30[12]|401)\b/)) {
            $ServerOK = 0;
            push(@detail,"$site: $res\n$headers\n");
        } elsif (!$cert) {
            $ServerOK = 0;
            push @detail, "$site: No certificate returned\n";
        } else {

          if ($EXPIREWARN) {
            my $servercertname = 
Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($cert));
            my $signingcertname = 
Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($cert));
            my $notafter = Net::SSLeay::P_ASN1_UTCTIME_put2string 
(Net::SSLeay::X509_get_notAfter($cert));
            my $notbefore = Net::SSLeay::P_ASN1_UTCTIME_put2string 
(Net::SSLeay::X509_get_notBefore($cert));
            my $na_time = parsedate($notafter);
            my $nb_time = parsedate($notbefore);
            my $now = time;
            my $later = $now + (86400 * $EXPIREWARN);
            print STDERR "XXXXX\nnotbefore $notbefore\nnotafter $notafter\nna_time 
$na_time\nnb_time $nb_time\nnow $now\nlater $later\n" if $opt_v;
            if ( $now < $nb_time ) {
                push @detail,"$site: Certificate not valid until 
$notbefore\ncertificate: $servercertname\nCA certificate: $signingcertname";
                $ServerOK = 0;
            }
            if ($now > $na_time) {
                push @detail,"$site: Certificate expired as of $notafter\ncertificate: 
$servercertname\nCA certificate: $signingcertname";
                $ServerOK = 0;
            } elsif ($later > $na_time ) {
                push @detail,"$site: Certificate will expire at 
$notafter\ncertificate: $servercertname\nCA certificate: $signingcertname";
                $ServerOK = 0;
            }
          }
        }

    };
    
    if ($EVAL_ERROR and ($EVAL_ERROR =~ 'Timeout Alarm')) {
        push @detail, "$site: *** Timeout\n";
        return 0;
    }

    if ($EVAL_ERROR) {
        push @detail, "$site:  Eval Error $EVAL_ERROR\n";
        return 0;
    }
    
    return $ServerOK;

}

_______________________________________________
mon mailing list
[EMAIL PROTECTED]
http://linux.kernel.org/mailman/listinfo/mon

Reply via email to