# -*- mmm-classes: donuts-perl -*-
# Copyright 2004-2007 SPARTA, Inc.  All rights reserved.
# See the COPYING file included with the DNSSEC-Tools package for details.
#
# This file checks aspects of parent/child relationships
#


name: DNS_MULTIPLE_NS
level: 6
minnsrecords: 2
help: minnsrecords: minimum number of NS records that must be present for a delegation
desc: Tests to see if at least two NS records exist for a delegated zone.
ruletype: name
class: Warning
test:
  return "Only " . ($#{$_[0]->{'NS'}}+1) . 
     " NS record(s) for $_[2] found, but at least " .
     $_[1]->{'minnsrecords'} . " are suggested/required"
        if (exists($_[0]->{'NS'}) && 
           $#{$_[0]->{'NS'}}+1 < $_[1]->{'minnsrecords'});

name: DNSSEC_SUB_NOT_SECURE
level: 3
ruletype: name
desc: Tests for the existence of a DS record in a zone for sub-domains.  If not present then the sub-domain is not being securely delegated to.
test:
  "sub-domain $_[2] is not securely delegated.  It is missing a DS record."
  if ($current_domain ne $_[2]                         &&  # not the root
      exists($_[0]->{'NS'}) && $#{$_[0]->{'NS'}} > -1  &&  # is a sub
      exists($_[0]->{'RRSIG'})                         &&  # DS||NSEC signed
      !exists($_[0]->{'DS'})                               # No DS
     );

name: DNSSEC_DNSKEY_PARENT_HAS_VALID_DS
level: 4
feature: live
type: DNSKEY
desc: tests for valid DS checksum and for RFC4034: section 5.2: The DNSKEY RR referred to in the DS RR MUST be a DNSSEC zone key.
test:
  my $keyrr = $_[0];
  $keyrr->setkeytag();
  return if ($keyrr->flags & 0x100);  # key is not a zone signing key
  my @DSs = live_query($keyrr->name, "DS");
  return "Parent zone has no DS records for $keyrr->{name} (keyid = $keyrr->{keytag})" if ($#DSs == -1);
  map { if ($_->verify($keyrr)) {
          if ($_->keytag !=  $keyrr->keytag) {  # tag ids match
	    return "KEY with tag $keyrr->{keytag} verifies DS record with non matching tag $_->{keytag}";
          }
          return;
        } } @DSs;
  return "DNSKEY record for $keyrr->{name} (keytag = " .
         $keyrr->keytag . 
         ") does not have a matching DS record in the live parent zone";

name: DNSSEC_DS_CHILD_HAS_MATCHING_DNSKEY
level: 4
feature: live
desc: tests for valid DS checksum and for RFC4034: section 5.2: The DNSKEY RR referred to in the DS RR MUST be a DNSSEC zone key.
type: DS
test:
  my $dsrr = $_[0];
  my @KEYs = live_query($dsrr->name, "DNSKEY");
  return "Child zone has no DNSKEY records for $dsrr->{name}" if ($#KEYs == -1);
  map { if ($dsrr->verify($_)) {
          return if ($_->flags & 0x100);  # zone bit set properly
          return "Key tag $_->{keytag} in child for $_->{name} does not match key tag $dsrr->{keytag}" if ($_->keytag != $dsrr->keytag);
          return "Key in child for $_->{keytag} referred to by DS for $dsrr->{name} does not have the zone flag set";
          return;
        } } @KEYs;
  return "DS record for $dsrr->{name} does not have a matching DNSKEY record in the live child zone";
