Net-DNS-SEC-0.16/000755 000765 000120 00000000000 11346437115 013273 5ustar00olafadmin000000 000000 Net-DNS-SEC-0.16/Changes000644 000765 000120 00000033662 11346437006 014577 0ustar00olafadmin000000 000000 Revision history for Perl extension Net::DNS::SEC. ***0.16 March 12, 2010 Feature: KEY inherits DNSKEY This helps maintenance in one part of the code. Feature: keylength methode rt.cpan.org #53468 Added keylength method for RSA and DSA Acknowledgements Hugo Salgado Fix: rt.cpan.org #51778 Empty bitmap would cause error about undefined ARRAY in NSEC/NSEC3. Now the code will allow empty bitmaps gracefully Feature: New Algorithm Support (rt.cpan.org #51092) SHA2 algorithm support, including NSEC3 algorithm parameters updated Acknowledgement Jakob Shlyter Fix: rt.cpan.org #42089 NSEC3 Algorithm support in NSEC3 broken patch by Wes Hardaker ***0.15 December 31, 2008 Fix: digestbin not set when an empty value passed to hash. Feature: Added DLV (rfcc 4431). The RR object is simply a clone of the DS RR and inherits ... everything Feature: Added NSEC3 and NSEC3PARAM support (RFC5155). This adds Mime::Base32 to the module dependency list. The RR type was still experimental at that time and is maintained in Net::DNS::RR. Fix: Test script recognizes change in Time::Local. Note that Time::Local does not deal with dates beyond 03:14:07 UTC on Tuesday, 19 January 2038. Therefore this code has a year 2038 problem. Fix: DS create_from_hash now produces objects that can create wireformat. Other: minor changes to the debug statements added t/05-rr.t (and identified a couple of bugs using it) Fix: a few inconsistencies with respect to parsing of trailing dots. During development the test signatures generated with the BIND tools were re-generated in order to troubleshoot a bug that (most probably) was caused by a version incompatibility between Net::DNS and Net::DNS::SEC. Before release the original test from the 0.14 release were ran against this version too. 0.14 February 14, 2005 FIX: The introducion of the keytag warning triggered a bug with RSAMD5 keys, causing RSAMD5 keys not to be loaded. 0.13 December 9, 2005 FEAT: rt.cpan.org 14588 Added support for passing (a reference to) an array of keys to the RRSIG verify function. FIX/FEAT: The Net::DNS::SEC::Private function will for RSA based keys verify if the keytag in the filename is actually correct. Since at parsing the value of the DNSKEY RR flags is not known we test against the currently defined flag values 256 and 257. If we cannot find a keytag match a warning is printed and Private key generation fails This inconsistency was spotted by Jakob Shlyter. FEAT: Added support for SHA256 to the DS RR. Assigned the expected digest type2 for SHA256 type hashes. Note that this makes the Net::DNS::SEC depend on Digest::SHA instead of Digest::SHA1. The default digest type is still set to 1. NB. The code makes assumptions about the IANA assignment of the digest type. The assignment may change. Do not use SHA256 in production zones!! FIX: rt.cpan.org #15662 Roy Arends noticed and patched the label counting did not ignore an initial asterisk label. FIX: Wes Hardaker noticed the default TTL values for created signatures to be different from the TTLs from the data that is being signed. FIX: Wes Hardaker reported there was a problem with validating RRsets that had ownernames with capitals. The fix depends on a fix in Net::DNS::RR that is available in version 0.53_03 or later of the Net::DNS distribution. FEAT: Propper dealing with mnemonics for algorithm and digest type added to DS FIX/FEAT: Mnemonics were written as RSA/MD5 and RSA/SHA1. This has been corrected tp RSASHA1 and RSAMD5, as in the IANA registry. 0.12_02 June 6, 2005 (beta 2 release for 0.13) Bug: new_from_hash would not correctly create the RR since internally typebm is used to store the data this has been fixed so that the following works Net::DNS::RR->new(name=>$name, ttl=>$ttl, type=>"NSEC", nxtdname=>$nxtdname, typelist=>join(" ",@types) ); FEAT: Introduced the "use bytes" pragma to force character interpretation of all the scalars. Any utf processing by perl makes the code behave unpredictable. 0.12_01 April 18, 2005. (beta release for version 0.13) FEAT (!!!): Changed the symantics of the Net::DNS::Keyset::verify method. Read the perldoc for details. The requirement that each key in a keyset has to be selfsigned has been loosened. FEAT: Added a "carp" to the new methods of the NXT RR. Warning that that record is depricated. FEAT: Cleaned the tests so that RRSIG and DNSKEY are used except for SIG0 based tests. FEAT: Changed the name of the siginceptation[SIC] to siginception. Thanks Jakob Schlyter for notifying me of this mistyping. An alias for the method remains available. FEAT: Renamed unset_sep() to clear_sep(). NOTE: To avoid confusion the Net::DNS::SIG::Private class has been removed. Use Net::DNS::SEC::Private! DOC: Added references to RFC 4033, RFC 4034 and RFC 4035. Rewrote parts of the perlpod. 0.12 June 2004 "DNSSEC-bis Release" FEAT: Added utility function key_difference() to Net::DNS::SEC. See perlpod for details. I needed this in other software and figured they are generic enough to make them available through this module. FEAT: Modified some functions to use DNSKEY and RRSIG instead off KEY and SIG. - Net::DNS::Keyset now uses DNSKEY and RRSIG. - the demo function getkeyset.pl now uses DNSKEY too. FEAT: Added the possibility to create a keyset out of two arrays of dnskey and rrsig object. FEAT: Added some helperfunctions to Net::DNS::SEC::Private to read X509 formated private keys and dump them into bind format. This functionality has not been tested well. BUG : When reading a RRSIG from a packet the signame would not have a trailing dot. 0.11_4 Apr 24 2004 Development snapshot. BUG: - Fixed MANIFEST. FEAT: Removed critical dependency on bubblebabble. It is available to DS if installed but not critically dependend. 0.11_3 Mar 4 2004 Development snapshot. BUG: - Fixed minor in signing unknown RR types. 0.11_2 Jan 27 2004 Development snapshot. FEAT: - Prelimanary support for draft-ietf-dnssec-nsec-rdata-02. This depends on support for unknown RR types (Net::DNS version 0.44) 0.11_1 Sep 23 2003 Development snapshot. FEAT: - To be able to deal with argument supplied as either mnemonics or by value the Net::DNS::SEC::argument method was created. It can be used as a class method but it is also inherited by Net::DNS::RR::RRSIG and Net::DNS::RR::DNSKEY. 0.11 August 28 2003 FEAT: - Implemented draft-ietf-dnsext-dnssec-2535typcode-change-04.txt This document has been through review and will be published as standard track RFCs shortly. (Publsished as RFC3755). IMPORTANT: the implementation of the typecode roll deprecated the use of SIG->create for any other reason than SIG0. If you try to create SIGs over RRsets you will be warned. FEAT: - Modified the namespace for the module that holds the name of the private key from Net::DNS::RR::SIG::Private to Net::DNS::SEC::Private. !!!!! Net::DNS::RR::SIG::Private will be deprecated in a next release. !!!!! CLEAN:- Crypt::OpenSSL::RSA v 0.19 introduced the possibility to create keys directly from parameters, although this introduced a dependency on Crypt::OpenSSL::Bignum it allowed to get rid from converting all parameters to DER/ANS1 encoding. Got rid of a number of lines of code. 0.10 January 8 2003 BUG: - Crypt::OpenSSL::RSA::new method has been depricated. Code has been modified to deal with the new constructors 0.09 January 6 2003 FEAT: - Added Net::DNS::RR::SIG::Private. The class provides an abstraction to the private key material. The SIG create method now either takes a filename, like previously, or a Private key object as an argument. If you have to create many signatures the latter is preferred because you only have to read the file with the private key material once. Note that by adding this feature a modification to Net::DNS::Resolver was needed to properly do SIG0. Use Net::DNS version 0.32 or later in combination with this version FEAT: - Wes Griffen added a parameter change to keyset: 'Attached is a diff for Net::DNS::SEC v0.8 that adds a parameter changes keyset->writekeyset($path) to keyset->writekeyset($prefix,$path) where prefix is an optional string that is prepended to the filename of the keyset. That way I can keep my unsigned keyset in keyset-. and have the signed keyset in signed-keyset-.' FEAT: - Babblebubble, handy for telephone confirmation of hashes. Added babblebubble string as comment to DS RR. DS->babble returns the babble bubble string FEAT: - Miek Gieben contributed demo/key2ds 0.08 November 4 2002 BUG: - DSA signature verification failed at random about 1 per 10 sigatures. Corrected allignment problem that lead to this. Added 'stresstest' that loops over creation and verification of signatures to spot these kind of seldomly occuring errors. On my VAIO PII 500Mhz the take about a minute: Files=3, Tests=3056, 69 wallclock secs (63.30 cusr + 0.70 csys = 63.99 CPU) FEAT: - Added Test::More as dependency as on some systems diag was failing. 0.07 October 2 2002 FEAT: - Added demo/make-signed-keyset, a contribution by Wes Griffin. FEAT: - Removed dependency on Math::Pari by porting away from Crypt::DSA to Crypt::OpenSSL::DSA (version 0.10). This should increase portability over platform. T.J. Mather, the Crypt::OpenSSL::DSA maintainer has been particularly helpfull and responsive by adding a few methods to the DSA modules. 0.06 August 16 2002 NOTE: In one of ther versions prior to Net::DNS 0.26 a bug got introduced that made Net::DNS::SEC break. The bug was fixed in version 0.27. BUG: - Check on the existence of the private file improved in SIG.pm - signame got trailing dot with the create methods and not with others. FEAT: - Added privatekeyname method to KEY.pm - Started work on Net::DNS::Keyset. - Added RSA/SHA1 (algorithm ID 5) to SIG.pm. Patch supplied by Andy Vaskys, Network Associates Laboratories. - Rewrote regexp's to not use $' (Postmatch). 0.05 and 0.04 June 17, 2002 BUG: Makefile.PL needed a fix for unused dependency. This failed made the installation fail :-(. 0.04 introduced another failing dependency. DOC: Clarified the documentation at points. 0.03 June 14, 2002 DOC: Few Clarifications 0.02 June 4, 2002 First CPAN Release. Some modifications to the packaging. 0.01 May 25, 2002 Version 0.01 of the package is an alpha for CPAN release. --------------------------------------------------------------------------- The extensions used to be published as a modified version of Net::DNS. The history of those is documented below. 0.20-DNSSEC-0.2: Branched off Net::DNS version 0.20 release (CPAN May 15, 2002) 0.20-DNSSEC-0.1: This version had limited distribution First patch against a version 0.20 snapshot (2002-03-27). http://www.dyndns.org/~ctriv/net-dns-snaps/2002/03/ Modified t/09-dnssec.t; uses Test::More now and includes a number of self consistency checks. DOC Cleaned up the documentation and removed some references to functions and libraries that where not used anyway. FIX 'aesthetic' patch supplied by Simon Josefsson reordering the NXT RR map for the print method. FEAT Added checks on keytype and updated to latest specs for DS Added SIG0 support. See Net::DNS::Packet for details. The verify and create methods of SIG.pm where modified somewhat to cope with the difference. Changed RSA backend from Crypt::RSA to Crypt::OpenSSL::RSA because Crypt::RSA failed during a 'loss of Math::Pari precision in Crypt::Primes'. 0.19-DNSSEC-0.5: BUG DS create method: Hash calculation was done over concattination of name and key material while the hash should be taken over concatenation of canonical name and key rdata. (Fix by Mike Schiraldi) 0.19-DNSSEC-0.4: Added CERT support: Courtesy of Mike Schiraldi for VeriSign BUG Fixed MANIFEST file. make dist will result in proper module tar ball 0.19-DNSSEC-0.3: Solved patch problems that where due to the $Id: Changes 848 2010-03-12 13:12:16Z olaf $ in headers not being from the original distribution. Added DSA signature creation Added DS support You have to uncomment line 77 in Net/DNS.pm to fully enable DS This will assign QTYPE 93 to the DS RR. That value is not assigned by IANA. Added this README.DNSSEC file Added t/09-dnssec.t to the test script with a number of consistency checks. after patching the original distribution direction perl Makefile.PL make test will call this function among other things. BUG KeyID set to 0 for null keys. BUG Sorting of canonical RDATA; Data over which SIG was created was not sorted properly (RFC2535 sect 8.3) causing signature verification errors for RDATA within a RRset having different length (e.g. some NS RRsets would not verify.) 0.19-DNSSEC-0.2: First somewhat public release. --------------------------------------------------------------------------- $Id: Changes 848 2010-03-12 13:12:16Z olaf $ Net-DNS-SEC-0.16/demo/000755 000765 000120 00000000000 11346437114 014216 5ustar00olafadmin000000 000000 Net-DNS-SEC-0.16/Keyset.pm000644 000765 000120 00000037320 11346437006 015101 0ustar00olafadmin000000 000000 # $Id: Keyset.pm 728 2008-10-12 09:02:24Z olaf $ package Net::DNS::Keyset; use Cwd; =head1 NAME Net::DNS::Keyset - DNSSEC Keyset object class =head1 SYNOPSIS use Net::DNS::Keyset; =head1 DESCRIPTION A keyset is a "administrative" unit used for DNSSEC maintenance. The bind dnssec-signzone tool uses it to genertate DS records. This class provides interfaces for reading keysets, creating and parsing them. Note that this class is still being developed. Attributes and methods are subject to change. =cut use Data::Dumper; use strict; use Net::DNS; use Carp; use vars qw ( $VERSION @EXPORT $keyset_err ); ( $VERSION ) = '$Revision: 728 $ ' =~ /\$Revision:\s+([^\s]+)/; my $debug=0; sub new { my $retval; $keyset_err="No Error"; if (@_ == 2 && ! ref $_[1] ) { $retval = new_from_file(@_); } elsif (@_ == 3 && (ref($_[2]) eq "ARRAY") && ref($_[2]->[0]) eq "Net::DNS::RR::RRSIG" && (ref($_[1]) eq "ARRAY") && ref($_[1]->[0]) eq "Net::DNS::RR::DNSKEY" ) { $retval = new_from_keys_sigs(@_); }elsif (@_ >= 2 && (ref($_[1]) eq "ARRAY") && ref($_[1]->[0]) eq "Net::DNS::RR::DNSKEY" ) { $retval = new_from_keys(@_); }elsif ( @_ == 2 && ref($_[1]) eq "Net::DNS::Packet" ){ $retval = new_from_packet(@_); }else{ $keyset_err="Could not parse argument"; return(0); } return $retval; } =head2 new (from file) $keyset=Net::DNS::Keyset->new("keyset-example.tld"); Creator method, will read the specified keyset file and return a keyset object. Fails if not all keys in the set are self-signed. Sets $Net::DNS::Keyset::keyset_err and returns 0 on failure. =cut sub new_from_file { my $class=shift; my $keysetfile=shift; $keyset_err="No Error"; my $TTL; croak "need keysetfile as argumnt" if ! $keysetfile; open(KEYSET, $keysetfile) # get sort's results || croak "Can't open $keysetfile for input: $!"; my $currentorigin; my $buffer=""; my $previouslabel; my @keys; my $k=0; my @sigs; my $s=0; my %names; # We now read the keyset as if it is a (bind) zone file. # To be #able to read the individual RRs into RR-objects we # have to fill #in the information that was conveniently left out # of the zone #file to make it more readable for us humans. # # This is code I reused. There is a whole chunk of code for dncame # completion for RR types other than DNSKEY and RRSIG. That may be # usefull # if you want to reuse the code for writing a zone # parser while (){ s/;.*//; # Remove comments next if /^\s*$/ ; if (!$TTL && /^\s*\$TTL\s+(\d+)/){ $TTL=$1; print ";; TTL found : ". $TTL ."\n" if $debug; next; } # replace the @ by the ORIGIN.. as given by the argument. s/@/$currentorigin/; # Set the current originin. This is the one from the $ORINIGIN value from # the zone file. It will be used to complete labels below. if ( /^\s*\$ORIGIN\s+(\S+)\s*$/){ $currentorigin=$1; print ";; currentorigin set to : ". $currentorigin ."\n" if $debug; next; } # Join multilines to one line if ( $buffer ne ""){ if (s/\)//) { $buffer.=$_; $_=$buffer; $buffer=""; s/\s+(\s)/$1/g; }else{ chop; $buffer.=$_; next; } }elsif (s/\(//) { chop; $buffer.=$_; next; } s/\s+/ /g; #Single spaces .. eases future matching s/ $//; #strips trailing space, that got introduced by the previous... # Use the previoous label if no label was qualified (line starts with blanks) if (/^(\S+) /){ $previouslabel=$1; }else{ $_ = $previouslabel . $_; } # Now we have # label optional TTL optional ClASS and QTYPE and RDATA # If the TTL and CLASS are not there we'll add them. Besides we'll # look at the QTYPE and may take some action to RDATA depending on that. { #LOCALIZE SOME VARIABLES my $label; my $ttl=$TTL; my $class='IN'; # We only considder IN my $rtype=''; my $rdata=''; my $prefix=''; # It should be easier to do this.... s/^(\S+) / /; # remove the label to put it back fully quallified if ($1){ $label=$1; _complete_dname($label,$currentorigin); $_ = $label . $_; print ";; read LABEL: " . $label ."\n" if $debug>2 ; }else{ croak "Couldnt match label in read method while reading\n". $_ . " \nthis Should not happen\n"; } # See if there is a TTL value, if not insert one if (/^\S+. (\d+)/) { print ";; TTL : " . $1. "\n" if $debug>2 ; $ttl=$1; }else { # instert default TTL s/^(\S+) (.*)$/$1 $ttl $2/; } # See if there is the CLASS is defined, if not insert one. if(! /^\S+ \d+ (IN)/){ #insert IN s/^(\S+ \d+ )(.*)$/$1IN $2/; } # We have everything specified.. We now get the RTYPE AND RDATA... /^\S+ \d+ IN (\S+) (.*)$/; if ($1) { print ";; rtype: " . $1 ."\n" if $debug>2 ; $rtype=$1; }else{ croak " We expected to match an RTYPE\n". $_ . " \nthis Should not happen\n"; } if ($2) { $rdata=$2; print ";; rdata:-->" . $rdata ."<---\n" if $debug>3 ; }else{ croak " We expected a match RDATA\n". $_ . " \nthis Should not happen\n"; } $prefix=$label." ".$ttl." IN ".$rtype." "; } #END LOCALIZATION print ";; " . $_ . "\n" if $debug>2; # The sting in $_ now contains a one-line RRset. We now turn it into # RR object. my $rr=Net::DNS::RR->new($_); if ($rr->type eq "DNSKEY") { $keys[$k++]=$rr; $names{$rr->name}=1; }elsif ($rr->type eq "RRSIG") { $sigs[$s++]=$rr; $names{$rr->name}=1; }else{ $keyset_err= "WARNING the following RR was found in a keyset and is not expected there\n". $rr->string; return(0); } } if ((keys %names )!=1){ $keyset_err = "Different names in the keyset: ". join ( " ",(keys %names))."\n"; return 0; } # @keys_and_sigs contains all keys and sigs from the RRset. my $ks; my $keyset; $keyset= { keys => [ @keys ], sigs => [ @sigs ], }; bless $ks= $keyset, $class; return 0 if (! $ks->verify); return $ks; } =head2 new (by signing keys) $keyset=Net::DNS::Keyset->new(\@keyrr,$privatekeypath); Creates a keyset object from the keys provided through the reference to an array of Net::DNS::RR::Key objects. The method will create selfsign the whole keyset. The private keys as generated by the BIND dnssec-keygen tool are assumed to be in the current directory or, if specified, in the directory indicat by the $privatekeypath. Sets $Net::DNS::Keyset::keyset_err and returns 0 on failure. =cut sub new_from_keys { my $class=shift; my $keyrr_ref=shift; my $privatekeypath=shift; $keyset_err="No Error"; if ( defined $privatekeypath ){ $privatekeypath =~ s!\/*\s*$!! ; #strip trailing spaces and slashes if (! -d $privatekeypath){ $keyset_err= "The file " . $privatekeypath . " could not be found\n"; return 0; } }else{ $privatekeypath=cwd; } my $key; my $privatekey; my @sigrr; my @keyrr; foreach $key (@{$keyrr_ref}){ my $privkey= $privatekeypath."/".$key->privatekeyname; if (! -r $privkey){ $keyset_err= "private key ".$privkey. "could not be found"; return 0; } my $sig=Net::DNS::RR::RRSIG->create($keyrr_ref,$privkey); push @sigrr, $sig; push @keyrr, $key; } my $ks; my $keyset= { keys => [ @keyrr ], sigs => [ @sigrr ], }; bless $ks= $keyset, $class; return 0 if (! $ks->verify); return $ks; } =head2 new (from keys and sig RRsets) $keyset=Net::DNS::Keyset->new(\@keyrr,\@sigrr); Creates a keyset object from the keys provided through the reference to an array of Net::DNS::RR::DNSKEY and Net::DNS::RR::RRSIG objects. Sets $Net::DNS::Keyset::keyset_err and returns 0 on failure. =cut sub new_from_keys_sigs{ my $class=shift; my $keyrr_ref=shift; my $sigrr_ref=shift; my @sigrr; my @keyrr; foreach my $key (@{$keyrr_ref}){ push @keyrr, $key; } foreach my $sig (@{$sigrr_ref}){ push @sigrr, $sig; } my $ks; my $keyset= { keys => [ @keyrr ], sigs => [ @sigrr ], }; bless $ks= $keyset, $class; return 0 if (! $ks->verify); return $ks; } =head2 new (from Packet) $res = Net::DNS::Resolver->new; $res->dnssec(1); $packet = $res->query ("example.com", "DNSKEY", "IN"); $keyset=Net::DNS::Keyset->new($packet) die "Corrupted selfsignature " if ! $keyset->verify; Creates a keyset object from a Net::DNS::Packet that contains the answer to a query for the apex key records. This is the method you want to use for automatically fetching keys. Sets $Net::DNS::Keyset::keyset_err and returns 0 on failure. =cut sub new_from_packet { my $class=shift; my $packet=shift; my @sigrr; my @keyrr; $keyset_err="No Error"; if (ref ($packet) ne "Net::DNS::Packet"){ $keyset_err="Input is not a Net::DNS::Packet" ; return (0); } # All the information is in the answer section. # We expect keys and signatures there. foreach my $rr ($packet->answer){ if ($rr->type eq "RRSIG"){ push @sigrr, $rr; } elsif ($rr->type eq "DNSKEY") { push @keyrr, $rr ; }else{ $keyset_err = "Unexpected RR in the answer section of the packet:\n". $rr->string."\n"; return (0); } } my $ks; my $keyset= { keys => [ @keyrr ], sigs => [ @sigrr ], }; bless $ks= $keyset, $class; return 0 if (! $ks->verify); return $ks; } =head2 keys @keyrr=$keyset->keys; Returns an array of Net::DNS::RR::Key objects =cut sub keys { my $self=shift; return @{$self->{'keys'}}; } =head2 sigs @keyrr=$keyset->sigs; Returns an array of Net::DNS::RR::Sig objects =cut sub sigs { my $self=shift; return @{$self->{'sigs'}}; } =head2 verify die $Net::DNS::Keyset::keyset_err if $keyset->verify; If no arguments are given: - Verifies if all signatures present verify the keyset. - Verifies if there are DNSKEYs with the SEP flag set there is at least one RRSIG made using that key - Verifies that if there are no DNSKEYS with the SEP flag set there is at lease one RRSIG made with one of the keys from the keyset. If an argument is given it is should be the KEYID of one of the keys in the keyset and the method verifies if the the RRSIG with that made with that key verifies. The argument returns 0 if verification fails and sets $Net::DNS::Keyset::keyset_err. If verification succeeds an array is returne with the key-tags of the keys for which signatures verified. =cut sub verify { my $self=shift; my $keyid=shift; my $key; my $sig; my $one_sep_key_found=0; my $one_sep_key_validated=0; my $one_key_validated=0; my $key_id_found=0; my @tags_verified=(); KEY: foreach $key ($self->keys) { $one_sep_key_found=1 if $key->is_sep; foreach $sig ($self->sigs) { print "Checking: " . $key->name .":". $key->keytag . ($key->is_sep?"(SEP)":"") . "---" . $sig->signame .":". $sig->keytag . "\n" if $debug; if ($key->keytag == $sig->keytag && $key->name."." eq $sig->signame."." ){ print "...\n" if $debug; my @keys=$self->keys ; if (! $sig->verify( \@keys , $key)){ $keyset_err="" if ($keyset_err eq "No Error"); $keyset_err .= $sig->vrfyerrstr. " on key ". $key->name. " ".$key->keytag ." "; # If we did supply an argument we want to fail if # the signature made with that keytag failed. if (defined $keyid && $sig->keytag == $keyid ){ $keyset_err= "Signature made with $keyid did not validate"; return 0; } # If we did not supply an argument we want to fail if any # of the signatures failed return 0 if (! defined $keyid); next KEY; } push @tags_verified, $key->keytag; # past verification $one_key_validated=1; $one_sep_key_validated=1 if $key->is_sep; $key_id_found=1 if (defined $keyid && $key->keytag == $keyid ); print "verified " .$key->keytag."\n" if $debug; } } } if ($one_sep_key_found && ! $one_sep_key_validated){ $keyset_err= "One key had the SEP flag set but non of the keys had a signature"; return 0; }elsif( ! $one_key_validated ){ $keyset_err= "None of the keys in the keyset had a signature"; return 0; }elsif ( defined($keyid) && ! $key_id_found ){ $keyset_err= "No signature made with $keyid found"; return 0; } @tags_verified = ($keyid) if defined ($keyid); return @tags_verified; } =head2 print $keyset->print; Prints the keyset =head2 string $keysetstring=$keyset->string; Returns a string representation of the keyset print $keyset->string; is similar to $keyset->print; =cut sub string { my $self=shift; my $string; foreach my $rr ($self->keys,$self->sigs){ $string .= $rr->string ."\n"; } return $string; } sub print { my $self=shift; print $self->string; } =head2 extract_ds @ds=$keyset->extract_ds; foreach $ds (@ds) { $ds->print; } Extracts DS records from the keyset. Note that the keyset will be verified during extraction: All keys will need to have a valid selfsignature. =cut sub extract_ds { my $self=shift; $keyset_err="No error"; my @ds; return (0) if (! $self->verify); foreach my $rr ($self->keys){ my $ds=Net::DNS::RR::DS->create($rr); push @ds, $ds; } return (@ds); } =head2 writekeyset die $Net::DNS::Keyset::keyset_err if ! $keyset->writekeyset($prefix, $path); Writes the keyset to a file named "keyset-." in the current working directory or the directory defined by $path. $prefix specifies an optional prefix that will be prepended to the string "keyset-." Returns 0 on failure and sets keyset_err. =cut sub writekeyset { my $self=shift; my $prefix=shift; my $keysetpath=shift; $keyset_err="No Error"; my $domainname=$self->{'keys'}->[0]->name; if ( defined $keysetpath ){ $keysetpath =~ s!\/*\s*$!! ; #strip trailing spaces and slashes if (! -d $keysetpath){ $keyset_err= "Directory " . $keysetpath . " could not be found\n"; return 0; } }else { $keysetpath=cwd; } my $keysetname="$keysetpath/$prefix" . "keyset-$domainname."; if (! open(KEYSET,"> $keysetname") ){ $keyset_err= " Could not open $keysetname for writing"; return 0; } print KEYSET $self->string; return (1); } sub _complete_dname { my $dname=shift; my $origin=shift; if ( $dname !~ /\.$/ ){ # breaks if a label ends in an escapped \. # Is that allowed? $dname .= ".".$origin; } return $dname; } 1; __END__ =head1 COPYRIGHT Copyright (c) 2002 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. =cut Net-DNS-SEC-0.16/Makefile.PL000644 000765 000120 00000004043 11346437006 015245 0ustar00olafadmin000000 000000 # # $Id: Makefile.PL 728 2008-10-12 09:02:24Z olaf $ # warn < 'Net::DNS::SEC', 'VERSION_FROM' => 'SEC.pm', 'PREREQ_PM' => { Net::DNS => 0.64, Test::More => 0.47, Crypt::OpenSSL::RSA => 0.19, Crypt::OpenSSL::Bignum => 0.03, Crypt::OpenSSL::DSA => 0.10, Digest::SHA => 5.23, File::Basename => 0.0, MIME::Base64 => 0.0, MIME::Base32 => 0.0, Math::BigInt => 0.0, Time::Local => 0.0, Digest::BubbleBabble => 0.01, Digest::SHA1 => 0.0, }, 'ABSTRACT' => 'DNSSEC extensions to Net::DNS', 'AUTHOR' => 'Olaf M. Kolkman ', 'PM' => { 'Keyset.pm' => '$(INST_LIBDIR)/Keyset.pm', 'SEC.pm' => '$(INST_LIBDIR)/SEC.pm', 'SEC/Private.pm' => '$(INST_LIBDIR)/SEC/Private.pm', 'RR/DS.pm' => '$(INST_LIBDIR)/RR/DS.pm', 'RR/DLV.pm' => '$(INST_LIBDIR)/RR/DLV.pm', 'RR/NXT.pm' => '$(INST_LIBDIR)/RR/NXT.pm', 'RR/KEY.pm' => '$(INST_LIBDIR)/RR/KEY.pm', 'RR/SIG.pm' => '$(INST_LIBDIR)/RR/SIG.pm', 'RR/RRSIG.pm' => '$(INST_LIBDIR)/RR/RRSIG.pm', 'RR/DNSKEY.pm' => '$(INST_LIBDIR)/RR/DNSKEY.pm', 'RR/NSEC.pm' => '$(INST_LIBDIR)/RR/NSEC.pm', 'RR/NSEC3.pm' => '$(INST_LIBDIR)/RR/NSEC3.pm', 'RR/NSEC3PARAM.pm' => '$(INST_LIBDIR)/RR/NSEC3PARAM.pm', }, clean => {FILES => "*~ t/keyset-*"} ); sub MY::libscan { my $path = $_[1]; return '' if $path =~ /\B\.svn\b/; return $path; } Net-DNS-SEC-0.16/MANIFEST000644 000765 000120 00000001125 11346437006 014422 0ustar00olafadmin000000 000000 Changes demo/getkeyset.pl demo/key2ds demo/make-signed-keyset Keyset.pm Makefile.PL MANIFEST This list of files META.yml README RR/DNSKEY.pm RR/DS.pm RR/KEY.pm RR/NSEC.pm RR/NSEC3.pm RR/NSEC3PARAM.pm RR/NXT.pm RR/RRSIG.pm RR/SIG.pm RR/DLV.pm SEC.pm SEC/Private.pm t/00-load.t t/00-pod.t t/01-parse.t t/07-sec.t t/09-dnssec.t t/10-keyset.t t/10-typeroll.t t/11-sep.t t/11-sigstress.t t/12-nsec++.t t/13-utilities.t t/14-misc.t t/15-ds.t t/16-dlv.t t/getpacket.pl t/Kexample.com.+001+28551.private t/Kexample.com.+001+28551.key t/Kexample.com.+005+34247.key t/Kexample.com.+005+34247.private TODO Net-DNS-SEC-0.16/META.yml000644 000765 000120 00000001552 11346437115 014547 0ustar00olafadmin000000 000000 --- #YAML:1.0 name: Net-DNS-SEC version: 0.16 abstract: DNSSEC extensions to Net::DNS author: - Olaf M. Kolkman license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 requires: Crypt::OpenSSL::Bignum: 0.03 Crypt::OpenSSL::DSA: 0.1 Crypt::OpenSSL::RSA: 0.19 Digest::BubbleBabble: 0.01 Digest::SHA: 5.23 Digest::SHA1: 0 File::Basename: 0 Math::BigInt: 0 MIME::Base32: 0 MIME::Base64: 0 Net::DNS: 0.64 Test::More: 0.47 Time::Local: 0 no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.48 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 Net-DNS-SEC-0.16/README000644 000765 000120 00000013760 11346437006 014161 0ustar00olafadmin000000 000000 Net::DNS::SEC - DNSSEC extensions to Net::DNS ============================================= IMPORTANT UPGRADE NOTE. Please always read the Changes file. It is accessible through: http://search.cpan.org/src/OLAF/Net-DNS-SEC/Changes 1. GENERAL INFO. This module implements DNS Resource Record types that are relevant for DNSSEC operations. This package implements RFC4034 "Resource Records for the DNS Security Extensions" and RFC2931 "DNS Request and Transaction Signatures ( SIG(0)s )" RFC 3225 (Indicating Resolver Support of DNSSEC) support has been is available Net::DNS. The extensions provide the following additional features on top of the Net::DNS package (http://www.net-dns.org/). - DS, RRSIG, DNSKEY and NSEC records. These are all implemented as RR objects. The cryptography has been implemented using Crypt::OpenSSL::DSA, Crypt::OpenSSL::RSA and related modules. The reason for not making these RRs a part of the regular Net::DNS distribution is that they rely on crypto modules that do not easily port. The DNSSEC protocol is a moving target. Follow the IETF DNSEXT working group if you are interested in the protocol developments. We try to keep the code in sync with the development. Also see the 'pod' documentation in: Net::DNS::RR::DNSKEY Net::DNS::RR::RRSIG Net::DNS::SEC::Private Net::DNS::RR::NSEC Net::DNS::RR::DS and for the use of SIG0 see: Net::DNS::Packet (sign_sig0) Net::DNS::RR::SIG Net::DNS::SEC::Private Net::DNS::RR::KEY On top of the RR classes defined above we also provide a class for handling keysets. Keysets are administrative files used by the BIND tools for keymaintenance tasks. Net::DNS::Keyset provides an abstract interface for doing fun things with them. 2. Dependencies This package relies on Net-DNS version 0.27 or higher (also see CHANGES). since that contains a number of place holders for Net::DNS::SEC functionality. Among other straightforward routines you will need to have Crypt::OpenSSL::DSA and Crypt::OpenSSL::RSA installed. The package was initially developed on FreeBSD 4.5 with perl5.6.1, as of version 0.11 development and testing where done on MacOS 10.2.6 with perl, v5.8.0 built for darwin. 3. Install Use CPAN. perl -MCPAN -e shell; cpan> install Net::DNS::SEC Alternatively install this package manually: tar -xvzf Net-DNS-SEC-??.tar.gz cd Net-DNS-SEC-??.tar.gz perl Makefile.PL make make test make install 'perl Makefile.PL' will test if all dependencies are in place. 'make test' will do some tests that should all succeed once all dependencies are satisfied. Please report failures during the test phase. 4. Maintenance Please use the CPAN request tracker if you find bugs in the extensions or have DNSSEC feature request. The request tracker is available through: https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-DNS-SEC Net::DNS contains a number of hooks for Net::DNS::SEC in the Net::DNS package. If you have problems with Net::DNS in general see: http://www.net-dns.org/ A snapshot of the development code is available through subversion: http://www.net-dns.org/svn/net-dns-sec/trunk Note that the code on the trunk may not be functional. 5. Staying up to date. Announcements about Net::DNS::SEC will be done on http://www.net-dns.net/blog/. An RSS feed is available. 6. Demos demo/getkeyset.pl - is a small demonstration program that will get fetch the keyset for a specified domain, stores them and prints out the DS RRs to STD out. demo/make-signed-keyset - A script contributed by Wes Griffin creates a self-signed keyset from a BIND public key file specified on the command line. demo/key2ds - reads the key data from STDIN and print the corresponding DS record on STDOUT. Contributed by Miek Gieben 7. History The modules in this package have somewhat of a history as a set of patches to the original Net::DNS package. Version 0.02 is the first distribution of the DNSSEC security for CPAN. See the Changes file for more information. 8. Acknowledgements Thanks to the numerous folk that took an interest during development. People that contributed to bug fixes should be acknowledged in the Changes file. If I forgot to mention you there it is not out of bad intention. Thanks to Chris Reinardt for putting the hooks in Net::DNS and suggesting some improvements to the package. Thanks Ian Robertson and T.J. Mather for their support with the Crypt::OpenSSL::[RSA|DSA] modules. 9. Author information Olaf M. Kolkman, RIPE NCC. support: olaf@net-dns.org 10. COPYRIGHT Copyright Notice and Disclaimer Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997-2001 Michael Fuhr. ------------------------------------------------------------------------------ $Id: README 359 2005-06-06 13:54:18Z olaf $ Net-DNS-SEC-0.16/RR/000755 000765 000120 00000000000 11346437114 013615 5ustar00olafadmin000000 000000 Net-DNS-SEC-0.16/SEC/000755 000765 000120 00000000000 11346437114 013704 5ustar00olafadmin000000 000000 Net-DNS-SEC-0.16/SEC.pm000644 000765 000120 00000020576 11346437071 014256 0ustar00olafadmin000000 000000 # # $Id: SEC.pm 850 2010-03-12 13:14:33Z olaf $ # use strict; package Net::DNS::SEC; use Net::DNS; use bytes; use Carp; use strict; use Exporter; use vars qw($SVNVERSION $VERSION $HAS_NSEC3 $HAS_DLV @EXPORT_OK @ISA); @ISA=qw(Exporter); $VERSION = '0.16'; $HAS_DLV=1; # Signals availability of DLV to Net::DNS::RR $HAS_NSEC3=1; # Signals availability of NSEC3 to Net::DNS::RR $SVNVERSION = (qw$LastChangedRevision: 850 $)[1]; @EXPORT_OK= qw ( key_difference verify_selfsig ); =head1 NAME Net::DNS::SEC - DNSSEC extensions to Net::DNS =head1 SYNOPSIS C The Net::DNS::SEC module implements a few class methods used by the other modules in this suite and a few functions that can be exported. =head1 DESCRIPTION The Net::DSN::SEC suite provides the resource records that are needed for DNSSEC (RFC 4033, 4034 and 4035). In addition the DLV RR, a clone of the DS RR is supported (RFC 4431) It also provides support for SIG0. That later is useful for dynamic updates using key-pairs. RSA and DSA crypto routines are supported. For details see L, L, L, L, L, and see L and L for the use with SIG0. Net::DNS contains all needed hooks to load the Net::DNS::SEC extensions when they are available. See L for general help. =head1 Utility function Use the following construct if you want to use thos function in your code. use Net::DNS::SEC qw( key_difference ); =head2 key_difference $result=key_differnece(\@a,\@b,\@result); Fills @result with all keys in the array "@a" that are not in the array "@b". Returns 0 on success or an error message on failure. =cut sub key_difference { my $a=shift; my $b=shift; my $r=shift; my %b_index; foreach my $b_key (@$b){ return "Second array contains something different than a ". "Net::DNS::RR::DNSKEY objects (".ref($b_key).")" if ref($b_key) ne "Net::DNS::RR::DNSKEY"; $b_index{$b_key->name."+".$b_key->algorithm."+".$b_key->keytag}++; } foreach my $a_key (@$a){ return "First array contains something different than a ". "Net::DNS::RR::DNSKEY objects (".ref($a_key).")" if ref($a_key) ne "Net::DNS::RR::DNSKEY"; push @$r,$a_key unless defined ($b_index{$a_key->name."+".$a_key->algorithm."+".$a_key->keytag}); } return (0); } =head1 Class methods These functions are inherited by relevant Net::DNS::RR classes. They are not exported. =head2 algorithm $value=Net::DNS::SEC->algorithm("RSASHA1"); $value=$self->algorithm("RSASHA1"); $value=$self->algorithm(5); $algorithm=$self->algorithm(); $memonic=$self->algorithm("mnemonic"); The algorithm method is used to set or read the value of the algorithm field in Net::DNS::RR::DNSKEY and Net::DNS::RR::RRSIG. If supplied with an argument it will set the algorithm accordingly, except when the argument equals the string "mnemonic" the method will return the mnemonic of the algorithm. Can also be called as a class method to do Mnemonic to Value conversion. =head2 digtype $value=$self->digtype("SHA1"); $value=$self->digtype(1); $algorithm=$self->digtype(); $memonic=$self->digtype("mnemonic"); The algorithm method is used to set or read the value of the digest or hash algorithm field in Net::DNS::RR::DS and Net::DNS::RR::NSEC3 objects. If supplied with an argument it will set the digetstype/hash algorithm accordingly, except when the argument equals the string "mnemonic" the method will return the mnemonic of the digetstype/hash algorithm. Can also be called as a class method to do Mnemonic to Value conversion, note however that it will then use the "Delegation Signer (DS) Resource Record (RR) Type Digest Algorithms" and not the "DNSSEC NSEC3 Hash Algorithms" IANA registry. If you want to specifically get access to the NSEC3 digest types then use a construct like: bless $self, Net::DNS::RR::NSEC3; $self->digtype("SHA1"); =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. =head1 SEE ALSO L L, L, L, L, L, L, L, L, L. RFC4033, 4034 and 4035. =cut sub algorithm { my $self=shift; my $argument=shift; # classmethod is true if called as class method. my $classmethod=0; $classmethod=1 unless ref ($self); my %algbyname = ( "RSAMD5" => 1, "DH" => 2, # Not implemented "DSA" => 3, "ECC" => 4, # Not implemented "RSASHA1" => 5, "DSA-NSEC3-SHA1" => 6, "RSA-NSEC3-SHA1" => 7, "RSASHA256" => 8, "RSASHA512" => 10, "INDIRECT" => 252, # Not implemented "PRIVATEDNS" => 253, # Not implemented "PRIVATEOID" => 254, # Not implemented ); my %algbyval = reverse %algbyname; # If the argument is undefined... if (!defined $argument){ return if $classmethod; return $self->{"algorithm"}; } # Argument has some value... $argument =~ s/\s//g; # Remove strings to be kind $argument =~ s!RSA/!RSA!; # Be kind for those who use RSA/SHA1 if ($argument =~ /^\d+$/ ){ #Numeric argument. if ($classmethod){ return $argument ; }else{ return $self->{"algorithm"}=$argument ; } }else{ # argument is not numeric if ($classmethod){ # This will return undefined if the argument does not exist return $algbyname{uc($argument)}; }else{ # Not a class method.. if (lc($argument) eq "mnemonic"){ return $algbyval{$self->{"algorithm"}}; }else{ # This will return undefined if the argument does not exist return $self->{"algorithm"}=$algbyname{uc($argument)}; } } } die "algorithm method should never end here"; } sub digtype { _digtype(@_); } sub _digtype { my $self=shift; my $argument=shift; # classmethod is true if called as class method. my $classmethod=0; $classmethod=1 unless ref ($self); my %digestbyname= ( "SHA1" => 1, "SHA256" => 2, ); if (! $classmethod && defined ($self->{'digestbyname'}) ){ %digestbyname= %{$self->{"digestbyname"}}; } my %digestbyval = reverse %digestbyname; # If the argument is undefined... if (!defined $argument){ return if $classmethod; return $self->{"digest"}; } # Argument has some value... $argument =~ s/\s//g; # Remove strings to be kind if ($argument =~ /^\d+$/ ){ #Numeric argument. carp "$argument does not map to a valid digest" unless exists $digestbyval{$argument}; if ($classmethod){ return $argument ; }else{ return $self->{"digest"}=$argument ; } }else{ # argument is not numeric if ($classmethod){ carp "$argument does not map to a valid digest" unless exists $digestbyname{uc($argument)}; return $digestbyname{uc($argument)}; }else{ # Not a class method.. if (lc($argument) eq "mnemonic"){ return $digestbyval{$self->{"digest"}}; }else{ carp "$argument does not map to a valid digest" unless exists $digestbyname{uc($argument)}; return $self->{"digest"}=$digestbyname{uc($argument)}; } } } die "digest method should never end here"; } Net-DNS-SEC-0.16/t/000755 000765 000120 00000000000 11346437114 013535 5ustar00olafadmin000000 000000 Net-DNS-SEC-0.16/TODO000644 000765 000120 00000000345 11346437006 013764 0ustar00olafadmin000000 000000 TODO for Net::DNS::SEC package. ---------------------------------------------------------------------- Last modified for version 0.12_1 ---------------------------------------------------------------------- - Code cleanup Net-DNS-SEC-0.16/t/00-load.t000644 000765 000120 00000004456 11346437006 015067 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for loading parser and zonemodules # $Id: 00-load.t 778 2008-12-30 17:19:35Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/ # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### We start with some black magic to print on failure. use Test::More tests=>2; use strict; #use Data::Dumper; BEGIN {use_ok('Net::DNS::SEC', qw(key_difference verify_selfsig)); } # test 1 require_ok('Net::DNS::SEC'); diag("\nThese tests were ran with:\n"); diag("Net::DNS::VERSION: ". $Net::DNS::VERSION); diag("Net::DNS (SVN) Version " .$Net::DNS::SVNVERSION); diag("Net::DNS::SEC::VERSION: ". $Net::DNS::SEC::VERSION); diag("Net::DNS::SEC::SVNVERSION: ". $Net::DNS::SEC::SVNVERSION); diag("Net::DNS::RR::RRSIG::VERSION: ". $Net::DNS::RR::RRSIG::VERSION); diag("Net::DNS::RR::DNSKEY::VERSION: ". $Net::DNS::RR::DNSKEY::VERSION); diag("Net::DNS::RR::NSEC::VERSION: ". $Net::DNS::RR::NSEC::VERSION); diag("Net::DNS::RR::NSEC3::VERSION: ". $Net::DNS::RR::NSEC3::VERSION); diag("Net::DNS::RR::NSEC3PARAM::VERSION: ". $Net::DNS::RR::NSEC3PARAM::VERSION); diag("Net::DNS::RR::DS::VERSION: ". $Net::DNS::RR::DS::VERSION); diag("Net::DNS::RR::DLV::VERSION: ". $Net::DNS::RR::DLV::VERSION); diag("Crypt::OpenSSL::DSA::VERSION: ". $Crypt::OpenSSL::DSA::VERSION); diag("Crypt::OpenSSL::RSA::VERSION: ". $Crypt::OpenSSL::RSA::VERSION); diag("Crypt::OpenSSL::Bignum::VERSION: ". $Crypt::OpenSSL::Bignum::VERSION); diag("Net::DNS::SEC::Private::VERSION: ". $Net::DNS::SEC::Private::VERSION); diag("File::Basename::VERSION: ". $File::Basename::VERSION); diag("MIME::Base64::VERSION: ". $MIME::Base64::VERSION); diag("MIME::Base32::VERSION: ". $MIME::Base32::VERSION); diag("Math::BigInt::VERSION: ". $Math::BigInt::VERSION); diag("Time::Local::VERSION: ". $Time::Local::VERSION); diag("Digest::SHA::VERSION: ". $Digest::SHA::VERSION); Net-DNS-SEC-0.16/t/00-pod.t000644 000765 000120 00000000720 11346437006 014720 0ustar00olafadmin000000 000000 # $Id: 00-pod.t 813 2009-11-27 09:10:10Z olaf $ use Test::More; use File::Spec; use File::Find; use strict; eval "use Test::Pod 0.95"; if ($@) { plan skip_all => "Test::Pod v0.95 required for testing POD"; } else { Test::Pod->import; my @files; my $blib = File::Spec->catfile(qw(blib lib)); find( sub { push(@files, $File::Find::name) if /\.p(l|m|od)$/}, $blib); plan tests => scalar @files; foreach my $file (@files) { pod_file_ok($file); } } Net-DNS-SEC-0.16/t/01-parse.t000644 000765 000120 00000003367 11346437006 015263 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw -*-perl-*- use Test::More tests=>5; use strict; BEGIN { use_ok('Net::DNS'); } # test 1 my $RR=Net::DNS::RR->new("example.com IN DS 42495 RSASHA1 1 0ffbeba0831b10b 8b83440dab81a2148576da 9f6"); my $string=$RR->string; $string=~ s/\s+/ /g; is($string, 'example.com. 0 IN DS 42495 5 1 0ffbeba0831b10b8b83440dab81a2148576da9f6 ; xefoz-rupop-babuc-rugor-mavef-gybot-puvoc-pumig-mahek-tepaz-kixox', "Correct parsing of DS RR RSASHA1 MNEMONIC"); undef $RR; $RR=Net::DNS::RR->new("example.com IN DS 42495 RSASHA1 SHA1 0ffbeba0831b10b 8b83440dab81a2148576da 9f6"); $string=$RR->string; $string=~ s/\s+/ /g; is($string, 'example.com. 0 IN DS 42495 5 1 0ffbeba0831b10b8b83440dab81a2148576da9f6 ; xefoz-rupop-babuc-rugor-mavef-gybot-puvoc-pumig-mahek-tepaz-kixox', "Correct parsing of DS RR (SHA1 MNEMONIC)"); diag("Ignore the two error messages"); undef $RR; $RR=Net::DNS::RR->new("example.com IN DS 42495 RSASHA1 FOOO 0ffbeba0831b10b 8b83440dab81a2148576da 9f6"); ok(! defined($RR),"string not parsed (digest mnemonic FOO)"); undef $RR; $RR=Net::DNS::RR->new("example.com IN DS 42495 FOOO 1 0ffbeba0831b10b 8b83440dab81a2148576da 9f6"); ok(! defined($RR),"string not parsed (algorithm mnemonic FOO)"); Net-DNS-SEC-0.16/t/07-sec.t000644 000765 000120 00000012265 11346437006 014726 0ustar00olafadmin000000 000000 # Test script for dnssec functionalty -*-perl-*- # $Id: 07-sec.t 847 2010-03-12 13:04:13Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/07-sec.t use Test::More tests=>23; use strict; use MIME::Base64; use Data::Dumper; BEGIN { use_ok('Net::DNS::SEC::Private'); } # test 1 diag ("Testing the algorithm method"); is (Net::DNS::SEC->algorithm("DSA"),3,"Class method parses DSA"); is (Net::DNS::SEC->algorithm("DsA"),3,"Class method parses DsA"); is (Net::DNS::SEC->algorithm("RSASHA1"),5,"Class method parses RSASHA1"); is (Net::DNS::SEC->algorithm("RSAMD5"),1,"Class method parses RSAMD5"); diag ("Do not worry about the warning"); is (Net::DNS::SEC->algorithm("CRYPTSAM"),undef,"Class method returns undef with CRYPTSAM"); ok (my $keyrr=Net::DNS::RR->new("test.tld. IN DNSKEY 256 3 1 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w=="),"Key succesfully created"); is( $keyrr->algorithm,1,"DNSKEY with numeric specification of the RR read from string"); ok (my $keyrr2=Net::DNS::RR->new("test.tld. IN DNSKEY 256 3 RSAMD5 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w=="),"Key succesfully created"); is( $keyrr2->algorithm,1,"DNSKEY with string specification of the RR read from string"); is ($keyrr2->algorithm("mnemonic"),"RSAMD5","mnemonic works as argument"); # This keyblob represents t/Kexample.com.+005+34247.private; # using 'openssl rsa -modulus', 'openssl rsa -text' I double # checked if the values reported by openssl and those in the file # are consistent. my $keyblob="-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCqyylc732/AE42mlUE3g44JS3O4tdvUwOK3lwpQ/xOJX6gFLEg /SRK36FXnXqbJzkqCkwVrCgbA2SM63axme57vbbnppljuiCKf6rxZE2602YhOLPd sw+1nRRyHZ8fPv761H8bPS9Zcx3IQyE33l1B+tPN9MtQus6fcsQy2tIwuwIBAwKB gHHcxj30/n9ViXm8OK3pXtAYyTSXOko3V7HpksYtUt7DqcANy2tTbYc/wOUTpxIa JhwG3WPIGrys7bNHpHZmnvwSTuZCYv7G6X9fG29P4HMMp4DvMlLRYcwoqcxax8DN 4XG/jBN/tfTkgUzO9sMtP6SDGsegTRER8WsYH3Ysg0L7AkEA1GAZ1v3tA96l2os1 enQEtINZ/Q2IHsd7Rr32qaTAS9qtTT5DQJKFvTA36+6+UiZ/0OxUaH2VECpuMHvh 3vz8xQJBAM3gdGwG+IvjpZZ2lPIJCYvnhdTa2Vo1iBlXyOvOvb5SIufuur0L5F8r nSDAVMhXS2U/ThvaIg+6EJ4ZH7kQT38CQQCNlWaPU/NX6cPnB3j8TVh4V5FTXlq/ L6eEfqRxGIAykcjeKYIrDFkoys/ynymMGaqLSDhFqQ4KxvQgUpaUqKiDAkEAiUBN nVn7B+0ZDvm4oVtbsppZOJHmPCOwEOUwnTR+fuFsmp8nKLKYP3JowIA4hY+HmNTe vTwWtSa1vrtqe2A0/wJAOGDWYhImmtzR/wYJyBliYPnn5fbMS/B9eL+PWC0+whBQ A5WkPqeImlJKkr7oWZE+VmuxicpW2VPVacMQYsV3dg== -----END RSA PRIVATE KEY----- "; my $privkeyfilename="t/Kexample.com.+005+34247.private"; my $pubkeyfilename="t/Kexample.com.+005+34247.key"; my $rsakey=Net::DNS::SEC::Private->new($privkeyfilename); my $privkey; my $pubkey; my $rsakeyfromder=Net::DNS::SEC::Private->new_rsa_priv($rsakey->dump_rsa_private_der); is ($rsakey->dump_rsa_private_der,$rsakeyfromder->dump_rsa_private_der, "Consistent DER parsing"); is ($rsakey->dump_rsa_private_der,$keyblob, "Consistent DER with keyblob"); #encode_base64($modulus) ."\n"; open(PRIVKEYFILE,"<$privkeyfilename" )|| die "Could not open testfile $privkeyfilename\n"; while (){ $privkey.=$_; } open(PUBKEYFILE,"<$pubkeyfilename" )|| die "Could not open testfile $pubkeyfilename\n"; while (){ $pubkey.=$_; } my $pubkeyrr=Net::DNS::RR->new($pubkey); my $dumpkey=$rsakey->dump_rsa_priv; is( $dumpkey,$privkey,"Read and dumped private keys equal"); my $key_rdata=$rsakey->dump_rsa_pub; my $key_rr_rdata=$pubkeyrr->key; is ($key_rr_rdata,$key_rdata,"Read and dumped public keys equal"); is($rsakey->dump_rsa_keytag(256),34247,"Calculated proper keytag"); # more consistency checking... Dump priv key into der format.. read it and # check again. my $der=$rsakey->dump_rsa_private_der; my $rsakey2=Net::DNS::SEC::Private->new_rsa_priv($der); my $dumpkey2=$rsakey2->dump_rsa_priv; is( $dumpkey2,$privkey,"Read and dumped private keys equal"); my $key_rdata2=$rsakey2->dump_rsa_pub; is ($key_rr_rdata,$key_rdata2,"Read and dumped public keys equal"); my $newkey=Net::DNS::SEC::Private->generate_rsa("example.com",257,1024); my $tstpubkeyrr= Net::DNS::RR->new ($newkey->signame." IN DNSKEY 257 3 5 ". $newkey->dump_rsa_pub()); is($tstpubkeyrr->keytag,$newkey->dump_rsa_keytag(),"Consistent keytag calculation"); my $sigrr= create Net::DNS::RR::RRSIG([$tstpubkeyrr],$newkey); is ($sigrr->keytag,$tstpubkeyrr->keytag,"Consisted keytag in the created signature");; ok($sigrr->verify([$tstpubkeyrr],$tstpubkeyrr), "Self verification consistent."); $privkeyfilename="t/Kexample.com.+001+28551.private"; $pubkeyfilename="t/Kexample.com.+001+28551.key"; $rsakey=Net::DNS::SEC::Private->new($privkeyfilename); $rsakeyfromder=Net::DNS::SEC::Private->new_rsa_priv($rsakey->dump_rsa_private_der); is ($rsakey->dump_rsa_private_der,$rsakeyfromder->dump_rsa_private_der, "Consistent DER parsing"); is($rsakey->dump_rsa_keytag(255,1),28551,"Consistent RSAMD5 keytag"); Net-DNS-SEC-0.16/t/09-dnssec.t000644 000765 000120 00000060635 11346437006 015441 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 09-dnssec.t 847 2010-03-12 13:04:13Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/09-dnssec.t use Net::DNS::RR::RRSIG; use Test::More tests=>83; use strict; BEGIN { use_ok('Net::DNS'); } my $datarrset; my ($datarr1, $datarr2, $datarr3); my $datastring1="test.tld. 7000 IN NS ns.test.tld."; my $datastring2="test.tld. 7000 IN NS ns.foo.tld."; my $datastring3="test.tld. 7000 IN NS ns.boo.tld."; my $otherrrset; my ($otherrr1, $otherrr2, $otherrr3); my $otherstring1="*.test.tld. 7000 IN TXT cruft"; my $otherstring2="*.test.tld. 7000 IN TXT more cruft."; my $otherstring3="*.test.tld. 7000 IN TXT last cruft"; $datarr1= new Net::DNS::RR($datastring1); ok ( $datarr1, 'data RR 1 loaded '); $datarr2= new Net::DNS::RR($datastring2); ok ( $datarr2, 'data RR 2 loaded '); $datarr3= new Net::DNS::RR($datastring3); ok ( $datarr3, 'data RR 3 loaded '); $datarrset = [ $datarr1, $datarr2 , $datarr3 ] ; $otherrr1= new Net::DNS::RR($otherstring1); ok ( $otherrr1, 'other RR 1 loaded '); $otherrr2= new Net::DNS::RR($otherstring2); ok ( $otherrr2, 'other RR 2 loaded '); $otherrr3= new Net::DNS::RR($otherstring3); ok ( $otherrr3, 'other RR 3 loaded '); $otherrrset = [ $otherrr1, $otherrr2 , $otherrr3 ] ; ############################################## # In the following tests we first sign a KEY and then verify it again. # We do this for both RSA and DSA. # This is a consistency check # # The private key will be written to disk first. # # Keypairs generated with dnssec-keygen. (9.2.0rc1) # # RSA/SHA-1 keypair # my $keypathrsa="Ktest.tld.+001+11567.private"; my $privrsakey= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 1 (RSA) Modulus: 6ASwF3rSBFnBBQ7PmdWJnNkT2XkbZP5Be28SyTohsnuT1Rw7OlbNVNiT+4S04JUS0itVbvgtYmDZGMU3nfZP+er20uJRo/mu6hSkJW3MX5ES8o/GnOST1zSCH1+aA1Y6AlhfLebC+ysVKftLYnEco6oHNioYOmYHozYr5d0tL/s= PublicExponent: Aw== PrivateExponent: mq3KulHhWDvWA181ETkGaJC35lC87f7WUkoMhibBIae342gnfDneOJBip63N6w4MjBzjn1AeQZXmEIN6aU7f+q0Fwsyl4FzrSa8ehjfTS4u4YZE/Zk9rv0VIZuYwyccgLEBLYNBYRLbkbuSqDspw+Th8dCGy7XZ06eRkGZSNMjs= Prime1: 9Fssra0OAl4kNX105Xdrnb7kS+/6QgWeJeBJCuajjWQ0uRiEClDzjVVVr6BW2DixP+6RCbSDioSIqsNc546UtQ== Prime2: 8xMCAavFa+/XWHjnNJgCob976feJK2yaJrU7+2oxHiWLPtWYo+2gi2kt9Kv1aTp8lV327ddSqdO7tNJilsrP7w== Exponent1: oudzHnNerD7CzlOjQ6TyaSnth/VRgVkUGUAwse8Xs5gjJhBYBuCiXjjjymrkkCXLf/RgsSMCXFhbHII977RjIw== Exponent2: ogysAR0uR/U6OvtEzbqsa9T9RqUGHPMRbyN9UkbLaW5c1I5lwp5rB5tz+HKjm3xTDj6kno+McTfSeIxBudyKnw== Coefficient: Cxwv14w+KY7rmiO4U0giXqOij9gON7TiByj5dQjHGUQdaQEJ0zK2SlxouEfgi3hcxTGI753pFmW0cF/MDjFURw== ENDRSA open (RSA,">$keypathrsa") or die "Could not open $keypathrsa"; print RSA $privrsakey; close(RSA); my $rsakeyrr=new Net::DNS::RR ("test.tld. IN KEY 256 3 1 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w== "); ok( $rsakeyrr, 'RSA/SHA-1 public key created'); # # RSA/SHA-256 keypair # my $keypathrsa256="Ktest.tld.+008+31374.private"; my $privrsakey256= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 8 (RSASHA256) Modulus: qMM+u+1QBzYCm6PteHMyPhLBLwagdf3SfkPwWUcjdfpFHKssWWKIVHNOhaYJy/YqyTeVpG+Ij6SdSeh/QN9G/p8k4UYsvlr9G6aofgcHrVOS3xVMXK4iH6P4UTvoNBuX48wHWC9426MyODf3DcK2NxDSdnOfhpUBBvC3z3mTSrM= PublicExponent: AQAB PrivateExponent: YN0v9M2RUZI+jPbaJnh4Lgi1uTgkgZTebHqySYv7Xov3fy0Al41mkpJcT3mtxdPVWwj8axVZXJkvbmx0HdgJ9sx9SoF5HmF078O5y7yit78gbbOEKyGRlU7kfEQrQ6uHBO99LJVtr89KplW3qVKwgH2FBiAyI9dNkevebJ4R8AE= Prime1: 3GiJfuE1kaPIH6TH+b0nmH+bCQ0a7egDVrPcLVh9ybENy3KbvkRy3MYgBXBt/Zv8QgtQA+esGIwSWzxurzp1Mw== Prime2: xAO6HUsZibwUv3aX9F2oPH1YmeZpdOXIdBMN4RpibbRqs5TfKQy8281nW5dKcFG97K9jKVGv9HGgPSuBC7DUgQ== Exponent1: iZrqXMCWBTtPshHal9y0X80rKdd4vJdhnjvkdpsMzWMwzZfcDEoHvDYlv7+VrAQ61bDiX82/8ANjYnq0T8obaQ== Exponent2: htg9h/trFSrTZyfRv2VS4FImyrEM6UNOlDOrf6kj/253XRVUNCw0HE4BBaxdpElHi/TYFcvBbTthzdMI0p8SgQ== Coefficient: pXn2+3pGnSRX9fDliY1msoLu8dLzzZaYzxKl8NDCaBfj8XJEs0Ix7iovG886LLoZ2bLAZkS+1ZbRfFr+1wbmqA== ENDRSA open (RSA,">$keypathrsa256") or die "Could not open $keypathrsa256"; print RSA $privrsakey256; close(RSA); my $rsakeyrr256=new Net::DNS::RR ("test.tld. IN KEY 256 3 1 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w== "); ok( $rsakeyrr256, 'RSA/SHA-256 public key created'); # # RSA/SHA-512 keypair # my $keypathrsa512="Ktest.tld.+010+04625.private"; my $privrsakey512= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 10 (RSASHA512) Modulus: 8feFRviN7LXET8rIBgoePE1Aj4Rml4bIEe24UiqOKsf5rsYy+F3T2HEYszKhhVpXFje3cjbtLOCnKsrg2iT+QQn8PBrc9y/AZ6sdR+qdYICx4V/QoCrzaBWIE6CUB3m1ZeoMDwnadkMGpYKuMIyi+oO8qfdYhIiElTY9/ctR7gE= PublicExponent: AQAB PrivateExponent: 6wlwYNwXoJN/ubJUUemKLTEtQTtvHElEFoY/wTCtIElX87l60V7y5RAW2hqYYxy5807z1vIbuLgQKbUgbUX54ffwans1E5jcXetTAUxYmAZbJMHJNk48ssbp8Kipr58O4BC0Fdg8iiJuUu+t4qnDp6Vxy+L4I07U1sjiUd7SpQE= Prime1: +6O0SL5Wg32Gd/oQOJchH0xojeltBVVeyayadY6dM14ygTk4kwm3+6V+lRMPHyzxzEyXDY7jV62yqxLY+0NumQ== Prime2: 9ijoalqp0VafFvv7jfQFceMmszAlnwzoxekuCdwO7CfRDHG4OOB3HvR1B/Ndr2LShS5X5pIHd1uAxPFrCYcjqQ== Exponent1: x74hG+DiIUuhUljPSWxFIWfwUj0oiaRDMkhs7sV+aMjrxAFcs/Jx9TFfcguH5FIzuNxOxrdWJEG/YeX7EC9teQ== Exponent2: ea1Q7Tlxlcu2ifr2pn2Hr3rz50EWZ59O9H1Fx5PiQHOSDw+rW1oBJ+j4bHysw4QawcBdrNhkHmi5pyAao7QMOQ== Coefficient: oEwXjm4z0dVIkNS08yDSgAj9QTZLoKjDfoO/bpLLUYh9WnwPu2Jc+1eMreVfbC0RHTohxEntUuZXsPR7Du+zEQ== ENDRSA open (RSA,">$keypathrsa512") or die "Could not open $keypathrsa512"; print RSA $privrsakey512; close(RSA); my $rsakeyrr512=new Net::DNS::RR ("test.tld. IN KEY 256 3 1 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w== "); ok( $rsakeyrr512, 'RSA/SHA-512 public key created'); my $keypathdsa="Ktest.tld.+003+09734.private"; my $privdsakey= << 'ENDDSA' ; Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): 7m5wm/8KMO1fLaBB2Wbq3s0/jMudrauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/joY2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srlslykC+LQRnsbxB5YJMgmkPaPZU8GpRcc= Subprime(q): jRgd5fwOUwUmNpcD6Uzs/tMzy3U= Base(g): a0/+JhZhnci+P8/GOvnokG3NAF10o0Pf6/oz5UpcmX89KqjPvn9aRTRI9sM2AJgFBkzrQhXcx9NPvhneW0zN/baQhaUkupJ8YazNkkVKfOM6aH9h8ONVgGNRiLEBILQa07EMzce9/+JDYFbOCajJqhb9MZlTau17GDDK+r4okJ0= Private_value(x): C7O98kp8pfDdqeuvD83nf1xc4sI= Public_value(y): kFKU1HfmfRxPWwS9mA3FBHZ9LbmEizsH7vFSD7m31crIDVpxIO02bhKyFAuurKNh6naG4iTo3ak0yv6/bP8VNFIxN2QHPnnQL72ctUpvMLe+kWX7fGXuXWPIUCWVnbAeP2SnxpjxU039E9A2Rk6Dp9Eu0oXsM8hcUUnRv6ekycA= ENDDSA my $dsakeyrr=new Net::DNS::RR ("test.tld. IN KEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMud rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA "); ok( $dsakeyrr, 'DSA public key created'); open (DSA,">$keypathdsa") or die "Could not open $keypathdsa"; print DSA $privdsakey; close(DSA); # Create the signature records. my $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature created'); my $sigrsa256= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa256, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa256, 'RSA signature created'); my $sigrsa512= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa512, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa512, 'RSA signature created'); is ( $sigrsa->ttl, 360, "TTL from argument"); my $sigdsa= create Net::DNS::RR::RRSIG($datarrset,$keypathdsa); ok ( $sigdsa, 'DSA signature created'); is ( $sigdsa->ttl, 7000, "TTL from RRset"); # Verify the just created signatures ok ($sigrsa->verify($datarrset,$rsakeyrr),'RSA/SHA-1 sig verifies'); # Verify the just created signatures ok ($sigrsa->verify($datarrset,$rsakeyrr256),'RSA/SHA-256 sig verifies'); # Verify the just created signatures ok ($sigrsa->verify($datarrset,$rsakeyrr512),'RSA/SHA-512 sig verifies'); # Verify the just created signatures ok ($sigdsa->verify($datarrset,$dsakeyrr), 'DSA sig verifies'); # on the other hand checking against the wrong key should fail. ok (! $sigrsa->verify($datarrset,$dsakeyrr), 'RSA sig fails agains corrupt data'); ok (! $sigdsa->verify($datarrset,$rsakeyrr), 'DSA sig fails agains corrupt data'); my $othersigrsa= create Net::DNS::RR::RRSIG($otherrrset,$keypathrsa, ( ttl => 360, )); is($othersigrsa->labels,2,"Correct label count in presence of asterisk label"); # Now corrupt the key and test again.. that should fail # Corruption is very hard to notice.. we modified one letter # in the base 64 representation. my $corrupt_rsakeyrr=new Net::DNS::RR ("test.tld. IN KEY 256 3 1 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfA ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t9 6KX/5w=="); ok (!$sigrsa->verify($datarrset,$corrupt_rsakeyrr),'RSA fails agains corrupt key'); my $corrupt_dsakeyrr=new Net::DNS::RR ("test.tld. IN KEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMue rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA"); ok (! $sigdsa->verify($datarrset,$corrupt_dsakeyrr),'DSA fails agains corrupt key'); # Now test some DSA stuff my $dsrr=create Net::DNS::RR::DS($rsakeyrr); ok( $dsrr,'DS created from KEY RR'); ok( $dsrr->verify($rsakeyrr),'DS matches KEY'); my $dsrr2=Net::DNS::RR->new("test.tld. 0 IN DS 42495 1 1 0ffbeba0831b10b 8b83440dab81a2148576da 9f6"); is ($dsrr2->digest,"0ffbeba0831b10b8b83440dab81a2148576da9f6","Digest read correctly"); ok( $dsrr,'DS(2) created from string'); ok( $dsrr->verify($rsakeyrr),'DS(2) matches KEY'); my ($nlkey1, $nlsig1, $nlNS1, $nlNS2, $nlNS3, $nldatarrset); $nlNS1=new Net::DNS::RR(" host100.ws.disi. 600 IN A 10.1.1.100"); $nlNS2=new Net::DNS::RR("host100.ws.disi. 600 IN A 10.1.2.100"); $nlNS3=new Net::DNS::RR("host100.ws.disi. 600 IN A 10.1.3.100"); $nldatarrset=[$nlNS1,$nlNS3, $nlNS2]; my $dsasigrr=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathdsa ); ok( $dsasigrr, 'DSA signature with bind generated key'); my $rsasigrr=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathrsa ); ok( $rsasigrr, 'RSA/SHA-1 signature with bind generated key'); my $rsasigrr256=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathrsa256 ); ok( $rsasigrr256, 'RSA/SHA-256 signature with bind generated key'); my $rsasigrr512=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathrsa512 ); ok( $rsasigrr512, 'RSA/SHA-512 signature with bind generated key'); ok( $dsasigrr->verify($nldatarrset,$dsakeyrr),'DSA sig (test 2) verifies'); is( $dsasigrr->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ok( $rsasigrr->verify($nldatarrset,$rsakeyrr),'RSA sig (test 2) verifies'); is( $rsasigrr->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ######## #### Couple of SIG0 tests my $update1 = Net::DNS::Update->new("test.test"); ok ( $update1, 'Creating Update packet 1' ); $update1->push("update", Net::DNS::rr_add("test.test.test 3600 IN A 10.0.0.1")); $update1->sign_sig0($keypathrsa); ok ($rsakeyrr,'RSA Public key for SIG0'); my $update2 = Net::DNS::Update->new("test.test"); ok ( $update2, 'Creating Update packet 2' ); $update2->sign_sig0($keypathdsa); ok ($dsakeyrr,'DSA Public key for SIG0'); $update1->data; $update2->data; my $sigrr1=$update1->pop("additional"); ok ($sigrr1,"Obtained RSA sig from packet"); my $sigrr2=$update2->pop("additional"); ok ($sigrr2,"Obtained DSA sig from packet"); ok ($sigrr1->verify($update1, $rsakeyrr),'RSA SIG0 verification of packet data'); ok ($sigrr2->verify($update2, $dsakeyrr),'DSA SIG0 verification of packet data'); ok (!$sigrr1->verify($update2, $rsakeyrr),'RSA SIG0 fails with invalid data'); ok (!$sigrr2->verify($update1, $dsakeyrr),'RSA SIG0 fails with invalid data'); # # SOA with escaped dot. $datarr1 = Net::DNS::RR->new("test.tld. 7000 IN SOA ( ns.test.tld. first\.last.test.tld. 2002042603 43200 7200 1209600 7200)"); $datarrset = [ $datarr1 ] ; $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature over SOA with escaped dot created'); ok ($sigrsa->verify($datarrset,$rsakeyrr),'RSA sig over SOA with escaped dot verifies'); # clean the private key files (not needed no more) # Cross check with a signature generated with bind tools. my $bindkey1=Net::DNS::RR->new(" example.com. 3600 IN DNSKEY 257 3 5 ( AQPUiszMMAi36agx/V+7Tw95l8PYmoVjHWvOKxx/0iH8ZE3sdEqQncCe Jg7IVQ+LNWSP9mT/B26eQb5WZ2IKFzNFQTMNi6um+yh3nytazwOwOx00 2VGnwpYwnUFV3bZ5BcgWC8wrUzVGgCVIvX+besZrIXMY60yriRqQqNGO DnKo2T6zYewfCw4lYxRKYT6RqA0y8nJqyLRmeZ0nYP6uvDYjHEu7mqUf XBzeZNMy3WgSCTbQoK/RaSR7adTgTe5t972c51Di7TCwxpDzCfAKuPPk liBM9Z0x4gC0AZfO5Ma0p+dhf2k7wfl8m8xEOEMJITLooy88Nh+u2c9H F1tw0naH ; key id = 40620 "); my $bindkey2=Net::DNS::RR->new(" example.com. 3600 IN DNSKEY 256 3 5 AQPaoHW/nC0fj9HuCW3hACSGiP0AkPS3dQFXDlEUjv1orbtx06TMmVKG K5K564OSd6UCf4ZQEu2CMPSAUFGHEZuANKYGwZh0k/HeoVNeom1L3Nt4 tVLiGMzrPQskzeK8sr1NKgqFmckQllMWd0ob8Ud6nqeQLHvXQgv1iHX3 dpBIPLYbRCzueqC5k09APl25PgJjjreyRXrxodvoiiaLHpdL5NtM2S9e ok2zmuRpYQSF1LTNfWwY9CkgL017Z/Zv00SbcoTM/eTXPqijGtUhh6UX 1gX89ybeyjtfcGbmTcB+I79NykZWoddO8zyzBXzzfFwtsAuryjQ/HFa5 r4mrbhkJ ; key id = 6227 "); my $bindsig=Net::DNS::RR->new(" example.com. 3600 RRSIG DNSKEY 5 2 3600 20380101000000 ( 20080225134340 40620 example.com. KXDsJ6gOFbGUA8cSwLIgnHQ2GwfpUJLWZK7/ MwF7+G2B5Ds7SQG1UWv0QuyNtWB0ubSn2ipw 4TclHDKjeYMFLD6I5Zuh4mW7n2QpPN79z57V C4Hf23lcWLRSL37jtX2qOPqWnFjy1AoGYzmy IksYcjPF5VPZyfQC0YprAQ35UKwAHfF9RMwi 7vdE0GzON1FkVCWN7uxYjnZT1jxs3EeSnR4+ 6ckK9OBJVHYUnjmIgViq6IuPV08zrelvZHcC WNFcjKKNpf3yx5YhyQBJBM6Fofl8Dk4zexsp VVjGDLrDwg73dOGEe3E00DQ9zDc++PGVNRPm r34ojumh85Ua0YVatw== ) "); my $binddataset=[$bindkey1, $bindkey2]; ok( $bindsig->verify($binddataset,$bindkey1), 'RSA sig generated with bind verifies') || diag ($bindsig->vrfyerrstr); my $nsecrr=Net::DNS::RR->new("example.com 300 NSEC itemA.with.caps.example.com. NS SOA TXT RRSIG NSEC DNSKEY "); ok ( $nsecrr, 'NSEC RR created from string'); my $nsecsig=Net::DNS::RR->new(" example.com. 300 RRSIG NSEC 5 2 300 20380101000000 ( 20080225134340 6227 example.com. TyfSavDAslOFzfiAQv29/KjGQBSyptVIHAl/ +BtV7YL7VBOBBxpYM0laQWfnvRPwqfqO0STD u3KpIH95/ZeIPA/20xqR9IqgQNx3NvMmNK2g R0qPK/tkKQpHsBGPgARXhQqUwT2HhhmwNOYb ZwvnbaarFVq3RWerJUAxWHm3OABqZ1RYr6rL JEIIwEuBs9zAmR0G03Ourg+vVzkIgOoiEcBy ketBJr7FfFsRAYJ0HWOupSw16lxoUkSrEZ/f NpSwOB7zdEuDeojcfK0JaanpWihA0hiiqq0D 7RKqrnkoTrPVN4lP7bIr4q52jEBlFVIrbIzL UGtebocRBrvlmVB3+A== ) "); my @nsecdata=($nsecrr); ok( $nsecsig->verify(\@nsecdata,$bindkey2), "RRSIG over NSEC verifies") || diag ($nsecsig->vrfyerrstr); # # RSA keypair # my $keypathrsasha1="Ktest.tld.+005+29159.private"; my $privrsakeysha1= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 5 (RSA-SHA1) Modulus: ovtC5gQH1fuAnQqMvNctGfX3o2F82164fO7toGiWddiLTuWxrXoHwcpIFLO+hJR9Xxr1gaWh6od66CJnOzBpIQjIe/htpRO2nmLFF5+cB3QRRMGQWmq3bPCXDBHE/Jx8ihzWZavXwIUN+oLqhnWbkT6sYGH8M+9VSW9rfeil/+c= PublicExponent: Aw== PrivateExponent: bKeB7q1ajqerE1xd0zoeEU6lF5ZTPOnQU0nzwEW5o+WyNJkhHlFagTGFYyJ/Aw2o6hH5ARkWnFpR8BbvfMrwv6AeCrahtJgilCpCYxwusOOikbkGR/sXP5ObscRmEuhfzVYBV62yMc34MyspHzXHNZAL+SgRswopy6MgWdAII2s= Prime1: 0GNRLAYLvgaIZ+8o/fVST6WEhQd4bDIEHnBtIxHj9NIrHL/nIerA80sth+Pwfed2zp109U+zvcizUSfJDbHRsQ== Prime2: yDgaunUKcXw3u3JZ92Crzvflpv92BeKJdL0USBn8Sxqq/xR7BWG03M6AOkjnJwlKF/z1sJHzok3kqZMuIuf5Fw== Exponent1: iuzgyAQH1ARa7/TF/qOMNRkDA1pQSCFYFErzbLaX+IwcvdVEwUcrTNzJBUKgU++kib5N+N/NKTB3i2/bXnaLyw== Exponent2: hXq8fE4G9lLP0kw7+kByifqZGf+kA+xboyi4MBFS3Lxx/2L8rkEjPd8AJttExLDcD/35IGFNFt6YcQzJbJqmDw== Coefficient: gAeUUI6YOtdNAh3kS7pOzYfn0ZrUCV8bGpZoaXANk2RL2zUiaSSa4wudhpHwMJt+psNkkiQyf4v600uHbxro4Q== ENDRSA my $rsasha1keyrr=new Net::DNS::RR ("test.tld. IN KEY 256 3 5 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t9 6KX/5w=="); ok( $rsasha1keyrr, 'RSA-SHA1 public key created'); open (RSA,">$keypathrsasha1") or die "Could not open $keypathrsasha1"; print RSA $privrsakeysha1; close(RSA); my $sigrsasha1= create Net::DNS::RR::RRSIG($datarrset,$keypathrsasha1, ( ttl => 360, # sigval => 100, )); ok ( $sigrsasha1, 'RSA SHA1 signature created'); ok ($sigrsasha1->verify($datarrset,$rsasha1keyrr),'RSA SHA1 sig verifies'); ok ($sigrsasha1->verify($datarrset,[$rsasha1keyrr]),'RSA SHA1 sig verifies for 1 element keyrr array'); is($sigrsasha1->vrfyerrstr,"No Error","Correct Errorstring for keyrr array (0)"); # Corrupted versions of rsasha1keyrr my $rsasha1keyrr2=new Net::DNS::RR ("test.tld. IN KEY 256 3 5 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t8 6KX/5w=="); my $rsasha1keyrr3=new Net::DNS::RR ("test.tld. IN KEY 256 3 5 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t7 6KX/5w=="); # This keyrr has been carefully crafted to have the same keytag as # rsasha1keyrr my $rsasha1keyrr4=new Net::DNS::RR ("test.tld. IN KEY 257 3 5 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t8 6KX/5w=="); ok ($sigrsasha1->verify($datarrset, [$rsasha1keyrr3,$rsasha1keyrr2,$rsasha1keyrr]), 'RSA SHA1 sig verifies for 3 element keyrr array '); is($sigrsasha1->vrfyerrstr,"No Error","Correct Errorstring for keyrr array (1)"); ok (! $sigrsasha1->verify($datarrset, [$rsasha1keyrr3,$rsasha1keyrr2,$rsasha1keyrr4]), 'RSA SHA1 sig fails for 3element keyrr array with broken keys'); is($sigrsasha1->vrfyerrstr,"key 1: keytag does not match key 2: keytag does not match key 3:RSA Verification failed ","Correct Errorstring for keyrr array (2)"); ok (! $sigrsasha1->verify($datarrset, [$sigrsasha1,$rsasha1keyrr2,$rsasha1keyrr3 ]), 'RSA SHA1 sig fails for 3element keyrr array with wrong object in array'); is($sigrsasha1->vrfyerrstr,"key 1:You are trying to pass Net::DNS::RR::RRSIG data for a key key 2: keytag does not match key 3: keytag does not match ","Correct Errorstring for array with non-keyobject"); ok ( $sigrsasha1->verify($datarrset, [$sigrsasha1,$rsasha1keyrr2,$rsasha1keyrr ]), 'RSA SHA1 sig validates for 3element keyrr array with wrong object in array'); ## my $dsaprivate=Net::DNS::SEC::Private->new($keypathdsa); my $dsasigrr_p=Net::DNS::RR::RRSIG->create($nldatarrset, $dsaprivate ); ok( $dsasigrr_p, 'DSA signature with bind generated key '); my $rsaprivate=Net::DNS::SEC::Private->new($keypathrsa); my $rsasigrr_p=Net::DNS::RR::RRSIG->create($nldatarrset, $rsaprivate ); ok( $rsasigrr_p, 'RSA signature with bind generated key'); ok( $dsasigrr_p->verify($nldatarrset,$dsakeyrr),'DSA sig (test 2) verifies'); is( $dsasigrr_p->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ok( $rsasigrr_p->verify($nldatarrset,$rsakeyrr),'RSA sig (test 2) verifies'); is( $rsasigrr_p->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ######## #### Couple of SIG0 tests repeated with the private key object as input. my $update1_p = Net::DNS::Update->new("test.test"); ok ( $update1, 'Creating Update packet 1' ); $update1_p->push("update", Net::DNS::rr_add("test.test.test 3600 IN A 10.0.0.1")); $update1_p->sign_sig0($rsaprivate); my $update2_p = Net::DNS::Update->new("test.test"); ok ( $update2_p, 'Creating Update packet 2' ); $update2_p->sign_sig0($dsaprivate); $update1_p->data; $update2_p->data; my $sigrr1_p=$update1_p->pop("additional"); ok ($sigrr1_p,"Obtained RSA sig from packet"); my $sigrr2_p=$update2_p->pop("additional"); ok ($sigrr2_p,"Obtained DSA sig from packet"); ok ($sigrr1_p->verify($update1_p, $rsakeyrr),'RSA SIG0 verification of packet data'); ok ($sigrr2_p->verify($update2_p, $dsakeyrr),'DSA SIG0 verification of packet data'); ok (!$sigrr1_p->verify($update2_p, $rsakeyrr),'RSA SIG0 fails with invalid data'); ok (!$sigrr2_p->verify($update1_p, $dsakeyrr),'RSA SIG0 fails with invalid data'); unlink($keypathrsa); unlink($keypathdsa); unlink($keypathrsasha1); is ($dsakeyrr->keylength, 8, "DSA (KEY) Keysize "); is ($rsakeyrr->keylength, 1024, "RSA (KEY) Keysize "); is ($bindkey1->keylength, 2048, "RSA (DNSKEY) Keysize "); Net-DNS-SEC-0.16/t/10-keyset.t000644 000765 000120 00000031175 11346437006 015453 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for keysetfunctionalty # $Id: 10-keyset.t 813 2009-11-27 09:10:10Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/09-dnssec.t #use Test::More qw(no_plan); use Test::More tests => 21; use strict; BEGIN {use_ok('Net::DNS'); } # test 1 BEGIN {use_ok('Net::DNS::Keyset'); } # test 1 # # RSA keypair # my $keypathrsa="Ktest.tld.+005+15791.private"; my $privrsakey= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 5 (RSASHA1) Modulus: tYGOVBZbUOH9GR51zxUGX3EEDaVyua9EZNOayy5mNF3gNZbvHpO1tVR7AY5IHvVlO3n3ad1OGpsVC0TEI+xdAcjit9fGoGqdrCFmDdd41dUS8ReRj8i6vradooRMiPMdD/HPUc4FZ9YseF3KKvryplqg09YxxOKAWPw8yPIMric= PublicExponent: Aw== PrivateExponent: eQEJjWQ84Jaou2mj32NZlPYCs8Oh0R+C7eJnMh7uzZPqzmSfabfOeOL8q7QwFKOY0lFPm+jevGdjXNiCwp2TVWZrFINEMwUpxPJCvQQLh0k9Ah3NN2ELPBSlUjkRa10KaRSVSdDaYUM9X1/ZT/9RQagi4ckuy0x6UcRmoSng/Ms= Prime1: 3SNqKvY2geGDxgpqUKy2gGKq2LBRZ0CruBsVQXtoBH2dwq1bUScC9HxrTYaGxn2BELZsYRMeGVqZ1WqzsLXeTw== Prime2: 0h6u5+odYP2A7/eIALrUZtTDEi1rT+k434qR7Tb/4w/UkEIHw5bS/NP+AH2sNXtCzbYUx1h11m5EgDgjgoVUqQ== Exponent1: k2zxcfl5q+utLrGcNch5quxx5crg74Byery41lJFWFO+gcjni29XTahHiQRZ2akAtc7y62IUEOcROPHNIHk+3w== Exponent2: jBR0mpwTlf5V9U+wAHyNmeMstsjyNUYl6lxhSM9VQgqNtYFagmSMqI1UAFPII6eB3nljL5BOjvQtqtAXrFjjGw== Coefficient: YJYWzNpbdj/11mE4kUwaiH9GQbY+uA28tv4aVAwAEcKPaU1QQ2k8Jlm+VXxh9v02QCFJYln3416972oeCx9eyw== ENDRSA my $rsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 5 AQO1gY5UFltQ4f0ZHnXPFQZfcQQNpXK5r0Rk05rLLmY0XeA1lu8ek7W1 VHsBjkge9WU7efdp3U4amxULRMQj7F0ByOK318agap2sIWYN13jV1RLx F5GPyLq+tp2ihEyI8x0P8c9RzgVn1ix4Xcoq+vKmWqDT1jHE4oBY/DzI 8gyuJw== "); ok( $rsakeyrr, 'RSA public key created'); # test 5 my $keypathdsa="Ktest.tld.+003+09734.private"; my $privdsakey= << 'ENDDSA' ; Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): 7m5wm/8KMO1fLaBB2Wbq3s0/jMudrauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/joY2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srlslykC+LQRnsbxB5YJMgmkPaPZU8GpRcc= Subprime(q): jRgd5fwOUwUmNpcD6Uzs/tMzy3U= Base(g): a0/+JhZhnci+P8/GOvnokG3NAF10o0Pf6/oz5UpcmX89KqjPvn9aRTRI9sM2AJgFBkzrQhXcx9NPvhneW0zN/baQhaUkupJ8YazNkkVKfOM6aH9h8ONVgGNRiLEBILQa07EMzce9/+JDYFbOCajJqhb9MZlTau17GDDK+r4okJ0= Private_value(x): C7O98kp8pfDdqeuvD83nf1xc4sI= Public_value(y): kFKU1HfmfRxPWwS9mA3FBHZ9LbmEizsH7vFSD7m31crIDVpxIO02bhKyFAuurKNh6naG4iTo3ak0yv6/bP8VNFIxN2QHPnnQL72ctUpvMLe+kWX7fGXuXWPIUCWVnbAeP2SnxpjxU039E9A2Rk6Dp9Eu0oXsM8hcUUnRv6ekycA= ENDDSA open (RSA,">$keypathrsa") or die "Could not open $keypathrsa"; print RSA $privrsakey; close(RSA); my $dsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMud rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA"); ok( $dsakeyrr, 'RSA public key created'); # test 6 open (DSA,">$keypathdsa") or die "Could not open $keypathdsa"; print DSA $privdsakey; close(DSA); # Create keysets my $keysetpath="t/keyset-test.tld."; open (KEYSET,">$keysetpath") or die "Could not open $keysetpath"; my $datarrset= [ $rsakeyrr, $dsakeyrr ]; my $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); my $sigdsa= create Net::DNS::RR::RRSIG($datarrset,$keypathdsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature created'); # test 7 print KEYSET $rsakeyrr->string ."\n"; print KEYSET $dsakeyrr->string ."\n"; print KEYSET $sigrsa->string . "\n"; print KEYSET $sigdsa->string . "\n"; close(KEYSET); my $keyset; $keyset=Net::DNS::Keyset->new($keysetpath); is (ref($keyset), "Net::DNS::Keyset", "Keyeset object read"); undef $keyset; $keyset=Net::DNS::Keyset->new($datarrset); is (ref($keyset), "Net::DNS::Keyset", "Keyeset object created"); my @ds=$keyset->extract_ds; if ($Net::DNS::RR::DS::_Babble){ is (lc($ds[0]->string),lc("test.tld. 0 IN DS 15791 5 1 C355F0F3F30C69BF2F7EA253ED82FBC280C2496B ; xuboh-hasiz-fosab-super-zyrol-vimuh-firom-dyvos-debis-daduk-rexix"), "DS 1 generated from keyset"); # test 8-with babble is (lc($ds[1]->string),lc("test.tld. 0 IN DS 9734 3 1 ". "0e045bfe67dec6e54d0f1338877a53841902ab4a ; xefib-gakiz-vynat-vacov-hyfeb-zugif-mecil-pegam-gykib-dapyg-pexox"), "DS 1 generated from keyset"); # test 9-with babble }else{ is (lc($ds[0]->string), lc("test.tld. 0 IN DS 15791 1 1 ". "0ffbeba0831b10b8b83440dab81a2148576da9f6"), "DS 1 generated from keyset"); # test 8-without babble is (lc($ds[1]->string), lc("test.tld. 0 IN DS 9734 3 1 ". "0e045bfe67dec6e54d0f1338877a53841902ab4a"), "DS 1 generated from keyset"); # test 9-without babble } ## # Corupted keyset $keysetpath="keyset-test-corrupt.tld."; open (KEYSET,">$keysetpath") or die "Could not open $keysetpath"; print KEYSET $rsakeyrr->string ."\n"; print KEYSET $dsakeyrr->string ."\n"; my $sigstr=$sigrsa->string; $sigstr =~ tr/A-Z/a-z/ ; #Corrupt the signature's base64 $sigstr=~s/in rrsig dnskey/IN RRSIG DNSKEY/; # fix what should not have been transponded print KEYSET $sigstr ."\n"; print KEYSET $sigdsa->string . "\n"; close(KEYSET); $keyset=Net::DNS::Keyset->new($keysetpath); ok ( ! $keyset , "Corrupted keyset not loaded"); # test 10 is( $Net::DNS::Keyset::keyset_err , "RSA Verification failed on key test.tld 15791 " , "Correct Error message" ); # test 11 # # The packet contains a keyset as returned from a bind nameserver # the keyset is signed with a signature valid untill 2030 06 .. # After that the test may fail :-) # This is the code sniplet used to get such a little packet as below. #use Net::DNS::Resolver; #my $res=Net::DNS::Resolver->new(); #$res->nameserver("10.0.53.204"); #$res->dnssec(1); #my $a_packet=$res->send("sub.tld","DNSKEY"); #$a_packet->print; #print unpack("H*",$a_packet->data); my $UUencodedPacket="e6cc81a000010004000000010373756203746c 640000300001c00c00300001000000200086010103050103bc54beaee1 1dc1a29ba945bf69d0db27b364b2dfe60396efff4c6fb359127ea696e1 4c66e1c6d23cd6f6c335e1679c61dd3fa4d68a689b8709ea686e43f175 6831193903613f6a5f3ff039b21eed9faad4edcb43191c76490ca0947a 9fa726740bc4449d6c58472a605913337d2dbddc94a7271d25c358fdaa 60fe1272a5f8b9c00c00300001000000200086010003050103f6d63a8a b9f775a0c7194d67edb5f249bf398c3d27d2985facf6fb7e25cc35c876 2eb8ea22200c847963442fb6634916dc2ec21cdbf2c7378799b8e7e399 e751ca1e25133349cab52ebf3fe8a5bc0239c28d64f4d8f609c191a7d2 d364578a159701ef73af93946b281f0aac42b42be17362c68d7a54bbb8 fa7bc6f70f455a75c00c002e000100000020009b003005020000006470 dc814040c02ced39d40373756203746c6400a7d9db75a4115794f871ec 71fc7469c74a6be1cf95434a00363506b354bf15656f7556c51355c8dc ac7f6c0a4061c0923e0bf341094e586619c2cb316949772ce5bd1e9949 f91b016f7e6bee0f6878e16b6e59ece086f8d5df68f048524e1bff3c09 dd15c203d28416600e936451d1646e71611ec95e12d709839369cbc442 c0c00c002e000100000020009b003005020000006470dc814040c02ced fbaf0373756203746c640017c6e59f317119da812c6b1e175e8aaec742 35a4bfad777e7759fa2daf7959f9611c26e11adde9bdc901c624ca6965 7b79653495e22647c5e0e5bedfe5524397d769d816746d10b2067472b4 f9b04fbde8e39d7861bd6773c80f632f55b46c7a537a83f0b5a50200c9 d2847b71d9dfaa643f558383e6e13d4e75f70029849444000029100000 0080000000"; $UUencodedPacket =~ s/\n//g; $UUencodedPacket =~ s/\s//g; my $packetdata=pack("H*",$UUencodedPacket); my $packet = Net::DNS::Packet->new(\$packetdata); $keyset=Net::DNS::Keyset->new($packet); is (ref($keyset), "Net::DNS::Keyset", "Keyeset object from packet"); # test 12 is (join(" ",sort($keyset->verify)),"14804 64431","Verify method returned the two proper keytags"); # test 13 my $keyset2= Net::DNS::Keyset->new($datarrset,"./"); is (ref($keyset2), "Net::DNS::Keyset", "Keyeset object from DNSKEY RR and signature"); # test 14 #print $Net::DNS::Keyset::keyset_err; #$keyset->print; unlink($keysetpath); ######### ### my $rr; my @keyrr; my @keyrr2; my @sigrr; # Note that the order on pushing the RRsigs is important for # succesfully testing. # All signatures have expiration date in 2030... this test should work for a while $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQOxFlzX8vShSG3JG2J/fngkgy64RoWr8ovG e7MuvPJqOMHTLM5V8+TJIahSoyUd990ictNv hDegUqLtZ8k5oQq44viFCU/H1apdEaJnLnXs cVo+08ATlEb90MYznK9K0pm2ixbyspzRrrXp nPi9vo9iU2xqWqw/Efha4vfi6QVs4w== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO4jhl6ilWV2mYjwWl7kcxrYyQsnnbV7pxX m48p+SgAr+R5SKyihkjg86IjZBQHFJKZ8RsZ dhclH2dikM+53uUEhrqVGhsqF8FsNi4nE9aM ISiX9Zs61pTYGYboYDvgpD1WwFbD4YVVlfk7 rCDP/zOE7H/AhkOenK2w7oiO0Jehcw== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); my $poppedkey=Net::DNS::RR->new($rr->string); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO5fWabr7bNxDXT8YrIeclI9nvYYdKni3ef gJfU749O3QVX9MON6WK0ed00odQF4cLeN3vP SdhasLDI3Z3TzyAPBQS926oodxe78K9zwtPT 1kzJxvunOdJr6+6a7/+B6rF/cwfWTW50I0+q FykldldB44a1uS34u3HgZRQXDmAesw== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO6uGWsox2oH36zusGA0+w3uxkZMdByanSC jiaRHtkOA+gIxT8jmFvohxQBpVfYD+xG2pt+ qUWauWPFPjsIUBoFqHNpqr2/B4CTiZm/rSay HDghZBIMceMa6t4NpaOep79QmiE6oGq6yWRB swBkPZx9uZE7BqG+WLKEp136iwWyyQ== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 11354 example.com. GTqyJTRbKJ0LuWbAnNni1M4JZ1pn+nXY1Zuz Z0Kvt6OMTYCAFMFt0Wv9bncYkUuUSMGM7yGG 9Z7g7tcdb4TKCqQPYo4gr3Qj/xgC4LESoQs0 yAsJtLUiDfO6e4aWHmanpMGyGixYzHriS1pt SRzirL1fTgV+kdNs5zBatUHRnQc=) "); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 28109 example.com. WemQqA+uaeKqCy6sEVBU3LDORG3f+Zmix6qK 9j1WL83UMWdd6sxNh0QJ0YL54lh9NBx+Viz7 gajO+IM4MmayxKY4QVjp+6mHeE5zBVHMpTTu r5T0reNtTsa8sHr15fsI49yn5KOvuq+DKG1C gI6siM5RdFpDsS3Rmf8fiK1PyTs= )"); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 33695 example.com. M3yVwTOMw+jAKYY5c6oS4DH7OjOdfMOevpIe zdKqWXkehoDg9YOwz8ai17AmfgkjZnsoNu0W NMIcaVubR3n02bkVhJb7dEd8bhbegF8T1xkL 7rf9EQrPmM5GhHmVC90BGrcEhe//94hdXSVU CRBi6KPFWSZDldd1go133bk/b/o= )"); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 39800 example.com. Mmhn2Ql6ExmyHvZFWgt+CBRw5No8yM0rdH1b eU4is5gRbd3I0j5z6PdtpYjAkWiZNdYsRT0o P7TQIsADfB0FLIFojoREg8kp+OmbpRTsLTgO QYC95u5WodYGz03O0EbnQ7k4gkje6385G40D JVl0xVfujHBMbB+keiSphD3mG4I= )"); push(@sigrr,$rr); my @errors; my $ks=Net::DNS::Keyset->new(\@keyrr,\@sigrr); ok($ks,"Keyset created from two arrays."); my @result; @result=$ks->keys; ok(eq_array(\@result,\@keyrr),"Keys out equal to keys in"); # test 16 @result=$ks->sigs; ok(eq_array(\@result,\@sigrr),"Sigs out equal to sigss in"); # test 17 open (KEYSET,">$keysetpath") or die "Could not open $keysetpath"; $datarrset= [ $rsakeyrr, $dsakeyrr ]; $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); $sigdsa= create Net::DNS::RR::RRSIG($datarrset,$keypathdsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature created'); # test 18 print KEYSET $rsakeyrr->string ."\n"; print KEYSET $dsakeyrr->string ."\n"; print KEYSET $sigrsa->string . "\n"; close(KEYSET); $keyset=Net::DNS::Keyset->new($keysetpath); is (join(" ",sort($keyset->verify)),"15791","Verify method returned the keytags"); # test 13 ok (! $keyset->verify(9734),"Verification agains keytag 9734 failed"); # Test 19 is( $Net::DNS::Keyset::keyset_err , "No signature made with 9734 found" , "Correct Error message" ); # test 20 unlink($keysetpath); unlink($keypathdsa); unlink($keypathrsa); 0; Net-DNS-SEC-0.16/t/10-typeroll.t000644 000765 000120 00000034133 11346437006 016016 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 10-typeroll.t 813 2009-11-27 09:10:10Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/10-typeroll.t use Net::DNS::RR::RRSIG; use Test::More tests=>38; use strict; BEGIN {use_ok('Net::DNS'); } # test 1 my $datarrset; my ($datarr1, $datarr2, $datarr3); my $datastring1="test.tld. 7000 IN NS ns.test.tld."; my $datastring2="test.tld. 7000 IN NS ns.foo.tld."; my $datastring3="test.tld. 7000 IN NS ns.boo.tld."; $datarr1= new Net::DNS::RR($datastring1); ok ( $datarr1, 'data RR 1 loaded '); # test 2 $datarr2= new Net::DNS::RR($datastring2); ok ( $datarr2, 'data RR 2 loaded '); # test 3 $datarr3= new Net::DNS::RR($datastring3); ok ( $datarr3, 'data RR 3 loaded '); # test 4 $datarrset = [ $datarr1, $datarr2 , $datarr3 ] ; ############################################## # In the following tests we first sign a DNSKEY and then verify it again. # We do this for both RSA and DSA. # This is a consistency check # # The private key will be written to disk first. # # Keypairs generated with dnssec-keygen. (9.2.0rc1) # # RSA keypair # my $keypathrsa="Ktest.tld.+001+11567.private"; my $privrsakey= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 1 (RSA) Modulus: 6ASwF3rSBFnBBQ7PmdWJnNkT2XkbZP5Be28SyTohsnuT1Rw7OlbNVNiT+4S04JUS0itVbvgtYmDZGMU3nfZP+er20uJRo/mu6hSkJW3MX5ES8o/GnOST1zSCH1+aA1Y6AlhfLebC+ysVKftLYnEco6oHNioYOmYHozYr5d0tL/s= PublicExponent: Aw== PrivateExponent: mq3KulHhWDvWA181ETkGaJC35lC87f7WUkoMhibBIae342gnfDneOJBip63N6w4MjBzjn1AeQZXmEIN6aU7f+q0Fwsyl4FzrSa8ehjfTS4u4YZE/Zk9rv0VIZuYwyccgLEBLYNBYRLbkbuSqDspw+Th8dCGy7XZ06eRkGZSNMjs= Prime1: 9Fssra0OAl4kNX105Xdrnb7kS+/6QgWeJeBJCuajjWQ0uRiEClDzjVVVr6BW2DixP+6RCbSDioSIqsNc546UtQ== Prime2: 8xMCAavFa+/XWHjnNJgCob976feJK2yaJrU7+2oxHiWLPtWYo+2gi2kt9Kv1aTp8lV327ddSqdO7tNJilsrP7w== Exponent1: oudzHnNerD7CzlOjQ6TyaSnth/VRgVkUGUAwse8Xs5gjJhBYBuCiXjjjymrkkCXLf/RgsSMCXFhbHII977RjIw== Exponent2: ogysAR0uR/U6OvtEzbqsa9T9RqUGHPMRbyN9UkbLaW5c1I5lwp5rB5tz+HKjm3xTDj6kno+McTfSeIxBudyKnw== Coefficient: Cxwv14w+KY7rmiO4U0giXqOij9gON7TiByj5dQjHGUQdaQEJ0zK2SlxouEfgi3hcxTGI753pFmW0cF/MDjFURw== ENDRSA my $rsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 1 AQPoBLAXetIEWcEFDs+Z1Ymc2RPZeRtk/kF7bxLJOiGye5PVHDs6Vs1U 2JP7hLTglRLSK1Vu+C1iYNkYxTed9k/56vbS4lGj+a7qFKQlbcxfkRLy j8ac5JPXNIIfX5oDVjoCWF8t5sL7KxUp+0ticRyjqgc2Khg6ZgejNivl 3S0v+w== "); ok( $rsakeyrr, 'RSA public key created'); # test 5 my $keypathdsa="Ktest.tld.+003+09734.private"; my $privdsakey= << 'ENDDSA' ; Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): 7m5wm/8KMO1fLaBB2Wbq3s0/jMudrauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/joY2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srlslykC+LQRnsbxB5YJMgmkPaPZU8GpRcc= Subprime(q): jRgd5fwOUwUmNpcD6Uzs/tMzy3U= Base(g): a0/+JhZhnci+P8/GOvnokG3NAF10o0Pf6/oz5UpcmX89KqjPvn9aRTRI9sM2AJgFBkzrQhXcx9NPvhneW0zN/baQhaUkupJ8YazNkkVKfOM6aH9h8ONVgGNRiLEBILQa07EMzce9/+JDYFbOCajJqhb9MZlTau17GDDK+r4okJ0= Private_value(x): C7O98kp8pfDdqeuvD83nf1xc4sI= Public_value(y): kFKU1HfmfRxPWwS9mA3FBHZ9LbmEizsH7vFSD7m31crIDVpxIO02bhKyFAuurKNh6naG4iTo3ak0yv6/bP8VNFIxN2QHPnnQL72ctUpvMLe+kWX7fGXuXWPIUCWVnbAeP2SnxpjxU039E9A2Rk6Dp9Eu0oXsM8hcUUnRv6ekycA= ENDDSA open (RSA,">$keypathrsa") or die "Could not open $keypathrsa"; print RSA $privrsakey; close(RSA); my $dsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMud rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA "); ok( $dsakeyrr, 'RSA public key created'); # test 6 open (DSA,">$keypathdsa") or die "Could not open $keypathdsa"; print DSA $privdsakey; close(DSA); # Create the signature records. my $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature created'); # test 7 my $sigdsa= create Net::DNS::RR::RRSIG($datarrset,$keypathdsa, ( ttl => 360, # sigval => 100, )); ok ( $sigdsa, 'DSA signature created'); # test 8 # Verify the just created signatures ok ($sigrsa->verify($datarrset,$rsakeyrr),'RSA sig verifies'); # test 9 # Verify the just created signatures ok ($sigdsa->verify($datarrset,$dsakeyrr), 'DSA sig verifies'); # test 10 # on the other hand checking against the wrong key should fail. ok (! $sigrsa->verify($datarrset,$dsakeyrr), 'RSA sig fails agains corrupt data'); # test 11 ok (! $sigdsa->verify($datarrset,$rsakeyrr), 'DSA sig fails agains corrupt data'); # test 12 # Now corrupt the key and test again.. that should fail # Corruption is very hard to notice.. we modified one letter # in the base 64 representation. my $corrupt_rsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 1 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfA ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t9 6KX/5w=="); ok (!$sigrsa->verify($datarrset,$corrupt_rsakeyrr),'RSA fails agains corrupt key'); # test 13 my $corrupt_dsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMue rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA"); ok (! $sigdsa->verify($datarrset,$corrupt_dsakeyrr),'DSA fails agains corrupt key'); # test 14 # Now test some DSA stuff my $dsrr=create Net::DNS::RR::DS($rsakeyrr); ok( $dsrr,'DS created from DNSKEY RR'); # test 15 ok( $dsrr->verify($rsakeyrr),'DS matches DNSKEY'); # test 16 my $dsrr2=Net::DNS::RR->new("test.tld. 0 IN DS 42495 1 1 0ffbeba0831b10b8b83440dab81a2148576da9f6"); ok( $dsrr,'DS(2) created from string'); # test 17 ok( $dsrr->verify($rsakeyrr),'DS(2) matches DNSKEY'); # test 18 my ($nlkey1, $nlsig1, $nlNS1, $nlNS2, $nlNS3, $nldatarrset); $nlNS1=new Net::DNS::RR(" host100.ws.disi. 600 IN A 10.1.1.100"); $nlNS2=new Net::DNS::RR("host100.ws.disi. 600 IN A 10.1.2.100"); $nlNS3=new Net::DNS::RR("host100.ws.disi. 600 IN A 10.1.3.100"); $nldatarrset=[$nlNS1,$nlNS3, $nlNS2]; my $dsasigrr=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathdsa ); ok( $dsasigrr, 'DSA signature with bind generated key'); # test 19 my $rsasigrr=Net::DNS::RR::RRSIG->create($nldatarrset, $keypathrsa ); ok( $rsasigrr, 'RSA signature with bind generated key'); # test 20 ok( $dsasigrr->verify($nldatarrset,$dsakeyrr),'DSA sig (test 2) verifies'); # test 21 is( $dsasigrr->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); # test 22 ok( $rsasigrr->verify($nldatarrset,$rsakeyrr),'RSA sig (test 2) verifies'); is( $rsasigrr->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); # test 24 # # SOA with escaped dot. $datarr1 = Net::DNS::RR->new("test.tld. 7000 IN SOA ( ns.test.tld. first\.last.test.tld. 2002042603 43200 7200 1209600 7200)"); $datarrset = [ $datarr1 ] ; $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); ok ( $sigrsa, 'RSA signature over SOA with escaped dot created'); #test 25 ok ($sigrsa->verify($datarrset,$rsakeyrr),'RSA sig over SOA with escaped dot verifies'); #test 26 # clean the private key files (not needed no more) # Cross check with a signature generated with bind tools. #test fails after October 2030 : my $bindkey=Net::DNS::RR->new(" netdns.work. 900 DNSKEY 257 3 5 ( AQOwktT7a2gfGNXWK+QWKP/Lln5Z/fSz0q2f R1fA4QBQsWsrnKz/yqXRmOHhf8X975ZVwpdo 456wYjbfrP03sSjI3Wj9y5Mnr09HUUaBdwF/ 7VVgpP8Mgwe3FJ4f2uPwBFm2/+7+wxMyjIbL mu0Ec6xtZtEARe99RLnRCnF1gXb6Uw== ) ; key id = 17895"); my $bindsig=Net::DNS::RR->new("netdns.work. 900 RRSIG DNSKEY 5 2 900 20350101000000 ( 20040121160223 17895 netdns.work. SUENn9MMZd9PPdtt//rbMbCgI7XGAmvb4QWO 6Zuwis3ErhZR5PdiQNqhY53pN44Dnq5Qv4CO nIpoFLMZKpT1W/8jNFHZI8wX63hn8kYDUW9C lJt2YlovakAo3tMR3L/QvbkentB3ljJVEMYF PwJCmzS64bXNr960ZlOfnKY4Yl8= )"); my $binddataset=[$bindkey]; my $nxtrr=Net::DNS::RR->new("example.com 7200 NSEC bert.example.com. NS SOA MX TXT LOC RRSIG NSEC DNSKEY"); ok ( $nxtrr, 'NXT RR created from string'); #test 27 my $nxtsig=Net::DNS::RR->new("example.com 7200 RRSIG NSEC 5 2 7200 20310101000000 ( 20040126131948 37790 example.com. IFK3Y4xZwkyHP0TwMnsC7g2IvHRZmsk8rFH7 l1dM7Jyb7+p2Mh1nm13vv56sBOItHNDGvQtN yVDNuG2brf0zpHLHSzB/KsW1NNLTrTCscK1W 0JNu2WwiZo62dZLQqIY4RQqTsWxf17c0f3aA w8ogGRXVnHwv0uGKRfMnWpX2AgA= )"); my $nxtkey=Net::DNS::RR->new("example.com 900 DNSKEY 256 3 5 ( AQOzkktb0iNYIj9GuasRjJixkK/YZ5eAe/Hs anvfZ7023ZPmEdNvRfygmCRDOFs0ud7J8u8n YnWn9EBxxS4AKSj8To+Dtx+vuW/g72SQjbNZ T3EGlwU3F2455qUAkAd4CADVMcbbLO0MbXRk /fd+Mq8A1zdX8q602fdaxaZ325nE0Q== )"); my @nxtdata=($nxtrr); SKIP: { skip "Test material not available yet, will be fixed in later release", 2 if 0; ok( $bindsig->verify($binddataset,$bindkey), 'RSA sig generated with bind verifies'); #test 29 ok( $nxtsig->verify(\@nxtdata,$nxtkey), "RRSIG over NXT verifies"); #test 29 } # # RSA keypair # my $keypathrsasha1="Ktest.tld.+005+29159.private"; my $privrsakeysha1= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 5 (RSA-SHA1) Modulus: ovtC5gQH1fuAnQqMvNctGfX3o2F82164fO7toGiWddiLTuWxrXoHwcpIFLO+hJR9Xxr1gaWh6od66CJnOzBpIQjIe/htpRO2nmLFF5+cB3QRRMGQWmq3bPCXDBHE/Jx8ihzWZavXwIUN+oLqhnWbkT6sYGH8M+9VSW9rfeil/+c= PublicExponent: Aw== PrivateExponent: bKeB7q1ajqerE1xd0zoeEU6lF5ZTPOnQU0nzwEW5o+WyNJkhHlFagTGFYyJ/Aw2o6hH5ARkWnFpR8BbvfMrwv6AeCrahtJgilCpCYxwusOOikbkGR/sXP5ObscRmEuhfzVYBV62yMc34MyspHzXHNZAL+SgRswopy6MgWdAII2s= Prime1: 0GNRLAYLvgaIZ+8o/fVST6WEhQd4bDIEHnBtIxHj9NIrHL/nIerA80sth+Pwfed2zp109U+zvcizUSfJDbHRsQ== Prime2: yDgaunUKcXw3u3JZ92Crzvflpv92BeKJdL0USBn8Sxqq/xR7BWG03M6AOkjnJwlKF/z1sJHzok3kqZMuIuf5Fw== Exponent1: iuzgyAQH1ARa7/TF/qOMNRkDA1pQSCFYFErzbLaX+IwcvdVEwUcrTNzJBUKgU++kib5N+N/NKTB3i2/bXnaLyw== Exponent2: hXq8fE4G9lLP0kw7+kByifqZGf+kA+xboyi4MBFS3Lxx/2L8rkEjPd8AJttExLDcD/35IGFNFt6YcQzJbJqmDw== Coefficient: gAeUUI6YOtdNAh3kS7pOzYfn0ZrUCV8bGpZoaXANk2RL2zUiaSSa4wudhpHwMJt+psNkkiQyf4v600uHbxro4Q== ENDRSA my $rsasha1keyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 5 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t9 6KX/5w=="); ok( $rsasha1keyrr, 'RSA-SHA1 public key created'); #test 30 open (RSA,">$keypathrsasha1") or die "Could not open $keypathrsasha1"; print RSA $privrsakeysha1; close(RSA); my $sigrsasha1= create Net::DNS::RR::RRSIG($datarrset,$keypathrsasha1, ( ttl => 360, # sigval => 100, )); ok ( $sigrsasha1, 'RSA SHA1 signature created'); #test 31 ok ($sigrsasha1->verify($datarrset,$rsasha1keyrr),'RSA SHA1 sig verifies'); #test 32 ### Test usability of the private key object.. same set of test as above my $dsaprivate=Net::DNS::SEC::Private->new($keypathdsa); my $dsasigrr_p=Net::DNS::RR::RRSIG->create($nldatarrset, $dsaprivate ); ok( $dsasigrr_p, 'DSA signature with bind generated key '); # test 33 my $rsaprivate=Net::DNS::SEC::Private->new($keypathrsa); my $rsasigrr_p=Net::DNS::RR::RRSIG->create($nldatarrset, $rsaprivate ); ok( $rsasigrr_p, 'RSA signature with bind generated key'); # test 34 ok( $dsasigrr_p->verify($nldatarrset,$dsakeyrr),'DSA sig (test 2) verifies'); # test 35 is( $dsasigrr_p->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); # test 36 ok( $rsasigrr_p->verify($nldatarrset,$rsakeyrr),'RSA sig (test 2) verifies'); is( $rsasigrr_p->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); # test 38 unlink($keypathrsa); unlink($keypathdsa); unlink($keypathrsasha1); Net-DNS-SEC-0.16/t/11-sep.t000644 000765 000120 00000001766 11346437006 014742 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 11-sep.t 813 2009-11-27 09:10:10Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/10-typeroll.t use Test::More tests=>6; use strict; BEGIN {use_ok('Net::DNS'); } # test 1 ok (my $key=Net::DNS::RR->new("test.foo 3600 IN DNSKEY 256 3 RSASHA1 ( AQPDgM2XU2rluutXFw6IJjDRSGHehcc1ZtMoG5RR/ jXJD1bZNFgqsKlJkVfj9wzrzAnBg7ZQSHwxYIGDm ocdBtW3 )"),"Key created"); my $keytag=$key->keytag; $key->set_sep; ok ($key->is_sep,"Sep bit set"); ok ($keytag != $key->keytag, "keytag modified after toggle"); $key->clear_sep; ok (!$key->is_sep,"Sep bit unset"); ok ($keytag == $key->keytag, "keytag modified back to original after toggle"); Net-DNS-SEC-0.16/t/11-sigstress.t000644 000765 000120 00000016556 11346437006 016204 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 11-sigstress.t 813 2009-11-27 09:10:10Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/09-dnssec.t use constant LOOPS=>50; use Test::More tests=> (LOOPS * 9 + 3 ); # 3 tests befor the loop, 9 inside. use strict; use Net::DNS; use Net::DNS::RR::SIG; ######## #### Couple of SIG0 and RRSIG tests diag("This may take a while, do not worry."); # # RSA keypair # my $keypathrsa="t/Ktest.tld.+001+42495.private"; my $privrsakey= << 'ENDRSA' ; Private-key-format: v1.2 Algorithm: 1 (RSA) Modulus: ovtC5gQH1fuAnQqMvNctGfX3o2F82164fO7toGiWddiLTuWxrXoHwcpIFLO+hJR9Xxr1gaWh6od66CJnOzBpIQjIe/htpRO2nmLFF5+cB3QRRMGQWmq3bPCXDBHE/Jx8ihzWZavXwIUN+oLqhnWbkT6sYGH8M+9VSW9rfeil/+c= PublicExponent: Aw== PrivateExponent: bKeB7q1ajqerE1xd0zoeEU6lF5ZTPOnQU0nzwEW5o+WyNJkhHlFagTGFYyJ/Aw2o6hH5ARkWnFpR8BbvfMrwv6AeCrahtJgilCpCYxwusOOikbkGR/sXP5ObscRmEuhfzVYBV62yMc34MyspHzXHNZAL+SgRswopy6MgWdAII2s= Prime1: 0GNRLAYLvgaIZ+8o/fVST6WEhQd4bDIEHnBtIxHj9NIrHL/nIerA80sth+Pwfed2zp109U+zvcizUSfJDbHRsQ== Prime2: yDgaunUKcXw3u3JZ92Crzvflpv92BeKJdL0USBn8Sxqq/xR7BWG03M6AOkjnJwlKF/z1sJHzok3kqZMuIuf5Fw== Exponent1: iuzgyAQH1ARa7/TF/qOMNRkDA1pQSCFYFErzbLaX+IwcvdVEwUcrTNzJBUKgU++kib5N+N/NKTB3i2/bXnaLyw== Exponent2: hXq8fE4G9lLP0kw7+kByifqZGf+kA+xboyi4MBFS3Lxx/2L8rkEjPd8AJttExLDcD/35IGFNFt6YcQzJbJqmDw== Coefficient: gAeUUI6YOtdNAh3kS7pOzYfn0ZrUCV8bGpZoaXANk2RL2zUiaSSa4wudhpHwMJt+psNkkiQyf4v600uHbxro4Q== ENDRSA my $rsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 1 AQOi+0LmBAfV+4CdCoy81y0Z9fejYXzbXrh87u2gaJZ12ItO5bGtegfB ykgUs76ElH1fGvWBpaHqh3roImc7MGkhCMh7+G2lE7aeYsUXn5wHdBFE wZBaards8JcMEcT8nHyKHNZlq9fAhQ36guqGdZuRPqxgYfwz71VJb2t9 6KX/5w=="); ok( $rsakeyrr, 'RSA public key created'); # test 1 open (RSA,">$keypathrsa") or die "Could not open $keypathrsa"; print RSA $privrsakey; close(RSA); my $keypathrsasha1="t/Ktest.tld.+005+32972.private"; my $privrsasha1key= << 'ENDRSASHA1' ; Private-key-format: v1.2 Algorithm: 5 (RSASHA1) Modulus: mI5MpW3OGQbD3X9aW9xCYbeKeyXh+NTOL1vts93rKuyq/cLIZsrJVG5LZlWHa7kEL3I1c0qj3fPZww6HRWtJeDZlSC3U81XeTE4z1vlJHYITiiLcyqUX1qK3/CGKeU6OlvhDL6mglshW2pPvKEs/SWEIRLP0/gahH0fJ1SAVfq8= PublicExponent: Aw== PrivateExponent: ZbQzGPPeu1nX6P+RkpLW68+xp26WpeM0H5Ked+lHcfMcqSyFmdyGOEmHmY5aR9CtdPbOTNxtPqKRLLRaLkeGTxyyxxapT8seZu5+r+Xniq+F+iHFG9nvQW+gB03WRvLJUf//mDKt7qBnXRVTqh51BXMQR5S80afmFMEFf8Q3hMs= Prime1: yjowRynvf+0mtTXljuFkKvq0xYNlts5ArRhSNV4+HRcSHCjrMGwbkJKQIhU38JxaVUPsBp8WA+geGxZCxBUXNw== Prime2: wR7tRK0MJUOLMz/pkYxpT8/eKrG7J2Kzzi+e92rQxUmJ3BrgLS+VRyk+0dxxLPNm3yvtTjqtht/iCytSta0gSQ== Exponent1: htF1hMafqp4ZziPuX0Dtcfx4g6zued7VyLrheOl+vg9haBtHdZ1ntbcKwWN6oGg8ONfyrxS5V/AUEg7XLWNkzw== Exponent2: gL9I2HNdbi0Hd3/xC7Lw39/pccvSGkHNNB+/T5yLLjEGkryVc3UOL3DUi+hLc0zvP3KeNCceWeqWshzhznNq2w== Coefficient: XST5nq13vpLpNiATuLDRWc5HvJfrZ6qw2qYgKBJ635Fye4N8XUM9Gxm1DxVrhJnSjER4r7WgqMmcnJyP39VCAw== ENDRSASHA1 my $rsasha1keyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 5 AQOYjkylbc4ZBsPdf1pb3EJht4p7JeH41M4vW+2z3esq7Kr9wshmyslU bktmVYdruQQvcjVzSqPd89nDDodFa0l4NmVILdTzVd5MTjPW+UkdghOK ItzKpRfWorf8IYp5To6W+EMvqaCWyFbak+8oSz9JYQhEs/T+BqEfR8nV IBV+rw=="); ok( $rsasha1keyrr, 'RSASHA1 public key created'); # test 2 open (RSASHA1,">$keypathrsasha1") or die "Could not open $keypathrsasha1"; print RSASHA1 $privrsasha1key; close(RSASHA1); my $keypathdsa="t/Ktest.tld.+003+09734.private"; my $privdsakey= << 'ENDDSA' ; Private-key-format: v1.2 Algorithm: 3 (DSA) Prime(p): 7m5wm/8KMO1fLaBB2Wbq3s0/jMudrauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/joY2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srlslykC+LQRnsbxB5YJMgmkPaPZU8GpRcc= Subprime(q): jRgd5fwOUwUmNpcD6Uzs/tMzy3U= Base(g): a0/+JhZhnci+P8/GOvnokG3NAF10o0Pf6/oz5UpcmX89KqjPvn9aRTRI9sM2AJgFBkzrQhXcx9NPvhneW0zN/baQhaUkupJ8YazNkkVKfOM6aH9h8ONVgGNRiLEBILQa07EMzce9/+JDYFbOCajJqhb9MZlTau17GDDK+r4okJ0= Private_value(x): C7O98kp8pfDdqeuvD83nf1xc4sI= Public_value(y): kFKU1HfmfRxPWwS9mA3FBHZ9LbmEizsH7vFSD7m31crIDVpxIO02bhKyFAuurKNh6naG4iTo3ak0yv6/bP8VNFIxN2QHPnnQL72ctUpvMLe+kWX7fGXuXWPIUCWVnbAeP2SnxpjxU039E9A2Rk6Dp9Eu0oXsM8hcUUnRv6ekycA= ENDDSA my $dsakeyrr=new Net::DNS::RR ("test.tld. IN DNSKEY 256 3 3 CI0YHeX8DlMFJjaXA+lM7P7TM8t17m5wm/8KMO1fLaBB2Wbq3s0/jMud rauMDg1G3SrOWOgX2AITudhGzT0c0FTxztM81IbmVETd/l5XXUEG0/jo Y2DNeyxD6I4Y94VcgUyf0l9ronUw+wXBhWCuueJPXSDIbbUDdcI7srls lykC+LQRnsbxB5YJMgmkPaPZU8GpRcdrT/4mFmGdyL4/z8Y6+eiQbc0A XXSjQ9/r+jPlSlyZfz0qqM++f1pFNEj2wzYAmAUGTOtCFdzH00++Gd5b TM39tpCFpSS6knxhrM2SRUp84zpof2Hw41WAY1GIsQEgtBrTsQzNx73/ 4kNgVs4JqMmqFv0xmVNq7XsYMMr6viiQnZBSlNR35n0cT1sEvZgNxQR2 fS25hIs7B+7xUg+5t9XKyA1acSDtNm4SshQLrqyjYep2huIk6N2pNMr+ v2z/FTRSMTdkBz550C+9nLVKbzC3vpFl+3xl7l1jyFAllZ2wHj9kp8aY 8VNN/RPQNkZOg6fRLtKF7DPIXFFJ0b+npMnA"); ok( $dsakeyrr, 'RSA public key created'); # test 3 open (DSA,">$keypathdsa") or die "Could not open $keypathdsa"; print DSA $privdsakey; close(DSA); my $datarrset=[$dsakeyrr, $rsakeyrr, $rsasha1keyrr]; my $PrivateRSA=Net::DNS::SEC::Private->new($keypathrsa); my $PrivateRSASHA1=Net::DNS::SEC::Private->new($keypathrsasha1); my $PrivateDSA=Net::DNS::SEC::Private->new($keypathdsa); for (my $i=0;$inew("test.test"); $update_rsa->push("update", Net::DNS::rr_add("test.test.test 3600 IN A 10.0.0.1")); $update_rsa->sign_sig0($PrivateRSA); my $update_rsasha1 = Net::DNS::Update->new("test.test"); $update_rsasha1->push("update", Net::DNS::rr_add("test.test.test 3600 IN A 10.0.0.1")); $update_rsasha1->sign_sig0($PrivateRSASHA1); my $update_dsa = Net::DNS::Update->new("test.test"); $update_dsa->push("update", Net::DNS::rr_add("test.test.test 3600 IN A 10.0.0.1")); $update_dsa->sign_sig0($PrivateDSA); $update_rsa->data; $update_rsasha1->data; $update_dsa->data; my $sigrrsa=$update_rsa->pop("additional"); my $sigrrsasha1=$update_rsasha1->pop("additional"); my $sigrrdsa=$update_dsa->pop("additional"); ok ($sigrrsa->verify($update_rsa, $rsakeyrr),'RSA SIG0 verification of packet data'); is( $sigrrsa->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ok ($sigrrsasha1->verify($update_rsasha1, $rsasha1keyrr),'RSASHA1 SIG0 verification of packet data'); is( $sigrrsasha1->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); ok ($sigrrdsa->verify($update_dsa, $dsakeyrr),'DSA SIG0 verification of packet data'); is( $sigrrdsa->vrfyerrstr, "No Error", "vrfyerrstr eq No Error"); my $sigdsa= create Net::DNS::RR::RRSIG($datarrset,$keypathdsa, ( ttl => 360, # sigval => 100, )); # Verify the just created signatures ok ($sigdsa->verify($datarrset,$dsakeyrr), 'DSA sig verifies'); my $sigrsa= create Net::DNS::RR::RRSIG($datarrset,$keypathrsa, ( ttl => 360, # sigval => 100, )); # Verify the just created signatures ok ($sigrsa->verify($datarrset,$rsakeyrr), 'DSA sig verifies'); my $sigrsasha1= create Net::DNS::RR::RRSIG($datarrset,$keypathrsasha1, ( ttl => 360, # sigval => 100, )); # Verify the just created signatures ok ($sigrsasha1->verify($datarrset,$rsasha1keyrr), 'DSA sig verifies'); } unlink($keypathrsa); unlink($keypathrsasha1); unlink($keypathdsa); Net-DNS-SEC-0.16/t/12-nsec++.t000644 000765 000120 00000006564 11346437006 015233 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 12-nsec++.t 778 2008-12-30 17:19:35Z olaf $ # use Net::DNS::SEC; use Test::More tests=>17; use Data::Dumper; use Net::DNS::RR::NSEC3 qw( name2hash ); use strict; BEGIN {use_ok('Net::DNS'); } # test 1 # Example draft-ietf-dnsext-nsec-rdata-01 my $typebmhex=" 00 06 40 01 00 00 00 03 04 1b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20"; $typebmhex=~ s/\s//g; my $typebm=pack("H*",$typebmhex); is (join(" ",Net::DNS::RR::NSEC::_typebm2typearray($typebm)),"A MX NSEC RRSIG TYPE1234","typebmhex function returns expected"); my @typearray=qw(A MX RRSIG NSEC TYPE1234); $typebm=Net::DNS::RR::NSEC::_typearray2typebm(@typearray); ok(my $rr=Net::DNS::RR->new("alfa.example.com 86400 IN NSEC host.example.com A MX TYPE1234 NSEC RRSIG "), "NSEC generated"); is( $rr->typelist,"A MX NSEC RRSIG TYPE1234","Typelist Correctly generated"); is ($rr->nxtdname,"host.example.com", "nxtdname correctly parsed"); is (unpack("H*",$rr->typebm),$typebmhex,"Typebitmap generated correctly"); # Testing the construction of a new object using hashes and using typelist # instead of bitmaps. my $rr2=Net::DNS::RR->new(name=> "alfa.example.com", ttl=> 86400, type=>"NSEC", nxtdname=>"host.example.com", typelist=>" A MX TYPE1234 NSEC RRSIG ", ); is( unpack("H*",$rr2->typebm()), unpack("H*",$rr->typebm()), "typebitmaps equal"); is( join(" ", sort split(' ',$rr2->typelist())), join(" ", sort split(' ',$rr->typelist())), "typelists equal"); my $newbitmap="00060008000000031606000000000002"; my $newtypelist="NSEC PTR RRSIG TYPE5678"; $rr->typelist($newtypelist); is (unpack("H*",$rr->typebm()),$newbitmap,"typebm appropritatly changed after invoking typelist method"); $rr2->typebm(pack("H*",$newbitmap)); is ($rr2->typelist,$newtypelist,"typelist appropritatly changed after invoking typelist method"); ######################## my $foo={};; bless($foo,"Net::DNS::RR::NSEC3"); $foo->salt("aabbccdd"); # H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom is ("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom",lc Net::DNS::RR::NSEC3::name2hash(1,"example.",12,$foo->saltbin),"name2hash over example"); # H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995 is ("b4um86eghhds6nea196smvmlo4ors995",lc Net::DNS::RR::NSEC3::name2hash(1,"x.w.example.",12,$foo->saltbin),"name2hash over example"); # H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh is ("0va5bpr2ou0vk0lbqeeljri88laipsfh",lc Net::DNS::RR::NSEC3::name2hash(1,"c.x.w.example.",12,$foo->saltbin),"name2hash over example"); # H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m is ("92pqneegtaue7pjatc3l3qnk738c6v5m",lc Net::DNS::RR::NSEC3::name2hash(1,"*.x.w.example.",12,$foo->saltbin),"name2hash over example"); my $nsec3param=Net::DNS::RR->new( "alfa.example.com 86400 NSEC3PARAM 2 0 12 aabbccdd", ); ok ($nsec3param, "NSEC3PARAM created"); undef $nsec3param; $nsec3param=Net::DNS::RR->new( "alfa.example.com 86400 NSEC3PARAM 2 0 12 aabbccfs", ); ok (!$nsec3param, "NSEC3PARAM not created with corrupt hex data"); my $hashalg=Net::DNS::SEC->digtype("SHA1"); my $salt=pack("H*","aabbccdd"); my $iterations=12; my $name="*.x.w.example"; my $hashedname= name2hash($hashalg,$name,$iterations,$salt); is( $hashedname,"92pqneegtaue7pjatc3l3qnk738c6v5m","name2hash exports and works"); Net-DNS-SEC-0.16/t/13-utilities.t000644 000765 000120 00000011540 11346437006 016157 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw # Test script for dnssec functionalty # $Id: 13-utilities.t 813 2009-11-27 09:10:10Z olaf $ # # Called in a fashion simmilar to: # /usr/bin/perl -Iblib/arch -Iblib/lib -I/usr/lib/perl5/5.6.1/i386-freebsd \ # -I/usr/lib/perl5/5.6.1 -e 'use Test::Harness qw(&runtests $verbose); \ # $verbose=0; runtests @ARGV;' t/13-utilities use Test::More tests=>6; use strict; use Net::DNS::Keyset; use Net::DNS::SEC qw( key_difference); my $rr; my @keyrr; my @keyrr2; my @sigrr; # Note that the order on pushing the RRsigs is important for # succesfully testing. # All signatures have expiration date in 2030... this test should work for a while $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQOxFlzX8vShSG3JG2J/fngkgy64RoWr8ovG e7MuvPJqOMHTLM5V8+TJIahSoyUd990ictNv hDegUqLtZ8k5oQq44viFCU/H1apdEaJnLnXs cVo+08ATlEb90MYznK9K0pm2ixbyspzRrrXp nPi9vo9iU2xqWqw/Efha4vfi6QVs4w== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO4jhl6ilWV2mYjwWl7kcxrYyQsnnbV7pxX m48p+SgAr+R5SKyihkjg86IjZBQHFJKZ8RsZ dhclH2dikM+53uUEhrqVGhsqF8FsNi4nE9aM ISiX9Zs61pTYGYboYDvgpD1WwFbD4YVVlfk7 rCDP/zOE7H/AhkOenK2w7oiO0Jehcw== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); my $poppedkey=Net::DNS::RR->new($rr->string); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO5fWabr7bNxDXT8YrIeclI9nvYYdKni3ef gJfU749O3QVX9MON6WK0ed00odQF4cLeN3vP SdhasLDI3Z3TzyAPBQS926oodxe78K9zwtPT 1kzJxvunOdJr6+6a7/+B6rF/cwfWTW50I0+q FykldldB44a1uS34u3HgZRQXDmAesw== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN DNSKEY 256 3 5 ( AQO6uGWsox2oH36zusGA0+w3uxkZMdByanSC jiaRHtkOA+gIxT8jmFvohxQBpVfYD+xG2pt+ qUWauWPFPjsIUBoFqHNpqr2/B4CTiZm/rSay HDghZBIMceMa6t4NpaOep79QmiE6oGq6yWRB swBkPZx9uZE7BqG+WLKEp136iwWyyQ== ) "); push(@keyrr,$rr); push(@keyrr2,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 11354 example.com. GTqyJTRbKJ0LuWbAnNni1M4JZ1pn+nXY1Zuz Z0Kvt6OMTYCAFMFt0Wv9bncYkUuUSMGM7yGG 9Z7g7tcdb4TKCqQPYo4gr3Qj/xgC4LESoQs0 yAsJtLUiDfO6e4aWHmanpMGyGixYzHriS1pt SRzirL1fTgV+kdNs5zBatUHRnQc=) "); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 28109 example.com. WemQqA+uaeKqCy6sEVBU3LDORG3f+Zmix6qK 9j1WL83UMWdd6sxNh0QJ0YL54lh9NBx+Viz7 gajO+IM4MmayxKY4QVjp+6mHeE5zBVHMpTTu r5T0reNtTsa8sHr15fsI49yn5KOvuq+DKG1C gI6siM5RdFpDsS3Rmf8fiK1PyTs= )"); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 33695 example.com. M3yVwTOMw+jAKYY5c6oS4DH7OjOdfMOevpIe zdKqWXkehoDg9YOwz8ai17AmfgkjZnsoNu0W NMIcaVubR3n02bkVhJb7dEd8bhbegF8T1xkL 7rf9EQrPmM5GhHmVC90BGrcEhe//94hdXSVU CRBi6KPFWSZDldd1go133bk/b/o= )"); push(@sigrr,$rr); $rr=Net::DNS::RR->new("example.com 100 IN RRSIG DNSKEY 5 2 100 20300101000000 ( 20040601105519 39800 example.com. Mmhn2Ql6ExmyHvZFWgt+CBRw5No8yM0rdH1b eU4is5gRbd3I0j5z6PdtpYjAkWiZNdYsRT0o P7TQIsADfB0FLIFojoREg8kp+OmbpRTsLTgO QYC95u5WodYGz03O0EbnQ7k4gkje6385G40D JVl0xVfujHBMbB+keiSphD3mG4I= )"); push(@sigrr,$rr); # # Test key_difference function from Net::DNS::SEC # # @keyrr and @keyrr2 contain exactly the same data, we'll now add two different # keys to @keyrr2 and to an array to compare the results agains. my @result; my @testresult; $rr=Net::DNS::RR->new("example.com. IN DNSKEY 256 3 5 AQOxZqVCFGc1pNh8TVnxPwcEauBXgxKFOc9stE/aKCQP/2vFE7N2agu+ /LlQlTmKFWLaGfJnVazLDEFi3Fp4PK1Z"); push(@keyrr2,$rr); push(@testresult,$rr); $rr=Net::DNS::RR->new("example.com. IN DNSKEY 256 3 5 AQOURUjSxNm1X5wIfSzUHWl8kOpVwCFVaCpn/qrIrdOMTetNA1M3Ph4g xaH+JNxYETFw+cH9ZZqhawd95mON1HJv"); push(@keyrr2,$rr); push(@testresult,$rr); ok(!key_difference(\@keyrr2,\@keyrr,\@result), "key_difference returns 0 as return code"); #test 1 ok( eq_array(\@result,\@testresult),"key_difference fills the return array with correct values"); # test 2 my $dummy=Net::DNS::RR->new("example.com IN A 10.0.0.1"); push(@keyrr2,$dummy); is(key_difference(\@keyrr2,\@keyrr,\@result),"First array contains something different than a Net::DNS::RR::DNSKEY objects (Net::DNS::RR::A)", "key_difference returns proper error with non DNSKEY objects in 1st array"); # test 3 is(key_difference(\@keyrr,\@keyrr2,\@result),"Second array contains something different than a Net::DNS::RR::DNSKEY objects (Net::DNS::RR::A)", "key_difference returns proper error with non DNSKEY objects in 2nd array"); #test 4 # Remove that dummy again. pop (@keyrr2); @result=(); ok( !key_difference(\@keyrr,\@keyrr2,\@result), "key_difference returns 0 as return code"); # test 5 is (@result,0,"key_difference returned empty array when 1st array is subset of 2nd"); # test 6 Net-DNS-SEC-0.16/t/14-misc.t000644 000765 000120 00000023370 11346437006 015104 0ustar00olafadmin000000 000000 # $Id: 14-misc.t 813 2009-11-27 09:10:10Z olaf $ -*-perl-*- # # # This is a hodgepodge of tests that are used to reproduce bugs found in # previous releases. use Test::More; use strict; use Net::DNS; plan tests=>4; my $nsec1=Net::DNS::RR->new( "example.com. 300 NSEC itemA.with.caps.example.com. NS SOA TXT RRSIG NSEC DNSKEY"); my $nsec2=Net::DNS::RR->new( "itemA.with.caps.example.com. 300 NSEC itemb.without.caps.example.com. TXT RRSIG NSEC"); my $sig_nsec1=Net::DNS::RR->new('example.com. 300 RRSIG NSEC 5 2 300 20301204005203 ( 20051104005258 6227 example.com. gXP6L0gw0WRfjVRn1I4KnQf5Eg0qsMScYjBW A8lWQHUx1JOIikLbsD+NA8sl9sIkHwxTeTdJ 2CycDZdHoy/QI3oRG1DVqiXIBD0PhKcdxO6e j65l8BokA0imnxwccufJjLKBhGO9argi+R72 TNDxDU5OVKjglSosSOtjcwI5T+bJfgM62MsU 1BWByNA2suCWxANhL9r+Tl9UZttdZ+cH8Xfw Fng2MSNaZw+snCCeE8sFqycY0DcnTub/O9bK NQErcKN9pK/BHGfQp4b8hHaeWF3nQbEVdA/y ISrgNXaJ4hQ0PhdxYbE5nO4KUPcDalPj1fW4 VxHnQg69lIz3QcgO0Q== ) '); my $sig_nsec2=Net::DNS::RR->new("itemA.with.caps.example.com. 300 RRSIG NSEC 5 5 300 20301204005203 ( 20051104005258 6227 example.com. zb11rwmxrgbfzIVV0V/wlJdAvmy1qZueQ1F7 UTtImaxbxZCrTeGmWyJE3iZAMQp2m+ybTrU0 wIXCPCd8kG9bBQUJJTO02tnJRDsiVOxJjVkS XbLOAZl9ycBT/A+963hAw7MS0oH3FxreyXHw PXrk8VHEOU7kZFNOGHsQZutlPWbucbMX/RrP 8Hso3h1aZ6SphA3K4a4UMVnlpezb2T+pWqV8 nM5Sj0x1UGIZFLMpWpF0o/dPMsdzaW4vizTk DySeu0BXDcWO2eIPdKTd80yHTITh8JrvJB1s pupGkoAN2VgNKTUZ3wE5oeAdUP7Sn7TPTLnk a8rvoxcqm6hqdrYsuQ== )"); my $dnskey=Net::DNS::RR->new('example.com 3600 DNSKEY 256 3 5 ( AQPaoHW/nC0fj9HuCW3hACSGiP0AkPS3dQFX DlEUjv1orbtx06TMmVKGK5K564OSd6UCf4ZQ Eu2CMPSAUFGHEZuANKYGwZh0k/HeoVNeom1L 3Nt4tVLiGMzrPQskzeK8sr1NKgqFmckQllMW d0ob8Ud6nqeQLHvXQgv1iHX3dpBIPLYbRCzu eqC5k09APl25PgJjjreyRXrxodvoiiaLHpdL 5NtM2S9eok2zmuRpYQSF1LTNfWwY9CkgL017 Z/Zv00SbcoTM/eTXPqijGtUhh6UX1gX89ybe yjtfcGbmTcB+I79NykZWoddO8zyzBXzzfFwt sAuryjQ/HFa5r4mrbhkJ ) ; key id = 6227 '); my $sig_nsec1_ldns=Net::DNS::RR->new(" example.com. 300 IN RRSIG NSEC RSASHA1 2 300 20380119031407 200703 09133715 6227 example.com. aXhXGPs5tiGFM4NFmgtsj7jW4p6A/hnY2JOwfD/gK1bFTIF/wHTRh na7t1L3auWileX1OymoivDw+HzoRnpL+IStqv4/7P0mMHGwwuyjhpMry8FMf1p3La8IzMV8pmAYsEENb 3izYio3Hjrvvnw2uv2IWOgf1zPmndlmV0B5gOuSJEkyDFP8Z6Zshaou+oGjmDGwMNt0e6IW7yg2r92+9 NNJiGk3EcRnC0uzFVs/4/zlcoTjd4bnK4hQIGyPGOFiC6ATdfIZzVybrUL3tYA1enSh1lBqVh4KVuq9q LkqaBzpNelbwXcSnd5ohLgC/thqMfuYjHnUT1sVEt5uQRL4XA== "); my $sig_nsec2_ldns=Net::DNS::RR->new(" itema.with.caps.example.com. 300 IN RRSIG NSEC RSASHA1 5 300 20380 119031407 20070309133715 6227 example.com. vvoRDdVtmRhnePyN9Fcm4+vUN7WR4VV6BP68o oHwqmYcllKB6dW1blPupRlVknxhpdGuiSt9D6AhBRFxZNKYhC0mPECHhIXD7wdM/ubMw5ebvRX25DdNy JmVeA1Dz2/mJDgId7reofns8AlFL0xgx5OytIQdiA8HVJqJqDOr3EQsnkhMZ575icJIuDwws7IHNDDZD 8QmEAw4RT/+b8bq3VkAKT6XHiFXBvpfMRHw/W3xOfJgYKckZAku2wSt8caWDooneIOUQxrEG5PR+jtHq zVSxaZtgZ0t9ZR2BPDjgXg3F4kxDetFzqSfjg1fhs+dD9nIn6mGmvNOL71l8vauIA== "); my $data=[$nsec1]; ok($sig_nsec1->verify($data, $dnskey),"Data did validate") || diag $sig_nsec1->vrfyerrstr; my $data2=[$nsec2]; ok($sig_nsec2->verify($data2, $dnskey),"Data validated") || diag $sig_nsec2->vrfyerrstr; #diag "PERL VERSION $]"; #diag "TIME::Local VERSION $Time::Local::VERSION"; SKIP:{ skip "Time::Local seems to check on unix time use beyond 2032", 2 if $Time::Local::VERSION > 1.11; ok(! $sig_nsec1_ldns->verify($data, $dnskey),"Data did not validate (now generated with 'broken signer')") || diag $sig_nsec1_ldns->vrfyerrstr; $data2=[$nsec2]; ok($sig_nsec2_ldns->verify($data2, $dnskey),"Data validated") || diag $sig_nsec2_ldns->vrfyerrstr; } my $UUencodedPacket=" 1e 71 85 00 00 01 00 00 00 04 00 05 05 69 74 65 6d 61 04 77 69 74 68 04 63 61 70 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 c0 1c 00 06 00 01 00 00 01 2c 00 2a 03 6e 73 31 c0 1c 04 6f 6c 61 66 05 64 61 63 68 74 03 6e 65 74 00 77 83 47 cf 00 00 01 c2 00 00 02 58 00 05 46 00 00 00 01 2c c0 1c 00 2e 00 01 00 00 01 2c 01 1f 00 06 05 02 00 00 0e 10 72 98 2e 33 43 6a b0 ea 18 53 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 5c 7c 61 27 63 19 fb 78 6e 3f 24 4b 03 09 96 fa 3a 65 e3 5d 36 76 ed 16 1f a3 04 28 e2 e8 3c a9 6d 84 1e f6 33 cb 66 62 17 9f 1a 69 3b d9 e9 59 dd 88 64 14 9f 3d f9 38 43 fe 43 de 80 d9 7d 8a 50 1f ae 7c 17 5e 1a ce 51 eb 4a 8a f0 f4 5e a7 0c 50 07 f3 88 ef 8b 8f 6d 6f dd 9f 25 4c dd eb fd 99 89 09 c2 d8 69 aa d2 d3 e8 be 00 fd c4 9f 3f 92 4f 4c 19 8e 3d 7d 1a bd 6a 38 ed c5 18 57 21 b7 88 6c 46 4d fe 5d 2d 24 ab f2 71 30 34 a3 a5 d9 be e4 f7 ab 62 90 35 b6 dd 9c 83 f4 93 fe 7c 7e 2d 97 e3 5d a8 65 e6 b4 43 e0 06 ca 92 82 13 86 a3 50 44 58 72 53 b2 7e 28 2c c2 de 8e 25 70 86 66 77 8a d6 f6 b9 e3 d2 4d 10 ce c8 f2 cb d9 d5 c8 10 f0 b5 ee bc d8 39 4a 82 b4 ea f7 f9 9a 05 6e 1d a4 07 15 f9 1a 70 03 f3 7c 9d e7 6c cc 2e 1c 16 cf bf c0 3a 37 4e c8 20 66 00 ac 59 c0 0c 00 2f 00 01 00 00 01 2c 00 28 05 69 74 65 6d 62 07 77 69 74 68 6f 75 74 04 63 61 70 73 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 06 00 00 80 00 00 03 c0 0c 00 2e 00 01 00 00 01 2c 01 1f 00 2f 05 05 00 00 01 2c 72 98 2e 33 43 6a b0 ea 18 53 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 cd bd 75 af 09 b1 ae 06 df cc 85 55 d1 5f f0 94 97 40 be 6c b5 a9 9b 9e 43 51 7b 51 3b 48 99 ac 5b c5 90 ab 4d e1 a6 5b 22 44 de 26 40 31 0a 76 9b ec 9b 4e b5 34 c0 85 c2 3c 27 7c 90 6f 5b 05 05 09 25 33 b4 da d9 c9 44 3b 22 54 ec 49 8d 59 12 5d b2 ce 01 99 7d c9 c0 53 fc 0f bd eb 78 40 c3 b3 12 d2 81 f7 17 1a de c9 71 f0 3d 7a e4 f1 51 c4 39 4e e4 64 53 4e 18 7b 10 66 eb 65 3d 66 ee 71 b3 17 fd 1a cf f0 7b 28 de 1d 5a 67 a4 a9 84 0d ca e1 ae 14 31 59 e5 a5 ec db d9 3f a9 5a a5 7c 9c ce 52 8f 4c 75 50 62 19 14 b3 29 5a 91 74 a3 f7 4f 32 c7 73 69 6e 2f 8b 34 e4 0f 24 9e bb 40 57 0d c5 8e d9 e2 0f 74 a4 dd f3 4c 87 4c 84 e1 f0 9a ef 24 1d 6c a6 ea 46 92 80 0d d9 58 0d 29 35 19 df 01 39 a1 e0 1d 50 fe d2 9f b4 cf 4c b9 e4 6b ca ef a3 17 2a 9b a8 6a 76 b6 2c b9 c1 e0 00 30 00 01 00 00 0e 10 01 06 01 01 03 05 01 03 d4 8a cc cc 30 08 b7 e9 a8 31 fd 5f bb 4f 0f 79 97 c3 d8 9a 85 63 1d 6b ce 2b 1c 7f d2 21 fc 64 4d ec 74 4a 90 9d c0 9e 26 0e c8 55 0f 8b 35 64 8f f6 64 ff 07 6e 9e 41 be 56 67 62 0a 17 33 45 41 33 0d 8b ab a6 fb 28 77 9f 2b 5a cf 03 b0 3b 1d 34 d9 51 a7 c2 96 30 9d 41 55 dd b6 79 05 c8 16 0b cc 2b 53 35 46 80 25 48 bd 7f 9b 7a c6 6b 21 73 18 eb 4c ab 89 1a 90 a8 d1 8e 0e 72 a8 d9 3e b3 61 ec 1f 0b 0e 25 63 14 4a 61 3e 91 a8 0d 32 f2 72 6a c8 b4 66 79 9d 27 60 fe ae bc 36 23 1c 4b bb 9a a5 1f 5c 1c de 64 d3 32 dd 68 12 09 36 d0 a0 af d1 69 24 7b 69 d4 e0 4d ee 6d f7 bd 9c e7 50 e2 ed 30 b0 c6 90 f3 09 f0 0a b8 f3 e4 96 20 4c f5 9d 31 e2 00 b4 01 97 ce e4 c6 b4 a7 e7 61 7f 69 3b c1 f9 7c 9b cc 44 38 43 09 21 32 e8 a3 2f 3c 36 1f ae d9 cf 47 17 5b 70 d2 76 87 c1 e0 00 30 00 01 00 00 0e 10 01 06 01 00 03 05 01 03 da a0 75 bf 9c 2d 1f 8f d1 ee 09 6d e1 00 24 86 88 fd 00 90 f4 b7 75 01 57 0e 51 14 8e fd 68 ad bb 71 d3 a4 cc 99 52 86 2b 92 b9 eb 83 92 77 a5 02 7f 86 50 12 ed 82 30 f4 80 50 51 87 11 9b 80 34 a6 06 c1 98 74 93 f1 de a1 53 5e a2 6d 4b dc db 78 b5 52 e2 18 cc eb 3d 0b 24 cd e2 bc b2 bd 4d 2a 0a 85 99 c9 10 96 53 16 77 4a 1b f1 47 7a 9e a7 90 2c 7b d7 42 0b f5 88 75 f7 76 90 48 3c b6 1b 44 2c ee 7a a0 b9 93 4f 40 3e 5d b9 3e 02 63 8e b7 b2 45 7a f1 a1 db e8 8a 26 8b 1e 97 4b e4 db 4c d9 2f 5e a2 4d b3 9a e4 69 61 04 85 d4 b4 cd 7d 6c 18 f4 29 20 2f 4d 7b 67 f6 6f d3 44 9b 72 84 cc fd e4 d7 3e a8 a3 1a d5 21 87 a5 17 d6 05 fc f7 26 de ca 3b 5f 70 66 e6 4d c0 7e 23 bf 4d ca 46 56 a1 d7 4e f3 3c b3 05 7c f3 7c 5c 2d b0 0b ab ca 34 3f 1c 56 b9 af 89 ab 6e 19 09 c1 e0 00 2e 00 01 00 00 0e 10 01 1f 00 30 05 02 00 00 0e 10 72 98 2e 33 43 6a b0 ea 18 53 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 82 7f 52 b3 ef 94 9b 28 76 7e cd 95 f5 3c f7 cf a7 2e a6 01 7b c8 99 64 f7 86 91 9f 52 dc a4 9e 42 73 d0 d1 e5 fd 83 56 c8 77 e5 17 03 72 19 c1 f8 60 09 0f c3 49 43 29 a7 eb 41 84 8b e9 e6 69 c1 68 94 24 6f bd b0 58 73 45 d4 70 39 20 c1 d8 65 5e 8c 7b d9 61 6c 7d 02 0d 34 21 94 58 fa f2 13 a3 bb d6 a0 e3 3e b1 fd 09 a3 73 9b ee 8b f3 4d c7 09 a8 6d dc 7f 72 c7 8b 82 6e 3f 8b da 11 99 4d 2d 3b 76 d6 90 23 f8 84 6c 7c 9b 77 7a 6f 8d 35 e0 f3 37 44 77 9c ec d0 9b b5 f7 f1 13 ec b9 ab 3f d6 b6 05 3f cc 76 0a 6f 7a ab f5 1a fe 91 05 1d a0 9f 45 ea c3 b4 ab 0a 15 c4 c7 68 0b cc 57 a8 d1 65 18 c9 46 3d 4d b3 d0 60 d3 79 76 48 cf 26 ba dc aa 0c 1d a1 60 c7 9d e8 69 c2 0f 6a 8c ff 14 32 6b c3 bb d1 00 88 96 2f cf b8 0c b8 bb 6e e9 38 b9 c7 fe 6b af a0 06 2e 52 f7 26 c5 2f 00 2e 00 01 00 00 0e 10 01 1f 00 30 05 02 00 00 0e 10 72 98 2e 33 43 6a b0 ea 9e ac 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 40 11 fa b5 16 85 0b 01 66 67 78 a6 ce bb 87 89 a6 a0 de 2c 3c 71 f3 f1 02 17 6a 69 0c ec 49 d2 3b 28 6b fc e6 0b 8b 64 24 d3 18 57 16 b9 25 d6 e3 48 3a 85 da f0 10 ed 5a 8c 94 0d 2e 41 c3 06 ae c5 45 06 b2 b4 16 a2 f7 0e 97 6b d5 ce dc c3 cd 09 9d 5e 68 3a 66 5f c9 9e f5 b0 f3 ca 60 5b 55 04 e9 3d eb b0 5d 60 43 1b ac 1e ac e5 a8 19 12 6b 18 5e f5 b0 c9 a0 48 02 72 70 fa 57 97 ff 49 14 a5 dc 33 b2 9e 7c 14 75 2a df e9 1d d3 67 be 52 a1 f1 69 ec 3f a6 ff c9 c4 dd 7b 06 ac df 41 a3 35 50 a0 50 a7 9e 90 66 99 7f a0 ca cf 85 6a 28 f1 c1 1a 10 f7 2a 04 a8 bd a1 47 c3 f0 0f 49 a0 a8 95 76 d9 95 50 56 c1 66 e8 45 46 ee 2d c6 94 b2 5f b1 2c f4 3d ab 28 2a 65 47 94 cc b2 63 ac a6 00 63 ff 51 72 5e fd f8 67 45 8b 44 2f 00 ed 8c f0 77 a7 99 42 77 39 99 d1 b1 83 ef 48 00 00 29 10 00 00 00 80 00 00 00 "; $UUencodedPacket =~ s/\s*//g; my $packetdata = pack('H*',$UUencodedPacket); my $packet = Net::DNS::Packet->new(\$packetdata); #$packet->print; Net-DNS-SEC-0.16/t/15-ds.t000644 000765 000120 00000003703 11346437006 014556 0ustar00olafadmin000000 000000 # $Id: 15-ds.t 813 2009-11-27 09:10:10Z olaf $ -*-perl-*- # # # These are test that relate to DS RRs. # Mainly used during implementation of the SHA256 algorithm use Test::More; use strict; use Net::DNS; plan tests=>3; my $dnskeyrr=Net::DNS::RR->new('dskey.example.com. 86400 IN DNSKEY 256 3 5 ( AQOeiiR0GOMYkDshWoSKz9Xz fwJr1AYtsmx3TGkJaNXVbfi/ 2pHm822aJ5iI9BMzNXxeYCmZ DRD99WYwYqUSdjMmmAphXdvx egXd/M5+X7OrzKBaMbCVdFLU Uh6DhweJBjEVv5f2wwjM9Xzc nOf+EPbtG9DMBmADjFDc2w/r ljwvFw== ) ; key id = 60485'); my $dsrr=Net::DNS::RR->new('dskey.example.com. 86400 IN DS 60485 5 2 ( D4B7D520E7BB5F0F67674A0C CEB1E3E0614B93C4F9E99B83 83F6A1E4469DA50A )'); $dsrr->print; ok($dsrr->verify($dnskeyrr),"Validated the SHA256 DS"); my $newdsrr=create Net::DNS::RR::DS($dnskeyrr, ( digtype => "SHA256" ) ); ok($newdsrr->verify($dnskeyrr),"Validated the second SHA256 DS"); my $ds1 = Net::DNS::RR->new( 'algorithm' => 3, 'class' => 'IN', 'digest' => '1234567890ABCDEF', 'digtype' => 5, 'keytag' => 123, 'name' => 'test1dom1.se', 'ttl' => 43200, 'type' => 'DS', 'digestbin' => '' ); #error only occurs when next line is commented my $ds2 = Net::DNS::RR->new( 'algorithm' => 3, 'class' => 'IN', 'digest' => '1234567890ABCDEF', 'digtype' => 5, 'keytag' => 123, 'name' => 'test1dom1.se', 'ttl' => 43200, 'type' => 'DS', ); is ($ds1->string,$ds2->string,"Digestbin calculation correct"); Net-DNS-SEC-0.16/t/16-dlv.t000644 000765 000120 00000002706 11346437006 014740 0ustar00olafadmin000000 000000 # $Id: 16-dlv.t 778 2008-12-30 17:19:35Z olaf $ -*-perl-*- # # # These are test that relate to DLV RRs. # Mainly used during implementation of the SHA256 algorithm use Test::More; use strict; use Net::DNS; plan tests=>2; my $dnskeyrr=Net::DNS::RR->new('dskey.example.com. 86400 IN DNSKEY 256 3 5 ( AQOeiiR0GOMYkDshWoSKz9Xz fwJr1AYtsmx3TGkJaNXVbfi/ 2pHm822aJ5iI9BMzNXxeYCmZ DRD99WYwYqUSdjMmmAphXdvx egXd/M5+X7OrzKBaMbCVdFLU Uh6DhweJBjEVv5f2wwjM9Xzc nOf+EPbtG9DMBmADjFDc2w/r ljwvFw== ) ; key id = 60485'); my $dsrr=Net::DNS::RR->new('dskey.example.com. 86400 IN DLV 60485 5 2 ( D4B7D520E7BB5F0F67674A0C CEB1E3E0614B93C4F9E99B83 83F6A1E4469DA50A )'); $dsrr->print; ok($dsrr->verify($dnskeyrr),"Validated the SHA256 DLV"); my $newdsrr=create Net::DNS::RR::DLV($dnskeyrr, ( digtype => "SHA256" ) ); ok($newdsrr->verify($dnskeyrr),"Validated the second SHA256 DLV"); Net-DNS-SEC-0.16/t/getpacket.pl000755 000765 000120 00000000652 11346437006 016047 0ustar00olafadmin000000 000000 #!/usr/bin/perl -w # Just a little helper program to create the UUencoded packet data in # t/10-keyset. # # There is no real use for it except that you may look at the code. use strict; use Net::DNS::Resolver; my $res = Net::DNS::Resolver->new; $res->dnssec(1); $res->nameservers('10.0.53.203'); my $packet = $res->query ("sub.tld", "KEY", "IN"); $packet->print; my $Uencoded=unpack("H*",$packet->data); print $Uencoded; Net-DNS-SEC-0.16/t/Kexample.com.+001+28551.key000644 000765 000120 00000000323 11346437006 017622 0ustar00olafadmin000000 000000 example.com. IN DNSKEY 256 3 1 AQPR6/oBmgGL77vj0xrgfEaf3pSaJlr+BvxkU8O+Vqcz9dpCDTtsv6BJ 2E6tt+XZ9VgqFtQjhe4gI3dAZ5Wu/xvGqq2BfCExPQxLxG17Nt8iTlu7 NpR9jc+FHFjmRPMyvCE9/iknk7kiwek1ttvv0tNzVKZlWJDC8JUATrFX pm+HCQ== Net-DNS-SEC-0.16/t/Kexample.com.+001+28551.private000644 000765 000120 00000001645 11346437006 020514 0ustar00olafadmin000000 000000 Private-key-format: v1.2 Algorithm: 1 (RSA) Modulus: 0ev6AZoBi++749Ma4HxGn96UmiZa/gb8ZFPDvlanM/XaQg07bL+gSdhOrbfl2fVYKhbUI4XuICN3QGeVrv8bxqqtgXwhMT0MS8RtezbfIk5buzaUfY3PhRxY5kTzMrwhPf4pJ5O5IsHpNbbb79LTc1SmZViQwvCVAE6xV6Zvhwk= PublicExponent: Aw== PrivateExponent: i/Kmq7wBB/Un7TdnQFLZv+m4ZsQ8qVn9mDfX1DnEzU6RgV4nndUVhpA0c8/ukU46xrniwllJasJPgEUOdKoSgzwl/K15z2g+IM52K8CwaPOmVbCP0meiUfmmQuEtZBwUU6/HYWN6zL5jfUERqz+ekkvY1h3DtL3yQq8NvlOibmM= Prime1: 9f/4py2p91NRNzXzmBKakOrgOZlyBM7SgWf6KaLIBCBKqM5Mso3m05XsUiDQnCRAUnTSCyGIemBdug+NBaEUzw== Prime2: 2nSN0LzQKVvJV4ZF/cPqT/dadCNP7Y03pHeHyYxUjeJ1za/Iy/MI0L4NgyCeV0FXkGxSIMmrWUk+jg0tI1rMpw== Exponent1: o//7Gh5xT4zgz3lNEAxnC0dAJmZMAzSMVkVRcRcwAsAxxd7dzF6Z4mPy4Ws1vW2ANviMB2uwUZWT0V+zWRYN3w== Exponent2: kaMJNdM1cOfbj67ZU9fxiqTm+BeKnl4lGE+v27LjCUGj3nUwh/dbNdQJAhW+5NY6YEg2wIZyO4YptAjIwjyIbw== Coefficient: R33iGsdBa8l4YqeSWRMaud+usrKDPw5g6TwZuAoqO1GRLLkSLcGFCWV8m70up4ZD4jPMKTd5Hi6ZqXvKfSqFdw== Net-DNS-SEC-0.16/t/Kexample.com.+005+34247.key000644 000765 000120 00000000323 11346437006 017625 0ustar00olafadmin000000 000000 example.com. IN DNSKEY 256 3 5 AQOqyylc732/AE42mlUE3g44JS3O4tdvUwOK3lwpQ/xOJX6gFLEg/SRK 36FXnXqbJzkqCkwVrCgbA2SM63axme57vbbnppljuiCKf6rxZE2602Yh OLPdsw+1nRRyHZ8fPv761H8bPS9Zcx3IQyE33l1B+tPN9MtQus6fcsQy 2tIwuw== Net-DNS-SEC-0.16/t/Kexample.com.+005+34247.private000644 000765 000120 00000001651 11346437006 020514 0ustar00olafadmin000000 000000 Private-key-format: v1.2 Algorithm: 5 (RSASHA1) Modulus: qsspXO99vwBONppVBN4OOCUtzuLXb1MDit5cKUP8TiV+oBSxIP0kSt+hV516myc5KgpMFawoGwNkjOt2sZnue72256aZY7ogin+q8WRNutNmITiz3bMPtZ0Uch2fHz7++tR/Gz0vWXMdyEMhN95dQfrTzfTLULrOn3LEMtrSMLs= PublicExponent: Aw== PrivateExponent: cdzGPfT+f1WJebw4rele0BjJNJc6SjdXsemSxi1S3sOpwA3La1Nthz/A5ROnEhomHAbdY8gavKzts0ekdmae/BJO5kJi/sbpf18bb0/gcwyngO8yUtFhzCipzFrHwM3hcb+ME3+19OSBTM72wy0/pIMax6BNERHxaxgfdiyDQvs= Prime1: 1GAZ1v3tA96l2os1enQEtINZ/Q2IHsd7Rr32qaTAS9qtTT5DQJKFvTA36+6+UiZ/0OxUaH2VECpuMHvh3vz8xQ== Prime2: zeB0bAb4i+OllnaU8gkJi+eF1NrZWjWIGVfI6869vlIi5+66vQvkXyudIMBUyFdLZT9OG9oiD7oQnhkfuRBPfw== Exponent1: jZVmj1PzV+nD5wd4/E1YeFeRU15avy+nhH6kcRiAMpHI3imCKwxZKMrP8p8pjBmqi0g4RakOCsb0IFKWlKiogw== Exponent2: iUBNnVn7B+0ZDvm4oVtbsppZOJHmPCOwEOUwnTR+fuFsmp8nKLKYP3JowIA4hY+HmNTevTwWtSa1vrtqe2A0/w== Coefficient: OGDWYhImmtzR/wYJyBliYPnn5fbMS/B9eL+PWC0+whBQA5WkPqeImlJKkr7oWZE+VmuxicpW2VPVacMQYsV3dg== Net-DNS-SEC-0.16/SEC/Private.pm000644 000765 000120 00000033410 11346437006 015655 0ustar00olafadmin000000 000000 package Net::DNS::SEC::Private; use vars qw(@ISA $VERSION @EXPORT ); use Net::DNS; use Carp; use bytes; use Crypt::OpenSSL::DSA; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Bignum; use File::Basename; use MIME::Base64; use Math::BigInt; use Time::Local; require Exporter; $VERSION = do { my @r=(q$Revision: 816 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $key_file) = @_; my $self={}; my ($Modulus,$PublicExponent,$PrivateExponent,$Prime1, $Prime2,$Exponent1,$Exponent2,$Coefficient, $prime_p,$subprime_q,$base_g,$private_val_x,$public_val_y); bless ($self,$class); my $keyname=basename($key_file); print "\nKeyname:\t ". $keyname ."\n" if $ debug; #Format something like: /Kbla.foo.+001+60114.private' # assuming proper file name. # We determine the algorithm from the filename. if ($keyname =~ /K(.*)\.\+(\d{3})\+(\d*)\.private/){ $self->{"signame"}=$1."."; $self->{"algorithm"}= 0 + $2; # Force non-string $self->{"keytag"}=$3; }else{ croak "$keyname does not seem to be a valid private key\n"; } open (KEYFH, "<$key_file" ) || croak "Cannot open keyfile: $key_file"; while () { if (/Private-key-format: (v\d*\.\d*)/) { if ($1 ne "v1.2") { croak "Private Key Format not regognized"; } }elsif (/^Algorithm:\s*(\d*)/) { if ($1 != 1 && $1 != 3 && $1 != 5 && $1 !=6 && $1 != 7 && $1 != 8 && $1 != 10 ) { croak "Key $key_file algorithm is not RSA or DSA (those are the only implemented algorithms) "; } } elsif (/^Modulus:\s*(\S+)/) { #RSA $Modulus=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^PublicExponent:\s*(\S+)/) { $PublicExponent=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^PrivateExponent:\s*(\S+)/) { $PrivateExponent=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Prime1:\s*(\S+)/) { $Prime1=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Prime2:\s*(\S+)/) { $Prime2=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Exponent1:\s*(\S+)/) { $Exponent1=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Exponent2:\s*(\S+)/) { $Exponent2=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Coefficient:\s*(\S+)/) { $Coefficient=Crypt::OpenSSL::Bignum->new_from_bin(decode_base64($1)); } elsif (/^Prime\(p\):\s*(\S+)/) { #DSA $prime_p=decode_base64($1); } elsif (/^Subprime\(q\):\s*(\S+)/) { $subprime_q=decode_base64($1); } elsif (/^Base\(g\):\s*(\S+)/) { $base_g=decode_base64($1); } elsif (/^Private_value\(x\):\s*(\S+)/) { $private_val_x=decode_base64($1); } elsif (/^Public_value\(y\):\s*(\S+)/) { $public_val_y=decode_base64($1); } } close(KEYFH); if ($self->{"algorithm"} == 1 || $self->{"algorithm"} == 5 || $self->{"algorithm"} == 7 || $self->{"algorithm"} == 8 || $self->{"algorithm"} == 10) { #RSA $self->{'privatekey'}=Crypt::OpenSSL::RSA-> new_key_from_parameters( $Modulus, $PublicExponent, $PrivateExponent, $Prime1, $Prime2, $Exponent1, $Exponent2, $Coefficient, ); # Trying to determine the keytag my $keytag_from_data1=$self->dump_rsa_keytag(256,1); my $keytag_from_data2=$self->dump_rsa_keytag(257,1); if (($self->{"keytag"} != $keytag_from_data1) && ($self->{"keytag"} != $keytag_from_data2)){ warn "NB: filename seems to have the wrong keytag.\n". "Depending on DNSKEY RR flags set for this key the keytag should be\n". $keytag_from_data1. " or ". $keytag_from_data2. " instead of ".$self->{"keytag"}."\n"; return(0); } }elsif ($self->{"algorithm"} == 3 || $self->{"algorithm"} == 6 ){ #DSA my $private_dsa = Crypt::OpenSSL::DSA->new(); $private_dsa->set_p($prime_p); $private_dsa->set_q($subprime_q); $private_dsa->set_g($base_g); $private_dsa->set_priv_key($private_val_x); $private_dsa->set_pub_key($public_val_y); $self->{"privatekey"}=$private_dsa; } return $self; } sub algorithm { my $self=shift; return $self->{'algorithm'}; } sub privatekey { my $self=shift; return $self->{'privatekey'}; } sub keytag { my $self=shift; return $self->{'keytag'}; } sub signame { my $self=shift; return $self->{'signame'}; } # Little helper function to put a BigInt into a binary (unsigned, #network order ) #sub bi2bin { # my($p, $l) = @_; # $l ||= 0; # my $base = Math::BigInt->new("+256"); # my $res = ''; # { # my $r = $p % $base; # my $d = ($p-$r) / $base; # $res = chr($r) . $res; # if ($d >= $base) { # $p = $d; # redo; # } # elsif ($d != 0) { # $res = chr($d) . $res; # } # } # $res = "\0" x ($l-length($res)) . $res # if length($res) < $l; # $res; #} sub new_rsa_priv { my ($class, $keyblob,$signame,$flags) = @_; my $self={}; bless ($self,$class); $self->{"signame"}=$signame; $self->{"algorithm"}=5; $self->{"flags"}=$flags; $self->{'privatekey'}=Crypt::OpenSSL::RSA-> new_private_key($keyblob); $self->{"keytag"}=$self->dump_rsa_keytag(); return $self; } sub dump_rsa_priv { my $self=shift; my ( $Modulus,$PublicExponent, $PrivateExponent, $Prime1, $Prime2, $Exponent1, $Exponent2,$Coefficient )=$self->{"privatekey"}->get_key_parameters; my $string="Private-key-format: v1.2\n"; $string .= "Algorithm: 5 (RSASHA1)\n"; if (defined $Modulus && defined $PublicExponent && defined $PrivateExponent && defined $Prime1 && defined $Prime2 && defined $Exponent1 && defined $Exponent2 && $Coefficient ){ $string .= "Modulus: ". encode_base64($Modulus->to_bin,"")."\n" ; $string .= "PublicExponent: ". encode_base64($PublicExponent->to_bin,"")."\n" ; $string .= "PrivateExponent: ". encode_base64($PrivateExponent->to_bin,"")."\n"; $string .= "Prime1: ". encode_base64($Prime1->to_bin,"")."\n" ; $string .= "Prime2: ". encode_base64($Prime2->to_bin,"")."\n" ; $string .= "Exponent1: ". encode_base64($Exponent1->to_bin,"")."\n" ; $string .= "Exponent2: ". encode_base64($Exponent2->to_bin,"")."\n" ; $string .= "Coefficient: ". encode_base64($Coefficient->to_bin,"")."\n" ; } else { $string= ""; }; return $string; } sub dump_rsa_pub { my $self=shift; my ( $Modulus,$PublicExponent, $PrivateExponent, $Prime1, $Prime2, $Exponent1, $Exponent2,$Coefficient )=$self->{"privatekey"}->get_key_parameters; return "" unless (defined $Modulus && defined $PublicExponent); my $explength; my $pubexp=$PublicExponent->to_bin; if (length($pubexp)>255){ $explength=pack("C",0).pack("n",length($pubexp)); }else{ $explength=pack("C",length($pubexp)); } return encode_base64($explength.$pubexp.$Modulus->to_bin, ""); } sub dump_rsa_keytag{ my $self=shift; my $flags; if (defined $self->{"flags"}){ $flags=$self->{"flags"} }else{ $flags=shift; } return() unless defined $flags; # This will set flag if empty before, note the undocumented # feature that a non-zero second argument to this function will # _not_ set the flag. $self->{"flags"}=$flags unless shift; my $alg=$self->{"algorithm"}; return () unless ($alg ==1 || $alg ==5 || $alg == 7 || $alg ==8 || $alg ==10); my $key=$self->dump_rsa_pub; return () unless $key; my $tmprr=Net::DNS::RR->new("tmp IN DNSKEY $flags 3 $alg $key"); return $tmprr->keytag; } sub dump_rsa_private_der { my $self=shift; return $self->{"privatekey"}->get_private_key_string; } sub generate_rsa { my ($class) =shift; my $name=shift; my $flags=shift; my $size=shift; $size=1024 if !defined ($size); my $good_entropy=shift; my $self={}; bless ($self,$class); $self->{"signame"}=$name; $self->{"algorithm"}= 5; # Force non-string if (defined($good_entropy)){ Crypt::OpenSSL::Random::random_seed($good_entropy); Crypt::OpenSSL::RSA->import_random_seed(); } $rsa = Crypt::OpenSSL::RSA->generate_key($size); $self->{"privatekey"}=$rsa; $self->{"keytag"}=$self->dump_rsa_keytag($flags); return $self; } 1; =head1 NAME Net::DNS::SEC::Private - DNS SIG Private key object =head1 SYNOPSIS use Net::DNS::SEC::Private; my $private=Net::DNS::SEC::Private->new($keypath); =head1 DESCRIPTION Class containing a the private key as read from a dnssec-keygen generate zonefile. The class is written to be used only in the context of the Net::DNS::RR::SIG create method. This class is not designed to interact with any other system. =head1 METHODS =head2 new $private->new("/home/foo/ Kexample.com.+001+11567.private") Creator method. The argument is the full path to a private key generated by the BIND dnssec-keygen tool. Note that the filename contains information about the algorithm and keyid. =head2 private $private->private Returns the private key material. This is either a Crypt::OpenSSL::RSA or Crypt::OpenSSL::DSA object. This is really only relevant to the Net::DNS::RR::SIG class. =head2 algorithm, keytag, signame $private->algorithm $private->keytag $private->signame Returns components as determined from the filename and needed by Net::DNS::RR::RRSIG. =head1 RSASHA1 specific helper functions These functions may be usefull to read and transfer BIND private keys to and from X509 format. =head2 new_rsa_private Constructor method. my $private=Net::DNS::SEC::Private->new_rsa_private($keyblob,$domain,$flag); Creates a Net::DNS::SEC::Private object from the supplied string. For the object to be useful you will have to provide the "domain" name for which this key is to be used as the second argument and the flag (either 256 or 257 for a non SEP and a SEP key respectivly). The string should include the -----BEGIN...----- and -----END...----- lines. The padding is set to PKCS1_OAEP, but can be changed with the use_xxx_padding methods It is the same =head2 dump_rsa_priv my $bind_keyfilecontent=$private->dump_rsa_priv Returns the content of a BIND private keyfile (Private-key-format: v1.2). An empty string will be returned if not all parameters are available (please supply the author with example code if this ever happens). =head2 dump_rsa_pub my $bind_keyfilecontent=$private->dump_rsa_pub Returns the publick key part of the DNSKEY RR. Returns an empty string on failure. =head2 dump_rsa_keytag my $flags=257; # SEP key. my $keytag=$private->dump_rsa_keytag($flags); This function will calculate the keyt with the value of the DNSKEY flags as input. The flags field may be needed in case it was not specified when the key was created. If the object allready knows it's flags vallue the input is ignored. returns undefined on failure =head2 dump_rsa_private_der my $keyblob=$private->dump_rsa_privat_der Return the DER-encoded PKCS1 representation of the private key. (Same format that can be read with the read_rsa_private method.) =head2 generate_rsa my $keypair=Net::DNS::SEC::Private->generate_rsa("example.com",$flag,1024,$random); prin $newkey->dump_rsa_priv; print $newkey->dump_rsa_pub(); Uses Crypt::OpenSSL::RSA generate_key to create a keypair. First argument is the name of the key, the second argument is the flag field (take a value of 257 for Keysigning keys and a value of 256 for zone signing keys). The 3rd argument is the keysize. If the 4th argument is defined it is passed to the Crypt::OpenSSL::Random::random_seed method (see Crypt::OpenSSL::RSA for details), not needed with a proper /dev/random. =head1 Example This is a code sniplet from the test script. First a new keypair is generated. An Net::DNS::RR object is created by constructing the resource record string - using the dump_rsa_pub() method. Then a self signature over the public key is created and verified. my $newkey=Net::DNS::SEC::Private->generate_rsa("example.com",257,1024); my $tstpubkeyrr= Net::DNS::RR->new ($newkey->signame . " IN DNSKEY 257 3 5 ". $newkey->dump_rsa_pub()); # flags not needed as argument for dump_rsa_keytag $ since they where set by generate_rsa is($tstpubkeyrr->keytag,$newkey->dump_rsa_keytag(), "Consistent keytag calculation"); my $sigrr= create Net::DNS::RR::RRSIG([$tstpubkeyrr],$newkey); is ($sigrr->keytag,$tstpubkeyrr->keytag, "Consisted keytag in the created signature");; ok($sigrr->verify([$tstpubkeyrr],$tstpubkeyrr), "Self verification consistent."); =head1 COPYRIGHT Copyright (c) 2002-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. This code uses Crypt::OpenSSL which uses the openssl library =head1 SEE ALSO L L, L, L, L,L, RFC 2435 Section 4, RFC 2931. =cut Net-DNS-SEC-0.16/RR/DLV.pm000644 000765 000120 00000001640 11346437006 014601 0ustar00olafadmin000000 000000 package Net::DNS::RR::DLV; # # $Id: DLV.pm 580 2006-04-20 15:56:57Z olaf $ # use strict; BEGIN { eval { require bytes; } } use vars qw(@ISA $VERSION); use Net::DNS::RR::DS; @ISA = qw(Net::DNS::RR::DS); $VERSION = (qw$LastChangedRevision: 580 $)[1]; =head1 NAME Net::DNS::RR::DLV - DNS DLV resource record =head1 SYNOPSIS C; =head1 DESCRIPTION This is a clone of the DS record. This class therfore completely inherits all properties of the Net::DNS::RR::DS class. Please see the L perldocumentation for details =head1 COPYRIGHT Copyright (c) 2005 Olaf Kolkman (NLnet Labs) All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L, L, L, L, L, L, L, RFC4431. =cut Net-DNS-SEC-0.16/RR/DNSKEY.pm000644 000765 000120 00000020206 11346437006 015150 0ustar00olafadmin000000 000000 package Net::DNS::RR::DNSKEY; # $Id: DNSKEY.pm 847 2010-03-12 13:04:13Z olaf $ use strict; use vars qw(@ISA $VERSION); use bytes; use Net::DNS::SEC; use MIME::Base64; use Carp; @ISA = qw(Net::DNS::RR Net::DNS::SEC); $VERSION = do { my @r=(q$Revision: 847 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $self, $data, $offset) = @_; bless $self, $class; if ($self->{"rdlength"} > 0) { my $offsettoprot=$offset+2; my $offsettoalg=$offset+3; my $offsettokey=$offset+4; $self->{"flags"}=unpack("n",substr($$data,$offset,2)); $self->{"protocol"}=unpack("C",substr($$data,$offsettoprot,1)); $self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1)); my $keymaterial=substr($$data,$offsettokey,$self->{"rdlength"}-4); $self->{"keybin"}=($keymaterial); $self->{"key"}= encode_base64($keymaterial); } bless $self, $class; $self->setkeytag; return $self; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($flags, $protocol, $algorithm,$key) = $string =~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+(.*)/; $key =~ s/\s*//g; $self->{"flags"}=$flags; $self->{"algorithm"}=Net::DNS::SEC->algorithm($algorithm); $self->{"protocol"}=$protocol; my $keymaterial=decode_base64($key); $self->{"keybin"}=($keymaterial); $self->{"key"}=$key; } bless $self, $class; $self->setkeytag(); return $self; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"flags"}) { $rdatastr = $self->{flags}; $rdatastr .= " " . "$self->{protocol}"; $rdatastr .= " " . $self->algorithm; $rdatastr .= " ( \n" ; # do some nice formatting my $keystring=$self->{key}; $keystring =~ s/\n//g; $keystring =~ s/(\S{36})/$1\n\t\t\t/g; $rdatastr .= "\t\t\t".$keystring; $rdatastr .= " \n\t\t\t) ; Key ID = " . "$self->{keytag}"; } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata { my $self = shift; my $rdata; if (exists $self->{"flags"}) { $rdata= pack("n",$self->{"flags"}) ; $rdata.= pack("C2",$self->{"protocol"} , $self->algorithm) ; $rdata.= $self->{"keybin"} } return $rdata; } sub setkeytag { my $self=shift; if (($self->{"flags"} & hex("0xc000") ) == hex("0xc000") ){ # NULL KEY $self->{"keytag"} = 0; }elsif ($self->algorithm == '1'){ # RFC 2535 4.1.6 most significant 16 bits of the least # significant 24 bits my @keystr=split //, $self->{"keybin"}; my $keysize= $#keystr+1; $self->{"keytag"} = (unpack("C",$keystr[$keysize - 3]) << 8) + unpack("C",$keystr[$keysize - 2]); 0; }else{ # All others # RFC 2535 Appendix C my ($ac, $i); # $self->{"rr_data"} cannot be # used if the object has not been constructed ?!? my $rdata= pack("n",$self->{"flags"}) ; $rdata.= pack("C2",$self->{"protocol"} , $self->algorithm) ; $rdata.= $self->{"keybin"}; my @keyrr=split //, $rdata; for ( $ac=0 , $i=0; $i <= $#keyrr ; $i++ ){ $ac += ($i & 1) ? unpack("C",$keyrr[$i]) : unpack("C", $keyrr[$i])<<8; } $ac += ($ac>>16) & 0xFFFF; $self->{"keytag"} =($ac & 0xFFFF); 0; } } sub set_sep { my $self=shift; return $self->is_sep if $self->is_sep; $self->{"flags"}+=1; $self->setkeytag; return if $self->is_sep; } sub unset_sep { my $self=shift; return $self->clear_sep(); } sub clear_sep { my $self=shift; return $self->is_sep if ! $self->is_sep; $self->{"flags"}-=1; $self->setkeytag; return $self->is_sep; } sub is_sep { my $self=shift; return $self->{"flags"} % 2; # Hey it;s odd. } sub privatekeyname { my $self=shift; return sprintf("K%s.+%03d+%05d.private", $self->name, $self->algorithm, $self->keytag); } # Return the length in bits of a RSA key and DSA key (crypto speaking) # -1 if it's not a know algorithm # RSA part contributed by Hugo Salgado sub keylength { my $self = shift; if ( $self->algorithm("mnemonic") =~ /RSA/ ){ # Modulus length, see RFC 2537 # First we need the total length in the wire rdata my $total = length(unpack("B*",$self->{"keybin"})); # Now we obtain the first octet (exponent length) my $octet = unpack("B8", $self->{"keybin"}); my $expo_length; # If the first octet is zero, we need the next two if ($octet == 0) { # This part is untested. I couldn't create a real key test case :( $octet = unpack("B24", $self->{"keybin"}); $expo_length = unpack("N", pack("B32", substr("0" x 8 . $octet, -24))); $expo_length += 3; # we add the 3 octets with the length } else { $expo_length = unpack("N", pack("B32", substr("0" x 32 . $octet, -32))); $expo_length++; # we add the first octet } # The modulus is the remaining, in bits return $total - ($expo_length*8); }elsif ( $self->algorithm("mnemonic") =~ /DSA/ ) { # T parameter see RFC 2536 return unpack("C", $self->{"keybin"}); }else { return -1; } } 1; =head1 NAME Net::DNS::RR::DNSKEY - DNS DNSKEY resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNSSEC KEY (DNSKEY) resource records. =head1 METHODS =head2 flags print "flags" = ", $rr->flags, "\n"; Returns the RR's flags in decimal representation =head2 protocol print "protocol" = ", $rr->protocol, "\n"; Returns the RR's protocol field in decimal representation =head2 algorithm print "algoritm" = ", $rr->algorithm, "\n"; Returns the RR's algorithm field in decimal representation 1 = RSA/MD5 2 = DH 3 = DSA/SHA-1 4 = Elliptic Curve 5 = RSA/SHA-1 6 - DSA/SHA-1 (NSEC3) 7 - RSA/SHA-1 (NSEC3) 8 - RSA/SHA-256 10 - RSA/SHA-512 Note that only algorithm 1 and 3 are supported by the methods provided through Net::DNS::RR::SIG.pm. =head2 key print "key" = ", $rr->key, "\n"; Returns the key in base64 representation =head2 keybin $keybin = $rr->keybin; Returns the key binary material =head2 keytag print "keytag" = ", $rr->keytag, "\n"; Returns the key tag of the key. (RFC2535 4.1.6) =head2 privatekeyname $privatekeyname=$rr->privatekeyname Returns the name of the privatekey as it would be generated by the BIND dnssec-keygen program. The format of that name being K\+\+\.private =head2 is_sep, set_sep, clear_sep is_sep() returns 1 if the secure entry point flag field is set, set_sep() sets secure entry point flag field is set and clear_sep() clears the value. =head2 keylength Return the length of a key. For RSA this method returns the length (in bits) of the modulus. For DSA this method returnse the value of the T parameter (See RFC2536) Returns -1 if the keysize cannot be determined (e.g. for unknown algorithms algorithm). =head1 COPYRIGHT Copyright (c) 2003-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. =head1 SEE ALSO L L, L, L, L, L, L, L, RFC 4033, RFC 4034, RFC 4035. =cut Net-DNS-SEC-0.16/RR/DS.pm000644 000765 000120 00000017307 11346437006 014471 0ustar00olafadmin000000 000000 package Net::DNS::RR::DS; # $Id: DS.pm 728 2008-10-12 09:02:24Z olaf $ use strict; use vars qw(@ISA $VERSION $_Babble); use Net::DNS; use Carp; use Digest::SHA qw(sha1 sha1_hex sha256 sha256_hex ); BEGIN { $_Babble=0; $_Babble=1 unless (eval "require Digest::BubbleBabble; import Digest::BubbleBabble qw(bubblebabble)") ; } $VERSION = do { my @r=(q$Revision: 728 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; my $debug=0; @ISA = qw(Net::DNS::RR); sub new { my ($class, $self, $data, $offset) = @_; if ($self->{"rdlength"} > 0) { my $offsettoalg=$offset+2; my $offsettodigtype=$offset+3; my $offsettodigest=$offset+4; my $digestlength; $self->{"keytag"}=unpack("n",substr($$data,$offset,2)); $self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1)); $self->{"digtype"}=unpack("C",substr($$data,$offsettodigtype,1)); if ($self->{"digtype"}==1){ $digestlength=20; # SHA1 digest 20 bytes long }elsif($self->{"digtype"}==2){ $digestlength=32; # SHA256 digest 32 bytes long }else{ $digestlength=0; } $self->{"digestbin"}= substr($$data,$offsettodigest, $digestlength); $self->{"digest"}= unpack("H*",$self->{"digestbin"}); } return bless $self, $class; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//g; my ($keytag, $algorithm, $digtype, $digest) = $string =~ /^\s*(\S+)\s+(\S+)\s+(\S+)\s+((\S+\s*)+)/; # We allow spaces in the digest. $digest=~s/\s//g; $self->{"keytag"}=$keytag; $self->{"algorithm"}=Net::DNS::SEC->algorithm($algorithm)|| return undef; $self->{"digtype"}=Net::DNS::SEC->digtype($digtype) || return undef; $self->{"digest"}=$digest; $self->{"digestbin"}=pack("H*",$digest); } return bless $self, $class; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"keytag"}) { $rdatastr = $self->{keytag}; $rdatastr .= " " . "$self->{algorithm}"; $rdatastr .= " " . "$self->{digtype}"; $rdatastr .= " " . "$self->{digest}"; $rdatastr .= " ; ".$self->babble if $_Babble; } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata { my $self = shift; my $rdata; if (exists $self->{"digest"}) { $rdata= pack("n",$self->{"keytag"}) ; $rdata.= pack("C", $self->{"algorithm"}) ; $rdata.= pack("C", $self->{"digtype"}) ; $rdata.= $self->digestbin; } return $rdata; } sub verify { my ($self, $key) = @_; my $tstds=create Net::DNS::RR::DS($key,( digtype => $self->digtype, ) ); if ($tstds->digestbin eq $self->digestbin){ return 1; }else{ return 0; } } sub babble { my $self=shift; if ($_Babble){ return bubblebabble(Digest=>$self->digestbin); }else{ return(""); } } sub digestbin { my ($self,$new_val)=@_; if (defined $new_val) { $self->{"digestbin"} = $new_val; $self->{"digest"} = unpack("H*",$new_val); return $self->{"digestbin"}; } $self->{"digestbin"}=pack("H*",$self->{"digest"}) unless( $self->{"digestbin"} ); return $self->{"digestbin"}; } sub create { my ($class, $keyrr ,%args) = @_; my $self; # Default SHA1... $self->{"digtype"}=1; if ($args{"digtype"}){ $self->{"digtype"}=2 if Net::DNS::SEC->digtype($args{"digtype"})==2; } $self->{"name"}=$keyrr->name; # Label is per definition the same as # keylabll $self->{"type"}="DS"; $self->{"class"}="IN"; if ($args{ttl}){ print "\nSetting TTL to ". $args{"ttl"} if $debug; $self->{"ttl"}= $args{"ttl"}; }else{ $self->{"ttl"}= $keyrr->ttl; } # The key must not be a NULL key. if (($keyrr->{"flags"} & hex("0xc000") ) == hex("0xc000") ){ croak "\nCreating a DS record for a NULL key is illegal"; } # Bit 0 must not be set. if (($keyrr->{"flags"}) & hex("0x8000")) { croak "\nCreating a DS record for a key with flag bit 0 set ". "to 0 is illegal"; } # Bit 6 must be set to 0 bit 7 must be set to 1 if ( ($keyrr->{"flags"} & hex("0x300")) != hex("0x100")){ croak "\nCreating a DS record for a key with flags 6 and 7 not set ". "0 and 1 respectively is illegal"; } if ($keyrr->{"protocol"} != 3 ){ croak "\nCreating a DS record for a non DNSSEC (protocol=3) ". "key is illegal"; } $self->{"keytag"}=$keyrr->keytag; $self->{"algorithm"}=$keyrr->algorithm; my $data = $keyrr->_name2wire ($keyrr->name) . $keyrr->_canonicalRdata; if ($self->{"digtype"}==1){ $self->{"digestbin"}= sha1($data); $self->{"digest"}= uc(sha1_hex($data)); }elsif($self->{"digtype"}==2){ $self->{"digestbin"}= sha256($data); $self->{"digest"}= uc(sha256_hex($data)); }else{ return undef; } return bless $self, $class; } 1; =head1 NAME Net::DNS::RR::DS - DNS DS resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for Delegation signer (DS) resource records. =head1 METHODS In addition to the regular methods =head2 create This constructor takes a key object as argument and will return a DS RR object. $dsrr=create Net::DNS::RR::DS($keyrr, ( digtype => "SHA256" ); $keyrr->print; $dsrr->print; The digest type defaults to SHA1. =head2 verify The verify method will return 1 if the hash over the key provided in the argument matches the data in the $dsrr itself i.e. if the DS pointing to the DNSKEY from the argument. It will return 0 otherwise. $dsrr->($keyrr); =head2 algorithm print "algoritm" = ", $rr->algorithm, "\n"; Returns the RR's algorithm field in decimal representation 1 = MD5 RSA 2 = DH 3 = DSA 4 = Elliptic curve =head2 digest print "digest" = ", $dsrr->digest, "\n"; Returns the SHA1 digest over the label and key in hexadecimal representation =head2 digestbin $digestbin = $dsrr->digestbin; Returns the digest as binary material =head2 keytag print "keytag" ." = ". $dsrr->keytag . "\n"; Returns the key tag of the key. (RFC2535 4.1.6) =head2 digtype print "digest type" . " = " . $dsrr->digtype ."\n"; Returns the digest type of the DS RR. =head2 babble print $dsrr->babble; Returns the 'BabbleBubble' representation of the digest. The 'BabbleBubble' string may be handy for telephone confirmation. The 'BabbleBubble' string returned as a comment behind the RDATA when the string method is called. =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. =head1 SEE ALSO L L, L, L, L, L, L, L, RFC 4033, RFC4034, RFC4035 =cut Net-DNS-SEC-0.16/RR/KEY.pm000644 000765 000120 00000005775 11346437006 014621 0ustar00olafadmin000000 000000 package Net::DNS::RR::KEY; # $Id: KEY.pm 847 2010-03-12 13:04:13Z olaf $ use strict; use vars qw(@ISA $VERSION); use bytes; use Net::DNS; use MIME::Base64; use Carp; @ISA = qw(Net::DNS::RR Net::DNS::RR::DNSKEY); $VERSION = do { my @r=(q$Revision: 847 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { return Net::DNS::RR::DNSKEY::new(@_); } sub new_from_string { return Net::DNS::RR::DNSKEY::new_from_string(@_); } 1; =head1 NAME Net::DNS::RR::KEY - DNS KEY resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNS Address (KEY) resource records. =head1 METHODS This class inherits most of its methods from DNSKEY. See DNSKEY for a complete list of available methods. =head2 flags print "flags" = ", $rr->flags, "\n"; Returns the RR's flags in decimal representation =head2 protocol print "protocol" = ", $rr->protocol, "\n"; Returns the RR's protocol field in decimal representation =head2 algorithm print "algoritm" = ", $rr->algorithm, "\n"; Returns the RR's algorithm field in decimal representation 1 = MD5 RSA 2 = DH 3 = DSA 4 = Elliptic curve 5 = SHA1 RSA Note that only algorithm 1 and 3 are supported by the methods provided through Net::DNS::RR::SIG.pm. =head2 key print "key" = ", $rr->key, "\n"; Returns the key in base64 representation =head2 keybin $keybin = $rr->keybin; Returns the key binary material =head2 keytag print "keytag" = ", $rr->keytag, "\n"; Returns the key tag of the key. (RFC2535 4.1.6) =head2 privatekeyname $privatekeyname=$rr->privatekeyname Returns the name of the privatekey as it would be generated by the BIND dnssec-keygen program. The format of that name being K\+\+\.private =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. =head1 SEE ALSO L L, L, L, L, L, L, L, RFC 2931. =cut Net-DNS-SEC-0.16/RR/NSEC.pm000644 000765 000120 00000015733 11346437006 014714 0ustar00olafadmin000000 000000 package Net::DNS::RR::NSEC; # $Id: NSEC.pm 813 2009-11-27 09:10:10Z olaf $ use strict; use vars qw(@ISA $VERSION); use Carp; use bytes; use Net::DNS; use Net::DNS::Packet; use Data::Dumper; use Carp; @ISA = qw(Net::DNS::RR); $VERSION = do { my @r=(q$Revision: 813 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $self, $data, $offset) = @_; if ($self->{"rdlength"} > 0) { my($nxtdname,$nxtoffset) = Net::DNS::Packet::dn_expand($data, $offset); $self->{"nxtdname"} = $nxtdname; my $typebm =substr($$data,$nxtoffset, $self->{"rdlength"}- $nxtoffset+$offset); $self->{"typebm"}=$typebm; $self->{"typelist"} = join " " , _typebm2typearray($typebm); } return bless $self, $class; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($nxtdname,$nxtstr) = $string =~ /^\s*(\S+)\s+(.*)/; my @nxttypes = split ' ' , $nxtstr; # everything after last match... $self->{"nxtdname"}= Net::DNS::stripdot($nxtdname); $self->{"typelist"}= join " " , sort @nxttypes ; $self->{"typebm"}=_typearray2typebm(@nxttypes); } return bless $self, $class; } #sub is_optin { # my $self =shift; # return 1 if $self->{"typelist"}!~/NSEC/; # 0; #} #sub set_optin { # my $self =shift; # $self->{"typelist"}=~s/NSEC//; # 1; #} sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"nxtdname"}) { $rdatastr = $self->{nxtdname}."."; $rdatastr .= " " . $self->typelist(); } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = "" ; if (exists $self->{"nxtdname"}) { # Compression used here... $rdata = $packet->dn_comp(($self->{"nxtdname"}),$offset); $rdata .= $self->typebm(); } return $rdata; } sub _normalize_dnames { my $self=shift; $self->_normalize_ownername(); $self->{'nxtdname'}=lc(Net::DNS::stripdot($self->{'nxtdname'})) if defined $self->{'nxtdname'}; } sub typebm { my ($self, $new_val) = @_; if (defined $new_val) { $self->{"typebm"} = $new_val; $self->{"typelist"}= join (" ", _typebm2typearray($self->{"typebm"})); } $self->{"typebm"}= _typearray2typebm(split(' ',$self->{"typelist"})) unless $self->{"typebm"}; return $self->{"typebm"}; } sub typelist { my ($self, $new_val) = @_; if (defined $new_val) { $self->{"typelist"} = $new_val; $self->{"typebm"}= _typearray2typebm(split (' ',($self->{"typelist"}))); } $self->{"typelist"}= join (" ", _typebm2typearray($self->{"typebm"})) unless $self->{"typelist"}; return $self->{"typelist"}; } sub _canonicalRdata { # rdata contains a compressed domainname... that should not have # been done @specification time :-) my ($self) = @_; my $rdata; $rdata=$self->_name2wire($self->{"nxtdname"}); $rdata .= $self->{"typebm"}; return $rdata; } sub _typearray2typebm { # typebm= (WindowBlockNumber |BitmapLength|Bitmap)+ my @typelist= @_; return "" unless @typelist; my $typebm=""; my $CurrentWindowNumber=0; # $bm is an array of arrays. # The first index maps onto the CurrentWindowNumber and the array # contained has its index mapped to types. The vallues will be set # if there is data for a paricular type otherwise undef. my $bm; TYPE: for(my $i=0;$i < @typelist; $i++){ use integer; my $typenumber=Net::DNS::typesbyname(uc($typelist[$i])); next TYPE if exists ($Net::DSN::qtypesbyname{uc($typelist[$i])}); next TYPE if exists ($Net::DSN::metatypesbyname{uc($typelist[$i])}); # Do net set the bitmap for meta types or qtypes. $CurrentWindowNumber= ($typenumber / 256); # use integer must be in scope.. $bm->[$CurrentWindowNumber]->[$typenumber-$CurrentWindowNumber*256] = 1; } # Turn the array of arrays referenced through $bm into the bitmap # as used in the RDATA for (my $i=0; $i < @{$bm}; $i++){ if (defined ($bm->[$i])){ use integer; my $BitmapLength=0; $BitmapLength = 8 * ((@{$bm->[$i]} / 8) ); # Make sure the remaining bits fit... $BitmapLength += 8 if (@{$bm->[$i]} % 8); for (my $j=0;$j< $BitmapLength; $j++){ $bm->[$i]->[$j]=0 if ! defined $bm->[$i]->[$j]; } $typebm.= pack("CCB$BitmapLength",$i,$BitmapLength/8, join ("", @{$bm->[$i]} )); } } return $typebm } sub _typebm2typearray { # This implements draft-ietfdnsext-nsec-rdata-01. # typebm= (WindowBlockNumber |BitmapLength|Bitmap)+ my $typebm=shift; # bit representation. my@typelist; while ($typebm){ my ($WindowBlockNumber,$BitmapLength)=unpack("CC",$typebm); substr($typebm,0,2,""); my $Bitmap=substr($typebm,0,$BitmapLength,""); # Turn the Bitmap in an array... my @bm=split //, unpack("B*", $Bitmap); # bit representation in arra for (my $i=0;$i < @bm; $i++){ @typelist=(@typelist, Net::DNS::typesbyval($WindowBlockNumber*256+$i)) if $bm[$i]; } } return sort @typelist; } 1; =head1 NAME Net::DNS::RR::NSEC - DNS NSEC resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNS Address (NSEC) resource records. =head1 METHODS =head2 nxtdname print "nxtdname" = ", $rr->nxtdname, "\n"; Returns the RR's next domain name field. =head2 typelist print "typelist" = ", $rr->typelist, "\n"; Returns a string with the list of qtypes for which data exists for this particular label. =head2 typebm print "typebm" = " unpack("B*", $rr->typebm), "\n"; Same as the typelist but now in a representation bitmap as in specified in the RFC. This is not the kind of method you will need on daily basis. =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. =head1 SEE ALSO L L, L, L, L, L, L, L, RFC4033, RFC4034, RFC4035. =cut Net-DNS-SEC-0.16/RR/NSEC3.pm000644 000765 000120 00000032264 11346437006 014775 0ustar00olafadmin000000 000000 package Net::DNS::RR::NSEC3; # # $Id: NSEC3.pm 767 2008-12-24 10:02:25Z olaf $ use strict; require Exporter; use vars qw( @ISA $VERSION @EXPORT_OK %digestbyname %digestbyval ); use Carp; use bytes; use MIME::Base64; use MIME::Base32; use Digest::SHA qw(sha1 sha1_hex sha256 sha256_hex ); use Net::DNS qw( name2labels ); use Net::DNS::SEC; use Net::DNS::Packet; use Net::DNS::RR::NSEC; #http://www.iana.org/assignments/dnssec-nsec3-parameters %digestbyname = ( "SHA1" => 1, ); @EXPORT_OK= qw ( name2hash ); # Inherit a couple of methods from NSEC. @ISA = qw(Exporter Net::DNS::SEC Net::DNS::RR Net::DNS::RR::NSEC); $VERSION = do { my @r=(q$Revision: 510 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $self, $data, $offset) = @_; if ($self->{'rdlength'} > 0) { # section 3.1 of NSEC3 specs # 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Hash Alg. | Flags Field | Iterations | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Salt Length | Salt / # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Hash Length | Next Hashed Ownername / # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # / Type Bit Maps / # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ my $offsettoits=$offset+2; my $offsettoflags=$offset+1; my $offsettosaltlength=$offset+4; my $offsettosalt=$offset+5; $self->{'hashalgo'}=unpack("C",substr($$data,$offset,1)); $self->{'flags'}=unpack("C",substr($$data,$offsettoflags,1)); $self->{'iterations'}=unpack("n",substr($$data,$offsettoits,3)); $self->{'saltlength'}=unpack("C",substr($$data,$offsettosaltlength,1)); $self->{'saltbin'}=substr($$data,$offsettosalt,$self->{'saltlength'}); $self->{'salt'}= unpack("H*",$self->{'saltbin'}); my $offsettohashlength= $offsettosalt+$self->{'saltlength'}; $self->{'hashlength'}=unpack("C",substr($$data,$offsettohashlength,1)); $self->{'hnxtnamebin'}=substr($$data,$offsettohashlength+1,$self->{'hashlength'}); $self->{'hnxtname'}=MIME::Base32::encode $self->{'hnxtnamebin'}; my $offsettotypebm=$offsettohashlength+1+$self->{'hashlength'}; my $typebm =substr($$data,$offsettotypebm, $self->{'rdlength'}-$offsettotypebm +$offset ); $self->{'typebm'}=$typebm; $self->{'typelist'} = join " " , Net::DNS::RR::NSEC::_typebm2typearray($typebm); } bless $self, $class; return $self; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($hashalgo,$flags,$iterations,$salt,$hnxtname,$nxtstr)= $string =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s?(.*)/; my @nxttypes = split ' ' , $nxtstr; # everything after last match... bless $self, $class; # This assumes that the digest type allocations follow the assignments as used for DS... #overwrite the digestby name table used by Net::DNS::SEC digtype $self->{'hashalgo'}=$self->digtype($hashalgo) || return undef; $self->{'flags'}=$flags; $self->{'iterations'}=$iterations; if ($salt eq '-') {$salt=''}; $self->{'salt'}=$salt; $self->{'saltbin'}=pack("H*",$salt); $self->{'saltlength'}=length $self->{saltbin}; $self->{'hnxtname'}= Net::DNS::stripdot($hnxtname); $self->{'hnxtnamebin'}=MIME::Base32::decode uc $hnxtname; $self->{'typelist'}= join " " , sort @nxttypes ; $self->{'typebm'}=Net::DNS::RR::NSEC::_typearray2typebm(@nxttypes); } return $self; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{hashalgo}) { $rdatastr .= $self->{hashalgo} ." "; $rdatastr .= $self->{flags}." "; $rdatastr .= $self->{iterations}. " "; $rdatastr .= $self->salt()." "; $rdatastr .= "(\n\t\t\t"; $rdatastr .= $self->{hnxtname} . "\n"; $rdatastr .= "\t\t\t$self->{typelist} )"; } else { $rdatastr = "; no data" } $rdatastr } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = "" ; if (exists $self->{'hnxtname'}) { $rdata = pack("C",$self->{'hashalgo'}); $rdata .= pack("C", $self->{'flags'} ); $rdata .= pack("n", $self->{'iterations'} ); unless( exists $self->{'saltbin'}) { if ($self->{'salt'} eq "-"){ $self->{'saltbin'}=""; }else{ $self->{'saltbin'}=pack("H*",$self->{'salt'}) } } $rdata.= pack("C",length($self->{'saltbin'})); $rdata .= $self->{'saltbin'}; $self->{'hnxtnamebin'}=MIME::Base32::decode(uc $self->{'hnxtname'}) unless exists $self->{'hnxtnamebin'} ; $rdata.= pack("C",length($self->{'hnxtnamebin'})); $rdata .= $self->{'hnxtnamebin'}; $rdata .= $self->typebm(); } return $rdata; } sub _normalize_dnames { my $self=shift; $self->_normalize_ownername(); $self->{'hnxtname'}= Net::DNS::stripdot($self->{'hnxtname'}) if defined $self->{'hnxtname'}; $self->{'hnxtnamebin'}=MIME::Base32::decode(uc $self->{'hnxtname'}); } sub salt { my ($self,$salt)=@_; if (defined $salt){ if ($salt eq "-"){ $self->{'salt'} = "" ; }else{ $self->{'salt'} = $salt ; unless ($salt =~ /^[0-9a-f]*$/i ) { # print "input ($salt) not hex" ; return undef; } $self->{'saltbin'} = pack("H*",$salt); } } return "-" if ($self->{'salt'} eq ""); return $self->{'salt'}; } sub name2hash { my $hashalg=shift; my $inname= lc shift; my $iterations=shift; my $saltbin=shift; my $hashfunc; if ($hashalg==1){ $hashfunc = sub {my $x=shift ; return sha1($x)}; }elsif($hashalg==2){ $hashfunc = sub {my $x=shift ; return sha256($x)}; }else{ return; } my $wirename=Net::DNS::RR->_name2wire($inname); my $i=0; for (0..$iterations) { $wirename=&$hashfunc($wirename.$saltbin); } return lc MIME::Base32::encode $wirename; } sub ownername { my $self=shift; if (defined $self->{'ownername'}){ return $self->{'ownername'}; }else{ return $self->{'ownername'} = (name2labels($self->name))[0] ; } } sub _zonelabels { # Extracts the labels that make up the zone from the owner name of the # record, simply by stripping the first label. # returns an array of labels in wire format. my $self=shift; unless (defined $self->{'zonelabels'}){ my @labels= (name2labels($self->name)) ; shift @labels; $self->{'zonelabels'} = \@labels ; } return @{$self->{'zonelabels'}}; } sub _zone { # Returns the result from the zonelabels method in presentation # format (without trailing dot my $self=shift; my $name; foreach my $label ($self->zonelabels){ $name .= wire2presentation($label) . "."; } chop($name); return $name; } sub optout { my ($self,$newval )= @_; if (defined ($newval)) { if ($newval){ $self->{'flags'} |= hex("0x01"); }else{ $self->{'flags'} &= ~hex("0x01"); } } return $self->{'flags'} & hex("0x01"); } sub covered { my $self=shift; my $domainname=shift; # first test if the domain name is in the NSEC zone. my @domainlabels=name2labels($domainname); my @zonelabels= $self->_zonelabels(); while (my $zlabel = pop @zonelabels ){ my $dlabel= pop @domainlabels; return 0 unless ($dlabel eq $zlabel) } my $hashedname= Net::DNS::RR::NSEC3::name2hash( $self->hashalgo, $domainname, $self->iterations, $self->saltbin, ); if ( ($self->ownername() cmp $self->hnxtname() )== 1 ) { # last name in the zone. return 1 if ( ( $hashedname cmp $self->hnxtname() ) == 1 ); return 1 if ( ( $hashedname cmp $self->ownername() ) == -1 ); } elsif ( ($self->ownername() cmp $self->hnxtname() )== 0 ) { # One entry in the zone. return 1; }else{ return 1 if ( ($self->ownername() cmp $hashedname) == -1 ) && ( ( $hashedname cmp $self->hnxtname() ) == -1 ); } return 0; } sub match { my $self=shift; my $domainname=shift; my $ownername=$self->ownername(); my $hashedname= Net::DNS::RR::NSEC3::name2hash( $self->hashalgo, $domainname, $self->iterations, $self->saltbin ); return $ownername eq $hashedname; } sub digtype { my $self=shift; $self->{'digestbyname'}= \%digestbyname; $self->_digtype(@_); } 1; =head1 NAME Net::DNS::RR::NSEC3 - DNS NSEC3 resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNS Address (NSEC3) resource records. The NSEC3 Resource Record (RR) provides authenticated denial of existence for DNS Resource Record Sets. The NSEC3 RR lists RR types present at the NSEC3 RR's original ownername. It includes the next hashed ownername in the hash order of the zone. The complete set of NSEC3 RRs in a zone indicates which RRsets exist for the original ownername of the RRset and form a chain of hashed ownernames in the zone. =head1 METHODS =head2 ownername Returns the hashed value of the original owner name as contained in the first label of the ownername of the record. The owner name for the NSEC3 RR is the base32 encoding of the hashed owner name prepended as a single label to the name of the zone. In other words the name(name) method returns the result of the ownername() method prepended to the name of the containing zone. =head2 optout Reads and sets the opt-out attribute. =head2 flags Reads and sets the flag field. =head2 hashalgo Reads and sets the hashalgo (hash algorithm) attribute. =head2 hnxtname Reads and sets the hnxtname (hashed next ownername) attribute. =head2 typelist (inhereted from NSEC) print "typelist" = ", $rr->typelist, "\n"; Returns a string with the list of qtypes for which data exists for this particular label. =head2 typebm (inhereted from NSEC) print "typebm" = " unpack("B*", $rr->typebm), "\n"; Same as the typelist but now in a representation bitmap as in specified in the RFC. This is not the kind of method you will need on daily basis. =head2 covered, matched print "covered" if $rr->covered{'example.foo'} covered returns a nonzero value when the the domain name provided as argument is covered as defined in the NSEC3 specification: To cover: An NSEC3 RR is said to "cover" a name if the hash of the name or "next closer" name falls between the owner name and the next hashed owner name of the NSEC3. In other words, if it proves the nonexistence of the name, either directly or by proving the nonexistence of an ancestor of the name. Similarly ismatched returns a nonzero value when the domainname in the argument matches as defined in the NSEC3 specification: To match: An NSEC3 RR is said to "match" a name if the owner name of the NSEC3 RR is the same as the hashed owner name of that name. =head1 Functions =head2 name2hash Takes the hash identifyer (numeric), a fullyqualfied domain name, the number of iterations and a binary salt to compute the hash value used in the NSEC3 calculations. $hashalg=Net::DNS::SEC->digtype("SHA1"); $salt=pack("H*","aabbccdd"); $iterations=12; $name="*.x.w.example"; $hashedname= Net::DNS::RR::NSEC3::name2hash($hashalg,$name,$iterations,$salt); print $hashedname; results in: 92pqneegtaue7pjatc3l3qnk738c6v5m Normally the salt and itterations would be fetched from an NSEC3PARAM record. =head1 COPYRIGHT Copyright (c) 2007, 2008 NLnet Labs. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. Acknowledgements to Roy Arends who made a test version for this class and whose code I've looked at before writing this module. =head1 SEE ALSO L L L, L, L, L, L, L, L, L, RFC4033, RFC4034, RFC4035, RFC5155 =cut Net-DNS-SEC-0.16/RR/NSEC3PARAM.pm000644 000765 000120 00000013750 11346437006 015555 0ustar00olafadmin000000 000000 package Net::DNS::RR::NSEC3PARAM; # $Id: NSEC3.pm 602 2006-07-24 14:23:15Z olaf $ use strict; use vars qw(@ISA $VERSION); use Carp; use bytes; use Net::DNS; use Net::DNS::SEC; use Net::DNS::Packet; use Net::DNS::RR::NSEC; use Data::Dumper; use Carp qw(cluck); # To be removed when finalized @ISA = qw(Net::DNS::RR Net::DNS::RR::NSEC3); $VERSION = do { my @r=(q$Revision: 510 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $self, $data, $offset) = @_; if ($self->{"rdlength"} > 0) { # 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Hash Alg. | Flags Field | Iterations | # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # | Salt Length | Salt / # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ # # Hash Algorithm is a single octet. # # Flags Field is a single octet. # # Iterations is represented as a 16-bit integer, with the most # significant bit first. # # Salt Length represents the length of the following Salt field in # octets. If the value is zero, the Salt field is omitted. my $offsettoflag=$offset+1; my $offsettoits=$offset+2; my $offesttosaltlength=$offset+4; my $offsettosalt=$offset+5; $self->{"hashalgo"}=unpack("C",substr($$data,$offset,1)); $self->{"flags"}=unpack("C",substr($$data,$offsettoflag,1)); $self->{"iterations"}= unpack("n",substr($$data,$offsettoits,2)); $self->{"saltlength"}=unpack("C",substr($$data,$offesttosaltlength,1)); $self->{"saltbin"}=substr($$data,$offsettosalt,$self->{"saltlength"}); $self->{"salt"}= unpack("H*",$self->{"saltbin"}); } bless $self, $class; return $self; } sub new_from_string { my ($class, $self, $string) = @_; bless $self, $class; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($hashalgo,$flags,$iterations,$salt)= $string =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S*)\s*$/; # This assumes that the digest type allocations follow the assignments as used for DS... defined($self->{'hashalgo'}=Net::DNS::SEC->digtype($hashalgo)) || return undef; defined($self->{'iterations'}=$iterations) || return undef; defined($self->{'flags'}=$flags) || return undef; defined($self->{"salt"}=$self->salt($salt)) || return undef; $self->{"saltbin"}=pack("H*",$salt) || return undef; $self->{saltlength}=length $self->{saltbin}; } return $self; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{hashalgo}) { $rdatastr .= $self->{hashalgo} ." "; $rdatastr .= $self->{flags}." "; $rdatastr .= $self->{iterations}. " "; $rdatastr .= $self->salt()." \n"; } else { $rdatastr = "; no data" } $rdatastr } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = "" ; if (exists $self->{'hashalgo'}) { $rdata = pack("C",$self->{'hashalgo'}); $rdata .= pack("C",$self->{'flags'}); $rdata .= pack("n",$self->{'iterations'}); unless( exists $self->{"saltbin"}) { if ($self->{"salt"} eq "-"){ $self->{"saltbin"}=""; }else{ $self->{"saltbin"}=pack("H*",$self->{"salt"}) } } $rdata .= pack("C",length($self->{'saltbin'})); $rdata .= $self->{'saltbin'}; } return $rdata; } 1; =head1 NAME Net::DNS::RR::NSEC3PARAM - DNS NSEC3PARAM resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNS Address (NSEC3PARAM) resource records. The NSEC3PARAM RR contains the NSEC3 parameters (hash algorithm, flags, iterations and salt) needed to calculate hashed ownernames. The presence of an NSEC3PARAM RR at a zone apex indicates that the specified parameters may be used by authoritative servers to choose an appropriate set of NSEC3 records for negative responses. =head1 METHODS =head2 hashalgo Reads and sets the hashalgo (hash algorithm) attribute. =head2 flags Reads and sets the flag field. Check the IANA registry for valid values. At the time of code release the only defined value was 0x00 =head2 iterations Reads and sets the iterations field =head2 salt Reads and sets the salt value. Accepts and returns a string with a number in hexadecimal notation. =head1 COPYRIGHT Copyright (c) 2007,2008 NLnet Labs. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. Acknowledgements to Roy Arends who made a test version for this class and whose code I've looked at before writing this module. =head1 SEE ALSO L L L, L, L, L, L, L, L, L, RFC4033, RFC4034, RFC4035, RFC 5155 =cut Net-DNS-SEC-0.16/RR/NXT.pm000644 000765 000120 00000012655 11346437006 014635 0ustar00olafadmin000000 000000 package Net::DNS::RR::NXT; # $Id: NXT.pm 318 2005-05-30 16:36:52Z olaf $ use strict; use vars qw(@ISA $VERSION); use Carp; use bytes; use Net::DNS; use Net::DNS::Packet; use Carp; @ISA = qw(Net::DNS::RR); $VERSION = do { my @r=(q$Revision: 318 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; sub new { my ($class, $self, $data, $offset) = @_; carp "The NXT RR is depricated as of RFC3755, please refrain from using this record"; if ($self->{"rdlength"} > 0) { my($nxtdname,$nxtoffset) = Net::DNS::Packet::dn_expand($data, $offset); $self->{"nxtdname"} = "$nxtdname"; my $typebm =substr($$data,$nxtoffset, $self->{"rdlength"}- $nxtoffset+$offset); $self->{"typebm"}=$typebm; $self->{"typelist"} = join " " , _typebm2typestr($typebm); } return bless $self, $class; } sub new_from_string { my ($class, $self, $string) = @_; carp "The NXT RR is depricated as of RFC3755"; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($nxtdname,$nxtstr) = $string =~ /^\s*(\S+)\s+(.*)/; my @nxttypes = split /\s+/ , $nxtstr; # everything after last match... $self->{"nxtdname"}= lc($nxtdname) ; $self->{"typelist"}= join " " , sort @nxttypes ; $self->{"typebm"}=_typestr2typebm(@nxttypes); } return bless $self, $class; } #sub is_optin { # my $self =shift; # return 1 if $self->{"typelist"}!~/NXT/; # 0; #} #sub set_optin { # my $self =shift; # $self->{"typelist"}=~s/NXT//; # 1; #} sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"nxtdname"}) { $rdatastr = $self->{nxtdname}; $rdatastr .= " " . "$self->{typelist}"; } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = "" ; if (exists $self->{"nxtdname"}) { # Compression used here... $rdata = $packet->dn_comp($self->{"nxtdname"},$offset); $rdata .= $self->{"typebm"}; } return $rdata; } sub _canonicalRdata { # rdata contains a compressed domainname... we should not have that. my ($self) = @_; my $rdata; $rdata=$self->_name2wire($self->{"nxtdname"}); $rdata .= $self->{"typebm"}; return $rdata; } sub _typestr2typebm { # RFC2535 5.1 needs the typebm # This needs to check for values > 127.... # Sets a bit for every qtype in the input array. # Minimum bitmaplenght 4 octets because NXT (30) is allways there # may be longer but trailing all zero octets should be dropped. my (@typelist, @typebitarray); @typelist= @_; for(my $i=0;$i < @typelist; $i++){ $typebitarray[$Net::DNS::typesbyname{uc($typelist[$i])}]=1; } my $finalsize=0; { use integer; $finalsize = 8 * ((@typebitarray / 8) + 1); } for (my $i=0;$i< $finalsize; $i++){ $typebitarray[$i]=0 if ! defined $typebitarray[$i]; } my $typebm= pack("B$finalsize",join "", @typebitarray ); return $typebm } sub _typebm2typestr { # RFC2535 5.1 needs the typebm # This needs to check for values > 127.... my @typebm=split //, unpack("B*", shift); # bit representation in array my @typelist; carp "Cannot deal with qtype > 127" if ($#typebm > 127); my($foo); foreach $foo (sort { $a <=> $b } keys(%Net::DNS::typesbyval) ){ next if $foo > $#typebm; # Skip larger aray vallues. @typelist=(@typelist,$Net::DNS::typesbyval{$foo}) if ($typebm[$foo] eq "1"); } return sort @typelist; } 1; =head1 NAME Net::DNS::RR::NXT - DNS NXT resource record =head1 SYNOPSIS C =head1 DESCRIPTION B Class for DNS Address (NXT) resource records. =head1 METHODS =head2 nxtdname print "nxtdname" = ", $rr->nxtdname, "\n"; Returns the RR's next domain name field. =head2 typelist print "typelist" = ", $rr->typelist, "\n"; Returns a string with the list of qtypes for which data exists for this particular label. =head2 typebm print "typebm" = " unpack("B*", $rr->typebm), "\n"; Same as the typelist but now in a representation bitmap as in specified in the RFC. This is not the kind of method you will need on daily basis. =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. =head1 SEE ALSO L L, L, L, L, L, L, L, RFC 2435 Section 5 =cut Net-DNS-SEC-0.16/RR/RRSIG.pm000644 000765 000120 00000105406 11346437006 015047 0ustar00olafadmin000000 000000 # perldoc RRSIG.pm for documentation. # Specs: RFC 2535 section 4 # $Id: RRSIG.pm 814 2009-11-27 09:28:30Z olaf $ package Net::DNS::RR::RRSIG; use vars qw(@ISA $VERSION @EXPORT ); use Net::DNS; use Carp; use bytes; use Data::Dumper; use Crypt::OpenSSL::DSA; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Bignum; use Net::DNS::SEC::Private; use File::Basename; use MIME::Base64; use Math::BigInt; use Time::Local; use Digest::SHA qw (sha1 sha256 sha512); # # Most of the cryptovariables should be interpred as unsigned # # require Exporter; $VERSION = do { my @r=(q$Revision: 814 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; @ISA = qw ( Exporter Net::DNS::RR Net::DNS::SEC ); @EXPORT = qw ( ); use strict; my $crypt_open_ssl=1; my $debug=0; sub new { my ($class, $self, $data, $offset) = @_; if ($self->{"rdlength"} > 0) { #RFC2535 section 4.1 my $offsettoalg=$offset+2; my $offsettolabels=$offset+3; my $offsettoorgttl=$offset+4; my $offsettosigexp=$offset+8; my $offsettosiginc=$offset+12; my $offsettokeytag=$offset+16; my $offsettosignm=$offset+18; $self->{"typecovered"}= _type2string(unpack("n",substr($$data,$offset,2))); $self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1)); $self->{"labels"}=lc(unpack("C",substr($$data,$offsettolabels,1))); $self->{"orgttl"}=unpack("N",substr($$data,$offsettoorgttl,4)); my @expt=gmtime(unpack("N",substr($$data,$offsettosigexp,4))); $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $expt[5]+1900 ,$expt[4]+1 , $expt[3] ,$expt[2] , $expt[1] , $expt[0]); my @inct=gmtime(unpack("N",substr($$data,$offsettosiginc,4))); $self->{"siginception"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); $self->{"keytag"}=unpack("n",substr($$data,$offsettokeytag,2)); my($signame,$sigoffset) = Net::DNS::Packet::dn_expand ($data, $offsettosignm); $self->{"signame"}=lc($signame); my($sigmaterial)=substr($$data,$sigoffset, ($self->{"rdlength"}-$sigoffset+$offset)); $self->{"sigbin"}=$sigmaterial; $self->{"sig"}= encode_base64($sigmaterial); $self->{"vrfyerrstr"}=""; } return bless $self, $class; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($typecovered, $algoritm, $labels, $orgttl, $sigexpiration, $siginception, $keytag,$signame,$sig) = $string =~ /^\s*(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)/; croak (" Invallid RRSIG RR, check your fomat ") if !$keytag; $sig =~ s/\s*//g; $self->{"typecovered"}= $typecovered; $self->{"algorithm"}= Net::DNS::SEC->algorithm($algoritm); $self->{"labels"}= lc($labels); $self->{"orgttl"}= $orgttl; _checktimeformat($sigexpiration); _checktimeformat($siginception); $self->{"sigexpiration"}= $sigexpiration; $self->{"siginception"}= $siginception; $self->{"keytag"}= $keytag; $self->{"signame"}= lc(Net::DNS::stripdot($signame)); $self->{"sig"}= $sig; $self->{"sigbin"}= decode_base64($sig); $self->{"vrfyerrstr"}=""; } return bless $self, $class; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"typecovered"}) { $rdatastr = $self->{typecovered}; $rdatastr .= " " . $self->algorithm; $rdatastr .= " " . "$self->{labels}"; $rdatastr .= " " . "$self->{orgttl}"; $rdatastr .= " " . "$self->{sigexpiration}"; $rdatastr .= " (\n\t\t\t" . "$self->{siginception}"; $rdatastr .= " " . "$self->{keytag}"; $rdatastr .= " " . "$self->{signame}."; # do some nice formatting my $sigstring=$self->{sig}; $sigstring =~ s/\n//g; $sigstring =~ s/(\S{45})/$1\n\t\t\t/g; $rdatastr .= "\n\t\t\t".$sigstring; $rdatastr .= " )"; } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata_without_sigbin { my ($self) = shift; my $rdata = ""; if (exists $self->{"typecovered"}) { $rdata = pack("n",_string2type($self->{typecovered})); $rdata .= pack("C",$self->algorithm); $rdata .= pack("C",$self->{"labels"}); $rdata .= pack("N",$self->{"orgttl"}); $self->{"sigexpiration"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; $rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900)); $self->{"siginception"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; $rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900)); $rdata .= pack("n",$self->{"keytag"}); # Since we will need canonical and expanded names while checking # we do not use the packet->dn_comp here but use RFC1035 p10. { my @dname= split /\./,lc($self->{"signame"}."."); #/ emacs fontlock for (my $i=0;$i<@dname;$i++){ $rdata .= pack ("C",length $dname[$i] ); $rdata .= $dname[$i] ; } $rdata .= pack ("C","0"); } } return $rdata; } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = ""; if (exists $self->{"typecovered"}) { $rdata=$self->rr_rdata_without_sigbin; if ($self->{"sig"} ne "NOTYETCALCULATED") { $self->{"sigbin"}= decode_base64($self->{"sig"}) unless defined $self->{"sigbin"} ; $rdata .= $self->{"sigbin"}; }else{ die "RRSIGs should not be used for SIG0 type signatures, use Net::DNS::RR::SIG"; } } return $rdata; } sub create { my ($class, $datarrset, $priv_key, %args) = @_; # This method returns a sigrr with the signature over the # datatrrset (an array of RRs) made with the private key stored in # the $key_file. my $self; $self->{"sigerrstr"}="---- Unknown Error Condition ------"; my $Private; if (UNIVERSAL::isa($priv_key,"Net::DNS::SEC::Private")){ $Private=$priv_key; }else{ $Private=Net::DNS::SEC::Private->new($priv_key); } unless (UNIVERSAL::isa($Private,"Net::DNS::SEC::Private")){ $self->{"sigerrstr"}= "Create did not manage to parse a private key into a Net::DNS::SEC::Private object "; return (0); } $self->{"algorithm"}=Net::DNS::SEC->algorithm($Private->algorithm); $self->{"keytag"}=$Private->keytag; $self->{"signame"}=Net::DNS::stripdot($Private->signame); die "Argument is not a reference to an array, are you trying to create a SIG0 using RRSIG?" if ! ref ($datarrset); $self->{"rr_rdata_recursion"}=0; # Start with seting up the data in the packet we can get our hands on... $self->{"name"}=$datarrset->[0]->name; $self->{"type"}="RRSIG"; $self->{"class"}="IN"; if (defined ($args{ttl})){ print "Setting TTL to ". $args{"ttl"} . "\n" if $debug; $self->{"ttl"}= $args{"ttl"}; }else{ $self->{"ttl"}= $datarrset->[0]->ttl; } $self->{"typecovered"}=$datarrset->[0]->type; #Sanity checks elsewhere if (defined ($args{response})){ $self->{"response"}=$args{"response"}; } if (defined($args{"sigin"})){ _checktimeformat($args{"sigin"}); print "\nSetting siginception to " . $args{"sigin"} if $debug; $self->{"siginception"} =$args{"sigin"}; }else{ my @inct=gmtime(time); my $currentdatestring= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); $self->{"siginception"} = $currentdatestring ; } # This will fail if the dateformat is not correct... $self->{"siginception"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ; my $siginc_time=timegm ($6, $5, $4, $3, $2-1, $1-1900); if (defined($args{"sigval"})){ #sigexpiration set by siginception + sigval my @inct; # treat sigval as days @inct=gmtime($siginc_time+$args{"sigval"}*24*3600 ); $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); }elsif ($args{"sigex"}) { #sigexpiration set by the argument _checktimeformat($args{"sigex"}); if ( $self->{"siginception"} > $args{"sigex"} ){ croak "Signature can only expire after it has been incepted (". $args{"sigex"} . "<" . $self->{"siginception"} . ")"; } print "\nSetting sigexpiration to " . $args{"sigex"} if $debug; $self->{"sigexpiration"}=$args{"sigex"} ; }else{ my @inct; # Take the 30 days default for sigexpiration @inct=gmtime($siginc_time+30*24*3600 ); $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); } my $labels=$datarrset->[0]->name; $labels =~ s/\.$//; # remove trailing dot. $labels =~ s/^\*\.//; # remove initial asterisk label my @labels= split /\./ , $labels; # / emacs font-lock-mode $self->{"labels"}= scalar(@labels); # All the TTLs need to be the same in the data RRset. if ( @{$datarrset}>1 ){ for (my $i=0; $i<@{$datarrset}; $i++){ if ($datarrset->[0]->{"ttl"} != $datarrset->[$i]->{"ttl"}){ croak "\nNot all TTLs in the data RRset are equal "; } } } $self->{"orgttl"}=$datarrset->[0]->{"ttl"}; $self->{"sig"}= "NOTYETCALCULATED"; # This is what we'll do in a bit... $self->{"sigbin"}= decode_base64($self->{"sig"}); # Bless the whole thing so we can get access to the methods... # (Don not ask me why I havent called the new method, There are # more ways to do things) bless $self, $class; my $sigdata=$self->_CreateSigData($datarrset); my $signature; # # Enjoy the crypto if ($self->algorithm == 1 || $self->algorithm == 5 || $self->algorithm == 7 || $self->algorithm == 8 || $self->algorithm == 10) { #RSA if (! ($Private->algorithm == 1 || $Private->algorithm == 5 || $Private->algorithm == 7 || $Private->algorithm == 8 || $Private->algorithm == 10 )) { die "Private key mismatch, not RSAMD5 or RSASHA."; } # my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($Private->privatekey); my $rsa_priv = $Private->privatekey; $self->{"private_key"}=$Private->privatekey; eval { $rsa_priv->use_pkcs1_oaep_padding; if ($self->algorithm == 1) { $rsa_priv->use_md5_hash; } elsif ($self->algorithm == 8) { $rsa_priv->use_sha256_hash; } elsif ($self->algorithm == 10) { $rsa_priv->use_sha512_hash; } else { $rsa_priv->use_sha1_hash; } }; die "RSA private key loading failed:".$@ if $@; eval { $signature = $rsa_priv->sign($sigdata); }; die "RSA Signature generation failed ".$@ if $@; print "\n SIGNED" if $debug ; }elsif ($self->algorithm == 3 || $self->algorithm == 6 ){ #DSA $self->{"private_key"}=$Private->privatekey; my $private_dsa=$Private->privatekey; if ($datarrset ne "" ){ if (my $sig_obj= $private_dsa->do_sign(sha1($sigdata))) { print "\n SIGNED" if $debug ; # See RFC 2535 for the content of the SIG my $T_parameter= (length($private_dsa->get_g)-64)/8; $signature=pack("C",$T_parameter); my $sig_r_param=$sig_obj->get_r; my $sig_s_param=$sig_obj->get_s; # both the R and S paramater in the RDATA need to be # 20 octets: while (length($sig_r_param)<20){ $sig_r_param=pack('x').$sig_r_param ; } while (length($sig_s_param)<20) { $sig_s_param=pack('x').$sig_s_param ; } $signature.=$sig_r_param.$sig_s_param; }else { confess "creation of DSA Signature failed " ; } } } if ($datarrset ne "" ){ # Replace the "sig" by the real signature and return the object. $self->{"sigbin"}=$signature; $self->{"sig"}= encode_base64($signature); } return $self; } sub verify { my ($self, $dataref, $keyrrref ) = @_; # Reminder... # $dataref may be a reference to an array of RR objects: # $dataref->[$i]->method is the call to the method of the $i th # object in the array... @{$dataref} is length of the array when # called in numerical context # $keyref is eiter a reference to an array of keys or a a key object. # if $dataref is not a reference it contains a string with data to be # verified using SIG0 my $sigzero_verify=0; my $packet_verify=0; my $rrarray_verify=0; my $keyrr; # This will be used to store the key to which we want to # verify. print "Second argument is of class".ref($keyrrref)."\n" if $debug;; if (ref($keyrrref) eq "ARRAY"){ # We will recurse for each key that matches algorithm and key-id # we return when there is a succesful verification. # If not we'll continue so that we even survive key-id collission. # The downside of this is that the error string only matches the # last error. my @keyarray=@{$keyrrref}; my $errorstring=""; my $i=0; print "Itterating over " . @keyarray ." keys \n" if $debug; KEYRR: foreach my $keyrr (@keyarray) { $i++; unless ($keyrr->algorithm == $self->algorithm){ print "key $i: algorithm does not match\n" if $debug; $errorstring.="key $i: algorithm does not match "; next KEYRR; } unless ($keyrr->keytag == $self->keytag){ print "key $i: keytag does not match (".$keyrr->keytag." ".$self->keytag.")\n" if $debug; $errorstring.="key $i: keytag does not match "; next KEYRR ; } my $result=$self->verify($dataref,$keyrr); print "key $i:".$self->vrfyerrstr if $debug; $errorstring.="key $i:".$self->vrfyerrstr." "; next KEYRR unless $result; $self->{"vrfyerrstr"}="No Error"; return $result; } $self->{"vrfyerrstr"}=$errorstring; return (0); }elsif(ref($keyrrref) eq 'Net::DNS::RR::DNSKEY' || ref($keyrrref) eq 'Net::DNS::RR::KEY' # we are liberal... ){ # substitute and continue processing after this conditional $keyrr=$keyrrref; print "Validating using key with keytag:".$keyrr->keytag." \n" if $debug; }else{ # Error condition $self->{"vrfyerrstr"} = "You are trying to pass ".ref($keyrrref) ." data for a key"; return (0); } print "Verifying data of class:". ref( $dataref) . "\n" if $debug; $sigzero_verify=1 unless (ref($dataref)); if (! $sigzero_verify ){ if (ref($dataref) eq "ARRAY"){ if (ref($dataref->[0]) and $dataref->[0]->isa('Net::DNS::RR')){ $rrarray_verify=1; }else{ die "Trying to verify an array of ". ref( $dataref->[0]) ."\n"; } }elsif( (ref($dataref)) and $dataref->isa("Net::DNS::Packet")){ $packet_verify=1 if ((ref($dataref)) and $dataref->isa("Net::DNS::Packet")); die "Trying to verify a packet while signature is not of SIG0 type" if ($self->{"typecovered"} ne "SIGZERO"); }else{ die "Do not know what kind of data this is" . ref( $dataref) . ")\n"; } } $self->{"vrfyerrstr"}="---- Unknown Error Condition ------"; print "\n ------------------------------- RRSIG DEBUG -----------------\n" if $debug; print "Reference: ".ref($dataref) if $debug;; print "\n RRSIG:\t", $self->string if $debug; if ( $rrarray_verify ){ for (my $i=0; $i<@{$dataref}; $i++){ print "\n DATA:\t", $dataref->[$i]->string if $debug ; } } print "\n KEY:\t" , $keyrr->string if $debug; print "\n ------------------------------------------------------------\n" if $debug; if (!$sigzero_verify && !$packet_verify && $dataref->[0]->type ne $self->typecovered ) { $self->{"vrfyerrstr"} = "\nCannot verify datatype " . $self->typecovered . " with a key intended for " . $dataref->[0]->type . " verification\n"; return 0; } if ( $rrarray_verify && !$dataref->[0]->type eq "RRSIG" ) { # if [0] has type RRSIG the whole RRset is type RRSIG. # There are no SIGs over SIG RRsets $self->{"vrfyerrstr"} = "RRSIGs over RRSIGs???\n" . " What are you trying to do. This is not possible.\n"; return 0; } if ( $self->algorithm != $keyrr->algorithm ){ $self->{"vrfyerrstr"} = "It is impossible to verify a signature made with algorithm " . $self->algorithm . "\nagainst a key made with algorithm " . $keyrr->algorithm . "\n"; return 0; } if ( $packet_verify){ # We keep the intelligence for verification in here.... # The packet is compressed ... we have to undo the compression. # Do this by creating a newpaclet my $newpacket; bless($newpacket = {},"Net::DNS::Packet"); %{$newpacket} = %{$dataref}; bless($newpacket->{"header"} = {},"Net::DNS::Header"); %{$newpacket->{"header"}} = %{$dataref->{"header"}}; @{$newpacket->{"additional"}} = @{$dataref->{"additional"}}; shift(@{$newpacket->{"additional"}}); $newpacket->{"header"}{"arcount"}--; $newpacket->{"compnames"} = {}; $dataref=$dataref->data; } # The data that is to be signed my $sigdata=$self->_CreateSigData($dataref); my $signature=$self->sigbin; my $verified=0; if ( $self->algorithm == 1 ){ #Verifying for RSA $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,0) || return 0; } elsif ( $self->algorithm == 3 || $self->algorithm == 6 ) # Verifying for DSA { $verified=$self->_verifyDSA($sigdata,$signature,$keyrr) || return 0; } elsif ( $self->algorithm == 5 || $self->algorithm == 7 ) # Verifying for RSASHA1 { $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,1) || return 0; } elsif ( $self->algorithm == 8 ) # Verifying for RSASHA256 { $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,256) || return 0; } elsif ( $self->algorithm == 10 ) # Verifying for RSASHA512 { $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,512) || return 0; } else # Verifying other algorithms { $self->{"vrfyerrstr"}= "Algoritm ". $self->algorithm . " has not yet been implemented"; return 0; } # This really is a redundant test if ($verified) { # time to do some time checking. my @inct=gmtime(time); my $currentdatestring= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); if ($self->{"siginception"} > $currentdatestring ){ $self->{"vrfyerrstr"}= "Signature may only be used in the future; after " . $self->{"siginception"} ; return 0; }elsif($self->{"sigexpiration"} < $currentdatestring ){ $self->{"vrfyerrstr"}= "Signature has expired since: " . $self->{"sigexpiration"} ; return 0; } $self->{"vrfyerrstr"}= "No Error"; return 1; } $self->{"vrfyerrstr"}="Verification method error."; return 0; } #END verify block # Below are all sorts of helper functions. # They should not really be used outside the scope of this class ... # # To do: make these functions invisable outside the class. # sub _type2string { my $index=shift; if( Net::DNS::typesbyval($index)){ return Net::DNS::typesbyval($index) ; }else{ return "UNKNOWN TYPE"; } } sub _string2type { my $index=shift; if( Net::DNS::typesbyname(uc($index))){ return Net::DNS::typesbyname(uc($index)) ; }else{ carp "UNKNOWN TYPE, cannot continue "; } } sub _verifyDSA { my ($self, $sigdata, $signature, $keyrr) = @_; print "\nDSA verification called with key:\n". $keyrr->string . " and sig:\n" . $self->string ."\n" if $debug; # RSA RFC2536 # # Setup a DSA::Key. # my $t_param=ord substr($keyrr->keybin, 0, 1); # This works since T is only one octed . my $q_param=substr($keyrr->keybin, 1, 20); my $p_param=substr($keyrr->keybin, 21, 64+$t_param*8 ); my $g_param=substr($keyrr->keybin, 21+64+$t_param*8, 64+$t_param*8); #rfc3279 section 2.3.2 # (...) # The DSA public key MUST be ASN.1 DER encoded as an INTEGER; this # encoding shall be used as the contents (i.e., the value) of the # subjectPublicKey component (a BIT STRING) of the # SubjectPublicKeyInfo data element. # (...) my $pubkey_param=substr($keyrr->keybin, 21+2*(64+$t_param*8), 64+$t_param*8); my $dsa_pub=Crypt::OpenSSL::DSA->new(); $dsa_pub->set_q($q_param); $dsa_pub->set_g($g_param); $dsa_pub->set_p($p_param); $dsa_pub->set_pub_key($pubkey_param); my $r_field=(substr($self->sigbin, 1, 20)); my $s_field=(substr($self->sigbin, 21, 20)); my $DSAsig=Crypt::OpenSSL::DSA::Signature->new(); $DSAsig->set_r($r_field); $DSAsig->set_s($s_field); if (my $valid=$dsa_pub->do_verify (sha1( $sigdata) , $DSAsig )){ if ($valid==-1){ print "Crypt::OpenSSL::DSA Verification failed with error\n" if $debug; $self->{"vrfyerrstr"}="DSA Verification failed with error"; return(0); }else{ print "Crypt::OpenSSL::DSA Verification successful:$valid\n" if $debug;; $self->{"vrfyerrstr"}="DSA Verification successful "; return(1); } }else{ print "Crypt::OpenSSL::DSA Verification failed\n " if $debug;; $self->{"vrfyerrstr"}="DSA Verification failed "; return(0); } $self->{"vrfyerrstr"}="DSA Verification failed: undefined error "; return 0; } sub _verifyRSA { # Implementation using crypt::openssl my ($self, $sigdata, $signature, $keyrr, $isSHA) = @_; print "\nRSA verification called with key:\n". $keyrr->string . " sig:\n" . $self->string ."\non sigdata:\t". unpack ("H*",$sigdata) . "\n" if $debug; # RSA RFC2535 # my $explength; my $exponent; my $modulus; my $RSAPublicKey; { #localise dummy my $dummy=1; # determine exponent length #RFC 2537 sect 2 ($dummy, $explength)=unpack("Cn",$keyrr->keybin) if ! ($explength=unpack("C",$keyrr->keybin)); print "\n\nEXPLENGTH:",$explength if $debug; # We are constructing the exponent and modulus as a hex number so # the AUTOLOAD function in Crypt::RSA::Key::Public can deal with it # later, there must be better ways to do this, if ($dummy) { # skip one octet $exponent=(substr ($keyrr->keybin, 1, $explength)); $modulus=( substr ($keyrr->keybin, 1+$explength, (length $keyrr->keybin) - 1 - $explength)); }else{ # skip two octets $exponent=(substr ($keyrr->keybin, 3, $explength)); $modulus=( substr ($keyrr->keybin, 3+$explength, (length $keyrr->keybin) - 3 - $explength)); } } my $bn_modulus=Crypt::OpenSSL::Bignum->new_from_bin($modulus); my $bn_exponent=Crypt::OpenSSL::Bignum->new_from_bin($exponent); my $rsa_pub = Crypt::OpenSSL::RSA->new_key_from_parameters($bn_modulus,$bn_exponent); die "Could not load public key" unless $rsa_pub; $rsa_pub->use_pkcs1_oaep_padding; if ($isSHA == 1) { $rsa_pub->use_sha1_hash; } elsif ($isSHA == 256) { $rsa_pub->use_sha256_hash; } elsif ($isSHA == 512) { $rsa_pub->use_sha512_hash; } else { $rsa_pub->use_md5_hash; } my $verified; eval { $verified=$rsa_pub->verify($sigdata, $signature); }; if ($@){ $self->{"vrfyerrstr"}= "Verification of RSA string generated error: ". $@; print "\nRSA library error.\n" if $debug; return 0; } if ($verified ) { print "\nVERIFIED\n\n" if $debug ; $self->{"vrfyerrstr"}="RSA Verification successful"; return 1; }else { $self->{"vrfyerrstr"}="RSA Verification failed"; # Data is not verified print "\nNOT VERIFIED\n" if $debug; return 0; } $self->{"vrfyerrstr"}="RSA Verification failed: This code should not be run "; 0; } sub _CreateSigData { # this is the data that will be signed, it will be fed to the # verifier. See RFC4034 section 6 on how this string is constructed # This method is called by the method that creates as signature # and by the method that verifies the signature. It is assumed # that the creation method has checked that all the TTL are the same # for the dataref and that sig->orgttl has been set to the TTL of # the data. This method will set the datarr->ttl to the sig->orgttl for # all the RR in the dataref. my ($self,$rawdata)=@_; my $sigzero= ! ref ($rawdata); my $sigdata; # construction of message print "_CreatSigData\n" if $debug; my $rdatawithoutsig=$self->rr_rdata_without_sigbin; print "raw RRsig:\t", unpack("H*", $rdatawithoutsig) if $debug; $sigdata= $rdatawithoutsig; if ( ! $sigzero ){ # Not a SIG0 if (@{$rawdata}>1) { my @canonicaldataarray; for (my $i=0; $i<@{$rawdata}; $i++){ if ($debug){ print "Setting TTL to from ". $rawdata->[$i]->{"ttl"} . " to " . $self->orgttl . "\n" if ( $rawdata->[$i]->{"ttl"}!=$self->orgttl); } $rawdata->[$i]->{"ttl"}=$self->orgttl; # Some error checking is done to. A RRset is defined by # Same label,class,qtype if (lc($rawdata->[$i]->name) ne lc($rawdata->[0]->name)){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nNot all labels in the data RRset above are equal "; } if ($rawdata->[$i]->type ne $rawdata->[0]->type){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nThe the data RRset consists of different types "; } if ($rawdata->[$i]->class ne $rawdata->[0]->class){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nThe the data RRset has different classes (What are you trying to do?) "; } print "\n\nCan Data RR: $i\t", unpack("H*", ($rawdata->[$i]->_canonicaldata)) if $debug; # To allow for sorting on RDATA we create an array of hashes. # We sort on canonicalRdata and use the full RR representation # in rr to build the digest. $canonicaldataarray[$i]= { rrdigest => $rawdata->[$i]->_canonicaldata, canonicalRdata => $rawdata->[$i]->_canonicalRdata, }; } # Sort acording to RFC2535 section 8.3 # Comparing left justified octet strings: perl sort does just that. # We have to sort on RDATA.. the array contains the whole RRset. # the sort routine my @sortedcanonicaldataarray= sort { $a->{"canonicalRdata"} cmp $b->{"canonicalRdata"}; } @canonicaldataarray; for (my $i=0; $i<@sortedcanonicaldataarray ; $i++){ print "\n>>>" . $i . ">>> \t" . unpack("H*",$sortedcanonicaldataarray[$i]{canonicalRdata}) . "\n>>>\t " . unpack("H*",$sortedcanonicaldataarray[$i]{rrdigest}) . "\n" if $debug; $sigdata .= $sortedcanonicaldataarray[$i]{rrdigest}; } }else{ if ($debug) { print "\nSetting TTL to from ". $rawdata->[0]->{"ttl"} . " to " . $self->orgttl . "\n" if ( $rawdata->[0]->{"ttl"}!=$self->orgttl ); } print "\nRDATA:\t\t" .$rawdata->[0]->_canonicalRdata ."\n-----:\t\t" . unpack("H*",$rawdata->[0]->_canonicalRdata) ."\n" if $debug; $rawdata->[0]->{"ttl"}=$self->orgttl; $sigdata .= $rawdata->[0]->_canonicaldata; } }else{ #SIG0 case print "\nsig0 proccessing\nrawdata:\t". unpack("H*",$rawdata)."\n"if $debug; $sigdata=$sigdata.$rawdata; } print "\n sigdata:\t". unpack("H*",$sigdata) . "\n" if $debug; return $sigdata; } sub _checktimeformat { # Function to check if the strings entered as time are properly formated. # Croaks if the format does not make sense... my $timestring=shift; my @timeval=($timestring =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/); if (@timeval != 6) { croak "The time " . $timestring . " is not in the expected format (yyyymmddhhmmss)"; } if ($timeval[0]< 1970) { croak "The year ". $timeval[0] . " is before the epoch (1970)"; } if ($timeval[1]> 12) { croak "What??? There is no month number ". $timeval[1] ; } # This is a rough check... # Feb 31 will work... if ($timeval[2]> 31) { croak "Intresting, a month with ". $timeval[2] . " days" ; } if ($timeval[3]> 24) { croak "Intresting, a day with ". $timeval[3] . " hours" ; } if ($timeval[4]> 60) { croak "Intresting, an hour with ". $timeval[3] . " minutes" ; } if ($timeval[5]> 60) { croak "Intresting, a minute with ". $timeval[3] . " seconds" ; } 0; } # The previous versions had a typo... *Sigh* sub siginceptation { my $self=shift; return $self->siginception(@_); } sub _normalize_dnames { my $self=shift; $self->_normalize_ownername(); $self->{'signame'}=lc(Net::DNS::stripdot($self->{'signame'})) if defined $self->{'signame'}; } 1; =head1 NAME Net::DNS::RR::RRSIG - DNS RRSIG resource record =head1 SYNOPSIS C =head1 DESCRIPTION Class for DNS Address (RRSIG) resource records. In addition to the regular methods in the Net::DNS::RR the Class contains a method to sign RRsets using private keys (create). And a class for verifying signatures over RRsets (verify). The RRSIG RR is an implementation of RFC 4034. See L for an impelementation of SIG0 (RFC 2931). =head1 METHODS =head2 create Create a signature over a RR set. my $keypath= "/home/olaf/keys/Kbla.foo.+001+60114.private"; my $sigrr= create Net::DNS::RR::RRSIG(\@datarrset, $keypath); my $sigrr= create Net::DNS::RR::RRSIG(\@datarrset, $keypath, %arguments); $sigrr->print; #Alternatively use Net::DNS::SEC::Private my $private=Net::DNS::SEC::Private-new( "/home/olaf/keys/Kbla.foo.+001+60114.private"); my $sigrr= create Net::DNS::RR::RRSIG(\@datarrset, $private); create is an alternative constructor for a RRSIG RR object. The first argument is either reference to an array that contains the RRset that needs to be signed. The second argument is a string containing the path to a file containing the the private key as generated with dnssec-keygen, a program that commes with the bind distribution. The third argument is an anonymous hash containing the following possible arguments: ( ttl => 3600, # TTL sigin => 20010501010101, # signature inception sigex => 20010501010101, # signature expiration sigval => 1.5 # signature validity ) The default for the ttl is 3600 seconds. sigin and sigex need to be specified in the following format 'yyyymmddhhmmss'. The default for sigin is the time of signing. sigval is the validity of the signature in minutes for SIG0s and days for other signatures (sigex=sigin+sigval). If sigval is specified then sigex is ignored. The default for sigval is 5 minutes for SIG0s and 30 days other types of signatures. Notes: - Do not change the name of the file generated by dnssec-keygen, the create method uses the filename as generated by dnssec-keygen to determine the keyowner, algorithm and the keyid (keytag). - Only RSA signatures (algorithm 1,5 and 7) and DSA signatures (algorithm 3, and 6) have been implemented. =head2 typecovered print "typecovered =", $rr->typecovered, "\n" Returns the qtype covered by the sig. =head2 algorithm print "algorithm =", $rr->algorithm, "\n" Returns the algorithm number used for the signature =head2 labels print "labels =", $rr->labels, "\n" Returns the the number of labels of the RRs over wich the sig was made. =head2 orgttl print "orgttl =", $rr->orgttl, "\n" Returns the RRs the original TTL of the signature =head2 sigexpiration print "sigexpiration =", $rr->sigexpiration, "\n" Returns the expiration date of the signature =head2 siginception print "siginception =", $rr->siginception, "\n" Returns the date the signature was incepted. =head2 keytag print "keytag =", $rr->keytag, "\n" Returns the the keytag (key id) of the key the sig was made with. Read "KeyID Bug in bind." below. =head2 signame print "signame =", $rr->signame, "\n" Returns the name of the public KEY RRs this sig was made with. =head2 sig print "sig =", $rr->sig, "\n" Returns the base64 representation of the signature. =head2 verify and vrfyerrstr $sigrr->verify($data, $keyrr) || croak $sigrr->vrfyerrstr; $sigrr->verify($data, [$keyrr, $keyrr2, $keyrr3]) || croak $sigrr->vrfyerrstr; If $data contains a reference to an array of RR objects then them method verifies the RRset against the signature contained in the $sigrr object itself using the public key in $keyrr. Because of the KeyID bug in bind (see below) a check on keyid is not performed. If $data contains a reference to a Net::DNS::Packet and if $sig->type equals zero a a sig0 verification is performed. Note that the signature needs to be 'popped' from the packet before verifying. The second argument can either be a Net::DNS::RR::KEYRR object or a reference to an array of such objects. Verification will return successful as soon as one of the keys in the array leads to positive validation. Returns 0 on error and sets $sig->vrfyerrstr =head2 Example my $sigrr=$packet->pop("additional"); print $sigrr->vrfyerrstr unless $sigrr1->verify($update1, $keyrr1); =head1 Remarks - The code is not optimized for speed whatsoever. It is probably not suitable to be used for signing large zones. =head1 TODO - Clean up the code. - If this code is still around by 2030 you have a few years to check the proper handling of times... - Add wildcard handling =head1 ACKNOWLEDGMENTS Andy Vaskys (Network Associates Laboratories) supplied the code for handling RSA with SHA1 (Algorithm 5). Chris Reinardt for maintianing Net::DNS. T.J. Mather, , the Crypt::OpenSSL::DSA maintainer, for his quick responses to bug report and feature requests. =head1 COPYRIGHT Copyright (c) 2001 - 2005 RIPE NCC. Author Olaf M. Kolkman Copyright (c) 2007 - 2008 NLnet Labs. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. This code uses Crypt::OpenSSL which uses the openssl library =head1 SEE ALSO L L, L, L, L, L, L, L,L, L, L, RFC 4034 =cut Net-DNS-SEC-0.16/RR/SIG.pm000644 000765 000120 00000105741 11346437006 014605 0ustar00olafadmin000000 000000 # perldoc SIG.pm for documentation. # Specs: RFC 2535 section 4 # $Id: SIG.pm 777 2008-12-30 17:18:54Z olaf $ package Net::DNS::RR::SIG; use vars qw(@ISA $VERSION @EXPORT ); use Net::DNS; use Carp; use bytes; use Crypt::OpenSSL::DSA; use Crypt::OpenSSL::RSA; use Crypt::OpenSSL::Bignum; use Net::DNS::SEC::Private; use File::Basename; use MIME::Base64; use Math::BigInt; use Time::Local; use Digest::SHA qw (sha1); # # Most of the cryptovariables should be interpred as unsigne # # require Exporter; $VERSION = do { my @r=(q$Revision: 777 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r }; @ISA = qw ( Exporter Net::DNS::RR ); @EXPORT = qw ( ); use strict; my $debug=0; my $crypt_open_ssl=1; my $__DeprecationWarningVerifyShown=0; my $__DeprecationWarningCreateShown=0; sub new { my ($class, $self, $data, $offset) = @_; if ($self->{"rdlength"} > 0) { #RFC2535 section 4.1 my $offsettoalg=$offset+2; my $offsettolabels=$offset+3; my $offsettoorgttl=$offset+4; my $offsettosigexp=$offset+8; my $offsettosiginc=$offset+12; my $offsettokeytag=$offset+16; my $offsettosignm=$offset+18; $self->{"typecovered"}= _type2string(unpack("n",substr($$data,$offset,2))); $self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1)); $self->{"labels"}=lc(unpack("C",substr($$data,$offsettolabels,1))); $self->{"orgttl"}=unpack("N",substr($$data,$offsettoorgttl,4)); my @expt=gmtime(unpack("N",substr($$data,$offsettosigexp,4))); $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $expt[5]+1900 ,$expt[4]+1 , $expt[3] ,$expt[2] , $expt[1] , $expt[0]); my @inct=gmtime(unpack("N",substr($$data,$offsettosiginc,4))); $self->{"siginception"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); $self->{"keytag"}=unpack("n",substr($$data,$offsettokeytag,2)); my($signame,$sigoffset) = Net::DNS::Packet::dn_expand ($data, $offsettosignm); $self->{"signame"}=lc($signame) ; my($sigmaterial)=substr($$data,$sigoffset, ($self->{"rdlength"}-$sigoffset+$offset)); $self->{"sigbin"}=$sigmaterial; $self->{"sig"}= encode_base64($sigmaterial); $self->{"vrfyerrstr"}=""; } return bless $self, $class; } sub new_from_string { my ($class, $self, $string) = @_; if ($string) { $string =~ tr/()//d; $string =~ s/;.*$//mg; $string =~ s/\n//mg; my ($typecovered, $algoritm, $labels, $orgttl, $sigexpiration, $siginception, $keytag,$signame,$sig) = $string =~ /^\s*(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)/; croak (" Invallid SIG RR, check your fomat ") if !$keytag; $sig =~ s/\s*//g; $self->{"typecovered"}=uc($typecovered); $self->{"algorithm"}= $algoritm; $self->{"labels"}= lc($labels); $self->{"orgttl"}= $orgttl; _checktimeformat($sigexpiration); _checktimeformat($siginception); $self->{"sigexpiration"}= $sigexpiration; $self->{"siginception"}= $siginception; $self->{"keytag"}= $keytag; $self->{"signame"}= Net::DNS::stripdot(lc($signame)); $self->{"sig"}= $sig; $self->{"sigbin"}= decode_base64($sig); $self->{"vrfyerrstr"}=""; } return bless $self, $class; } sub rdatastr { my $self = shift; my $rdatastr; if (exists $self->{"typecovered"}) { $rdatastr = $self->{typecovered}; $rdatastr .= " " . "$self->{algorithm}"; $rdatastr .= " " . "$self->{labels}"; $rdatastr .= " " . "$self->{orgttl}"; $rdatastr .= " " . "$self->{sigexpiration}"; $rdatastr .= " (\n\t\t\t" . "$self->{siginception}"; $rdatastr .= " " . "$self->{keytag}"; $rdatastr .= " " . "$self->{signame}"; # do some nice formatting my $sigstring=$self->{sig}; $sigstring =~ s/\n//g; $sigstring =~ s/(\S{45})/$1\n\t\t\t/g; $rdatastr .= "\n\t\t\t".$sigstring; $rdatastr .= " )"; } else { $rdatastr = "; no data"; } return $rdatastr; } sub rr_rdata_without_sigbin { my ($self) = shift; my $rdata = ""; if (exists $self->{"typecovered"}) { $rdata = pack("n",_string2type($self->{typecovered})); $rdata .= pack("C",$self->{algorithm}); $rdata .= pack("C",$self->{"labels"}); $rdata .= pack("N",$self->{"orgttl"}); $self->{"sigexpiration"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; $rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900)); $self->{"siginception"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; $rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900)); $rdata .= pack("n",$self->{"keytag"}); # Since we will need canonical and expanded names while checking # we do not use the packet->dn_comp here but use RFC1035 p10. { my @dname= split /\./,lc($self->{"signame"}); for (my $i=0;$i<@dname;$i++){ $rdata .= pack ("C",length $dname[$i] ); $rdata .= $dname[$i] ; } $rdata .= pack ("C","0"); } } return $rdata; } sub rr_rdata { my ($self, $packet, $offset) = @_; my $rdata = ""; if (exists $self->{"typecovered"}) { $rdata=$self->rr_rdata_without_sigbin; if ($self->{"sig"} ne "NOTYETCALCULATED") { $self->{"sigbin"}= decode_base64($self->{"sig"}) unless defined $self->{"sigbin"} ; $rdata .= $self->{"sigbin"}; }else{ #do sigzero calculation based on current packet content... die "Signature not known for a not SIG0 type of signature" if ($self->{"typecovered"} ne "TYPE000"); die "Private key not known for SIG0" if (! exists $self->{"private_key"}); my $rr=$packet->pop("additional"); die "SIG0 should be the last RR in the packet" if ($rr->type ne "SIG"); die "Unexpected error during creation of SIG0. " if ($rr ne $self); print "Processing SIG0 signature\n" if $debug; my $data; # Compress the data and make sure we will not go into deep # recursion if ($self->{"rr_rdata_recursion"}==0){ $self->{"rr_rdata_recursion"}=1; $data=$packet->data; my $sigdata=$self->_CreateSigData($data); my $signature; if ($self->{"algorithm"} == 1 || $self->{"algorithm"} == 5) { #RSA my $rsa_priv=$self->{"private_key"}; eval { $rsa_priv->use_pkcs1_oaep_padding; if ($self->{"algorithm"} == 1) { $rsa_priv->use_md5_hash; } else { $rsa_priv->use_sha1_hash; } }; die "Error loading RSA private key " . $@ if $@; eval { $signature = $rsa_priv->sign($sigdata); }; die "RSA Signature generation failed ".$@ if $@; print "\n SIGNED" if $debug ; }elsif ($self->{"algorithm"} == 3){ #DSA my $private_dsa = $self->{"private_key"}; # If $sigzero then we want to sign data if given # in the argument. If the argument is empty we # sign when the packet put on the wire. if (my $sig_obj= $private_dsa->do_sign(sha1($sigdata))) { print "\n SIGNED" if $debug ; # See RFC 2536 for the content of the DSA SIG rdata my $T_parameter= (length($private_dsa->get_g)-64)/8; $signature=pack("C",$T_parameter); my $sig_r_param=$sig_obj->get_r; my $sig_s_param=$sig_obj->get_s; # both the R and S paramater in the RDATA need to be # 20 octets while (length($sig_r_param)<20){ $sig_r_param=pack("x").$sig_r_param ; } while (length($sig_s_param)<20) { $sig_s_param=pack("x").$sig_s_param ; } $signature.=$sig_r_param.$sig_s_param; }else { confess "creation of DSA Signature failed " ; } } $self->{"sigbin"}=$signature; $self->{"sig"}= encode_base64($signature); $rdata .= $self->{"sigbin"}; } $packet->push("additional", $self); } } return $rdata; } sub create { my ($class, $datarrset, $priv_key, %args) = @_; # This method returns a sigrr with the signature over the # datatrrset (an array of RRs) made with the private key stored in # the $key_file. my $self; $self->{"sigerrstr"}="---- Unknown Error Condition ------"; my $Private; if (UNIVERSAL::isa($priv_key,"Net::DNS::SEC::Private")){ $Private=$priv_key; }else{ $Private=Net::DNS::SEC::Private->new($priv_key); } die "Create did not manage obtain a Net::DNS::SEC::Private object "unless (UNIVERSAL::isa($Private,"Net::DNS::SEC::Private")); $self->{"algorithm"}=$Private->algorithm; $self->{"keytag"}=$Private->keytag; $self->{"signame"}=$Private->signame; # if $datarrset is a plain datastrream then construct a sigzero sig. # So any number will actually do. my $sigzero= ! ref ($datarrset); $self->{"rr_rdata_recursion"}=0; # Start with seting up the data in the packet we can get our hands on... if ($sigzero){ $self->{"name"}=""; }else{ $self->{"name"}=$datarrset->[0]->name; } $self->{"type"}="SIG"; $self->{"class"}="IN"; if ($sigzero){ # RFC 2931 sect 3 $self->{"ttl"}=0; $self->{"class"}="any"; }elsif ($args{ttl}){ print "\nSetting TTL to ". $args{"ttl"} if $debug; $self->{"ttl"}= $args{"ttl"}; }else{ $self->{"ttl"}= 3600; } if ($sigzero){ $self->{"typecovered"}="TYPE000"; }else{ print "Note: the SIG RR has been deprecated for use other than SIG0; use the RRSIG instead\n" if !$__DeprecationWarningCreateShown ; $__DeprecationWarningCreateShown=1; $self->{"typecovered"}=$datarrset->[0]->type; #Sanity checks elsewhere } if ($args{response}){ $self->{"response"}=$args{"response"}; } if ($args{"sigin"}){ _checktimeformat($args{"sigin"}); print "\nSetting siginception to " . $args{"sigin"} if $debug; $self->{"siginception"} =$args{"sigin"}; }else{ my @inct=gmtime(time); my $currentdatestring= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); $self->{"siginception"} = $currentdatestring ; } # This will fail if the dateformat is not correct... $self->{"siginception"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ; my $siginc_time=timegm ($6, $5, $4, $3, $2-1, $1-1900); if ($args{"sigval"}){ #sigexpiration set by siginception + sigval my @inct; if ($sigzero){ # treat sigval as minutes @inct=gmtime($siginc_time+$args{"sigval"}*60 ); }else{ # treat sigval as days @inct=gmtime($siginc_time+$args{"sigval"}*24*3600 ); } $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); }elsif ($args{"sigex"}) { #sigexpiration set by the argument _checktimeformat($args{"sigex"}); if ( $self->{"siginception"} > $args{"sigex"} ){ croak "Signature can only expire after it has been incepted (". $args{"sigex"} . "<" . $self->{"siginception"} . ")"; } print "\nSetting sigexpiration to " . $args{"sigexp"} if $debug; $self->{"sigexpiration"}=$args{"sigex"} ; }else{ my @inct; if ($sigzero){ #default 5 minutes @inct=gmtime($siginc_time+5*60 ); }else{ # Take the 30 days default for sigexpiration @inct=gmtime($siginc_time+30*24*3600 ); } $self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); } if (!$sigzero) { my $labels=$datarrset->[0]->name; $labels =~ s/\.$//; # remove trailing dot. $labels =~ s/^\*\.//; # remove initial asterisk label my @labels= split /\./ , $labels; $self->{"labels"}= scalar(@labels); }else{ $self->{"labels"}= 0; } # All the TTLs need to be the same in the data RRset. if ( (!$sigzero) && @{$datarrset}>1){ for (my $i=0; $i<@{$datarrset}; $i++){ if ($datarrset->[0]->{"ttl"} != $datarrset->[$i]->{"ttl"}){ croak "\nNot all TTLs in the data RRset are equal "; } } } if ($sigzero){ $self->{"orgttl"}=0; }else{ $self->{"orgttl"}=$datarrset->[0]->{"ttl"}; } $self->{"sig"}= "NOTYETCALCULATED"; # This is what we'll do in a bit... $self->{"sigbin"}= decode_base64($self->{"sig"}); # Bless the whole thing so we can get access to the methods... # (Don not ask me why I havent called the new method, There are # more ways to do things) bless $self, $class; my $sigdata=$self->_CreateSigData($datarrset); my $signature; # # Enjoy the crypto if ($self->{"algorithm"} == 1 || $self->{"algorithm"} == 5) { #RSA if (! ($Private->algorithm == 1 || $self->algorithm == 5 )) { die "Private key mismatch, not RSAMD5 or RSASHA."; } # my $rsa_priv = Crypt::OpenSSL::RSA->new_private_key($Private->privatekey); my $rsa_priv = $Private->privatekey; $self->{"private_key"}=$Private->privatekey; eval { $rsa_priv->use_pkcs1_oaep_padding; if ($self->{"algorithm"} == 1) { $rsa_priv->use_md5_hash; } else { $rsa_priv->use_sha1_hash; } }; die "RSA private key loading failed:".$@ if $@; eval { $signature = $rsa_priv->sign($sigdata); }; die "RSA Signature generation failed ".$@ if $@; print "\n SIGNED" if $debug ; }elsif ($self->{"algorithm"} == 3){ #DSA $self->{"private_key"}=$Private->privatekey; my $private_dsa=$Private->privatekey; # If $sigzero then we want to sign data if given in the # argument. If the argument is empty we sign when the packet # put on the wire. if ($datarrset ne "" ){ if (my $sig_obj= $private_dsa->do_sign(sha1($sigdata))) { print "\n SIGNED" if $debug ; # See RFC 2535 for the content of the SIG my $T_parameter= (length($private_dsa->get_g)-64)/8; $signature=pack("C",$T_parameter); my $sig_r_param=$sig_obj->get_r; my $sig_s_param=$sig_obj->get_s; # both the R and S paramater in the RDATA need to be # 20 octets: while (length($sig_r_param)<20){ $sig_r_param=pack('x').$sig_r_param ; } while (length($sig_s_param)<20) { $sig_s_param=pack('x').$sig_s_param ; } $signature.=$sig_r_param.$sig_s_param; }else { confess "creation of DSA Signature failed " ; } } } if ($datarrset ne "" ){ # Replace the "sig" by the real signature and return the object. $self->{"sigbin"}=$signature; $self->{"sig"}= encode_base64($signature); } return $self; } sub verify { my ($self, $dataref, $keyrr) = @_; # Reminder... # $dataref may be a reference to an array of RR objects: # $dataref->[$i]->method is the call to the method of the $i th # object in the array... @{$dataref} is length of the array when # called in numerical context # Alternatively %dataref may refer to a a Net::DNS::Packet. # if $dataref is not a reference it contains a string with data to be # verified using SIG0 my $sigzero_verify=0; my $packet_verify=0; my $rrarray_verify=0; print "Verifying data of class:". ref( $dataref) . "\n" if $debug; $sigzero_verify=1 unless (ref($dataref)); if (! $sigzero_verify ){ if (ref($dataref) eq "ARRAY"){ if (ref($dataref->[0]) and $dataref->[0]->isa('Net::DNS::RR')){ $rrarray_verify=1; print "Note: the SIG RR has been deprecated for use other than SIG0; use the RRSIG instead\n" if !$__DeprecationWarningVerifyShown ; $__DeprecationWarningVerifyShown=1; }else{ die "Trying to verify an array of ". ref( $dataref->[0]) ."\n"; } }elsif( (ref($dataref)) and $dataref->isa("Net::DNS::Packet")){ $packet_verify=1 if ((ref($dataref)) and $dataref->isa("Net::DNS::Packet")); die "Trying to verify a packet while signature is not of SIG0 type" if ($self->{"typecovered"} ne "TYPE000"); }else{ die "Do not know what kind of data this is" . ref( $dataref) . ")\n"; } } $self->{"vrfyerrstr"}="---- Unknown Error Condition ------"; print "\n ------------------------------- SIG DEBUG -----------------\n" if $debug; print "Reference: ".ref($dataref) if $debug;; print "\n SIG:\t", $self->string if $debug; if ( $rrarray_verify ){ for (my $i=0; $i<@{$dataref}; $i++){ print "\n DATA:\t", $dataref->[$i]->string if $debug ; } } print "\n KEY:\t" , $keyrr->string if $debug; print "\n ------------------------------------------------------------\n" if $debug; if (!$sigzero_verify && !$packet_verify && $dataref->[0]->type ne $self->typecovered ) { $self->{"vrfyerrstr"} = "\nCannot verify datatype " . $self->typecovered . " with a key intended for " . $dataref->[0]->type . " verification\n"; return 0; } if ( $rrarray_verify && !$dataref->[0]->type eq "SIG" ) { # if [0] has type SIG the whole RRset is type SIG. # There are no SIGs over SIG RRsets $self->{"vrfyerrstr"} = "SIGs over SIGs???\n" . " What are you trying to do. This is not possible.\n"; return 0; } if ( $self->algorithm != $keyrr->algorithm ){ $self->{"vrfyerrstr"} = "It is impossible to verify a signature made with algorithm " . $self->algorithm . "\nagainst a key made with algorithm " . $keyrr->algorithm . "\n"; return 0; } if ( $packet_verify){ # We keep the intelligence for verification in here.... # The packet is compressed ... we have to undo the compression. # Do this by creating a newpaclet my $newpacket; bless($newpacket = {},"Net::DNS::Packet"); %{$newpacket} = %{$dataref}; bless($newpacket->{"header"} = {},"Net::DNS::Header"); %{$newpacket->{"header"}} = %{$dataref->{"header"}}; @{$newpacket->{"additional"}} = @{$dataref->{"additional"}}; shift(@{$newpacket->{"additional"}}); $newpacket->{"header"}{"arcount"}--; $newpacket->{"compnames"} = {}; $dataref=$dataref->data; } # The data that is to be signed my $sigdata=$self->_CreateSigData($dataref); my $signature=$self->sigbin; my $verified=0; if ( $self->algorithm == 1 ){ #Verifying for RSA $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,0) || return 0; } elsif ( $self->algorithm == 3 ) # Verifying for DSA { $verified=$self->_verifyDSA($sigdata,$signature,$keyrr) || return 0; } elsif ( $self->algorithm == 5 ) # Verifying for RSASHA1 { $verified=$self->_verifyRSA($sigdata,$signature,$keyrr,1) || return 0; } else # Verifying other algorithms { $self->{"vrfyerrstr"}= "Algoritm ". $self->algorithm . " has not yet been implemented"; return 0; } # This really is a redundant test if ($verified) { # time to do some time checking. my @inct=gmtime(time); my $currentdatestring= sprintf ("%d%02d%02d%02d%02d%02d", $inct[5]+1900 ,$inct[4]+1 , $inct[3] ,$inct[2] , $inct[1] , $inct[0]); if ($self->{"siginception"} > $currentdatestring ){ $self->{"vrfyerrstr"}= "Signature may only be used in the future; after " . $self->{"siginception"} ; return 0; }elsif($self->{"sigexpiration"} < $currentdatestring ){ $self->{"vrfyerrstr"}= "Signature has expired since: " . $self->{"sigexpiration"} ; return 0; } $self->{"vrfyerrstr"}= "No Error"; return 1; } $self->{"vrfyerrstr"}="Verification method error."; return 0; } #END verify block # Below are all sorts of helper functions. # They should not really be used outside the scope of this class ... # # To do: make these functions invisable outside the class. # sub _type2string { my $index=shift; if( Net::DNS::typesbyval($index)){ return Net::DNS::typesbyval($index) ; }else{ return "UNKNOWN TYPE"; } } sub _string2type { my $index=shift; if( Net::DNS::typesbyname(uc($index))){ return Net::DNS::typesbyname(uc($index)) ; }else{ carp "UNKNOWN QTYPE, cannot continue "; } } sub _verifyDSA { my ($self, $sigdata, $signature, $keyrr) = @_; print "\nDSA verification called with key:\n". $keyrr->string . " and sig:\n" . $self->string ."\n" if $debug; # RSA RFC2536 # # Setup a DSA::Key. # my $t_param=ord substr($keyrr->keybin, 0, 1); # This works since T is only one octed . my $q_param=substr($keyrr->keybin, 1, 20); my $p_param=substr($keyrr->keybin, 21, 64+$t_param*8 ); my $g_param=substr($keyrr->keybin, 21+64+$t_param*8, 64+$t_param*8); #rfc3279 section 2.3.2 # (...) # The DSA public key MUST be ASN.1 DER encoded as an INTEGER; this # encoding shall be used as the contents (i.e., the value) of the # subjectPublicKey component (a BIT STRING) of the # SubjectPublicKeyInfo data element. # (...) my $pubkey_param=substr($keyrr->keybin, 21+2*(64+$t_param*8), 64+$t_param*8); my $dsa_pub=Crypt::OpenSSL::DSA->new(); $dsa_pub->set_q($q_param); $dsa_pub->set_g($g_param); $dsa_pub->set_p($p_param); $dsa_pub->set_pub_key($pubkey_param); my $r_field=(substr($self->sigbin, 1, 20)); my $s_field=(substr($self->sigbin, 21, 20)); my $DSAsig=Crypt::OpenSSL::DSA::Signature->new(); $DSAsig->set_r($r_field); $DSAsig->set_s($s_field); if (my $valid=$dsa_pub->do_verify (sha1( $sigdata) , $DSAsig )){ if ($valid==-1){ print "Crypt::OpenSSL::DSA Verification failed with error\n" if $debug; $self->{"vrfyerrstr"}="DSA Verification failed with error"; return(0); }else{ print "Crypt::OpenSSL::DSA Verification successful:$valid\n" if $debug;; $self->{"vrfyerrstr"}="DSA Verification successful "; return(1); } }else{ print "Crypt::OpenSSL::DSA Verification failed\n " if $debug;; $self->{"vrfyerrstr"}="DSA Verification failed "; return(0); } $self->{"vrfyerrstr"}="DSA Verification failed: undefined error "; return 0; } sub _verifyRSA { # Implementation using crypt::openssl my ($self, $sigdata, $signature, $keyrr, $isSHA) = @_; print "\nRSA verification called with key:\n". $keyrr->string . " sig:\n" . $self->string ."\non sigdata:\t". unpack ("H*",$sigdata) . "\n" if $debug; # RSA RFC2535 # my $explength; my $exponent; my $modulus; my $RSAPublicKey; { #localise dummy my $dummy=1; # determine exponent length #RFC 2537 sect 2 ($dummy, $explength)=unpack("Cn",$keyrr->keybin) if ! ($explength=unpack("C",$keyrr->keybin)); print "\n\nEXPLENGTH:",$explength if $debug; # We are constructing the exponent and modulus as a hex number so # the AUTOLOAD function in Crypt::RSA::Key::Public can deal with it # later, there must be better ways to do this, if ($dummy) { # skip one octet $exponent=(substr ($keyrr->keybin, 1, $explength)); $modulus=( substr ($keyrr->keybin, 1+$explength, (length $keyrr->keybin) - 1 - $explength)); }else{ # skip two octets $exponent=(substr ($keyrr->keybin, 3, $explength)); $modulus=( substr ($keyrr->keybin, 3+$explength, (length $keyrr->keybin) - 3 - $explength)); } } my $bn_modulus=Crypt::OpenSSL::Bignum->new_from_bin($modulus); my $bn_exponent=Crypt::OpenSSL::Bignum->new_from_bin($exponent); my $rsa_pub = Crypt::OpenSSL::RSA->new_key_from_parameters($bn_modulus,$bn_exponent); die "Could not load public key" unless $rsa_pub; $rsa_pub->use_pkcs1_oaep_padding; if ($isSHA) { $rsa_pub->use_sha1_hash; } else { $rsa_pub->use_md5_hash; } my $verified; eval { $verified=$rsa_pub->verify($sigdata, $signature); }; if ($@){ $self->{"vrfyerrstr"}= "Verification of RSA string generated error: ". $@; print "\nRSA library error.\n" if $debug; return 0; } if ($verified ) { print "\nVERIFIED\n\n" if $debug ; $self->{"vrfyerrstr"}="RSA Verification successful"; return 1; }else { $self->{"vrfyerrstr"}="RSA Verification failed"; # Data is not verified print "\nNOT VERIFIED\n" if $debug; return 0; } $self->{"vrfyerrstr"}="RSA Verification failed: This code should not be run "; 0; } sub _CreateSigData { # this is the data that will be signed, it will be fed to the # verifier. See RFC4034 section 6 on how this string is constructed # This method is called by the method that creates as signature # and by the method that verifies the signature. It is assumed # that the creation method has checked that all the TTL are the same # for the dataref and that sig->orgttl has been set to the TTL of # the data. This method will set the datarr->ttl to the sig->orgttl for # all the RR in the dataref. my ($self,$rawdata)=@_; my $sigzero= ! ref ($rawdata); my $sigdata; # construction of message my $rdatawithoutsig=$self->rr_rdata_without_sigbin; print "\n\nstrip:\t\t", unpack("H*", $rdatawithoutsig) if $debug; $sigdata= $rdatawithoutsig; if ( ! $sigzero ){ # Not a SIG0 if (@{$rawdata}>1) { my @canonicaldataarray; for (my $i=0; $i<@{$rawdata}; $i++){ if ($debug){ print "Setting TTL to from ". $rawdata->[$i]->{"ttl"} . " to " . $self->orgttl . "\n" if ( $rawdata->[$i]->{"ttl"}!=$self->orgttl); } $rawdata->[$i]->{"ttl"}=$self->orgttl; # Some error checking is done to. A RRset is defined by # Same label,class,qtype if ($rawdata->[$i]->name ne $rawdata->[0]->name){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nNot all labels in the data RRset above are equal "; } if ($rawdata->[$i]->type ne $rawdata->[0]->type){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nThe the data RRset consists of different types "; } if ($rawdata->[$i]->class ne $rawdata->[0]->class){ print "\nError:\n"; for (my $j=0; $j<@{$rawdata}; $j++){ print "\n"; $rawdata->[$j]->print; } croak "\nThe the data RRset has different classes (What are you trying to do?) "; } print "\n\nCan Data RR: $i\t", unpack("H*", ($rawdata->[$i]->_canonicaldata)) if $debug; # To allow for sorting on RDATA we create an array of hashes. # We sort on canonicalRdata and use the full RR representation # in rr to build the digest. $canonicaldataarray[$i]= { rrdigest => $rawdata->[$i]->_canonicaldata, canonicalRdata => $rawdata->[$i]->_canonicalRdata, }; } # Sort acording to RFC2535 section 8.3 # Comparing left justified octet strings: perl sort does just that. # We have to sort on RDATA.. the array contains the whole RRset. # the sort routine my @sortedcanonicaldataarray= sort { $a->{"canonicalRdata"} cmp $b->{"canonicalRdata"}; } @canonicaldataarray; for (my $i=0; $i<@sortedcanonicaldataarray ; $i++){ print "\n>>>" . $i . ">>> \t" . unpack("H*",$sortedcanonicaldataarray[$i]{canonicalRdata}) . "\n>>>\t " . unpack("H*",$sortedcanonicaldataarray[$i]{rrdigest}) . "\n" if $debug; $sigdata .= $sortedcanonicaldataarray[$i]{rrdigest}; } }else{ if ($debug) { print "\nSetting TTL to from ". $rawdata->[0]->{"ttl"} . " to " . $self->orgttl . "\n" if ( $rawdata->[0]->{"ttl"}!=$self->orgttl ); } print "\nRDATA: \t" .$rawdata->[0]->_canonicalRdata ."\t" . unpack("H*",$rawdata->[0]->_canonicalRdata) ."\n" if $debug; $rawdata->[0]->{"ttl"}=$self->orgttl; $sigdata .= $rawdata->[0]->_canonicaldata; } }else{ #SIG0 case print "\nsig0 proccessing\nrawdata:\t". unpack("H*",$rawdata)."\n"if $debug; $sigdata=$sigdata.$rawdata; } print "\n sigdata:\t". unpack("H*",$sigdata) . "\n" if $debug; return $sigdata; } sub _checktimeformat { # Function to check if the strings entered as time are properly formated. # Croaks if the format does not make sense... my $timestring=shift; my @timeval=($timestring =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/); if (@timeval != 6) { croak "The time " . $timestring . " is not in the expected format (yyyymmddhhmmss)"; } if ($timeval[0]< 1970) { croak "The year ". $timeval[0] . " is before the epoch (1970)"; } if ($timeval[1]> 12) { croak "What??? There is no month number ". $timeval[1] ; } # This is a rough check... # Feb 31 will work... if ($timeval[2]> 31) { croak "Intresting, a month with ". $timeval[2] . " days" ; } if ($timeval[3]> 24) { croak "Intresting, a day with ". $timeval[3] . " hours" ; } if ($timeval[4]> 60) { croak "Intresting, an hour with ". $timeval[3] . " minutes" ; } if ($timeval[5]> 60) { croak "Intresting, a minute with ". $timeval[3] . " seconds" ; } 0; } # The previous versions had a typo... *Sigh* sub siginceptation { my $self=shift; return $self->siginception(@_); } 1; =head1 NAME Net::DNS::RR::SIG - DNS SIG resource record =head1 SYNOPSIS C =head1 DESCRIPTION IMPORTANT: For any other use than SIG0 signatures the SIG RR has been deprecated (RFC3755). Use the DNSSIG instead. All functionality currently remains present although a warning will be printed at first usage of the verify and create methods. Class for DNS Address (SIG) resource records. In addition to the regular methods in the Net::DNS::RR the Class contains a method to sign RRsets using private keys (create). And a class for verifying signatures over RRsets (verify). The SIG RR is an implementation of RFC 2931. =head1 SIG0 Support When Net::DNS::RR::SIG.pm is available the Net::DNS::Packet module will have the abilityh for sig0 support. See L for details. my $keypathrsa="Ktest.example.+001+11567.private"; my $update1 = Net::DNS::Update->new("test.example"); $update1->push("update", Net::DNS::rr_add("foo.test.example 3600 IN A 10.0.0.1")); $update1->sign_sig0($keypathrsa); =head1 METHODS =head2 create create is an alternative constructor for a SIG RR object. You are advised to create a packet object and then use the sign_sig0 method to create a sig0 signature. To create a signature over a packet (SIG0) you can use the following alternative recipe. my $keypath= "/home/olaf/keys/Kbla.foo.+001+60114.private"; $sig0 = Net::DNS::RR::SIG->create('', $keypath); $packet->push('additional', $sig0) if $sig0; $packet->data; # When the data method on a packet is called # the actual sig0 calculation is done. The first argument to the create method should be an empty string in order for the SIG0 magic to work. The second argument is a string containing the path to a file containing the the private key as generated with dnssec-keygen, a program that commes with the bind distribution. The third argument is an anonymous hash containing the following possible arguments: ( ttl => 3600, # TTL sigin => 20010501010101, # signature inception sigex => 20010501010101, # signature expiration sigval => 1.5 # signature validity ) The default for the ttl is 3600 seconds. sigin and sigex need to be specified in the following format 'yyyymmddhhmmss'. The default for sigin is the time of signing. sigval is the validity of the signature in minutes. If sigval is specified then sigex is ignored. The default for sigval is 5 minutes. Note that for SIG0 signatures the default sigin is calculated at the moment the object is created, not at the moment that the packet is put on the wire. Notes: - Do not change the name of the file generated by dnssec-keygen, the create method uses the filename as generated by dnssec-keygen to determine the keyowner, algorithm and the keyid (keytag). - Only RSA signatures (algorithm 1 and 5) and DSA signatures (algorithm 3) have been implemented. =head2 typecovered print "typecovered =", $rr->typecovered, "\n" Returns the type covered by the sig (should be TYPE000 with common SIG0 usage) =head2 algorithm print "algorithm =", $rr->algorithm, "\n" Returns the algorithm number used for the signature =head2 sigexpiration print "sigexpiration =", $rr->sigexpiration, "\n" Returns the expiration date of the signature =head2 siginception print "siginception =", $rr->siginception, "\n" Returns the date the signature was incepted. =head2 keytag print "keytag =", $rr->keytag, "\n" Returns the the keytag (key id) of the key the sig was made with. Read "KeyID Bug in bind." below. =head2 signame print "signame =", $rr->signame, "\n" Returns the name of the public KEY RRs this sig was made with. (Note: the name does not contain a trailing dot.) =head2 sig print "sig =", $rr->sig, "\n" Returns the base64 representation of the signature. =head2 verify and vrfyerrstr my $sigrr=$update1->pop("additional"); $sigrr->verify($packet, $keyrr) || croak $sigrr->vrfyerrstr; If the first argument is a Net::DNS::Packet object and if $sig->type equals zero a a sig0 verification is performed. Note that the signature needs to be 'popped' from the packet before verifying. Returns 0 on error and sets $sig->vrfyerrstr =head2 Example my $sigrr=$packet->pop("additional"); print $sigrr->vrfyerrstr unless $sigrr1->verify($update1, $keyrr1); =head1 Remarks - The code is not optimized for speed whatsoever. It is probably not suitable to be used for signing large zones. =head1 TODO - Clean up the code, it still contains some cruft left from the times that the SIG RR was used for signing packets and RR sets. - If this code is still around by 2030 you have a few years to check the proper handling of times... =head1 ACKNOWLEDGMENTS Andy Vaskys (Network Associates Laboratories) supplied the code for handling RSA with SHA1 (Algorithm 5). Chris Reinardt for maintianing Net::DNS. T.J. Mather, , the Crypt::OpenSSL::DSA maintainer, for his quick responses to bug report and feature requests. =head1 COPYRIGHT Copyright (c) 2001-2005 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Based on, and contains, code by Copyright (c) 1997 Michael Fuhr. This code uses Crypt::OpenSSL which uses the openssl library =head1 SEE ALSO L L, L, L, L, L, L, L,L,L, RFC 2931. =cut Net-DNS-SEC-0.16/demo/getkeyset.pl000755 000765 000120 00000004213 11346437006 016562 0ustar00olafadmin000000 000000 #!/usr/bin/perl -sw -I./blib/lib use Net::DNS; use Net::DNS::Keyset; use strict; my $res; my $packet; my $keyset; my $domain=shift; my $nameserver=shift; die "At least one argument needed " if !defined $domain; $res = Net::DNS::Resolver->new; $res->dnssec(1); $res->nameservers($nameserver) if defined $nameserver; $packet = $res->query($domain, 'DNSKEY', 'IN'); die "No results for query $domain DNSKEY" if ! defined $packet; $keyset=Net::DNS::Keyset->new($packet) ; if ( ! $keyset ){ print $Net::DNS::Keyset::keyset_err; return 0; } # Print DS records to STD out # my @ds=$keyset->extract_ds; foreach my $ds ( @ds ) { $ds->print; } # write keyset in current dir. # $keyset->writekeyset; 1; __END__ =head1 NAME getkeyset.pl - DS extraction demo =head1 SYNOPSIS getkeyset.pl [auth_nameserver] =head1 DESCRIPTION The program queries for the key-set of 'domain'. Spits out the DS records and writes the keyset to the current directory. If the second argument is specified the query is performed to that nameserver. =head1 TODO This is only a demonstration program to show how the interface can be used. =head1 COPYRIGHT Copyright (c) 2002 RIPE NCC. Author Olaf M. Kolkman All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. =cut =cut Net-DNS-SEC-0.16/demo/key2ds000644 000765 000120 00000001330 11346437006 015337 0ustar00olafadmin000000 000000 #!/usr/bin/perl #$Id: key2ds 169 2004-03-09 14:28:00Z olaf $ use strict; use Net::DNS; # A little util to convert DNSKEY records to DS records # From stdin to stdout # # Author: Miek Gieben, NLnetLabs my $key; while (<>) { chomp; $key .= $_ }; my $keyrr = new Net::DNS::RR($key); my $dsrr = create Net::DNS::RR::DS($keyrr); print $dsrr->string,"\n"; exit 0; =head1 NAME key2ds - Utility to convert a DNSSEC KEY to a DS record =head1 SYNOPSIS C =head1 DESCIPTION C reads the key data from STDIN and print the corresponding DS record on STDOUT. =head1 COPYRIGHT This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 0; Net-DNS-SEC-0.16/demo/make-signed-keyset000644 000765 000120 00000005542 11346437006 017635 0ustar00olafadmin000000 000000 #!/usr/bin/perl # # takes a bind public key file and creates a self-signed keyset # use Getopt::Std; use Net::DNS; use File::Basename; # global variables $VERSION = "0.1"; $verbose = 0; $printds = 0; $progname = basename($0); chomp($progname); # main program getopts('dvhVf:n:'); if (defined($opt_d)) { $printds = 1; } if (defined($opt_v)) { $verbose = 1; } if (defined($opt_h)) { &usage(); } if (defined($opt_V)) { &version(); } if ($#ARGV < 0) { &usage(); } # silent some compiler warnings until i figure them out $opt_d=0; $opt_v=0; $opt_h=0; $opt_V=0; &make_keyset(@ARGV); exit(0); # print the usage and exit sub usage { print("usage: $progname [-vhV] file\n"); print("Options:\n"); print(" -d Print the DS record for each key in the keyset.\n"); print(" -v Be verbose.\n"); print(" -h Print this usage message.\n"); print(" -V Print version information.\n"); print(" file BIND public key file.\n"); exit(0); } # print version information sub version { print("$progname v$VERSION using Net::DNS v", Net::DNS->version, "\n"); exit(0); } sub make_keyset { my $file = shift(); my $directory = dirname($file); print("Processing file: $file\n"); if ($verbose) { print("Opening $file\n"); } open(FILE, $file) or die("$progname: unable to open $file.\n"); if ($verbose) { print("Reading $file\n"); } my $keyrr_txt; while () { if (m/^\$.*/) { if ($verbose) { print("Discarding BIND keyword in $file\n"); } next; } $keyrr_txt = $keyrr_txt . $_; } if ($verbose) { print("Creating DNSKEY RR\n"); } my $keyrr = Net::DNS::RR->new($keyrr_txt); if ($verbose) { print("Creating Keyset\n"); } my @keys = ($keyrr); use Net::DNS::Keyset; my $keyset = Net::DNS::Keyset->new(\@keys, "$directory") or die("$progname: unable to create keyset. $Net::DNS::Keyset::keyset_err.\n"); if ($verbose) { print("Verifying Keyset\n"); } $keyset->verify() or die("$progname: unable to verify keyset. $Net::DNS::Keyset::keyset_err.\n"); if ($verbose) { print("Keyset:\n"); $keyset->print(); print("Writing Keyset\n"); } $keyset->writekeyset("signed-") or die("$progname: unable to write keyset. $Net::DNS::Keyset::keyset_err.\n"); if ($printds) { if ($verbose) { print("Extracting DS RR\n"); } my @ds=$keyset->extract_ds(); foreach $ds (@ds) { $ds->print(); } } } =head1 NAME make-signed-keyset - create a self-signed keyset =head1 SYNOPSIS make-signed-keyset [-v] file =head1 DESCRIPTION make-signed-keyset is a program that creates a self-signed keyset from a BIND public key file specified on the command line. The options are as follows: =over =item -v Be verbose. -d Print the DS record for each key in the keyset. =head2 Author Contributed by Wes Griffin =back