You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2012/12/21 19:21:45 UTC

svn commit: r1425068 - in /spamassassin/trunk: lib/Mail/SpamAssassin/Dns.pm lib/Mail/SpamAssassin/DnsResolver.pm lib/Mail/SpamAssassin/Plugin/AskDNS.pm lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm sa-update.raw

Author: mmartinec
Date: Fri Dec 21 18:21:45 2012
New Revision: 1425068

URL: http://svn.apache.org/viewvc?rev=1425068&view=rev
Log:
Bug 6872 - replace $rr->rdatastr with $rr->txtdata where appropriate

Modified:
    spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
    spamassassin/trunk/sa-update.raw

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm?rev=1425068&r1=1425067&r2=1425068&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm Fri Dec 21 18:21:45 2012
@@ -185,9 +185,11 @@ sub dnsbl_hit {
   if (substr($rule, 0, 2) eq "__") {
     # don't bother with meta rules
   } elsif ($answer->type eq 'TXT') {
+    # txtdata returns a non- zone-file-format encoded result, unlike rdatastr;
+    # avoid space-separated RDATA <character-string> fields if possible,
+    # txtdata provides a list of strings in a list context since Net::DNS 0.69
+    $log = join('',$answer->txtdata);
     local $1;
-    $log = $answer->rdatastr;
-    $log =~ s/^"(.*)"\z/$1/s;
     $log =~ s{ (?<! [<(\[] ) (https? : // \S+)}{<$1>}xgi;
   } else {  # assuming $answer->type eq 'A'
     local($1,$2,$3,$4,$5);
@@ -226,8 +228,13 @@ sub dnsbl_uri {
   my ($self, $question, $answer) = @_;
 
   my $qname = $question->qname;
-  my $rdatastr = $answer->rdatastr;
 
+  # txtdata returns a non- zone-file-format encoded result, unlike rdatastr;
+  # avoid space-separated RDATA <character-string> fields if possible,
+  # txtdata provides a list of strings in a list context since Net::DNS 0.69
+  #
+  my $rdatastr = $answer->UNIVERSAL::can('txtdata') ? join('',$answer->txtdata)
+                                                    : $answer->rdatastr;
   if (defined $qname && defined $rdatastr) {
     my $qclass = $question->qclass;
     my $qtype = $question->qtype;
@@ -289,7 +296,13 @@ sub process_dnsbl_result {
 sub process_dnsbl_set {
   my ($self, $set, $question, $answer) = @_;
 
-  my $rdatastr = $answer->rdatastr;
+  # txtdata returns a non- zone-file-format encoded result, unlike rdatastr;
+  # avoid space-separated RDATA <character-string> fields if possible,
+  # txtdata provides a list of strings in a list context since Net::DNS 0.69
+  #
+  my $rdatastr = $answer->UNIVERSAL::can('txtdata') ? join('',$answer->txtdata)
+                                                    : $answer->rdatastr;
+
   while (my ($subtest, $rule) = each %{ $self->{dnspost}->{$set} }) {
     next if $self->{tests_already_hit}->{$rule};
 
@@ -305,8 +318,7 @@ sub process_dnsbl_set {
         next;
       }
 
-      $rdatastr =~ s/^"?\d+-//;
-      $rdatastr =~ s/"$//;
+      $rdatastr =~ s/^\d+-//;
       my %sb = ($rdatastr =~ m/(?:^|\|)(\d+)=([^|]+)/g);
       my $undef = 0;
       while ($subtest =~ m/\bS(\d+)\b/g) {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm?rev=1425068&r1=1425067&r2=1425068&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/DnsResolver.pm Fri Dec 21 18:21:45 2012
@@ -596,7 +596,7 @@ sub _packet_id {
     # Net::DNS::Packet::dn_expand and Net::DNS::wire2presentation in turn.
     # Let's undo the effect of the wire2presentation routine here to make
     # sure the query section of an answer packet matches the query section
-    # in our packet formed by new_dns_packet():
+    # in our packet as formed by new_dns_packet():
     #
     my $qname = $ques->qname;
     $qname =~ s/\\([0-9]{3}|.)/length($1)==1 ? $1 : chr($1)/gse;

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm?rev=1425068&r1=1425067&r2=1425068&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/AskDNS.pm Fri Dec 21 18:21:45 2012
@@ -192,7 +192,7 @@ use Mail::SpamAssassin::Plugin;
 use Mail::SpamAssassin::Util;
 use Mail::SpamAssassin::Logger;
 
-use vars qw(@ISA %rcode_value);
+use vars qw(@ISA %rcode_value $txtdata_can_provide_a_list);
 @ISA = qw(Mail::SpamAssassin::Plugin);
 
 %rcode_value = (  # http://www.iana.org/assignments/dns-parameters, RFC 6195
@@ -211,6 +211,8 @@ sub new {
 
   $self->set_config($sa_main->{conf});
 
+  $txtdata_can_provide_a_list = Net::DNS->VERSION >= 0.69;
+
   return $self;
 }
 
@@ -534,20 +536,40 @@ sub process_response_packet {
     # evaluate also rules which only care for rcode status
     @answer = ( undef );
   }
+
+  # NOTE:  $rr->rdatastr returns the result encoded in a DNS zone file
+  # format, i.e. enclosed in double quotes if a result contains whitespace
+  # (or other funny characters), and may use \DDD encoding or \X quoting as
+  # per RFC 1035.  Using $rr->txtdata instead avoids this unnecessary encoding
+  # step and a need for decoding by a caller, returning an unmodified string.
+  # Caveat: in case of multiple RDATA <character-string> fields contained
+  # in a resource record (TXT, SPF, HINFO), starting with Net::DNS 0.69
+  # the $rr->txtdata in a list context returns these strings as a list.
+  # The $rr->txtdata in a scalar context always returns a single string
+  # with <character-string> fields joined by a single space character as
+  # a separator.  The $rr->txtdata in Net::DNS 0.68 and older returned
+  # such joined space-separated string even in a list context.
+
+  # RFC 5518: If the RDATA in the TXT record contains multiple
+  # character-strings (as defined in Section 3.3 of [RFC1035]),
+  # the code handling that reply from DNS MUST assemble all of these
+  # marshaled text blocks into a single one before any syntactical
+  # verification takes place.
+  # The same goes for RFC 4408 (SPF), RFC 4871 (DKIM), RFC 5617 (ADSP) ...
+
   for my $rr (@answer) {
     my($rr_rdatastr, $rdatanum, $rr_type);
     if (!$rr) {
       # special case, no answer records, only rcode can be tested
     } else {
       $rr_type = uc $rr->type;
-      if ($rr_type eq 'TXT' || $rr_type eq 'SPF') {
-        # RFC 5518: If the RDATA in the TXT record contains multiple
-        # character-strings (as defined in Section 3.3 of [RFC1035]),
-        # the code handling that reply from DNS MUST assemble all of these
-        # marshaled text blocks into a single one before any syntactical
-        # verification takes place.
-        # The same goes for RFC 4408 (SPF), RFC 4871 (DKIM), RFC 5617 (ADSP) ...
-        $rr_rdatastr = join('', $rr->char_str_list);  # as per RFC 5518
+      if ($rr->UNIVERSAL::can('txtdata')) {  # TXT, SPF
+        # join with no intervening spaces, as per RFC 5518
+        if ($txtdata_can_provide_a_list || $rr_type ne 'TXT') {
+          $rr_rdatastr = join('', $rr->txtdata);  # txtdata() in list context!
+        } else {  # char_str_list() is only available for TXT records
+          $rr_rdatastr = join('', $rr->char_str_list);  # historical
+        }
       } else {
         $rr_rdatastr = $rr->rdatastr;
         if ($rr_type eq 'A' &&
@@ -555,9 +577,6 @@ sub process_response_packet {
           $rdatanum = Mail::SpamAssassin::Util::my_inet_aton($rr_rdatastr);
         }
       }
-      # decode DNS presentation format as returned by Net::DNS
-      local $1;
-      $rr_rdatastr =~ s/\\([0-9]{3}|.)/length($1)==1 ? $1 : chr($1)/gse;
     # dbg("askdns: received rr type %s, data: %s", $rr_type, $rr_rdatastr);
     }
 

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm?rev=1425068&r1=1425067&r2=1425068&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/URIDNSBL.pm Fri Dec 21 18:21:45 2012
@@ -1075,7 +1075,13 @@ sub complete_dnsbl_lookup {
     next if ($rr->type ne 'A' && $rr->type ne 'TXT');
 
     my $dom = $ent->{obj}->{dom};
-    my $rdatastr = $rr->rdatastr;
+
+    # txtdata returns a non- zone-file-format encoded result, unlike rdatastr;
+    # avoid space-separated RDATA <character-string> fields if possible,
+    # txtdata provides a list of strings in a list context since Net::DNS 0.69
+    #
+    my $rdatastr = $rr->type eq 'TXT' ? join('',$rr->txtdata) : $rr->rdatastr;
+
     my $rdatanum;
     if ($rdatastr =~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
       $rdatanum = Mail::SpamAssassin::Util::my_inet_aton($rdatastr);

Modified: spamassassin/trunk/sa-update.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/sa-update.raw?rev=1425068&r1=1425067&r2=1425068&view=diff
==============================================================================
--- spamassassin/trunk/sa-update.raw (original)
+++ spamassassin/trunk/sa-update.raw Fri Dec 21 18:21:45 2012
@@ -1243,16 +1243,32 @@ sub do_dns_query {
   my $RR = $res->query($query, $rr_type);
   my @result;
 
+  # NOTE:  $rr->rdatastr returns the result encoded in a DNS zone file
+  # format, i.e. enclosed in double quotes if a result contains whitespace
+  # (or other funny characters), and may use \DDD encoding or \X quoting as
+  # per RFC 1035.  Using $rr->txtdata instead avoids this unnecessary encoding
+  # step and a need for decoding by a caller, returning an unmodified string.
+  # Caveat: in case of multiple RDATA <character-string> fields contained
+  # in a resource record (TXT, SPF, HINFO), starting with Net::DNS 0.69
+  # the $rr->txtdata in a list context returns these strings as a list.
+  # The $rr->txtdata in a scalar context always returns a single string
+  # with <character-string> fields joined by a single space character as
+  # a separator.  The $rr->txtdata in Net::DNS 0.68 and older returned
+  # such joined space-separated string even in a list context.
+  #
+  # From Net::DNS maintainers (Willem Toorop, NLnet Labs):
+  #   I encourage you to use txtdata for getting the values of
+  # <version>.updates.spamassassin.org and mirros.updates.spamassassin.org.
+  # As those records have only a single rdata field, txtdata would return
+  # the same value since Net::DNS 0.34.
+  #
   if ($RR) {
     foreach my $rr ($RR->answer) {
       next if !$rr;  # no answer records, only rcode
       next if $rr->type ne $rr_type;
-      my $text = $rr->rdatastr;
-      if (defined $text && $text ne '') {
-        local($1);
-        $text =~ s/^"(.*)"\z/$1/s;
-        push(@result,$text);
-      }
+      # scalar context!
+      my $text = $rr->UNIVERSAL::can('txtdata') ? $rr->txtdata : $rr->rdatastr;
+      push(@result,$text)  if defined $text && $text ne '';
     }
     printf("DNS %s query: %s -> %s\n", $rr_type, $query, join(", ",@result))
       if $opt{'verbose'} && $opt{'verbose'} > 1;