#!/usr/bin/perl
#
# $Cambridge: hermes/conf/bind/bin/validate-trust-anchor,v 1.3 2010/07/16 14:13:15 fanf2 Exp $

use strict;
use warnings;

die "usage: validate-trust-anchor [anchors.xml] [dnskey] [ds]\n"
    unless @ARGV == 3;

sub slurp {
	my $f = shift;
	open my $h, "<", $f
	    or die "open $f: $!\n";
	return <$h>;
}

my @xml    = slurp $ARGV[0];
my @dnskey = slurp $ARGV[1];
my @ds     = slurp $ARGV[2];

my $xml = join "", @xml;
$xml =~ s{\s*<}{<}g;
$xml =~ s{>\s*}{>}g;

die "No zone in $ARGV[0]\n"
    unless $xml =~ m{<Zone>([0-9A-Za-z.-]+)</Zone>};
my $zone = $1;

die "Too many DNSKEY RRs\n"
    unless @dnskey == 1;

my $dnskey = $dnskey[0];
unless ($dnskey =~ m{^
    ([0-9A-Za-z.-]+)\s+ # owner
    (\d+\s+)?           # ttl
    (IN\s+)?            # class
    DNSKEY\s+           # type
    257\s+              # flags
    3\s+                # protocol
    (\d+)\s+            # algorithm
    ([0-9A-Za-z/+= ]*)  # key
$}x) {
	die "Unrecognized DNSKEY\n";
}
my $dnskey_owner = $1;
my $dnskey_algo = $4;
my $dnskey_key = $5;

die "DNSKEY owner $dnskey_owner is not $zone\n"
    unless $dnskey_owner eq $zone;

sub gripe {
	print STDERR "@_\n";
	next;
}

my $valid = 0;

for my $ds (@ds) {
	unless ($ds =~ m{^
	    ([0-9A-Za-z.-]+)\s+ # owner
	    (\d+\s+)?           # ttl
	    (IN\s+)?            # class
	    DS\s+               # type
	    (\d+)\s+            # tag
	    (\d+)\s+            # algorithm
	    (\d+)\s+            # digest type
	    ([0-9A-Za-z/+= ]*)  # digest
	$}x) {
		gripe "unrecognized DS";
	}
	my $ds_owner = $1;
	my $ds_tag = $4;
	my $ds_algo = $5;
	my $ds_type = $6;
	my $ds_digest = $7;
	$ds_digest =~ s{ }{};

	if ($ds_owner ne $zone) {
		gripe "DS owner $ds_owner is not $zone";
	}
	if ($dnskey_algo != $ds_algo) {
		gripe "DS algorithm does not match";
	}

	my $ds_xml = join '',
		"<KeyDigest[^>]*>",
		"<KeyTag>$ds_tag</KeyTag>",
		"<Algorithm>$ds_algo</Algorithm>",
		"<DigestType>$ds_type</DigestType>",
		"<Digest>$ds_digest</Digest>",
		"</KeyDigest>";

	$valid++ if $xml =~ m{$ds_xml};
}

die "Untrusted key\n" unless $valid;

$dnskey_key =~ s{^}{" }g;
$dnskey_key =~ s{$}{ "}g;
$dnskey_key =~ s{ }{\n\t\t}g;

print "\t\"$dnskey_owner\" initial-key 257 3 $dnskey_algo $dnskey_key;\n";
