summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc van der Wal <marc.vanderwal@afnic.fr>2022-10-06 14:39:33 +0200
committerMarc van der Wal <marc.vanderwal@afnic.fr>2022-10-12 15:50:22 +0200
commit8b8dd0ba1af6330cdd6dff46df02c0e6984a0761 (patch)
tree6b06ef892998c0bd4eb37f11218fd0398652f434
parentef0a666ee5b71ce029c61fc683bfbfeadd7d9f02 (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.pm14
-rw-r--r--src/LDNS.xs12
-rw-r--r--t/rr.t17
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
diff --git a/t/rr.t b/t/rr.t
index a442386..fdd2bc8 100644
--- a/t/rr.t
+++ b/t/rr.t
@@ -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;