Skip Menu |

This queue is for tickets about the DNS-ZoneParse CPAN distribution.

Report information
The Basics
Id: 81111
Status: open
Priority: 0/
Queue: DNS-ZoneParse

People
Owner: Nobody in particular
Requestors: hugh [...] davenport.net.nz
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.10
Fixed in: 1.10



Subject: Add support for SPF records
When a domain contains records of the SPF type (99) as defined by RFC 4408 [1], the parser responds in the following warning and is not included in any output. Unparseable line (Unknown record type) @ IN SPF "v=spf1 mx -all" Attached is a patch that allows these SPF records to be used. The only verification that they are the correct format is the check of a version tag of "v=spf1". More detail could be given to check whether correct mechanisms are used. This patch has been tested against perl running on debian wheezy, and the diff is against the 1.10 source obtained from CPAN. Also, may be another bug. I would suggest that any records that fail to parse should be stored in a separate section in the parser that can't be modified (easily?) and is output when required. This allows new record types to still be used in output, while not being able to be manipulated (easily..). Cheers, Hugh [1] http://tools.ietf.org/html/rfc4408
Subject: spf.patch
24c24 < %dns_generate, --- > %dns_generate, %dns_spf, 81a82 > delete $dns_spf{$self}; 108a110 > : $method eq 'spf' ? $dns_spf{$self} 136a139 > SPF => $dns_spf{$self}, 277a281,286 > foreach my $o ( @{ $dns_spf{$self} } ) { > next unless defined $o; > next unless $o->{'ORIGIN'} eq $process_this_origin; > $self->_escape_chars( $o ); > $output .= qq[$o->{name} $o->{ttl} $o->{class} SPF "$o->{text}"\n]; > } 370a380 > $dns_spf{$self} = []; 730a741,754 > } elsif ( > /($valid_name)? \s+ > $ttl_cls > SPF \s+ > ("v=spf1\s($valid_quoted_txt_char*(?<!\\)"|$valid_txt_char+)) > /ixo > ) { > push @{ $dns_spf{$self} }, > $self->_massage( { > name => $1, > ttl => $2, > class => $3, > text => $4, > } );
Attached a unified diff On Sun Nov 11 20:09:30 2012, https://launchpad.net/~hugh-catalyst wrote: Show quoted text
> When a domain contains records of the SPF type (99) as defined by RFC > 4408 [1], the parser responds in the following warning and is not > included in any output. > Unparseable line (Unknown record type) > @ IN SPF "v=spf1 mx -all" > > Attached is a patch that allows these SPF records to be used. The only > verification that they are the correct format is the check of a
version Show quoted text
> tag of "v=spf1". More detail could be given to check whether correct > mechanisms are used. > > This patch has been tested against perl running on debian wheezy, and > the diff is against the 1.10 source obtained from CPAN. > > Also, may be another bug. I would suggest that any records that fail
to Show quoted text
> parse should be stored in a separate section in the parser that can't
be Show quoted text
> modified (easily?) and is output when required. This allows new record > types to still be used in output, while not being able to be
manipulated Show quoted text
> (easily..). > > Cheers, > > Hugh > > [1] http://tools.ietf.org/html/rfc4408
Subject: spf.patch
--- a/DNS/ZoneParse.pm 2010-09-30 20:35:33.000000000 +1300 +++ b/DNS/ZoneParse.pm 2012-11-12 14:00:27.227925769 +1300 @@ -21,7 +21,7 @@ my ( %dns_id, %dns_soa, %dns_ns, %dns_a, %dns_cname, %dns_mx, %dns_txt, %dns_ptr, %dns_a4, %dns_srv, %dns_hinfo, %dns_rp, %dns_loc, - %dns_generate, + %dns_generate, %dns_spf, %dns_last_name, %dns_last_origin, %dns_last_class, %dns_last_ttl, %dns_found_origins, %unparseable_line_callback, %last_parse_error_count, ); @@ -79,6 +79,7 @@ delete $dns_loc{$self}; delete $dns_id{$self}; delete $dns_generate{$self}; + delete $dns_spf{$self}; delete $dns_last_name{$self}; delete $dns_last_origin{$self}; delete $dns_last_ttl{$self}; @@ -106,6 +107,7 @@ : $method eq 'rp' ? $dns_rp{$self} : $method eq 'loc' ? $dns_loc{$self} : $method eq 'generate' ? $dns_generate{$self} + : $method eq 'spf' ? $dns_spf{$self} : $method eq 'zonefile' ? $dns_id{$self}->{ZoneFile} : $method eq 'origin' ? $dns_id{$self}->{Origin} : undef; @@ -134,6 +136,7 @@ HINFO => $dns_hinfo{$self}, RP => $dns_rp{$self}, LOC => $dns_loc{$self}, + SPF => $dns_spf{$self}, } ); } @@ -275,6 +278,12 @@ $self->_escape_chars( $o ); $output .= "\$GENERATE $o->{range} $o->{lhs} $o->{ttl} $o->{class} $o->{type} $o->{rhs}\n"; } + foreach my $o ( @{ $dns_spf{$self} } ) { + next unless defined $o; + next unless $o->{'ORIGIN'} eq $process_this_origin; + $self->_escape_chars( $o ); + $output .= qq[$o->{name} $o->{ttl} $o->{class} SPF "$o->{text}"\n]; + } } @@ -368,6 +377,7 @@ $dns_rp{$self} = []; $dns_loc{$self} = []; $dns_generate{$self} = []; + $dns_spf{$self} = []; $dns_last_name{$self} = undef; $dns_last_origin{$self} = undef; $dns_last_ttl{$self} = undef; @@ -728,6 +738,20 @@ rhs => $6, } ); + } elsif ( + /($valid_name)? \s+ + $ttl_cls + SPF \s+ + ("v=spf1\s($valid_quoted_txt_char*(?<!\\)"|$valid_txt_char+)) + /ixo + ) { + push @{ $dns_spf{$self} }, + $self->_massage( { + name => $1, + ttl => $2, + class => $3, + text => $4, + } ); } else { die "Unknown record type\n"; }
Subject: Add support for SPF records, newer patch
See attachment.
Subject: patch-ZoneParse.pm
--- ../ZoneParse.pm-orig 2014-07-22 09:36:10.000000000 +0200 +++ lib/DNS/ZoneParse.pm 2014-07-22 12:28:32.000000000 +0200 @@ -19,14 +19,18 @@ $VERSION = '1.10'; my ( - %dns_id, %dns_soa, %dns_ns, %dns_a, %dns_cname, %dns_mx, %dns_txt, + %dns_id, %dns_soa, %dns_ns, %dns_a, %dns_cname, %dns_mx, + %dns_txt, %dns_spf, %dns_ptr, %dns_a4, %dns_srv, %dns_hinfo, %dns_rp, %dns_loc, %dns_generate, %dns_last_name, %dns_last_origin, %dns_last_class, %dns_last_ttl, %dns_found_origins, %unparseable_line_callback, %last_parse_error_count, ); -my %possibly_quoted = map { $_ => undef } qw/ os cpu text mbox /; +my %possibly_quoted = map { $_ => undef } qw/ os cpu text mbox spf /; + +# https://kb.isc.org/article/AA-00356/0/Can-I-have-a-TXT-or-SPF-record-longer-than-255-characters.html +my %possibly_multiple = map { $_ => undef } qw/ text spf /; sub new { my $class = shift; @@ -71,6 +75,7 @@ delete $dns_cname{$self}; delete $dns_mx{$self}; delete $dns_txt{$self}; + delete $dns_spf{$self}; delete $dns_ptr{$self}; delete $dns_a4{$self}; delete $dns_srv{$self}; @@ -99,6 +104,7 @@ : $method eq 'cname' ? $dns_cname{$self} : $method eq 'mx' ? $dns_mx{$self} : $method eq 'txt' ? $dns_txt{$self} + : $method eq 'spf' ? $dns_spf{$self} : $method eq 'ptr' ? $dns_ptr{$self} : $method eq 'aaaa' ? $dns_a4{$self} : $method eq 'srv' ? $dns_srv{$self} @@ -130,6 +136,7 @@ MX => $dns_mx{$self}, PTR => $dns_ptr{$self}, TXT => $dns_txt{$self}, + SPF => $dns_spf{$self}, SRV => $dns_srv{$self}, HINFO => $dns_hinfo{$self}, RP => $dns_rp{$self}, @@ -235,7 +242,21 @@ next unless defined $o; next unless $o->{'ORIGIN'} eq $process_this_origin; $self->_escape_chars( $o ); - $output .= qq[$o->{name} $o->{ttl} $o->{class} TXT "$o->{text}"\n]; + my $t = $o->{text}; + if ( length($t) > 250 ) { + $t=join('" "',( $t =~ m/.{1,250}/g )); + } + $output .= qq[$o->{name} $o->{ttl} $o->{class} TXT "$t"\n]; + } + foreach my $o ( @{ $dns_spf{$self} } ) { + next unless defined $o; + next unless $o->{'ORIGIN'} eq $process_this_origin; + $self->_escape_chars( $o ); + my $t = $o->{spf}; + if ( length($t) > 250 ) { + $t=join('" "',( $t =~ m/.{1,250}/g )); + } + $output .= qq[$o->{name} $o->{ttl} $o->{class} SPF "$t"\n]; } foreach my $o ( @{ $dns_ptr{$self} } ) { next unless defined $o; @@ -361,6 +382,7 @@ $dns_cname{$self} = []; $dns_mx{$self} = []; $dns_txt{$self} = []; + $dns_spf{$self} = []; $dns_ptr{$self} = []; $dns_a4{$self} = []; $dns_srv{$self} = []; @@ -614,6 +636,20 @@ text => $4, } ); } elsif ( + /($valid_name)? \s+ + $ttl_cls + SPF \s+ + ("$valid_quoted_txt_char*(?<!\\)"|$valid_txt_char+) + /ixo + ) { + push @{ $dns_spf{$self} }, + $self->_massage( { + name => $1, + ttl => $2, + class => $3, + spf => $4, + } ); + } elsif ( /^\s*\$TTL \s+ ($rr_ttl) /ixo @@ -817,9 +853,12 @@ $record->{$r} = ''; next; } - if ( exists $possibly_quoted{$r} ) { + if ( exists $possibly_quoted{$r} ) { + if ( exists $possibly_multiple{$r} ) { + $record->{$r} =~ s/"\s+"//; + } ( $record->{$r} =~ s/^"// ) && ( $record->{$r} =~ s/"$// ); - } + } # We return email addresses just as they are in the file... for better # or worse (mostly for backwards compatability reasons). @@ -1051,7 +1090,7 @@ If you plan to pass a on_unparseable_line callback but do not wish to specify an C<$origin>, pass 'undef' as the C<$origin> parameter. -=item a(), cname(), srv(), mx(), ns(), ptr(), txt(), hinfo(), rp(), loc() +=item a(), cname(), srv(), mx(), ns(), ptr(), txt(), spf(), hinfo(), rp(), loc() These methods return references to the resource records. For example: @@ -1069,6 +1108,9 @@ TXT records also have a 'text' property representing the record's 'txt-data' descriptive text. +SPF records also have a 'spf' property representing the record's 'spf-data' +descriptive text. + HINFO records also have 'cpu' and 'os' properties. RP records also have 'mbox' and 'text' properties.
https://tools.ietf.org/html/rfc6686 says that SPF records in DNS zones are considered a failure.