|
Packit Service |
f6e53a |
package Net::DNS::RR::TSIG;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
#
|
|
Packit Service |
f6e53a |
# $Id: TSIG.pm 1597 2017-09-22 08:04:02Z willem $
|
|
Packit Service |
f6e53a |
#
|
|
Packit Service |
f6e53a |
our $VERSION = (qw$LastChangedRevision: 1597 $)[1];
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use strict;
|
|
Packit Service |
f6e53a |
use warnings;
|
|
Packit Service |
f6e53a |
use base qw(Net::DNS::RR);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 NAME
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Net::DNS::RR::TSIG - DNS TSIG resource record
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=cut
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use integer;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use Carp;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
eval 'require Digest::HMAC';
|
|
Packit Service |
f6e53a |
eval 'require Digest::MD5';
|
|
Packit Service |
f6e53a |
eval 'require Digest::SHA';
|
|
Packit Service |
f6e53a |
eval 'require MIME::Base64';
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use Net::DNS::DomainName;
|
|
Packit Service |
f6e53a |
use Net::DNS::Parameters;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use constant ANY => classbyname qw(ANY);
|
|
Packit Service |
f6e53a |
use constant TSIG => typebyname qw(TSIG);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
{
|
|
Packit Service |
f6e53a |
# source: http://www.iana.org/assignments/tsig-algorithm-names
|
|
Packit Service |
f6e53a |
my @algbyname = (
|
|
Packit Service |
f6e53a |
'HMAC-MD5.SIG-ALG.REG.INT' => 157,
|
|
Packit Service |
f6e53a |
'HMAC-SHA1' => 161,
|
|
Packit Service |
f6e53a |
'HMAC-SHA224' => 162,
|
|
Packit Service |
f6e53a |
'HMAC-SHA256' => 163,
|
|
Packit Service |
f6e53a |
'HMAC-SHA384' => 164,
|
|
Packit Service |
f6e53a |
'HMAC-SHA512' => 165,
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my @algalias = (
|
|
Packit Service |
f6e53a |
'HMAC-MD5' => 157,
|
|
Packit Service |
f6e53a |
'HMAC-SHA' => 161,
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my %algbyval = reverse @algbyname;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my @algrehash = map /^\d/ ? ($_) x 3 : do { s/[\W_]//g; uc($_) }, @algbyname, @algalias;
|
|
Packit Service |
f6e53a |
my %algbyname = @algrehash; # work around broken cperl
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _algbyname {
|
|
Packit Service |
f6e53a |
my $key = uc shift; # synthetic key
|
|
Packit Service |
f6e53a |
$key =~ s/[\W_]//g; # strip non-alphanumerics
|
|
Packit Service |
f6e53a |
$algbyname{$key};
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _algbyval {
|
|
Packit Service |
f6e53a |
my $value = shift;
|
|
Packit Service |
f6e53a |
$algbyval{$value};
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _decode_rdata { ## decode rdata from wire-format octet string
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
my ( $data, $offset ) = @_;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $limit = $offset + $self->{rdlength};
|
|
Packit Service |
f6e53a |
( $self->{algorithm}, $offset ) = decode Net::DNS::DomainName(@_);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# Design decision: Use 32 bits, which will work until the end of time()!
|
|
Packit Service |
f6e53a |
@{$self}{qw(time_signed fudge)} = unpack "\@$offset xxN n", $$data;
|
|
Packit Service |
f6e53a |
$offset += 8;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $mac_size = unpack "\@$offset n", $$data;
|
|
Packit Service |
f6e53a |
$self->{macbin} = unpack "\@$offset xx a$mac_size", $$data;
|
|
Packit Service |
f6e53a |
$offset += $mac_size + 2;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
@{$self}{qw(original_id error)} = unpack "\@$offset nn", $$data;
|
|
Packit Service |
f6e53a |
$offset += 4;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $other_size = unpack "\@$offset n", $$data;
|
|
Packit Service |
f6e53a |
$self->{other} = unpack "\@$offset xx a$other_size", $$data;
|
|
Packit Service |
f6e53a |
$offset += $other_size + 2;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
croak('misplaced or corrupt TSIG') unless $limit == length $$data;
|
|
Packit Service |
f6e53a |
my $raw = substr $$data, 0, $self->{offset};
|
|
Packit Service |
f6e53a |
$self->{rawref} = \$raw;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _encode_rdata { ## encode rdata as wire-format octet string
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $macbin = $self->macbin;
|
|
Packit Service |
f6e53a |
unless ($macbin) {
|
|
Packit Service |
f6e53a |
my ( $offset, undef, $packet ) = @_;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $sigdata = $self->sig_data($packet); # form data to be signed
|
|
Packit Service |
f6e53a |
$macbin = $self->macbin( $self->_mac_function($sigdata) );
|
|
Packit Service |
f6e53a |
$self->original_id( $packet->header->id );
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $rdata = $self->{algorithm}->canonical;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# Design decision: Use 32 bits, which will work until the end of time()!
|
|
Packit Service |
f6e53a |
$rdata .= pack 'xxN n', $self->time_signed, $self->fudge;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$rdata .= pack 'na*', length($macbin), $macbin;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$rdata .= pack 'nn', $self->original_id, $self->{error};
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $other = $self->other;
|
|
Packit Service |
f6e53a |
$rdata .= pack 'na*', length($other), $other;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return $rdata;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _defaults { ## specify RR attribute default values
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->algorithm(157);
|
|
Packit Service |
f6e53a |
$self->class('ANY');
|
|
Packit Service |
f6e53a |
$self->error(0);
|
|
Packit Service |
f6e53a |
$self->fudge(300);
|
|
Packit Service |
f6e53a |
$self->other('');
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _size { ## estimate encoded size
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
my $clone = bless {%$self}, ref($self); # shallow clone
|
|
Packit Service |
f6e53a |
length $clone->encode( 0, undef, new Net::DNS::Packet() );
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub encode { ## overide RR method
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $kname = $self->{owner}->encode(); # uncompressed key name
|
|
Packit Service |
f6e53a |
my $rdata = eval { $self->_encode_rdata(@_) } || '';
|
|
Packit Service |
f6e53a |
pack 'a* n2 N n a*', $kname, TSIG, ANY, 0, length $rdata, $rdata;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub string { ## overide RR method
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $owner = $self->{owner}->string;
|
|
Packit Service |
f6e53a |
my $type = $self->type;
|
|
Packit Service |
f6e53a |
my $algorithm = $self->algorithm;
|
|
Packit Service |
f6e53a |
my $time_signed = $self->time_signed;
|
|
Packit Service |
f6e53a |
my $fudge = $self->fudge;
|
|
Packit Service |
f6e53a |
my $signature = $self->mac;
|
|
Packit Service |
f6e53a |
my $original_id = $self->original_id;
|
|
Packit Service |
f6e53a |
my $error = $self->error;
|
|
Packit Service |
f6e53a |
my $other = $self->other;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return <<"QQ";
|
|
Packit Service |
f6e53a |
; $owner $type
|
|
Packit Service |
f6e53a |
; algorithm: $algorithm
|
|
Packit Service |
f6e53a |
; time signed: $time_signed fudge: $fudge
|
|
Packit Service |
f6e53a |
; signature: $signature
|
|
Packit Service |
f6e53a |
; original id: $original_id
|
|
Packit Service |
f6e53a |
; $error $other
|
|
Packit Service |
f6e53a |
QQ
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub algorithm { &_algorithm; }
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub key {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->keybin( MIME::Base64::decode( join "", @_ ) ) if scalar @_;
|
|
Packit Service |
f6e53a |
MIME::Base64::encode( $self->keybin(), "" ) if defined wantarray;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub keybin { &_keybin; }
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub time_signed {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{time_signed} = 0 + shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{time_signed} = time() unless $self->{time_signed};
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub fudge {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{fudge} = 0 + shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{fudge} || 0;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub mac {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->macbin( pack "H*", map { die "!hex!" if m/[^0-9A-Fa-f]/; $_ } join "", @_ ) if scalar @_;
|
|
Packit Service |
f6e53a |
unpack "H*", $self->macbin() if defined wantarray;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub macbin {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{macbin} = shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{macbin} || "";
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub prior_mac {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
return unpack "H*", $self->prior_macbin() unless scalar @_;
|
|
Packit Service |
f6e53a |
$self->prior_macbin( pack "H*", map /[^\dA-F]/i ? croak "corrupt hex" : $_, join "", @_ );
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub prior_macbin {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{prior_macbin} = shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{prior_macbin} || "";
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub request_mac {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
return unpack "H*", $self->request_macbin() unless scalar @_;
|
|
Packit Service |
f6e53a |
$self->request_macbin( pack "H*", map /[^\dA-F]/i ? croak "corrupt hex" : $_, join "", @_ );
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub request_macbin {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{request_macbin} = shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{request_macbin} || "";
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub original_id {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->{original_id} = 0 + shift if scalar @_;
|
|
Packit Service |
f6e53a |
$self->{original_id} || 0;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub error {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
$self->{error} = rcodebyname(shift) if scalar @_;
|
|
Packit Service |
f6e53a |
rcodebyval( $self->{error} );
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub other {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
$self->{other} = shift if scalar @_;
|
|
Packit Service |
f6e53a |
my $time = $self->{error} == 18 ? pack 'xxN', time() : '';
|
|
Packit Service |
f6e53a |
$self->{other} = $time unless $self->{other};
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub other_data { &other; } # uncoverable pod
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub sig_function {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return $self->{sig_function} unless scalar @_;
|
|
Packit Service |
f6e53a |
$self->{sig_function} = shift;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub sign_func { &sig_function; } # uncoverable pod
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub sig_data {
|
|
Packit Service |
f6e53a |
my ( $self, $message ) = @_;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
if ( ref($message) ) {
|
|
Packit Service |
f6e53a |
die 'missing packet reference' unless $message->isa('Net::DNS::Packet');
|
|
Packit Service |
f6e53a |
my @unsigned = grep ref($_) ne ref($self), @{$message->{additional}};
|
|
Packit Service |
f6e53a |
local $message->{additional} = \@unsigned; # remake header image
|
|
Packit Service |
f6e53a |
my @part = qw(question answer authority additional);
|
|
Packit Service |
f6e53a |
my @size = map scalar( @{$message->{$_}} ), @part;
|
|
Packit Service |
f6e53a |
if ( my $rawref = $self->{rawref} ) {
|
|
Packit Service |
f6e53a |
delete $self->{rawref};
|
|
Packit Service |
f6e53a |
my $hbin = pack 'n6', $self->original_id, $message->{status}, @size;
|
|
Packit Service |
f6e53a |
$message = join '', $hbin, substr $$rawref, length $hbin;
|
|
Packit Service |
f6e53a |
} else {
|
|
Packit Service |
f6e53a |
my $data = $message->data;
|
|
Packit Service |
f6e53a |
my $hbin = pack 'n6', $message->{id}, $message->{status}, @size;
|
|
Packit Service |
f6e53a |
$message = join '', $hbin, substr $data, length $hbin;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# Design decision: Use 32 bits, which will work until the end of time()!
|
|
Packit Service |
f6e53a |
my $time = pack 'xxN n', $self->time_signed, $self->fudge;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# Insert the prior MAC if present (multi-packet message).
|
|
Packit Service |
f6e53a |
$self->prior_macbin( $self->{link}->macbin ) if $self->{link};
|
|
Packit Service |
f6e53a |
my $prior_macbin = $self->prior_macbin;
|
|
Packit Service |
f6e53a |
return pack 'na* a* a*', length($prior_macbin), $prior_macbin, $message, $time if $prior_macbin;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# Insert the request MAC if present (used to validate responses).
|
|
Packit Service |
f6e53a |
my $req_mac = $self->request_macbin;
|
|
Packit Service |
f6e53a |
my $sigdata = $req_mac ? pack( 'na*', length($req_mac), $req_mac ) : '';
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$sigdata .= $message || '';
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $kname = $self->{owner}->canonical; # canonical key name
|
|
Packit Service |
f6e53a |
$sigdata .= pack 'a* n N', $kname, ANY, 0;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$sigdata .= $self->{algorithm}->canonical; # canonical algorithm name
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$sigdata .= $time;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$sigdata .= pack 'n', $self->{error};
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $other = $self->other;
|
|
Packit Service |
f6e53a |
$sigdata .= pack 'na*', length($other), $other;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return $sigdata;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub create {
|
|
Packit Service |
f6e53a |
my $class = shift;
|
|
Packit Service |
f6e53a |
my $karg = shift;
|
|
Packit Service |
f6e53a |
croak 'argument undefined' unless defined $karg;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
if ( ref($karg) ) {
|
|
Packit Service |
f6e53a |
if ( $karg->isa('Net::DNS::Packet') ) {
|
|
Packit Service |
f6e53a |
my $sigrr = $karg->sigrr;
|
|
Packit Service |
f6e53a |
croak 'no TSIG in request packet' unless defined $sigrr;
|
|
Packit Service |
f6e53a |
return new Net::DNS::RR( # ( request, options )
|
|
Packit Service |
f6e53a |
name => $sigrr->name,
|
|
Packit Service |
f6e53a |
type => 'TSIG',
|
|
Packit Service |
f6e53a |
algorithm => $sigrr->algorithm,
|
|
Packit Service |
f6e53a |
request_macbin => $sigrr->macbin,
|
|
Packit Service |
f6e53a |
@_
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} elsif ( ref($karg) eq __PACKAGE__ ) {
|
|
Packit Service |
f6e53a |
my $tsig = $karg->_chain;
|
|
Packit Service |
f6e53a |
$tsig->{macbin} = undef;
|
|
Packit Service |
f6e53a |
return $tsig;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} elsif ( ref($karg) eq 'Net::DNS::RR::KEY' ) {
|
|
Packit Service |
f6e53a |
return new Net::DNS::RR(
|
|
Packit Service |
f6e53a |
name => $karg->name,
|
|
Packit Service |
f6e53a |
type => 'TSIG',
|
|
Packit Service |
f6e53a |
algorithm => $karg->algorithm,
|
|
Packit Service |
f6e53a |
key => $karg->key,
|
|
Packit Service |
f6e53a |
@_
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
croak "Usage: create $class(keyfile)\n\tcreate $class(keyname, key)"
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} elsif ( scalar(@_) == 1 ) {
|
|
Packit Service |
f6e53a |
my $key = shift; # ( keyname, key )
|
|
Packit Service |
f6e53a |
return new Net::DNS::RR(
|
|
Packit Service |
f6e53a |
name => $karg,
|
|
Packit Service |
f6e53a |
type => 'TSIG',
|
|
Packit Service |
f6e53a |
key => $key
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} elsif ( $karg =~ /private$/ ) { # ( keyfile, options )
|
|
Packit Service |
f6e53a |
require File::Spec;
|
|
Packit Service |
f6e53a |
require Net::DNS::ZoneFile;
|
|
Packit Service |
f6e53a |
my $keyfile = new Net::DNS::ZoneFile($karg);
|
|
Packit Service |
f6e53a |
my ( $alg, $key, $junk );
|
|
Packit Service |
f6e53a |
while ( $keyfile->_getline ) {
|
|
Packit Service |
f6e53a |
( $junk, $alg ) = split if /Algorithm:/;
|
|
Packit Service |
f6e53a |
( $junk, $key ) = split if /Key:/;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my ( $vol, $dir, $file ) = File::Spec->splitpath( $keyfile->name );
|
|
Packit Service |
f6e53a |
croak "misnamed private key" unless $file =~ /^K([^+]+)+.+private$/;
|
|
Packit Service |
f6e53a |
my $kname = $1;
|
|
Packit Service |
f6e53a |
return new Net::DNS::RR(
|
|
Packit Service |
f6e53a |
name => $kname,
|
|
Packit Service |
f6e53a |
type => 'TSIG',
|
|
Packit Service |
f6e53a |
algorithm => $alg,
|
|
Packit Service |
f6e53a |
key => $key,
|
|
Packit Service |
f6e53a |
@_
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} else { # ( keyfile, options )
|
|
Packit Service |
f6e53a |
require Net::DNS::ZoneFile;
|
|
Packit Service |
f6e53a |
my $keyrr = new Net::DNS::ZoneFile($karg)->read;
|
|
Packit Service |
f6e53a |
croak 'key file incompatible with TSIG' unless $keyrr->type eq 'KEY';
|
|
Packit Service |
f6e53a |
return new Net::DNS::RR(
|
|
Packit Service |
f6e53a |
name => $keyrr->name,
|
|
Packit Service |
f6e53a |
type => 'TSIG',
|
|
Packit Service |
f6e53a |
algorithm => $keyrr->algorithm,
|
|
Packit Service |
f6e53a |
key => $keyrr->key,
|
|
Packit Service |
f6e53a |
@_
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub verify {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
my $data = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
unless ( abs( time() - $self->time_signed ) < $self->fudge ) {
|
|
Packit Service |
f6e53a |
$self->error(18); # bad time
|
|
Packit Service |
f6e53a |
return;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
if ( scalar @_ ) {
|
|
Packit Service |
f6e53a |
my $arg = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
unless ( ref($arg) ) {
|
|
Packit Service |
f6e53a |
$self->error(16); # bad sig (multi-packet)
|
|
Packit Service |
f6e53a |
return;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $signerkey = lc( join '+', $self->name, $self->algorithm );
|
|
Packit Service |
f6e53a |
if ( $arg->isa('Net::DNS::Packet') ) {
|
|
Packit Service |
f6e53a |
my $request = $arg->sigrr; # request TSIG
|
|
Packit Service |
f6e53a |
my $rqstkey = lc( join '+', $request->name, $request->algorithm );
|
|
Packit Service |
f6e53a |
$self->error(17) unless $signerkey eq $rqstkey;
|
|
Packit Service |
f6e53a |
$self->request_macbin( $request->macbin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} elsif ( $arg->isa(__PACKAGE__) ) {
|
|
Packit Service |
f6e53a |
my $priorkey = lc( join '+', $arg->name, $arg->algorithm );
|
|
Packit Service |
f6e53a |
$self->error(17) unless $signerkey eq $priorkey;
|
|
Packit Service |
f6e53a |
$self->prior_macbin( $arg->macbin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} else {
|
|
Packit Service |
f6e53a |
croak 'Usage: $tsig->verify( $reply, $query )';
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
return if $self->{error};
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $sigdata = $self->sig_data($data); # form data to be verified
|
|
Packit Service |
f6e53a |
my $tsigmac = $self->_mac_function($sigdata);
|
|
Packit Service |
f6e53a |
my $tsig = $self->_chain;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $macbin = $self->macbin;
|
|
Packit Service |
f6e53a |
my $maclen = length $macbin;
|
|
Packit Service |
f6e53a |
my $minlen = length($tsigmac) >> 1; # per RFC4635, 3.1
|
|
Packit Service |
f6e53a |
$self->error(16) unless $macbin eq substr $tsigmac, 0, $maclen;
|
|
Packit Service |
f6e53a |
$self->error(1) if $maclen < $minlen or $maclen < 10 or $maclen > length $tsigmac;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return $self->{error} ? undef : $tsig;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub vrfyerrstr {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
return $self->error;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
########################################
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
{
|
|
Packit Service |
f6e53a |
my %digest = (
|
|
Packit Service |
f6e53a |
'157' => ['Digest::MD5'],
|
|
Packit Service |
f6e53a |
'161' => ['Digest::SHA'],
|
|
Packit Service |
f6e53a |
'162' => ['Digest::SHA', 224, 64],
|
|
Packit Service |
f6e53a |
'163' => ['Digest::SHA', 256, 64],
|
|
Packit Service |
f6e53a |
'164' => ['Digest::SHA', 384, 128],
|
|
Packit Service |
f6e53a |
'165' => ['Digest::SHA', 512, 128],
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my %keytable;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _algorithm { ## install sig function in key table
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
if ( my $algname = shift ) {
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
unless ( my $digtype = _algbyname($algname) ) {
|
|
Packit Service |
f6e53a |
$self->{algorithm} = new Net::DNS::DomainName($algname);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
} else {
|
|
Packit Service |
f6e53a |
$algname = _algbyval($digtype);
|
|
Packit Service |
f6e53a |
$self->{algorithm} = new Net::DNS::DomainName($algname);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my ( $hash, @param ) = @{$digest{$digtype}};
|
|
Packit Service |
f6e53a |
my ( undef, @block ) = @param;
|
|
Packit Service |
f6e53a |
my $digest = new $hash(@param);
|
|
Packit Service |
f6e53a |
my $function = sub {
|
|
Packit Service |
f6e53a |
my $hmac = new Digest::HMAC( shift, $digest, @block );
|
|
Packit Service |
f6e53a |
$hmac->add(shift);
|
|
Packit Service |
f6e53a |
return $hmac->digest;
|
|
Packit Service |
f6e53a |
};
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$self->sig_function($function);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $keyname = ( $self->{owner} || return )->canonical;
|
|
Packit Service |
f6e53a |
$keytable{$keyname}{digest} = $function;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
return $self->{algorithm}->name if defined wantarray;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _keybin { ## install key in key table
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
croak 'Unauthorised access to TSIG key material denied' unless scalar @_;
|
|
Packit Service |
f6e53a |
my $keyref = $keytable{$self->{owner}->canonical} ||= {};
|
|
Packit Service |
f6e53a |
my $private = shift; # closure keeps private key private
|
|
Packit Service |
f6e53a |
$keyref->{key} = sub {
|
|
Packit Service |
f6e53a |
my $function = $keyref->{digest};
|
|
Packit Service |
f6e53a |
return &$function( $private, @_ );
|
|
Packit Service |
f6e53a |
};
|
|
Packit Service |
f6e53a |
return undef;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _mac_function { ## apply keyed hash function to argument
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $owner = $self->{owner}->canonical;
|
|
Packit Service |
f6e53a |
$self->algorithm( $self->algorithm ) unless $keytable{$owner}{digest};
|
|
Packit Service |
f6e53a |
my $keyref = $keytable{$owner};
|
|
Packit Service |
f6e53a |
$keyref->{digest} = $self->sig_function unless $keyref->{digest};
|
|
Packit Service |
f6e53a |
my $function = $keyref->{key};
|
|
Packit Service |
f6e53a |
&$function(@_);
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
# _chain() creates a new TSIG object linked to the original
|
|
Packit Service |
f6e53a |
# RR, for the purpose of signing multi-message transfers.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub _chain {
|
|
Packit Service |
f6e53a |
my $self = shift;
|
|
Packit Service |
f6e53a |
$self->{link} = undef;
|
|
Packit Service |
f6e53a |
bless {%$self, link => $self}, ref($self);
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
1;
|
|
Packit Service |
f6e53a |
__END__
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 SYNOPSIS
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
use Net::DNS;
|
|
Packit Service |
f6e53a |
$tsig = create Net::DNS::RR::TSIG( $keyfile );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$tsig = create Net::DNS::RR::TSIG( $keyfile,
|
|
Packit Service |
f6e53a |
fudge => 300
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 DESCRIPTION
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Class for DNS Transaction Signature (TSIG) resource records.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 METHODS
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The available methods are those inherited from the base class augmented
|
|
Packit Service |
f6e53a |
by the type-specific methods defined in this package.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Use of undocumented package features or direct access to internal data
|
|
Packit Service |
f6e53a |
structures is discouraged and could result in program termination or
|
|
Packit Service |
f6e53a |
other unpredictable behaviour.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 algorithm
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$algorithm = $rr->algorithm;
|
|
Packit Service |
f6e53a |
$rr->algorithm( $algorithm );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
A domain name which specifies the name of the algorithm.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 key
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$rr->key( $key );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Base64 representation of the key material.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 keybin
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$rr->keybin( $keybin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Binary representation of the key material.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 time_signed
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$time_signed = $rr->time_signed;
|
|
Packit Service |
f6e53a |
$rr->time_signed( $time_signed );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Signing time as the number of seconds since 1 Jan 1970 00:00:00 UTC.
|
|
Packit Service |
f6e53a |
The default signing time is the current time.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 fudge
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$fudge = $rr->fudge;
|
|
Packit Service |
f6e53a |
$rr->fudge( $fudge );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
"fudge" represents the permitted error in the signing time.
|
|
Packit Service |
f6e53a |
The default fudge is 300 seconds.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 mac
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$mac = $rr->mac;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Returns the message authentication code (MAC) as a string of hex
|
|
Packit Service |
f6e53a |
characters. The programmer must call the Net::DNS::Packet data()
|
|
Packit Service |
f6e53a |
object method before this will return anything meaningful.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=cut
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 macbin
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$macbin = $rr->macbin;
|
|
Packit Service |
f6e53a |
$rr->macbin( $macbin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Binary message authentication code (MAC).
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 prior_mac
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$prior_mac = $rr->prior_mac;
|
|
Packit Service |
f6e53a |
$rr->prior_mac( $prior_mac );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Prior message authentication code (MAC).
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 prior_macbin
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$prior_macbin = $rr->prior_macbin;
|
|
Packit Service |
f6e53a |
$rr->prior_macbin( $prior_macbin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Binary prior message authentication code.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 request_mac
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$request_mac = $rr->request_mac;
|
|
Packit Service |
f6e53a |
$rr->request_mac( $request_mac );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Request message authentication code (MAC).
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 request_macbin
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$request_macbin = $rr->request_macbin;
|
|
Packit Service |
f6e53a |
$rr->request_macbin( $request_macbin );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Binary request message authentication code.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 original_id
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$original_id = $rr->original_id;
|
|
Packit Service |
f6e53a |
$rr->original_id( $original_id );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The message ID from the header of the original packet.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 error
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 vrfyerrstr
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$rcode = $tsig->error;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Returns the RCODE covering TSIG processing. Common values are
|
|
Packit Service |
f6e53a |
NOERROR, BADSIG, BADKEY, and BADTIME. See RFC 2845 for details.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 other
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$other = $tsig->other;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
This field should be empty unless the error is BADTIME, in which
|
|
Packit Service |
f6e53a |
case it will contain the server time as the number of seconds since
|
|
Packit Service |
f6e53a |
1 Jan 1970 00:00:00 UTC.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 sig_function
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
sub signing_function {
|
|
Packit Service |
f6e53a |
my ( $keybin, $data ) = @_;
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
my $hmac = new Digest::HMAC( $keybin, 'Digest::MD5' );
|
|
Packit Service |
f6e53a |
$hmac->add( $data );
|
|
Packit Service |
f6e53a |
return $hmac->digest;
|
|
Packit Service |
f6e53a |
}
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$tsig->sig_function( \&signing_function );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
This sets the signing function to be used for this TSIG record.
|
|
Packit Service |
f6e53a |
The default signing function is HMAC-MD5.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 sig_data
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$sigdata = $tsig->sig_data($packet);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Returns the packet packed according to RFC2845 in a form for signing. This
|
|
Packit Service |
f6e53a |
is only needed if you want to supply an external signing function, such as is
|
|
Packit Service |
f6e53a |
needed for TSIG-GSS.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 create
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$tsig = create Net::DNS::RR::TSIG( $keyfile );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$tsig = create Net::DNS::RR::TSIG( $keyfile,
|
|
Packit Service |
f6e53a |
fudge => 300
|
|
Packit Service |
f6e53a |
);
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Returns a TSIG RR constructed using the parameters in the specified
|
|
Packit Service |
f6e53a |
key file, which is assumed to have been generated by dnssec-keygen.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$tsig = create Net::DNS::RR::TSIG( $keyname, $key );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The two argument form is supported for backward compatibility.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head2 verify
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$verify = $tsig->verify( $data );
|
|
Packit Service |
f6e53a |
$verify = $tsig->verify( $packet );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$verify = $tsig->verify( $reply, $query );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$verify = $tsig->verify( $packet, $prior );
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The boolean verify method will return true if the hash over the
|
|
Packit Service |
f6e53a |
packet data conforms to the data in the TSIG itself
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 TSIG Keys
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
TSIG keys are symmetric keys generated using dnssec-keygen:
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
$ dnssec-keygen -a HMAC-SHA1 -b 160 -n HOST <keyname>
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The key will be stored as a private and public keyfile pair
|
|
Packit Service |
f6e53a |
K<keyname>+161+<keyid>.private and K<keyname>+161+<keyid>.key
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
where
|
|
Packit Service |
f6e53a |
<keyname> is the DNS name of the key.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
<keyid> is the (generated) numerical identifier used to
|
|
Packit Service |
f6e53a |
distinguish this key.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Other algorithms may be substituted for HMAC-SHA1 in the above example.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
It is recommended that the keyname be globally unique and incorporate
|
|
Packit Service |
f6e53a |
the fully qualified domain names of the resolver and nameserver in
|
|
Packit Service |
f6e53a |
that order. It should be possible for more than one key to be in use
|
|
Packit Service |
f6e53a |
simultaneously between any such pair of hosts.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Although the formats differ, the private and public keys are identical
|
|
Packit Service |
f6e53a |
and both should be stored and handled as secret data.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 Configuring BIND Nameserver
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
The following lines must be added to the /etc/named.conf file:
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
key <keyname> {
|
|
Packit Service |
f6e53a |
algorithm HMAC-SHA1;
|
|
Packit Service |
f6e53a |
secret "<keydata>";
|
|
Packit Service |
f6e53a |
};
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
<keyname> is the name of the key chosen when the key was generated.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
<keydata> is the key string extracted from the generated key file.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 ACKNOWLEDGMENT
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Most of the code in the Net::DNS::RR::TSIG module was contributed
|
|
Packit Service |
f6e53a |
by Chris Turbeville.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Support for external signing functions was added by Andrew Tridgell.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
TSIG verification, BIND keyfile handling and support for HMAC-SHA1,
|
|
Packit Service |
f6e53a |
HMAC-SHA224, HMAC-SHA256, HMAC-SHA384 and HMAC-SHA512 functions was
|
|
Packit Service |
f6e53a |
added by Dick Franks.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 BUGS
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
A 32-bit representation of time is used, contrary to RFC2845 which
|
|
Packit Service |
f6e53a |
demands 48 bits. This design decision will need to be reviewed
|
|
Packit Service |
f6e53a |
before the code stops working on 7 February 2106.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 COPYRIGHT
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Copyright (c)2000,2001 Michael Fuhr.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Portions Copyright (c)2002,2003 Chris Reinhardt.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Portions Copyright (c)2013 Dick Franks.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
All rights reserved.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Package template (c)2009,2012 O.M.Kolkman and R.W.Franks.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 LICENSE
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
Permission to use, copy, modify, and distribute this software and its
|
|
Packit Service |
f6e53a |
documentation for any purpose and without fee is hereby granted, provided
|
|
Packit Service |
f6e53a |
that the above copyright notice appear in all copies and that both that
|
|
Packit Service |
f6e53a |
copyright notice and this permission notice appear in supporting
|
|
Packit Service |
f6e53a |
documentation, and that the name of the author not be used in advertising
|
|
Packit Service |
f6e53a |
or publicity pertaining to distribution of the software without specific
|
|
Packit Service |
f6e53a |
prior written permission.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit Service |
f6e53a |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit Service |
f6e53a |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
Packit Service |
f6e53a |
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
Packit Service |
f6e53a |
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
Packit Service |
f6e53a |
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
Packit Service |
f6e53a |
DEALINGS IN THE SOFTWARE.
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=head1 SEE ALSO
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
L<perl>, L<Net::DNS>, L<Net::DNS::RR>, RFC2845, RFC4635
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
L<TSIG Algorithm Names|http://www.iana.org/assignments/tsig-algorithm-names>
|
|
Packit Service |
f6e53a |
|
|
Packit Service |
f6e53a |
=cut
|