#!/usr/bin/perl -w
use strict; # $Id: monm_ssl 87 2019-07-14 15:36:48Z abalama $
use utf8;

=encoding utf8

=head1 NAME

monm_ssl - SSL/TLS checker for App::MonM

=head1 VERSION

Version 1.00

=head1 SYNOPSIS

    monm_ssl [-d DAYS] HOST

=head1 OPTIONS

=over 4

=item B<-h, --help>

Show short help information and quit

=item B<-H, --longhelp>

Show long help information and quit

=item B<-d DAYS, --days=DAYS>

Alert days

Default: 14

=back

=head1 DESCRIPTION

SSL/TLS checker for App::MonM

=head1 AUTHOR

Serż Minus (Sergey Lepenkov) L<http://www.serzik.com> E<lt>abalama@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved

=head1 LICENSE

This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

See L<https://dev.perl.org/licenses/>

=cut

use Getopt::Long;
use Pod::Usage;


use DateTime::Format::x509;
use List::Util qw/ max /;
use CTK::Util qw/ execute trim /;

use App::MonM::Const qw/
        OK DONE ERROR SKIPPED PASSED FAILED UNKNOWN PROBLEM
    /;

use constant {
    DAYS    => 14,
    PORT    => 443,
};

$| = 1;  # autoflush

my $options = {};
Getopt::Long::Configure("bundling");
GetOptions($options,
    # Information
    "help|usage|h",         # Show help page
    "longhelp|H|?",         # Show long help page

    # General
    "days|day|d=i",         # Days
    "port|P=i",             # Port

) || pod2usage(-exitval => 1, -verbose => 0, -output => \*STDERR);
pod2usage(-exitval => 0, -verbose => 1) if $options->{help};
pod2usage(-exitval => 0, -verbose => 2) if $options->{longhelp};

my $host    = shift(@ARGV);
my $port    = $options->{port} || PORT;
my $days    = $options->{days} || DAYS;
unless ($host) { 
    print STDERR "Incorrect host\n";
    print ERROR, "\n";
    exit 1;
}

my $command = sprintf("echo | openssl s_client -servername %s -connect %s:%d 2>/dev/null | openssl x509 -noout -dates", $host, $host, $port);

# Run command
my $exe_err = '';
my $exe_out = execute($command, undef, \$exe_err);
my $stt = ($? >> 8);
my $exe_stt = $stt ? 0 : 1;
   $exe_stt = 1 if $stt == 1;
unless ($exe_stt) {
    if ($exe_err) {
        printf STDERR "%s\n", $exe_err;
    } else {
        printf STDERR "Command error [%d]: %s\n", $stt, $command;
    }
    print ERROR, "\n";
    exit 1;
}
unless ($exe_out) {
    print STDERR "Incorrect openssl output data\n";
    print ERROR, "\n";
    exit 1;
}

#print $exe_out;
my $f = DateTime::Format::x509->new();

# Parse pool
my @lines = (0);
foreach my $line (split /\n/, $exe_out) {
    chomp($line);
    next unless $line;
    my $l = trim($line);
    next unless $l;
    if ($l =~ /^\w+\=(.+)$/) {
        my $dt = $f->parse_datetime($1);
        push @lines, $dt->epoch;
    }
}

# Get max
my $exp = max(@lines);
unless ($exp) {
    print STDERR "Can't get the expiry date\n";
    print ERROR, "\n";
    exit 1;
}

# Got
my $secs = $exp - time();
my $got = ($secs - ($secs % (24 * 60 * 60))) / (24 * 60 * 60);
if ($got <= $days) {
    printf STDERR "%d days left (alert=%d; expiry=%s)\n", $got, $days, scalar(gmtime($exp));
    print ERROR, "\n";
    exit 1;
}

print OK, "\n";
exit 0;

__END__
