[Mimedefang] Authenticated Users Filter modification (especially for POP BEFORE AUTH users) for SA & Blacklist issue
Ole Craig
olc at cs.umass.edu
Thu May 20 12:04:44 EDT 2004
On 05/12/04 at 18:15, 'twas brillig and Kevin A. McGrail scrobe:
> After thinking about how to solve the problem, I decided that users that
> have authenticated to send email should be exempted from SA checks. This
> may not scale for everyone but all our users are not going to send spam. We
> still check for virii though. *I very much want comments on this line of
> thought*
> [...]
Kevin -
I actually just implemented some of these things, starting
with your ideas and going from there. I have some comments on the code
itself, but first let me remark on the paragraph above... I still run
mail through SA if it has site-local origin (although I disable
network SA tests for such mail) because if someone within my network
is contributing to the delinquency of the 'net I want to know about
it. (One of my first experiences as a postmaster, seven or eight years
ago, was that of finding that one of "my" grad students was spamming
the entire university from her SGI workstation, to advertise the
continuing-ed course she was teaching, for which she received
per-student fees. You'd think a CS grad student studying networking
wouldn't need an exhaustive explanation of the logic behind the phrase
"spam is BAD"...)
> Anyway, our system uses pop before smtp authentication to prevent SPAM from
> relaying so I've modded my filter to read the popauth database to see if we
> can bypass SpamAssassin altogether (see above).
[...]
> sub filter_initialize {
> #SETUP A TIE TO THE POP BEFORE SMTP AUTH DATABASE
> use DB_File;
>
> our ($popauthdbfile, $popauthdb);
> $popauthdbfile = "/etc/mail/popauth.db";
>
> $popauthdb = &opendb_read($popauthdbfile);
> }
Problem? AIUI, filter_initialize is called only once in the
life of a slave, and DB_File doesn't check the timestamp of the
on-disk DB when you use the contents of the hash. If a slave takes
half an hour to process its allotted number of messages, then
$popauthdb will be a half-hour out of date by the time the last
message is processed, unless you are calling opendb_read before every
check (in which case, why bother calling it in filter_init?) This
means that someone potentially has to wait some non-trivial amount of
time after checking mail to be sure of sending it without some risk of
incurring the SA penalties you are trying to avoid. Maybe not a big
deal, but probably not what you wanted.
[...]
> These function will allow your mimedefang filter to detect whether an email
> was sent using POP Before SMTP
> Authentication. I then used that information to add a header to the email
> and to set a variable $popauth
> to true in my filter_end routine.
[...]
> Now, I use the existence of this header to bypass calling SpamAssassin. If
> you are calling SpamAssassin
> from your filter, simply add a check for the variable $popauth:
So you're setting $popauth in filter_end() and using it in
filter() ? Or is "your filter" above intended to refer loosely to the
entire thing, with the understanding that you're calling SA from
filter_end() also? Because mimedefang-filter(5) says:
The following list describes the lifetime of global
variables (thanks to Tony Nugent for providing this documentation.)
If you set a global variable:
[...]
In filter_end
Available within filter_end
So here's what I do... (feel free to tear it apart :-) my
comments interspersed in brackets.
# the DB used for popauth relay authentication
# MUST BE READABLE BY THE DEFANG USER (try
# "chgrp defang /etc/mail/access.db")
$popauthdbfile = "/etc/mail/access.db";
<we have a homegrown pop-before-smtp solution # dating from before
drac et al were available>
sub filter_initialize () {
use DB_File;
# build our static spamassassin objects
if ($Features{"SpamAssassin"}) {
spam_assassin_init()->compile_now(1) if defined(spam_assassin_init());
spam_assassin_init_net()->compile_now(1) if defined(spam_assassin_init_net());
}
}
<my opendb_read and closedb are stolen line-for-line from KAM>
sub popauthget ($) {
# read sendmail's access.db and look for ip RELAY
my ($ip) =@_;
my $popauthdb = &opendb_read($popauthdbfile);
if ($popauthdb->{$ip} =~ /RELAY/) {
&closedb($popauthdb);
return "popauth";
}
return 0;
}
sub authget () {
# return 0 if not authenticated, authid otherwise
# see http://lists.roaringpenguin.com/pipermail/mimedefang/2003-November/018351.html
open(COMM, "<./COMMANDS") or return 0;
while(<COMM>) {
if (/^=auth_authen\s+(\w+)/) {
close(COMM);
return $1;
}
}
close(COMM);
return 0;
}
<then, in filter_sender(), I use these for allowing bogus HELOs from
client MUAs -- if I wanted to use them for other purposes, I guess I'd
write a file in WORKDIR rather than doing the DB lookup again.>
sub filter_sender ($$$$) {
my ($envfrom, $ip, $hname, $helo) = @_;
# match someone who's pretending to be us or HELOing one of "our" IPs
# -- legit MTAs should never do this, some ratware does
if ($helo =~ /^($ThisHost)$|^\w*\.cs\.umass\.edu$|^128.119.(24\d|4[012])\.\d+$/i ) {
if ($ip !~ /^128\.119\.(24\d|4[012])\.\d+|^127\.0\.0\.1/) {
if (my $luser = (authget or popauthget($ip))) {
md_syslog('warning', "forged_helo_auth: Host $ip ($hname) authenticated by $luser said HELO $helo with ENVFROM of \'$envfrom\'");
return ('CONTINUE', "ok");
} else {
md_syslog('warning', "forged_helo: Host $ip ($hname) said HELO $helo with ENVFROM of \'$envfrom\'");
return("REJECT", "Invalid SMTP transaction");
}
} else {
if ($ip !~ /127\.0\.0\.1|128\.119\.243\.168/ and $helo =~ /^$ThisHost.*|^128.119.243.168/) {
md_syslog('warning', "forged_helo_local: Onsite host $ip ($hname) said HELO $helo with ENVFROM of \'$envfrom\'");
}
}
}
return ('CONTINUE', "ok");
}
Cheers,
Ole
--
Ole Craig * UNIX, linux, SMTP-ninja; news, web; SGI martyr * CS Computing
Facility, UMass * <www.cs.umass.edu/~olc/pgppubkey.txt> for public key
Where are the missing deficit-reduction program-related activities?
More information about the MIMEDefang
mailing list