You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by he...@apache.org on 2018/09/27 14:38:33 UTC

svn commit: r1842098 - in /spamassassin/trunk/lib/Mail/SpamAssassin: AsyncLoop.pm Conf.pm PerMsgStatus.pm

Author: hege
Date: Thu Sep 27 14:38:33 2018
New Revision: 1842098

URL: http://svn.apache.org/viewvc?rev=1842098&view=rev
Log:
Bug 6728 - DNSBLs need a way to turn off queries based on BLOCKED rules triggering

Modified:
    spamassassin/trunk/lib/Mail/SpamAssassin/AsyncLoop.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
    spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/AsyncLoop.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/AsyncLoop.pm?rev=1842098&r1=1842097&r2=1842098&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/AsyncLoop.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/AsyncLoop.pm Thu Sep 27 14:38:33 2018
@@ -322,17 +322,39 @@ sub bgsend_and_start_lookup {
 
   else {  # no existing query, open a new DNS query
     $dns_query_info = $self->{all_lookups}{$dnskey} = {};  # new query needed
-    my($id, $blocked);
+    my($id, $blocked, $check_dbrdom);
+    # dns_query_restriction
+    my $blocked_by = 'dns_query_restriction';
     my $dns_query_blockages = $self->{main}->{conf}->{dns_query_blocked};
-    if ($dns_query_blockages) {
+    # dns_block_rule
+    my $dns_block_domains = $self->{main}->{conf}->{dns_block_rule_domains};
+    if ($dns_query_blockages || $dns_block_domains) {
       my $search_list = domain_to_search_list($domain);
       foreach my $parent_domain (@$search_list) {
-        $blocked = $dns_query_blockages->{$parent_domain};
-        last if defined $blocked; # stop at first defined, can be true or false
+        if ($dns_query_blockages) {
+          $blocked = $dns_query_blockages->{$parent_domain};
+          last if defined $blocked; # stop at first defined, can be true or false
+        } elsif ($dns_block_domains->{$parent_domain}) {
+          # save for later check.. ps. untainted already
+          $check_dbrdom = $dns_block_domains->{$parent_domain};
+        }
+      }
+    }
+    if (!$blocked && $check_dbrdom) {
+      my $blockfile =
+        $self->{main}->sed_path("__userstate__/dnsblock_${check_dbrdom}");
+      if (my $mtime = (stat($blockfile))[9]) {
+        if (time - $mtime <= $self->{main}->{conf}->{dns_block_time}) {
+          $blocked = 1;
+          $blocked_by = 'dns_block_rule';
+        } else {
+          dbg("async: dns_block_rule removing expired $blockfile");
+          unlink($blockfile);
+        }
       }
     }
     if ($blocked) {
-      dbg("async: blocked by dns_query_restriction: %s", $dnskey);
+      dbg("async: blocked by %s: %s", $blocked_by, $dnskey);
     } else {
       dbg("async: launching %s for %s", $dnskey, $key);
       $id = $self->{main}->{resolver}->bgsend($domain, $type, $class, sub {

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=1842098&r1=1842097&r2=1842098&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Thu Sep 27 14:38:33 2018
@@ -1965,6 +1965,55 @@ options, leaving the list empty, i.e. al
     }
   });
 
+=item dns_block_rule RULE domain
+
+If rule named RULE is hit, DNS queries to specified domain are
+I<temporarily> blocked. Intended to be used with rules that check
+RBL return codes for specific blocked status.  For example:
+
+  urirhssub URIBL_BLOCKED multi.uribl.com. A 1
+  dns_block_rule URIBL_BLOCKED multi.uribl.com
+
+Block status is maintained across all processes by empty statefile in
+userstate directory (~/.spamassassin/dnsblock_multi.uribl.com).
+
+=cut
+
+  push (@cmds, {
+    setting => 'dns_block_rule',
+    type => $CONF_TYPE_STRING,
+    code => sub {
+      my ($self, $key, $value, $line) = @_;
+      defined $value && $value =~ /^(\S+)\s+(.+)$/
+        or return $INVALID_VALUE;
+      my $rule = $1;
+      foreach my $domain (split(/\s+/, lc($2))) {
+        $domain =~ s/^\.//; $domain =~ s/\.\z//;  # strip dots
+        if ($domain !~ /^[a-z0-9.-]+$/) {
+          return $INVALID_VALUE;
+        }
+        $domain = untaint_var($domain); # will be in filename!
+        # got_hit() uses this
+        $self->{dns_block_rule}{$rule}{$domain} = 1;
+        # bgsend_and_start_lookup() uses this
+        $self->{dns_block_rule_domains}{$domain} = $domain;
+      }
+    }
+  });
+
+=item dns_block_time   (default: 300)
+
+dns_block_rule query blockage will last this many seconds.
+
+=cut
+
+  push (@cmds, {
+    setting => 'dns_block_time',
+    is_admin => 1,
+    default => 60,
+    type => $CONF_TYPE_NUMERIC,
+  });
+
 =back
 
 =head2 LEARNING OPTIONS
@@ -5422,6 +5471,7 @@ sub feature_edns { 1 }  # supports 'dns_
 sub feature_dns_query_restriction { 1 }  # supported config option
 sub feature_registryboundaries { 1 } # replaces deprecated registrarboundaries
 sub feature_geodb { 1 } # if needed for some reason
+sub feature_dns_block_rule { 1 } # supports 'dns_block_rule' config option
 sub perl_min_version_5010000 { return $] >= 5.010000 }  # perl version check ("perl_version" not neatly backwards-compatible)
 
 ###########################################################################

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm?rev=1842098&r1=1842097&r2=1842098&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/PerMsgStatus.pm Thu Sep 27 14:38:33 2018
@@ -2773,6 +2773,17 @@ sub got_hit {
     }
   }
 
+  # dns_block_rule
+  if (defined $conf_ref->{dns_block_rule}{$rule}) {
+    foreach my $domain (keys %{$conf_ref->{dns_block_rule}{$rule}}) {
+      my $blockfile = 
+        $self->{main}->sed_path("__userstate__/dnsblock_$domain");
+      next if -f $blockfile; # no need to warn and create again..
+      warn("check: dns_block_rule $rule hit, creating $blockfile\n");
+      Mail::SpamAssassin::Util::touch_file($blockfile, { create_exclusive => 1 });
+    }
+  }
+
   %{$self->{test_log_msgs}} = ();  # clear test logs
   return 1;
 }