1*00b67f09SDavid van Moolenbroek#!@PERL@ 2*00b67f09SDavid van Moolenbroek# 3*00b67f09SDavid van Moolenbroek# Copyright (C) 2010, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") 4*00b67f09SDavid van Moolenbroek# 5*00b67f09SDavid van Moolenbroek# Permission to use, copy, modify, and/or distribute this software for any 6*00b67f09SDavid van Moolenbroek# purpose with or without fee is hereby granted, provided that the above 7*00b67f09SDavid van Moolenbroek# copyright notice and this permission notice appear in all copies. 8*00b67f09SDavid van Moolenbroek# 9*00b67f09SDavid van Moolenbroek# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10*00b67f09SDavid van Moolenbroek# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11*00b67f09SDavid van Moolenbroek# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12*00b67f09SDavid van Moolenbroek# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13*00b67f09SDavid van Moolenbroek# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14*00b67f09SDavid van Moolenbroek# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15*00b67f09SDavid van Moolenbroek# PERFORMANCE OF THIS SOFTWARE. 16*00b67f09SDavid van Moolenbroek 17*00b67f09SDavid van Moolenbroek# Id: check-secure-delegation.pl.in,v 1.2 2010/12/21 02:32:21 marka Exp 18*00b67f09SDavid van Moolenbroek 19*00b67f09SDavid van Moolenbroekuse warnings; 20*00b67f09SDavid van Moolenbroekuse FileHandle; 21*00b67f09SDavid van Moolenbroekuse IPC::Open2; 22*00b67f09SDavid van Moolenbroekuse POSIX qw/strftime/; 23*00b67f09SDavid van Moolenbroek 24*00b67f09SDavid van Moolenbroek# 25*00b67f09SDavid van Moolenbroek# We only compare keyid / DNSSEC algorithm pairs. If this succeeds then 26*00b67f09SDavid van Moolenbroek# the crypto will likely succeed. If it fails then the crypto will definitely 27*00b67f09SDavid van Moolenbroek# fail. 28*00b67f09SDavid van Moolenbroek# 29*00b67f09SDavid van Moolenbroek$prefix = "@prefix@"; 30*00b67f09SDavid van Moolenbroek$dig = "$prefix/bin/dig +cd +dnssec +noall +answer"; 31*00b67f09SDavid van Moolenbroek$dsfromkey = "$prefix/sbin/dnssec-dsfromkey -1 -A -f /dev/stdin"; 32*00b67f09SDavid van Moolenbroek 33*00b67f09SDavid van Moolenbroek# Get "now" in a RRSIG datestamp format. 34*00b67f09SDavid van Moolenbroek$now = strftime "%Y%m%d%H%M%S", gmtime; 35*00b67f09SDavid van Moolenbroek 36*00b67f09SDavid van Moolenbroekforeach $zone (@ARGV) { 37*00b67f09SDavid van Moolenbroek my %algorithms = (); 38*00b67f09SDavid van Moolenbroek my %dnskeygood = (); 39*00b67f09SDavid van Moolenbroek my %dnskeyalg = (); 40*00b67f09SDavid van Moolenbroek my %dnskey = (); 41*00b67f09SDavid van Moolenbroek my %dsgood = (); 42*00b67f09SDavid van Moolenbroek my %ds = (); 43*00b67f09SDavid van Moolenbroek 44*00b67f09SDavid van Moolenbroek # Read the DS records and extract the key id, algorithm pairs 45*00b67f09SDavid van Moolenbroek open(DS, "$dig -t DS -q $zone|") || die("dig DS failed"); 46*00b67f09SDavid van Moolenbroek while(<DS>) { 47*00b67f09SDavid van Moolenbroek @words = split; 48*00b67f09SDavid van Moolenbroek if ($words[3] eq "RRSIG" && $words[4] eq "DS") { 49*00b67f09SDavid van Moolenbroek next if ($words[8] >= $now && $words[9] <= $now); 50*00b67f09SDavid van Moolenbroek print "BAD SIG DATES: $_"; 51*00b67f09SDavid van Moolenbroek } 52*00b67f09SDavid van Moolenbroek next if ($words[3] ne "DS"); 53*00b67f09SDavid van Moolenbroek $ds{"$words[4] $words[5]"} = 1; 54*00b67f09SDavid van Moolenbroek $algorithms{"$words[5]"} = 1; 55*00b67f09SDavid van Moolenbroek } 56*00b67f09SDavid van Moolenbroek close(DS); 57*00b67f09SDavid van Moolenbroek 58*00b67f09SDavid van Moolenbroek # Read the RRSIG(DNSKEY) records and extract the key id, 59*00b67f09SDavid van Moolenbroek # algorithm pairs. Set good if we have a match against the DS 60*00b67f09SDavid van Moolenbroek # records. DNSKEY records should be before the RRSIG records. 61*00b67f09SDavid van Moolenbroek open(DNSKEY, "$dig -t DNSKEY -q $zone|") || die("dig DNSKEY failed"); 62*00b67f09SDavid van Moolenbroek while (<DNSKEY>) { 63*00b67f09SDavid van Moolenbroek @words = split; 64*00b67f09SDavid van Moolenbroek if ($words[3] eq "DNSKEY") { 65*00b67f09SDavid van Moolenbroek $dnskeyalg{"$words[6]"} = 1; 66*00b67f09SDavid van Moolenbroek next if (! -e "/dev/stdin"); 67*00b67f09SDavid van Moolenbroek # get the key id ($dswords[3]). 68*00b67f09SDavid van Moolenbroek $pid = open2(*Reader, *Writer, "$dsfromkey $zone"); 69*00b67f09SDavid van Moolenbroek die("dsfromkey failed") if ($pid == -1); 70*00b67f09SDavid van Moolenbroek print Writer "$_"; 71*00b67f09SDavid van Moolenbroek close(Writer); 72*00b67f09SDavid van Moolenbroek $line = <Reader>; 73*00b67f09SDavid van Moolenbroek close(Reader); 74*00b67f09SDavid van Moolenbroek @dswords = split /\s/, $line; 75*00b67f09SDavid van Moolenbroek $dnskey{"$dswords[3] $dswords[4]"} = 1; 76*00b67f09SDavid van Moolenbroek next; 77*00b67f09SDavid van Moolenbroek } 78*00b67f09SDavid van Moolenbroek next if ($words[3] ne "RRSIG" || $words[4] ne "DNSKEY"); 79*00b67f09SDavid van Moolenbroek if ($words[8] >= $now && $words[9] <= $now) { 80*00b67f09SDavid van Moolenbroek # If we don't have /dev/stdin then just check for the 81*00b67f09SDavid van Moolenbroek # RRSIG otherwise check for both the DNSKEY and 82*00b67f09SDavid van Moolenbroek # RRSIG. 83*00b67f09SDavid van Moolenbroek $dsgood{"$words[5]"} = 1 84*00b67f09SDavid van Moolenbroek if (! -e "/dev/stdin" && 85*00b67f09SDavid van Moolenbroek exists($ds{"$words[10] $words[5]"})); 86*00b67f09SDavid van Moolenbroek $dsgood{"$words[5]"} = 1 87*00b67f09SDavid van Moolenbroek if (exists($ds{"$words[10] $words[5]"}) && 88*00b67f09SDavid van Moolenbroek exists($dnskey{"$words[10] $words[5]"})); 89*00b67f09SDavid van Moolenbroek $dnskeygood{"$words[5]"} = 1 90*00b67f09SDavid van Moolenbroek if (! -e "/dev/stdin"); 91*00b67f09SDavid van Moolenbroek $dnskeygood{"$words[5]"} = 1 92*00b67f09SDavid van Moolenbroek if (exists($dnskey{"$words[10] $words[5]"})); 93*00b67f09SDavid van Moolenbroek } else { 94*00b67f09SDavid van Moolenbroek $dnskeygood{"$words[5]"} = 1; 95*00b67f09SDavid van Moolenbroek print "BAD SIG DATES: $_"; 96*00b67f09SDavid van Moolenbroek } 97*00b67f09SDavid van Moolenbroek } 98*00b67f09SDavid van Moolenbroek close(DNSKEY); 99*00b67f09SDavid van Moolenbroek 100*00b67f09SDavid van Moolenbroek # Do we have signatures for all DNSKEY algorithms? 101*00b67f09SDavid van Moolenbroek foreach $alg ( keys %dnskeyalg ) { 102*00b67f09SDavid van Moolenbroek print "Missing $zone DNSKEY RRSIG for algorithm $alg\n" 103*00b67f09SDavid van Moolenbroek if (!exists($dnskeygood{$alg})); 104*00b67f09SDavid van Moolenbroek } 105*00b67f09SDavid van Moolenbroek 106*00b67f09SDavid van Moolenbroek # Do we have a matching self signed DNSKEY for all DNSSEC algorithms 107*00b67f09SDavid van Moolenbroek # in the DS records. 108*00b67f09SDavid van Moolenbroek $count = 0; 109*00b67f09SDavid van Moolenbroek foreach $alg ( keys %algorithms ) { 110*00b67f09SDavid van Moolenbroek if (exists($dsgood{$alg})) { 111*00b67f09SDavid van Moolenbroek print "$zone algorithm $alg good " . 112*00b67f09SDavid van Moolenbroek "(found DS / self signed DNSKEY pair)\n"; 113*00b67f09SDavid van Moolenbroek } else { 114*00b67f09SDavid van Moolenbroek print "$zone algorithm $alg bad " . 115*00b67f09SDavid van Moolenbroek "(no DS / self signed DNSKEY pair found)\n"; 116*00b67f09SDavid van Moolenbroek } 117*00b67f09SDavid van Moolenbroek $count++; 118*00b67f09SDavid van Moolenbroek } 119*00b67f09SDavid van Moolenbroek print "$zone has no secure delegation records\n" 120*00b67f09SDavid van Moolenbroek if (! $count); 121*00b67f09SDavid van Moolenbroek} 122