2 # Check peer certificate validity
3 # Require perl module : IO::Socket, Net::SSLeay, Date::Parse
4 # Require unix programs : openssl, echo, sendmail
6 # Copyright (C) 2003 Emmanuel Lacour <elacour@home-dn.net>
8 # This file is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by the
10 # Free Software Foundation; either version 2, or (at your option) any
13 # This file is distributed in the hope that it will be
14 # useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this file; see the file COPYING. If not, write to the Free
20 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25 # Local variables are prefixed with "l_"
33 Net::SSLeay::SSLeay_add_ssl_algorithms();
34 Net::SSLeay::randomize();
36 my $VERSION = '0.6.3';
37 my $AUTHOR = 'Emmanuel Lacour, <elacour@home-dn.net>';
40 my $opensslpath = "/usr/bin/openssl";
41 my $sendmailpath = "/usr/lib/sendmail";
45 my $conf = "/etc/sslexpire/sslexpire.conf";
59 # output : -m = mail, default = stdout
60 # host : -h host, -p port, default = from config file
61 # config : -f configfile, default /etc/sslexpire/sslexpire.conf
62 # standard : --help, --version, --verbose
74 # Command line is used
75 if (($opts{'host'}) && ($opts{'port'})) {
76 push @{$hosts{$opts{'host'}}}, $opts{'port'};
78 } elsif (($opts{'host'}) || ($opts{'port'})) {
79 print STDERR "ERR: please provide HOST _and_ PORT or use a configuration file.\n";
82 # Configuration file is used
86 $conf = $opts{'conf'};
91 open (CONF,$conf) or die "ERR: Couldn't read configuration file $conf: $!\n";
96 if (/^alert[ \t]*=/) {
97 ($tmp,$alert) = split /=/, $_;
99 } elsif (/^mail[ \t]*=/) {
100 ($tmp,$mail) = split /=/, $_;
101 # Use hosts from config file if none are given by command line
102 } elsif ((!$opts{'host'}) && (!$opts{'port'}) && (/:/)) {
103 ($tmp,$portlist) = split /:/, $_;
106 # There is multiple ports
108 @ports = split /,/, $portlist;
110 push @{$hosts{$tmp}}, $_;
112 # There is only one port
114 push @{$hosts{$tmp}},$portlist;
122 $mailreport = 1 if ($opts{'mail'});
128 if ($opts{'version'}) {
129 print "sslexpire $VERSION\n";
130 print "Written by $AUTHOR\n";
134 # Print program usage
136 print "Usage: sslexpire [OPTION]...
137 -h, --host=HOST check only this host
138 -p, --port=TCPPORT check this port on the previous host
139 -m, --mail report by mail instead of STDOUT
140 -c, --conf=FILE use this config file
141 -v, --verbose print out verbose messages
142 --help print this help, then exit
143 --version print out version information
149 # This will return the expiration date
152 my ($l_host,$l_port) = @_;
153 my ($l_expdate,$l_comment);
155 # Connect to $l_host:$l_port
156 my $socket = IO::Socket::INET->new(
161 # If we connected successfully
164 my $l_ctx = Net::SSLeay::CTX_new();
165 my $l_ssl = Net::SSLeay::new($l_ctx);
167 Net::SSLeay::set_fd($l_ssl, fileno($socket));
168 my $res = Net::SSLeay::connect($l_ssl);
170 # Get peer certificate
171 my $l_x509 = Net::SSLeay::get_peer_certificate($l_ssl);
173 my $l_string = Net::SSLeay::PEM_get_string_X509($l_x509);
174 # Get the expiration date, using openssl
175 ($l_expdate,$l_comment) = split(/\n/, `echo "$l_string" | $opensslpath x509 -enddate -subject -noout 2>&1`);
176 $l_expdate =~ s/.*=//;
184 Net::SSLeay::free($l_ssl);
185 Net::SSLeay::CTX_free($l_ctx);
191 return ($l_expdate,$l_comment);
199 # Convert date into epoch
200 my ($l_expdate,$l_comment,$l_host,$l_port) = @_;
203 if ($l_expdate ne "1") {
206 my $l_epochdate = str2time($l_expdate);
208 # Calculate diff between expiration date and today
209 my $l_diff = ($l_epochdate - $l_today)/(3600*24);
212 if ($l_diff < $alert) {
213 $l_subject = "Warning ssl certificate on $l_host:$l_port expires in $l_diff days:" if ($l_diff > 1);
214 $l_subject = "Warning ssl certificate on $l_host:$l_port expires today:" if (($l_diff > 0) && ($l_diff < 1));
215 $l_subject = "Warning ssl certificate on $l_host:$l_port expired:" if ($l_diff <= 0);
216 my $l_mesg = "Expiration date: $l_expdate\n$l_comment\n";
219 sendmail($mail, $l_subject, $l_mesg);
221 print "$l_subject\n";
226 $l_subject = "Unable to read certificate on $l_host:$l_port!";
228 sendmail($mail, $l_subject, "");
230 print "$l_subject\n";
236 # Send mail - sendmail (to,subject,body)
244 open (MAIL,"| $sendmailpath -t") or die "Couldn't open $sendmailpath: $!\n";
245 print MAIL "To: $to\n";
246 print MAIL "Subject: $subj\n";
248 print MAIL "$mesg\n" if $mesg;
250 if ((my $status = $?>>8) != 0) {
251 die "sendmail: exit status $status\n";
259 # We haven't hosts to check...
261 print STDERR "No host to check!\n";
267 foreach $host (keys %hosts) {
268 # Parse ports for each hosts
269 foreach $port (@{$hosts{$host}}) {
270 if ($opts{'verbose'}) {
271 print "Checking\t$host:$port\n";
274 # Get expiration date
275 my ($expdate,$comment) = &getExpire($host,$port);
278 &report("$expdate","$comment","$host","$port");
283 # script documentation (POD style)
287 sslexpire - Remotely check ssl certificate expiration date.
291 This program connect to an host:port to retrieve the expiration date of the ssl
292 certificate. It gives a report to STDOUT or by email using configuration file.
294 =head1 COMMAND LINE PARAMETERS
296 Optional command line parameters are the host and the port to connect. This
297 allow checking a single host instead of using those given in the configuration
298 file for periodically checks.
302 =head2 B<-c> I<FILE>, B<--conf>=I<FILE>
304 Specify an alternate config file.
306 =head2 B<-h> I<HOST>, B<--host>=I<HOST>
308 Connect to I<HOST> instead of those given in the config file.
310 =head2 B<-p> I<PORT>, B<--port>=I<PORT>
312 Specify the port to connect to (used in conjonction with --host).
314 =head2 B<-v>, B<--verbose>
316 Prints out verbose messages.
318 =head2 B<-m>, B<--mail>
320 Send report by mail instead of STDOUT. It will use the address given in the
321 config file or root by default.
325 Prints out command-line help.
329 Prints out version information.
333 /etc/sslexpire/sslexpire.conf
337 Emmanuel Lacour, elacour@home-dn.net