#! /usr/bin/perl -w

use strict;

my $sign_alert_time  = 72; # Warnzeit in Stunden
my $sign_critic_time = 12;  # Critical-Zeit in Stunden
my $indexserver = "84.19.194.5";
my $dns_server = "muli.schlittermann.de";
my $indexzone  = "idx.net.schlittermann.de";
my @sec_zones = ();
my $set_exit = 0;
my (@print_zones, @print_infos);
my $inter_time;
my $count;
my $oldest_time = 9000000000;
my $oldest_name;
my $dsrec;
my $abltime;
my $oldest_ftime;
my $ftime;
chomp( my $unixtime = `date +%s` );

# erzeugt liste @sec_zones aus der dig-abfrage
my @digtxt = `dig \@$indexserver $indexzone TXT` or
	print "PROBLEM: no results from dig \n" and exit 2;

# abbruch des skripts wenn dig nicht korrekt antwortet
# ausfiltern der zonen im index mit dnssec unterstuetzung
for (@digtxt) {
    chomp;
	if (m#status\:.(.*)\,#) {
		unless ($1 eq "NOERROR") {
			print "PROBLEM: $indexzone not reachable \n";
			exit 2;
		}
	}
    if (m#ZONE::(.*)::sec-on#) {
	    push @sec_zones, $1;
    }
}

# erstellt $alert_time aus der systemunixzeit und dem
# konfigurationswert in $sign_alert_time
$inter_time = $unixtime + ( 3600 * $sign_alert_time );
chomp( my $alert_time = `date -d \@$inter_time +%Y%m%d%H`);
# erstellt $critic_time
$inter_time = $unixtime + ( 3600 * $sign_critic_time );
chomp( my $critic_time = `date -d \@$inter_time +%Y%m%d%H`);

# durchlauf fuer jede dnssec-zone
for (@sec_zones) {
    chomp (my @zone_dig = `dig +dnssec \@$dns_server $_`);
    my $zone = $_;

	# parst die ablaufzeit der signatur 
    for (@zone_dig) {
        unless (m#RRSIG.*SOA#) { next;}
		s#($zone).*([0-9]{10})([0-9]{4}).*[0-9]{14}.*#$2#;
		# ermittelt die naechste ablaufsdomain
		if ($oldest_time > $_) {
			$oldest_time = $_;
			$oldest_name = $zone;
			$oldest_ftime = $ftime;
		}
		# setzt exit 2 wen die critical-time ueberschritten ist
        if($_ < $critic_time) {
            $set_exit = 2;
            push @print_zones, $zone;
            last;
        }
		# setzt exit 1 wen die alert-time ueberschritten ist
        if($_ < $alert_time) {
            unless ($set_exit == 2) {
                $set_exit = 1;
        	}
            push @print_zones, $zone;
            last;
        }
    }
    
    my @digtest_1 = `dig \@$dns_server $zone +dnssec DNSKEY`;
    my @digtest_2 = `dig \@$dns_server $zone +dnssec DS`;
    my @digtest_3 = `dig \@$dns_server $zone\.dlv.isc.org`;

    # ermittelt und formatiert die ablaufzeit
    for (@digtest_1) {
        if (m#RRSIG.*DNSKEY.*(\d{4})(\d{2})(\d\d)(\d\d)(\d\d)(\d\d).*(\d{14})#) {
            $ftime = "$3.$2.$1 $4:$5";
        	last;
    	}
    }
    # setzt die zeit fuer die naechste ablaufsdomain 
	if ($oldest_name eq $zone) {
		$oldest_ftime = $ftime;
	}
    
    # zskanzahl
    my $zskcount = 0;
    for (@digtest_1) {
        if (m#DNSKEY.*256#) {
        	$zskcount ++;
    	}
    }
	# kskanzahl
    my $kskcount = 0;
    for (@digtest_1) {
    	if (m#DNSKEY.*257#) {
        	$kskcount ++;
    	}
    }
    # ds-test
    for (@digtest_2) {
        if (m#IN.*RRSIG.*DS.*(\d{14}).*(\d{14}).*(\s)([a-z]{0,100}\.)(\s).*#) {
        	print "DSDS ($4) ";
    	}
    }
    # dlv-check
    for (@digtest_3) {
        if (m#NOERROR#) {
        	$dsrec = "dlv";
		}    
    }
    push @print_infos, "$zone - $zskcount - $kskcount - $dsrec - $ftime \n";
	$count ++;
}

#print @print_infos;# @print_infos enthält mehr informationen

# Ausgabe und Ende
if ($set_exit == 0) { 
	print "OK: $count DNSSEC-Zones checked; ";
	print "next end is $oldest_name at $oldest_ftime \n";
}
if ($set_exit == 1) { print "WARNING: "}
if ($set_exit == 2) { print "CRITICAL: "}
print "@print_zones ($oldest_ftime)\n";
exit $set_exit;
