check-cert.pl
branchhs12
changeset 3 23a6e0a1407e
parent 2 0e4dd7478d70
equal deleted inserted replaced
2:0e4dd7478d70 3:23a6e0a1407e
    12 use POSIX ":sys_wait_h";
    12 use POSIX ":sys_wait_h";
    13 use feature qw(:5.10);
    13 use feature qw(:5.10);
    14 use lib "/usr/lib/nagios/plugins";
    14 use lib "/usr/lib/nagios/plugins";
    15 use utils qw (%ERRORS &print_revision &support);
    15 use utils qw (%ERRORS &print_revision &support);
    16 
    16 
    17 my $ME        = basename $0;
    17 my $ME    = basename $0;
    18 my $USAGE = <<EOF;
    18 my $USAGE = <<EOF;
    19 Usage: $ME [-b <binary>] [-i init] [-d <path>] [-w <time>] [-c <time>] [-s <signature algorithm>] [-e <file,file,file,...>]
    19 Usage: $ME [-b <binary>] [-i init] [-d <path>] [-w <time>] [-c <time>] [-s <signature algorithm>] [-e <file,file,file,...>]
    20        $ME [-h | --help]
    20        $ME [-h | --help]
    21        $ME [-V | --version]
    21        $ME [-V | --version]
       
    22 
       
    23        Consult „--help“ for even more options.
    22 EOF
    24 EOF
    23 my $VERSION   = "0.4";
    25 my $VERSION = "0.4";
    24 my $hash_file = "/var/tmp/" . basename($0) . ".known.db";
    26 
    25 my (%known, %excluded);
       
    26 my %certs = ();
       
    27 my $no_print =
    27 my $no_print =
    28 "no_header,no_version,no_serial,no_validity,no_subject,no_issuer,no_pubkey,no_sigdump,no_extensions";
    28 "no_header,no_version,no_serial,no_validity,no_subject,no_issuer,no_pubkey,no_sigdump,no_extensions";
    29 my @cmd_x509 = (
    29 my @cmd_x509 = (
    30     "openssl",  "x509",      "-noout",   "-text",
    30     "openssl",  "x509",      "-noout",   "-text",
    31     "-certopt", "$no_print", "-subject", "-enddate"
    31     "-certopt", "$no_print", "-subject", "-enddate"
    32 );
    32 );
    33 my @cmd_pkcs12 = qw(openssl pkcs12 -clcerts -nokeys -nomacver -passin pass:);
    33 my @cmd_pkcs12 = qw(openssl pkcs12 -clcerts -nokeys -nomacver -passin pass:);
    34 my @cmd_pipe = (
    34 my @cmd_pipe   = (
    35     "openssl",  "x509",    "-noout",   "-text",
    35     "openssl",  "x509",    "-noout",   "-text",
    36     "-certopt", $no_print, "-subject", "-enddate"
    36     "-certopt", $no_print, "-subject", "-enddate"
    37 );
    37 );
    38 
    38 
    39 my (
    39 my (%cache, %excluded, %certs);
    40     $opt_debug,  $opt_init,    $opt_signature, $opt_version,
    40 
    41     $opt_help,   $opt_warning, $opt_directory, $opt_critical,
    41 my $opt_binary    = "/usr/bin/openssl";
    42     $opt_binary, @opt_exclude
    42 my $opt_signature = "md5WithRSAEncryption";
    43 );
    43 my $opt_warning   = "1month";
    44 my ($file, $w_time, $c_time);
    44 my $opt_critical  = "1week";
    45 
    45 my $opt_directory = "/etc";
    46 my (@critical, @warning);
    46 my $opt_debug     = 0;
    47 
    47 my $opt_init      = undef;
    48 $opt_binary    = "/usr/bin/openssl";
    48 my @opt_exclude   = ();
    49 $opt_signature = "md5WithRSAEncryption";
    49 
    50 $opt_warning   = "1month";
    50 my $opt_cache = "/var/tmp/@{[basename($0)]}.known.db";
    51 $opt_critical  = "1week";
       
    52 $opt_directory = "/etc";
       
    53 
    51 
    54 sub process_file();
    52 sub process_file();
    55 sub print_help();
    53 sub print_help();
    56 sub print_usage();
    54 sub print_usage();
    57 sub get_id(;$);
    55 sub get_id(;$);
    58 
    56 
    59 MAIN: {
    57 MAIN: {
       
    58     my ($w_time,   $c_time);
       
    59     my (@critical, @warning);
    60 
    60 
    61     Getopt::Long::Configure('bundling');
    61     Getopt::Long::Configure('bundling');
    62     GetOptions(
    62     GetOptions(
    63         "i|init"        => \$opt_init,
    63         "i|init"    => \$opt_init,
    64         "h|help"        => \$opt_help,
    64         "h|help"    => sub { print_help(); exit $ERRORS{OK}; },
    65         "V|version"     => \$opt_version,
    65         "V|version" => sub { print_revision($ME, $VERSION); exit $ERRORS{OK}; },
    66         "b|binary=s"    => \$opt_binary,
    66         "b|binary=s"    => \$opt_binary,
    67         "d|directory=s" => \$opt_directory,
    67         "d|directory=s" => \$opt_directory,
    68         "w|warning=s"   => \$opt_warning,
    68         "w|warning=s"   => \$opt_warning,
    69         "c|critical=s"  => \$opt_critical,
    69         "c|critical=s"  => \$opt_critical,
    70         "s|signature"   => \$opt_signature,
    70         "s|signature"   => \$opt_signature,
    71         "e|exclude=s"   => \@opt_exclude,
    71         "e|exclude=s"   => \@opt_exclude,
    72         "d|debug"       => \$opt_debug,
    72         "d|debug"       => \$opt_debug,
       
    73 	"cache=s"	=> \$opt_cache,
    73     );
    74     );
    74 
    75 
    75     print_revision($ME, $VERSION) and exit $ERRORS{"OK"} if $opt_version;
    76     tie(%cache, DB_File => $opt_cache, O_RDWR | O_CREAT, 0600)
    76     print_help() and exit $ERRORS{"OK"} if $opt_help;
    77       or die "Couldn't tie hash to file $opt_cache: $!; aborting";
    77 
       
    78     tie(%known, DB_File => $hash_file, O_RDWR | O_CREAT, 0600)
       
    79       or die "Couldn't tie hash to file $hash_file: $!; aborting";
       
    80 
    78 
    81     # initiate file-data hash
    79     # initiate file-data hash
    82     %known = () if $opt_init;
    80     %cache = () if $opt_init;
    83 	@excluded{@opt_exclude} = ();
    81     @excluded{@opt_exclude} = ();
    84 
    82 
    85     find({ wanted => \&process_file }, $opt_directory);
    83     find({ wanted => \&process_file }, $opt_directory);
    86 
    84 
    87 	exit;
    85     exit;
    88 
    86 
    89     # calculate the time
    87     # calculate the time
    90 	# $w_time = time() + 4 * 7 * 86400;
    88     # $w_time = time() + 4 * 7 * 86400;
    91     $w_time = DateCalc("today", "+ $opt_warning");
    89     $w_time = DateCalc("today", "+ $opt_warning");
    92     $c_time = DateCalc("today", "+ $opt_critical");
    90     $c_time = DateCalc("today", "+ $opt_critical");
    93 
    91 
    94     # check expire date
    92     # check expire date
    95     foreach (sort keys %certs) {
    93     foreach (sort keys %certs) {
   141     else {
   139     else {
   142         print "CERT OK: all certificates in limit\n";
   140         print "CERT OK: all certificates in limit\n";
   143         exit $ERRORS{"OK"};
   141         exit $ERRORS{"OK"};
   144     }
   142     }
   145 
   143 
   146     untie %known;
   144     untie %cache;
   147 
   145 
   148     exit;
   146     exit;
   149 }
   147 }
   150 
   148 
   151 sub get_id(;$) { return join " ", (@_ ? stat($_[0]) : stat(_))[7, 9] }
   149 sub get_id(;$) { return join " ", (@_ ? stat($_[0]) : stat(_))[7, 9] }
   152 
   150 
   153 sub process_file() {
   151 sub process_file() {
   154 
   152 
   155 	return if exists $excluded{$File::Find::name};
   153     return if exists $excluded{$File::Find::name};
   156     return if not -f;
   154     return if not -f;
   157 
   155 
   158     my $id             = get_id();
   156     my $id             = get_id();
   159     my $is_certificate = 0;
   157     my $is_certificate = 0;
   160     my $in_cert        = 0;
   158     my $in_cert        = 0;
   161     my @cert           = ();
   159     my @cert           = ();
   162     my ($rc, $temp, $signature, $subject, $enddate);
   160     my ($rc, $temp, $signature, $subject, $enddate);
   163 
   161 
   164     # excluded files
   162     # excluded files
   165 	# @opt_exclude = split(/,/, join(',', @opt_exclude)) if @opt_exclude;
   163     # @opt_exclude = split(/,/, join(',', @opt_exclude)) if @opt_exclude;
   166 
   164 
   167     return
   165     return
   168       if exists $known{$File::Find::name}
   166       if exists $cache{$File::Find::name}
   169           and $known{$File::Find::name} eq $id;
   167           and $cache{$File::Find::name} eq $id;
   170 
   168 
   171 	  #say $File::Find::name;
   169     #say $File::Find::name;
   172     # checking for pkcs12 certificates
   170     # checking for pkcs12 certificates
   173 
   171 
   174 	if (0) {
   172     if (0) {
   175     my @cmd_pkcs12_current = @cmd_pkcs12;
   173         my @cmd_pkcs12_current = @cmd_pkcs12;
   176     push @cmd_pkcs12_current, "-in", $File::Find::name, "2>/dev/null";
   174         push @cmd_pkcs12_current, "-in", $File::Find::name, "2>/dev/null";
   177     my $cid = open(FILE, "@cmd_pkcs12_current |") || die "Can't fork: $!";
   175         my $cid = open(FILE, "@cmd_pkcs12_current |") || die "Can't fork: $!";
   178 
   176 
   179     while (<FILE>) {
   177         while (<FILE>) {
   180         /^$cid:error:.*/ and last;
   178             /^$cid:error:.*/ and last;
   181         $temp .= $_;
   179             $temp .= $_;
   182     }
   180         }
       
   181         close(FILE);
       
   182 
       
   183         if ($temp) {
       
   184             local (*READ, *WRITE);
       
   185             my $cid = open2(\*READ, \*WRITE, @cmd_pipe)
       
   186               or die "Can't fork: $!\n";
       
   187             print WRITE $temp;
       
   188             close(WRITE);
       
   189             while (<READ>) {
       
   190                 /Signature\sAlgorithm:\s(.*)\s+$/ and $signature = $1;
       
   191                 /^subject=\s+(.*)\s+$/            and $subject   = $1;
       
   192                 /^notAfter=(.*)\s+$/              and $enddate   = $1;
       
   193             }
       
   194             close(READ);
       
   195 
       
   196             # waiting for child processes
       
   197             do {
       
   198                 $cid = waitpid(-1, WNOHANG);
       
   199             } while $cid > 0;
       
   200 
       
   201             $is_certificate = 1;
       
   202             push(
       
   203                 @{ $certs{$File::Find::name} },
       
   204                 ($subject, $enddate, $signature)
       
   205             );
       
   206 
       
   207             $cache{$File::Find::name} = $id if not($is_certificate);
       
   208             return;
       
   209         }
       
   210     }
       
   211 
       
   212     open(FILE, $_) or die "can't open $File::Find::name: $!";
       
   213     my $file = join "", <FILE>;
   183     close(FILE);
   214     close(FILE);
   184 
   215 
   185     if ($temp) {
   216     while ($file =~ /^(-+BEGIN CERTIFICATE.*?-+END CERTIFICATE-+)$/msg) {
       
   217 
       
   218         # open filehandles (for read and write)
   186         local (*READ, *WRITE);
   219         local (*READ, *WRITE);
   187         my $cid = open2(\*READ, \*WRITE, @cmd_pipe)
   220         my $cid = open2(\*READ, \*WRITE, @cmd_x509)
   188           or die "Can't fork: $!\n";
   221           or die "Can' fork: $!\n";
   189         print WRITE $temp;
   222         print WRITE $1;
   190         close(WRITE);
   223         close(WRITE);
       
   224 
   191         while (<READ>) {
   225         while (<READ>) {
   192             /Signature\sAlgorithm:\s(.*)\s+$/ and $signature = $1;
   226             /Signature\sAlgorithm:\s(.*)\s+$/ and $signature = $1;
   193             /^subject=\s+(.*)\s+$/            and $subject   = $1;
   227             /^subject=\s+(.*)$/               and $subject   = $1;
   194             /^notAfter=(.*)\s+$/              and $enddate   = $1;
   228             /^notAfter=(.*)\s+$/              and $enddate   = $1;
   195         }
   229         }
   196         close(READ);
   230         close(READ);
   197 
   231 
   198         # waiting for child processes
   232         waitpid($cid, 0) < 0 and die "no child with pid $cid\n";
   199         do {
   233 
   200             $cid = waitpid(-1, WNOHANG);
   234         if ($opt_debug) {
   201         } while $cid > 0;
   235             print "-----\n";
       
   236             print "$File::Find::name\n";
       
   237             print "Signature Algorithm: $signature\n" if ($signature);
       
   238             print "subject: $subject\n"               if ($subject);
       
   239             print "enddate: $enddate\n"               if ($enddate);
       
   240         }
       
   241 
       
   242         push(@{ $certs{$File::Find::name} }, ($subject, $enddate, $signature));
   202 
   243 
   203         $is_certificate = 1;
   244         $is_certificate = 1;
   204         push(@{ $certs{$File::Find::name} }, ($subject, $enddate, $signature));
   245     }
   205 
   246 
   206         $known{$File::Find::name} = $id if not($is_certificate);
   247     $cache{$File::Find::name} = $id if not($is_certificate);
   207         return;
       
   208     }
       
   209 }
   248 }
   210 
   249 
   211     open(FILE, $_) or die "can't open $File::Find::name: $!";
   250 sub print_usage() { print $USAGE }
   212 	my $file = join "", <FILE>;
       
   213 	close(FILE);
       
   214 
       
   215 	while ($file =~ /^(-+BEGIN CERTIFICATE.*?-+END CERTIFICATE-+)$/msg) {
       
   216 
       
   217 			# open filehandles (for read and write)
       
   218 			local (*READ, *WRITE);
       
   219 			my $cid = open2(\*READ, \*WRITE, @cmd_x509)
       
   220 			  or die "Can' fork: $!\n";
       
   221 			print WRITE $1;
       
   222 			close(WRITE);
       
   223 
       
   224 			while (<READ>) {
       
   225 				/Signature\sAlgorithm:\s(.*)\s+$/ and $signature = $1;
       
   226 				/^subject=\s+(.*)$/               and $subject   = $1;
       
   227 				/^notAfter=(.*)\s+$/              and $enddate   = $1;
       
   228 			}
       
   229 			close(READ);
       
   230 
       
   231 			waitpid($cid, 0) < 0 and die "no child with pid $cid\n";
       
   232 
       
   233                 if ($opt_debug) {
       
   234                     print "-----\n";
       
   235                     print "$File::Find::name\n";
       
   236                     print "Signature Algorithm: $signature\n" if ($signature);
       
   237                     print "subject: $subject\n"               if ($subject);
       
   238                     print "enddate: $enddate\n"               if ($enddate);
       
   239                 }
       
   240 
       
   241                 push(
       
   242                     @{ $certs{$File::Find::name} },
       
   243                     ($subject, $enddate, $signature)
       
   244                 );
       
   245 
       
   246 				$is_certificate = 1;
       
   247         }
       
   248 
       
   249     $known{$File::Find::name} = $id if not($is_certificate);
       
   250 }
       
   251 
       
   252 
       
   253 sub print_usage() { print $USAGE };
       
   254 
   251 
   255 sub print_help() {
   252 sub print_help() {
   256     print_revision($ME, $VERSION);
   253     print_revision($ME, $VERSION);
   257 print <<EOF;
   254     print <<EOF;
   258 Copyright (c) 2009 Christian Arnold
   255 Copyright (c) 2009 Christian Arnold
   259 
   256 
   260 This plugin checks the expire date for openssl certificates.
   257 This plugin checks the expire date for openssl certificates.
   261 
   258 
   262 $USAGE
   259 $USAGE
   263 	-b, --binary <binary>
   260 	-b, --binary <binary>
   264           Path of openssl binary (default: /usr/bin/openssl)
   261           Path of openssl binary (default: /usr/bin/openssl)
   265 	-d, --directory <path>
   262 	-d, --directory <path>
       
   263 
       
   264 	… --cache=s db file where the known files are stored
   266 EOF
   265 EOF
   267 
   266 
   268 print "Absolute directory path in which will be recursively search for certificate files (default: /etc).\n";
   267     print
       
   268 "Absolute directory path in which will be recursively search for certificate files (default: /etc).\n";
   269     print "  -w, --warning <time>\n";
   269     print "  -w, --warning <time>\n";
   270     print
   270     print
   271 "     Certificat should not be more than this time older (default: 1month).\n";
   271 "     Certificat should not be more than this time older (default: 1month).\n";
   272     print
   272     print
   273 "     For time can be used year, month, day, hour, minute, second and weeks.\n";
   273 "     For time can be used year, month, day, hour, minute, second and weeks.\n";