diff options
author | Marc van der Wal <marc.vanderwal@afnic.fr> | 2022-10-06 14:39:33 +0200 |
---|---|---|
committer | Marc van der Wal <marc.vanderwal@afnic.fr> | 2022-10-12 15:50:22 +0200 |
commit | 8b8dd0ba1af6330cdd6dff46df02c0e6984a0761 (patch) | |
tree | 6b06ef892998c0bd4eb37f11218fd0398652f434 | |
parent | ef0a666ee5b71ce029c61fc683bfbfeadd7d9f02 (diff) |
Improve access to data in SPF records
SPF resource records are, in essence, TXT resource records with a
different type identifier. The only real difference between SPF and TXT
resource records lies in their uses: TXT is more generic, where SPF was
meant for publishing Sender Policy Framework policies before being
deprecated.
The Zonemaster::LDNS::RR::SPF module suffered from the same problem as
its TXT counterpart, i.e. the spfdata() method only returns the first
string, in presentation format.
For parsing actual SPF policies, however, the behavior of the spfdata()
method is both not very useful as well as incorrect: RFC 7208 states
that the SPF policy is the concatenation of *all* strings in a single
TXT (or SPF) resource record.
So like with the txtdata() method in the TXT package, we entirely
replace the spfdata() method with a correct and pure-Perl
variant.
-rw-r--r-- | lib/Zonemaster/LDNS/RR/SPF.pm | 14 | ||||
-rw-r--r-- | src/LDNS.xs | 12 | ||||
-rw-r--r-- | t/rr.t | 17 |
3 files changed, 26 insertions, 17 deletions
diff --git a/lib/Zonemaster/LDNS/RR/SPF.pm b/lib/Zonemaster/LDNS/RR/SPF.pm index 48e4fec..9ff290f 100644 --- a/lib/Zonemaster/LDNS/RR/SPF.pm +++ b/lib/Zonemaster/LDNS/RR/SPF.pm @@ -5,6 +5,12 @@ use warnings; use parent 'Zonemaster::LDNS::RR'; +sub spfdata() { + my ($rr) = @_; + + return join( "", map { substr($rr->rdf($_ - 1), 1) } 1..$rr->rd_count() ); +} + 1; =head1 NAME @@ -21,6 +27,12 @@ A subclass of L<Zonemaster::LDNS::RR>, so it has all the methods of that class a =item spfdata() -Returns the SPF string. +Returns the concatenation of all the strings composing the data of the resource record. + +For example, if an SPF resource record has the following presentation format: + + test.example. 3600 IN SPF "v=spf1 " "mx " "a " "-all" + +then C<spfdata()> returns the string C<"v=spf1 mx a -all">. =back diff --git a/src/LDNS.xs b/src/LDNS.xs index 2341a3d..bf051ff 100644 --- a/src/LDNS.xs +++ b/src/LDNS.xs @@ -2366,18 +2366,6 @@ rr_cname_cname(obj) CLEANUP: free(RETVAL); -MODULE = Zonemaster::LDNS PACKAGE = Zonemaster::LDNS::RR::SPF PREFIX=rr_spf_ - -char * -rr_spf_spfdata(obj) - Zonemaster::LDNS::RR::SPF obj; - CODE: - RETVAL = D_STRING(obj,0); - OUTPUT: - RETVAL - CLEANUP: - free(RETVAL); - MODULE = Zonemaster::LDNS PACKAGE = Zonemaster::LDNS::RR::KEY PREFIX=rr_key_ U16 @@ -220,10 +220,19 @@ subtest 'SRV' => sub { }; subtest 'SPF' => sub { - my $spf = Zonemaster::LDNS::RR->new( - 'frobbit.se. 1127 IN SPF "v=spf1 ip4:85.30.129.185/24 mx:mail.frobbit.se ip6:2a02:80:3ffe::0/64 ~all"' ); - isa_ok( $spf, 'Zonemaster::LDNS::RR::SPF' ); - is( $spf->spfdata, '"v=spf1 ip4:85.30.129.185/24 mx:mail.frobbit.se ip6:2a02:80:3ffe::0/64 ~all"' ); + my @data = ( + q{frobbit.se. 1127 IN SPF "v=spf1 ip4:85.30.129.185/24 mx:mail.frobbit.se ip6:2a02:80:3ffe::0/64 ~all"}, + q{spf.example. 3600 IN SPF "v=spf1 " "ip4:192.0.2.25/24 " "mx:mail.spf.example " "ip6:2001:db8::25/64 -all"} + ); + + my @rr = map { Zonemaster::LDNS::RR->new($_) } @data; + for my $spf (@rr) { + isa_ok( $spf, 'Zonemaster::LDNS::RR::SPF' ); + } + + is( $rr[0]->spfdata(), 'v=spf1 ip4:85.30.129.185/24 mx:mail.frobbit.se ip6:2a02:80:3ffe::0/64 ~all' ); + is( $rr[1]->spfdata(), 'v=spf1 ip4:192.0.2.25/24 mx:mail.spf.example ip6:2001:db8::25/64 -all' ); + }; done_testing; |