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$/) {
    ...

Reply via email to