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