[exim-dev] ${if touch{}}

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Mike Cardwell
Datum:  
To: exim-dev
Betreff: [exim-dev] ${if touch{}}
Hi,

I recently wrote a greylisting implementation that uses ${exists},
${stat}, and ${run{/bin/touch}} in order to use the filesystem as a
database, rather than using something more complex like MySQL, or
talking to an external daemon via a socket.

It occured to me, that if I could do something like:

${if touch{/path/to/file}{succeeded}{failed}}

I could do it entirely "natively" inside exim rather than having the
massive overhead of spawning an external process with ${run}

We already have expansions to check if a file/dir exists, one to get the
mode, timestamps, uid, gid, and one for reading the contens of files so
why not a an expansion to create them as well? My attempt...

https://secure.grepular.com/exim-4.67_touch.patch.txt

That updates expand.c and macros.h. I'm not an experienced C coder and
this is my first attempt at implementing something more complicated in
Exims code than a couple of characters change. But that patch works for
me... Well, it works against 4.63 which is what I'm using, and I've just
modified the patch so it applies against 4.67 before submitting here.

This feature *basically* gives you the ability to set a light weight,
persistant flag that you can check/update the age of, without having
to use a much more heavy weight ${lookup} against a DB. So it has a
much wider scope for usage than just my greylisting solution.

Here's another simplified example of how it could be used: You want to
defer any mail from a host if it has sent a virus in the last 10
minutes:

## Macros
   BLACKLIST_FILE     = /var/spool/mail/blacklist/$sender_host_address
   BLACKLIST_FILE_AGE = ${eval:\
                           $tod_epoch - \
                           ${extract{mtime}{${stat:BLACKLIST_FILE}}}\
                        }


## acl_smtp_mail
   acl_check_sender:
      defer condition = ${if exists{BLACKLIST_FILE}}
            condition = ${if <{BLACKLIST_FILE_AGE}{600}}
            message   = You are blacklisted. Try again in \
                        ${eval:600-BLACKLIST_FILE_AGE} seconds


## acl_smtp_data
   acl_check_data:
      deny malware   = *
           continue  = ${if touch{BLACKLIST_FILE}}
           message   = Virus attached. You have been blocked for 10 \
                       minutes


How else would you do stuff like this without using an external db, or
an external process or, "abusing," the new ratelimit features?

There are also some other functions I'd like to see in Exim too like:
${mkdir}, ${rmdir}, ${unlink}, ${writefile}, but I'm waiting to see if I
get slapped down for this one before I worry about those ;)

My main concern was the security implications, but I don't *think* there
are any as the writes only happen as the exim user, and it should have
the same restrictions regarding filters etc as do the
${exists}/${readfile} etc functions...

There are no locking issues afaics as we're only creating a file and not
writing. It works the same as the GNU touch util regarding touching
symlinks and dirs...

I'll stop babbling now. :)

Mike