On 1/11/2011 6:55 AM, Steve Freegard wrote:
Hi Tapio,
On 11 Jan 2011, at 11:34, Tapio Salonsaari wrote:
My web gui stores black / white lists into psql-database and the idea is
to do an SQL-search like:
SELECT * FROM blacklist WHERE sender="$senderdomain" AND
recipient="$recipientdomain";
Then if the query returns any rows the plugin would return DENY. If
there's no rows on blacklist search the same for whitelist -table and
process the data accordingly.
I'm using http://devin.com/qpsmtpd/whitelist as an base (don't know if
there's something more suitable to start with) and currently I'm stuck
with sub mail_handler, since I can't figure out how to pass both sender
and recipient addresses to function.
You can't do anything with the recipient addresses in the mail handler because
they haven't been received yet! In an SMTP transaction the recipients are sent
after the MAIL command (see rfc5321).
The whitelist plugin he's using for has both mail from and rcpt to hooks
(and helos), so as to do whitelisting in all three, and, you can access
both mail from and rcpt to in the rcpt hook. So, he could do the coding
he wants in the rcpt hook.
However, I'm not sure why he needs both at the same time. In order for
his version of blacklisting or whitelisting to do anything, _both_ mail
from and rcpt to have to be in the same list.
In other words, you can only say "A can't send mail to B" - you can't
say "A can't send mail".
This isn't how you normally set up black/whitelists, and the usefulness
would be minimal.
Normally, you'd do something like this (state would be a qpsmtpd note)
state=neutral
if receiver in whitelist
state=whitelist
else if sender in whitelist
state=whitelist
if state == neutral
if sender in blacklist
reject
if receiver in blacklist
reject
[You wouldn't normally have blacklists on receivers]
Or, more simply, do each in separate plugins and remember state.
All of my filter/don't filter plugins merely set state (neutral, allow,
reject) in a note. Filtering plugins return OK if the state is allow or
reject, and only apply filtering heuristics if the state is neutral.
Then your subsequent plugins would check state before applying _their_
filtering.
As a FYI, the whitelist plugin is rather suboptimal. It linear-searches
thru the list of hash keys for a match on host or full address so it can
do regexps against the keys (to catch domain-wide listings) in addition
to exact matches on full addresses.
The better way is to load _both_ the domain and email address as
separate items into the hash. Then you can do direct hash lookups
without scanning.
I do mine somewhat differently:
I do my analogous from/to whitelist and blacklist lookups in separate
plugins - whitelist on MAILFROM, blacklist on MAILFROM, whitelist on
From: and whitelist on RCPTTO (filter bypass). Each has a separate flat
file.
The files are maintained in a postgresql database with a web front end.
When it's ready to publish the config, the postgresql dumps to the
file, and rsyncs it to the qpsmtpds (note the plural).
The flat files are turned into an alternating regexp. Eg: something
like this as a blacklist:
f...@bar.com
b...@bar.com
/....@foo\.com/
[The first two are non-regexp exact matches, the latter is full regexp]
gets turned into:
... notes('blacklistfrom', '(f...@bar\.com|b...@bar\.com|....@foo\.com)')
[I don't use hashes as I described above, because I really do want full
regexps on it, and not constrain myself to full addresses or domains
only. For example, I can do thing like /\...@.*/ if I want to block all
numeric LHSes.]
[I have a library routine to do the conversion - most of my filtering
plugins use it.]
which I test in the plugin with something like:
$pat = ... notes('blacklistfrom')
if (from =~ /^$pat$/) {
...