You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by fe...@apache.org on 2006/05/24 22:04:46 UTC
svn commit: r409236 - in /spamassassin/branches/3.1: ./
lib/Mail/SpamAssassin/ lib/Mail/SpamAssassin/Message/Metadata/
lib/Mail/SpamAssassin/Plugin/ t/ t/data/spam/
Author: felicity
Date: Wed May 24 13:04:44 2006
New Revision: 409236
URL: http://svn.apache.org/viewvc?rev=409236&view=rev
Log:
bug 4861, 4760: handle dccifd and dccproc failover properly, backport relays_internal and relays_external code, backport bug 4760 fix so that it's not possible to be in internal_networks without being in trusted_networks as well
Added:
spamassassin/branches/3.1/t/data/spam/gtubedcc.eml
- copied unchanged from r409234, spamassassin/trunk/t/data/spam/gtubedcc.eml
spamassassin/branches/3.1/t/dcc.t
- copied unchanged from r409234, spamassassin/trunk/t/dcc.t
Modified:
spamassassin/branches/3.1/MANIFEST
spamassassin/branches/3.1/lib/Mail/SpamAssassin/Conf.pm
spamassassin/branches/3.1/lib/Mail/SpamAssassin/Message/Metadata/Received.pm
spamassassin/branches/3.1/lib/Mail/SpamAssassin/PerMsgStatus.pm
spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm
spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm
spamassassin/branches/3.1/t/config.dist
Modified: spamassassin/branches/3.1/MANIFEST
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/MANIFEST?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/MANIFEST (original)
+++ spamassassin/branches/3.1/MANIFEST Wed May 24 13:04:44 2006
@@ -344,6 +344,7 @@
t/data/spam/bsmtpnull
t/data/spam/dnsbl.eml
t/data/spam/gtube.eml
+t/data/spam/gtubedcc.eml
t/data/spam/spf1
t/data/spam/spf2
t/data/spam/spf3
@@ -374,6 +375,7 @@
t/db_awl_path.t
t/db_based_whitelist.t
t/db_based_whitelist_ips.t
+t/dcc.t
t/debug.t
t/desc_wrap.t
t/dnsbl.t
Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Conf.pm?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Conf.pm Wed May 24 13:04:44 2006
@@ -2648,6 +2648,8 @@
(note: limited to 50 'stars')
_RELAYSTRUSTED_ relays used and deemed to be trusted
_RELAYSUNTRUSTED_ relays used that can not be trusted
+ _RELAYSINTERNAL_ relays used and deemed to be internal
+ _RELAYSEXTERNAL_ relays used and deemed to be external
_AUTOLEARN_ autolearn status ("ham", "no", "spam", "disabled",
"failed", "unavailable")
_TESTS(,)_ tests hit separated by "," (or other separator)
Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Message/Metadata/Received.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Message/Metadata/Received.pm?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Message/Metadata/Received.pm (original)
+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Message/Metadata/Received.pm Wed May 24 13:04:44 2006
@@ -68,6 +68,14 @@
$self->{num_relays_untrusted} = 0;
$self->{relays_untrusted_str} = '';
+ $self->{relays_internal} = [ ];
+ $self->{num_relays_internal} = 0;
+ $self->{relays_internal_str} = '';
+
+ $self->{relays_external} = [ ];
+ $self->{num_relays_external} = 0;
+ $self->{relays_external_str} = '';
+
$self->{num_relays_unparseable} = 0;
# now figure out what relays are trusted...
@@ -135,6 +143,12 @@
$in_internal = 0;
}
+ # note: you can't be in internal networks, but not be in a trusted
+ # net. (bug 4760)
+ if ($in_internal && !$in_trusted) {
+ $in_trusted = 1;
+ }
+
# OK, infer the trusted/untrusted handover, if we don't have real info.
# Here's the algorithm used (taken from Dan's mail):
#
@@ -262,12 +276,22 @@
push (@{$self->{relays_untrusted}}, $relay);
$self->{allow_fetchmail_markers} = 0;
}
+
+ if ($in_internal) {
+ push (@{$self->{relays_internal}}, $relay);
+ } else {
+ push (@{$self->{relays_external}}, $relay);
+ }
}
$self->{relays_trusted_str} = join(' ', map { $_->{as_string} }
@{$self->{relays_trusted}});
$self->{relays_untrusted_str} = join(' ', map { $_->{as_string} }
@{$self->{relays_untrusted}});
+ $self->{relays_internal_str} = join(' ', map { $_->{as_string} }
+ @{$self->{relays_internal}});
+ $self->{relays_external_str} = join(' ', map { $_->{as_string} }
+ @{$self->{relays_external}});
# drop the temp PerMsgStatus object
delete $self->{dns_pms};
@@ -282,21 +306,31 @@
if ($self->{msg}->can ("delete_header")) {
$self->{msg}->delete_header ("X-Spam-Relays-Trusted");
$self->{msg}->delete_header ("X-Spam-Relays-Untrusted");
+ $self->{msg}->delete_header ("X-Spam-Relays-Internal");
+ $self->{msg}->delete_header ("X-Spam-Relays-External");
if ($self->{msg}->can ("put_metadata")) {
$self->{msg}->put_metadata ("X-Spam-Relays-Trusted",
$self->{relays_trusted_str});
$self->{msg}->put_metadata ("X-Spam-Relays-Untrusted",
$self->{relays_untrusted_str});
+ $self->{msg}->put_metadata ("X-Spam-Relays-Internal",
+ $self->{relays_internal_str});
+ $self->{msg}->put_metadata ("X-Spam-Relays-External",
+ $self->{relays_external_str});
}
}
# be helpful; save some cumbersome typing
$self->{num_relays_trusted} = scalar (@{$self->{relays_trusted}});
$self->{num_relays_untrusted} = scalar (@{$self->{relays_untrusted}});
+ $self->{num_relays_internal} = scalar (@{$self->{relays_internal}});
+ $self->{num_relays_external} = scalar (@{$self->{relays_external}});
dbg("metadata: X-Spam-Relays-Trusted: ".$self->{relays_trusted_str});
dbg("metadata: X-Spam-Relays-Untrusted: ".$self->{relays_untrusted_str});
+ dbg("metadata: X-Spam-Relays-Internal: ".$self->{relays_internal_str});
+ dbg("metadata: X-Spam-Relays-External: ".$self->{relays_external_str});
}
sub lookup_all_ips {
@@ -1224,6 +1258,8 @@
if ($self->{allow_fetchmail_markers}) {
dbg("received-header: found fetchmail marker, restarting parse");
$self->{relays_trusted} = [ ];
+ $self->{relays_internal} = [ ];
+ $self->{relays_external} = [ ];
} else {
dbg("received-header: found fetchmail marker outside trusted area, ignored");
}
Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/PerMsgStatus.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/lib/Mail/SpamAssassin/PerMsgStatus.pm?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/lib/Mail/SpamAssassin/PerMsgStatus.pm (original)
+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/PerMsgStatus.pm Wed May 24 13:04:44 2006
@@ -1351,6 +1351,8 @@
foreach my $item (qw(
relays_trusted relays_trusted_str num_relays_trusted
relays_untrusted relays_untrusted_str num_relays_untrusted
+ relays_internal relays_internal_str num_relays_internal
+ relays_external relays_external_str num_relays_external
num_relays_unparseable
))
{
@@ -1359,6 +1361,8 @@
$self->{tag_data}->{RELAYSTRUSTED} = $self->{relays_trusted_str};
$self->{tag_data}->{RELAYSUNTRUSTED} = $self->{relays_untrusted_str};
+ $self->{tag_data}->{RELAYSINTERNAL} = $self->{relays_internal_str};
+ $self->{tag_data}->{RELAYSEXTERNAL} = $self->{relays_external_str};
$self->{tag_data}->{LANGUAGES} = $self->{msg}->get_metadata("X-Languages");
# This should happen before we get called, but just in case.
@@ -1494,6 +1498,14 @@
# trusted relays list, as string
elsif ($request eq 'X-Spam-Relays-Trusted') {
$result = $self->{relays_trusted_str};
+ }
+ # external relays list, as string
+ elsif ($request eq 'X-Spam-Relays-External') {
+ $result = $self->{relays_external_str};
+ }
+ # internal relays list, as string
+ elsif ($request eq 'X-Spam-Relays-Internal') {
+ $result = $self->{relays_internal_str};
}
# ToCc: the combined recipients list
elsif ($request eq 'ToCc') {
Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm (original)
+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/DCC.pm Wed May 24 13:04:44 2006
@@ -97,7 +97,7 @@
type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL,
});
-=item dcc_timeout n (default: 5)
+=item dcc_timeout n (default: 8)
How many seconds you wait for DCC to complete, before scanning continues
without the DCC results.
@@ -106,7 +106,7 @@
push (@cmds, {
setting => 'dcc_timeout',
- default => 5,
+ default => 8,
type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
});
@@ -238,14 +238,14 @@
Specify additional options to the dccproc(8) command. Please note that only
characters in the range [0-9A-Za-z ,._/-] are allowed for security reasons.
-The default is C<-R>.
+The default is C<undef>.
=cut
push (@cmds, {
setting => 'dcc_options',
is_admin => 1,
- default => '-R',
+ default => undef,
code => sub {
my ($self, $key, $value, $line) = @_;
if ($value !~ m{^([0-9A-Za-z ,._/-]+)$}) {
@@ -255,6 +255,28 @@
}
});
+=item dccifd_options options
+
+Specify additional options to send to the dccifd(8) daemon. Please note that only
+characters in the range [0-9A-Za-z ,._/-] are allowed for security reasons.
+
+The default is C<undef>.
+
+=cut
+
+ push (@cmds, {
+ setting => 'dccifd_options',
+ is_admin => 1,
+ default => undef,
+ code => sub {
+ my ($self, $key, $value, $line) = @_;
+ if ($value !~ m{^([0-9A-Za-z ,._/-]+)$}) {
+ return $Mail::SpamAssassin::Conf::INVALID_VALUE;
+ }
+ $self->{dccifd_options} = $1;
+ }
+ });
+
$conf->{parser}->register_commands(\@cmds);
}
@@ -352,23 +374,34 @@
return 0;
}
+ my $client = $permsgstatus->{relays_external}->[0]->{ip};
if ($self->{dccifd_available}) {
- return $self->dccifd_lookup($permsgstatus, $full);
+ my $clientname = $permsgstatus->{relays_external}->[0]->{rdns};
+ my $helo = $permsgstatus->{relays_external}->[0]->{helo} || "";
+ if ($client) {
+ if ($clientname) {
+ $client = $client . "\r" . $clientname;
+ }
+ } else {
+ $client = "0.0.0.0";
+ }
+ return $self->dccifd_lookup($permsgstatus, $full, $client, $clientname, $helo);
}
else {
- return $self->dccproc_lookup($permsgstatus, $full);
+ return $self->dccproc_lookup($permsgstatus, $full, $client);
}
return 0;
}
sub dccifd_lookup {
- my ($self, $permsgstatus, $fulltext) = @_;
+ my ($self, $permsgstatus, $fulltext, $client, $clientname, $helo) = @_;
my $response = "";
my %count;
my $left;
my $right;
my $timeout = $self->{main}->{conf}->{dcc_timeout};
my $sockpath = $self->{main}->{conf}->{dcc_dccifd_path};
+ my $opts = $self->{main}->{conf}->{dccifd_options} || '';
$count{body} = 0;
$count{fuz1} = 0;
@@ -385,9 +418,9 @@
Peer => $sockpath) || dbg("dcc: failed to open socket") && die;
# send the options and other parameters to the daemon
- $sock->print("header\n") || dbg("dcc: failed write") && die; # options
- $sock->print("0.0.0.0\n") || dbg("dcc: failed write") && die; # client
- $sock->print("\n") || dbg("dcc: failed write") && die; # HELO value
+ $sock->print("header " . $opts . "\n") || dbg("dcc: failed write") && die; # options
+ $sock->print($client . "\n") || dbg("dcc: failed write") && die; # client
+ $sock->print($helo . "\n") || dbg("dcc: failed write") && die; # HELO value
$sock->print("\n") || dbg("dcc: failed write") && die; # sender
$sock->print("unknown\r\n") || dbg("dcc: failed write") && die; # recipients
$sock->print("\n") || dbg("dcc: failed write") && die; # recipients
@@ -469,7 +502,7 @@
}
sub dccproc_lookup {
- my ($self, $permsgstatus, $fulltext) = @_;
+ my ($self, $permsgstatus, $fulltext, $client) = @_;
my $response = undef;
my %count;
my $timeout = $self->{main}->{conf}->{dcc_timeout};
@@ -493,11 +526,12 @@
my $path = Mail::SpamAssassin::Util::untaint_file_path($self->{main}->{conf}->{dcc_path});
my $opts = $self->{main}->{conf}->{dcc_options} || '';
+ $opts = "-a " . $client . " " . $opts if $client;
- dbg("dcc: opening pipe: " . join(' ', $path, "-H", $opts, "< $tmpf"));
+ dbg("dcc: opening pipe: " . join(' ', $path, "-H", "-x", "0", $opts, "< $tmpf"));
$pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
- $tmpf, 1, $path, "-H", split(' ', $opts));
+ $tmpf, 1, $path, "-H", "-x", "0", split(' ', $opts));
$pid or die "$!\n";
my @null = <DCC>;
@@ -596,29 +630,103 @@
sub plugin_report {
my ($self, $options) = @_;
+ return if $self->{options}->{dont_report_to_dcc};
+ $self->get_dcc_interface();
return if $self->{dcc_disabled};
- if (!defined $self->{dccproc_available}) {
- $self->is_dccproc_available();
- }
-
- if ($self->{dccproc_available} && !$self->{options}->{dont_report_to_dcc}) {
+ # get the metadata from the message so we can pass the external relay information
+ $options->{msg}->extract_message_metadata($options->{report}->{main});
+ my $client = $options->{msg}->{metadata}->{relays_external}->[0]->{ip};
+ if ($self->{dccifd_available}) {
+ my $clientname = $options->{msg}->{metadata}->{relays_external}->[0]->{rdns};
+ my $helo = $options->{msg}->{metadata}->{relays_external}->[0]->{helo} || "";
+ if ($client) {
+ if ($clientname) {
+ $client = $client . "\r" . $clientname;
+ }
+ } else {
+ $client = "0.0.0.0";
+ }
+ if ($self->dccifd_report($options, $options->{text}, $client, $helo)) {
+ $options->{report}->{report_available} = 1;
+ info("reporter: spam reported to DCC");
+ $options->{report}->{report_return} = 1;
+ }
+ else {
+ info("reporter: could not report spam to DCC via dccifd");
+ }
+ } else {
# use temporary file: open2() is unreliable due to buffering under spamd
my $tmpf = $options->{report}->create_fulltext_tmpfile($options->{text});
- if ($self->dcc_report($options, $tmpf)) {
+
+ if ($self->dcc_report($options, $tmpf, $client)) {
$options->{report}->{report_available} = 1;
info("reporter: spam reported to DCC");
$options->{report}->{report_return} = 1;
}
else {
- info("reporter: could not report spam to DCC");
+ info("reporter: could not report spam to DCC via dccproc");
}
$options->{report}->delete_fulltext_tmpfile();
}
}
+sub dccifd_report {
+ my ($self, $options, $fulltext, $client, $helo) = @_;
+ my $timeout = $self->{main}->{conf}->{dcc_timeout};
+ my $sockpath = $self->{main}->{conf}->{dcc_dccifd_path};
+ my $opts = $self->{main}->{conf}->{dccifd_options} || ''; # instead of header use whatever the report option is
+
+ $options->{report}->enter_helper_run_mode();
+ my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
+
+ my $err = $timer->run_and_catch(sub {
+
+ local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
+
+ my $sock = IO::Socket::UNIX->new(Type => SOCK_STREAM,
+ Peer => $sockpath) || dbg("report: dccifd failed to open socket") && die;
+
+ # send the options and other parameters to the daemon
+ $sock->print("spam " . $opts . "\n") || dbg("report: dccifd failed write") && die; # options
+ $sock->print($client . "\n") || dbg("report: dccifd failed write") && die; # client
+ $sock->print($helo . "\n") || dbg("report: dccifd failed write") && die; # HELO value
+ $sock->print("\n") || dbg("report: dccifd failed write") && die; # sender
+ $sock->print("unknown\r\n") || dbg("report: dccifd failed write") && die; # recipients
+ $sock->print("\n") || dbg("report: dccifd failed write") && die; # recipients
+
+ $sock->print($$fulltext);
+
+ $sock->shutdown(1) || dbg("report: dccifd failed socket shutdown: $!") && die;
+
+ $sock->getline() || dbg("report: dccifd failed read status") && die;
+ $sock->getline() || dbg("report: dccifd failed read multistatus") && die;
+
+ my @ignored = $sock->getlines();
+ });
+
+ $options->{report}->leave_helper_run_mode();
+
+ if ($timer->timed_out()) {
+ dbg("reporter: DCC report via dccifd timed out after $timeout secs.");
+ return 0;
+ }
+
+ if ($err) {
+ chomp $err;
+ if ($err eq "__brokenpipe__ignore__") {
+ dbg("reporter: DCC report via dccifd failed: broken pipe");
+ } else {
+ warn("reporter: DCC report via dccifd failed: $err\n");
+ }
+ return 0;
+ }
+
+ return 1;
+}
+
sub dcc_report {
- my ($self, $options, $tmpf) = @_;
+ my ($self, $options, $tmpf, $client) = @_;
my $timeout = $options->{report}->{conf}->{dcc_timeout};
# note: not really tainted, this came from system configuration file
@@ -626,6 +734,9 @@
my $opts = $options->{report}->{conf}->{dcc_options} || '';
+ # get the metadata from the message so we can pass the external relay information
+ $opts = "-a " . $client . " " . $opts if $client;
+
my $timer = Mail::SpamAssassin::Timeout->new({ secs => $timeout });
$options->{report}->enter_helper_run_mode();
@@ -633,8 +744,10 @@
local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };
+ dbg("report: opening pipe: " . join(' ', $path, "-H", "-t", "many", "-x", "0", $opts, "< $tmpf"));
+
my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
- $tmpf, 1, $path, "-t", "many", split(' ', $opts));
+ $tmpf, 1, $path, "-H", "-t", "many", "-x", "0", split(' ', $opts));
$pid or die "$!\n";
my @ignored = <DCC>;
@@ -645,16 +758,16 @@
$options->{report}->leave_helper_run_mode();
if ($timer->timed_out()) {
- dbg("reporter: DCC report timed out after $timeout seconds");
+ dbg("reporter: DCC report via dccproc timed out after $timeout seconds");
return 0;
}
if ($err) {
chomp $err;
if ($err eq "__brokenpipe__ignore__") {
- dbg("reporter: DCC report failed: broken pipe");
+ dbg("reporter: DCC report via dccproc failed: broken pipe");
} else {
- warn("reporter: DCC report failed: $err\n");
+ warn("reporter: DCC report via dccproc failed: $err\n");
}
return 0;
}
Modified: spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm (original)
+++ spamassassin/branches/3.1/lib/Mail/SpamAssassin/Plugin/SPF.pm Wed May 24 13:04:44 2006
@@ -345,56 +345,8 @@
sub _get_relay {
my ($self, $scanner) = @_;
- # return relay if already determined
- return $scanner->{spf_relay} if exists $scanner->{spf_relay};
-
- # DOS: For SPF checks we want to use the relay that passed the message to
- # the internal network. This relay can be any of the trusted relays or the
- # first untrusted relay. No matter which it is, the next (newer) relay has
- # to be an internal relay. If there are no trusted relays, the first
- # untrusted relay is the one we want. If internal_networks aren't set we
- # have to assume all trusted relays are internal.
-
- my $relay = undef;
- my $relays_trusted = $scanner->{relays_trusted};
-
- # no trusted relays, use first untrusted
- if (scalar @{$relays_trusted} == 0) {
- $relay = $scanner->{relays_untrusted}->[0];
- dbg("spf: no trusted relays found, using first (untrusted) relay (if present) for SPF checks");
- }
-
- # last trusted relay is internal (or internal_networks not set), use first untrusted
- elsif ($relays_trusted->[-1]->{internal} || !($scanner->{conf}->{internal_networks}->get_num_nets() > 0)) {
- $relay = $scanner->{relays_untrusted}->[0];
- dbg("spf: last trusted relay is internal, using first untrusted relay (parsed relay #". (scalar @{$relays_trusted}+1) ." if present) for SPF checks");
- }
-
- # find external relay that passed the message to the last internal relay
- else {
-
- # found an internal relay?
- my $found = 0;
-
- # start at the end; don't check for an internal relay before the first one
- for (my $i = scalar @{$relays_trusted} - 1; $i > 0 && !$found; $i--) {
- # if the next relay is internal, we can use the current external one
- if ($relays_trusted->[$i-1]->{internal}) {
- $relay = $relays_trusted->[$i];
- $found = 1;
- dbg("spf: using first external trusted relay (parsed relay #". ($i+1) .") for SPF checks");
- }
- }
-
- # if none of the trusted relays were internal, internal_networks isn't set
- # correctly -- dbg about it
- if (!$found) {
- dbg("spf: none of the trusted relays are internal, please check your internal_networks configuration");
- }
- }
-
- $scanner->{spf_relay} = $relay;
- return $relay;
+ # dos: first external relay, not first untrusted
+ return $scanner->{relays_external}->[0];
}
sub _get_sender {
Modified: spamassassin/branches/3.1/t/config.dist
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.1/t/config.dist?rev=409236&r1=409235&r2=409236&view=diff
==============================================================================
--- spamassassin/branches/3.1/t/config.dist (original)
+++ spamassassin/branches/3.1/t/config.dist Wed May 24 13:04:44 2006
@@ -7,6 +7,9 @@
run_net_tests=n
+# Run DCC Tests
+run_dcc_tests=y
+
# ---------------------------------------------------------------------------
# Run SQL-based Auto-whitelist tests during 'make test' (additional
# information required, below:)