LMTP level filtering helper script

From: Dave Cridland (
Date: Sun 16 Dec 2001 - 13:59:09 UTC

  • Next message: Dave Cridland: "The LMTP filtering script itself."

    I've knocked together a little Perl script to wrap the Anomy Sanitizer,
    and sit in between an LMTP server and the MTA.

    For those who haven't met LMTP yet, it's a cut down version of SMTP
    designed to handle a generic linking between the MTA and the MDA. Among
    the MDAs currently using it is the Cyrus IMAP server.

    Because this is Perl, and uses references, it may prove somewhat nasty
    to follow, so a quick and rapid description follows:

    This script sits in between the system's LMTP server and the system's
    MTA. It passes commands to the "real" LMTP server, and passes responses
    back. Minimal parsing happens along the way, enough to know when we're
    closing for real, and when we're closing because of some kind of error.

    When we're given the DATA command, we pass that on, too, but pass the
    actual data to an open2()ed script. The output from that
    goes into the system LMTP server connection we have open.

    Making the script work as a SMTP filter would be trivial, in as much as
    it works at all, however, SMTP may use extensions which would balk at th
    man-in-the-middle attack we're effectively doing, and besides which, we
    want to sanitize delivered email, and not submitted.

    Most errors are handled naively - if things close on us, we issue a 421
    and close the connection. This is poor, but enough, with the exception
    that if the script actually crashes, we may generate a
    SIGPIPE, and we die ourselves. More on that later.

    Because a typical intervention, according to the documented
    sendmail setup, currently uses more processes than I can reasonably
    count to deliver the email (sendmail->sanitizer->sendmail->MDA -
    obviously I can't count very high), the only time this process forks it
    to create the process. Everything else is done in a single
    process, cutting down the dedicated processes used for delivery by a
    massive 1. On busy mailservers this might make a difference. This will
    only run on one CPU, though there'll be plenty of other processes to tie
    up your other CPU(s), if you have any. If you do end up with a spare
    CPU, send it to me.

    All state information about a connection is held within the map (sorry,
    hash) that the main select loop uses, and is deleted on close(). In
    theory, therefore, I shouldn't have any memory leaks with this design,
    unless Perl doesn't free up references as I think it does.

    I'd like to merge/incorporate the code. I'll work on this
    later, however, since the code in this script runs on buffers only, and
    the code in the script works on STDIN. Getting the two
    scripts merged/melded would, of course, cut out one more process.

    The coding style used in the script is to my own taste. I make no
    apologies. :-)

    Current Code Level:

    This script is ALPHA quality. And that's being generous. It has not been
    used in any production system. It has been tested, to an extent, and
    actually runs, much to my surprise.

    Usage Instructions:

    1) Open up the script in your least favourite text editor. Struggle to
    find the line '## CONFIG START'.
    2) Randomly change the values you find there until things might work.
    What the values mean should be explained on the previous line. What the
    values as supplied are is supplied at the end of the line.
    3) Experiment with different values for "preopen" and "max", until you
    realise they're unimplemented anyway.
    4) Save the script, and run it.


    This software has no warranty including fitness for purpose, and the
    author disclaims all responsibility in so far as he is able. In fact,
    the author would like to suggest that calling this software is a very
    charitable act, and if it runs at all, let alone does what you might
    expect it to, then the author would be really interested.

    The software is copyright 2001 Dave Cridland.

    You may distribute it under the GPL, version 2, or at your discretion
    any later version. If the GPL is too restrictive, please contact the
    author, who will consider LGPL terms instead.


    Dave Cridland <>

    hosted by