[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

sendmail -bv workaround on postfix.

From: Shadwick, Tony
Subject: sendmail -bv workaround on postfix.
Date: Fri, 25 Mar 2011 10:34:03 -0500
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv: Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8

So I've been putting off writing to the list about this, because I'm not 
sure what a good way to deal with the result is without creating another 
security vulnerability.

To bring some of you up to speed, way back in like 2002/2003, I wrote 
this very list stating that I needed to be able to call `sendmail -bv` 
on email addresses so that aliases correctly resolved.  A very short 
time later, the -x flag was added, and all was well.

Years later, sendmail miltering support is added to Postfix, and there 
is much rejoicing.  But all is not well.  `sendmail -bv` on postfix, 
instead of resolving the name and returning the output to stdout, 
instead delivers the information to the user's inbox.  This is not at 
all helpful for spamass-milter.

The problem for us, as I see it, is that depending on how virtual maps 
are configured in postfix, the actual replacement for `sendmail -bv` 
could be very different from one server to another.  It should always be 
(I think) `postmap -q <email address> /path/to/virtual/map`, except that 
too will fail for addresses with plus signs - an example:

The username I have on my box is tshadwick.
The email address I tend to use is address@hidden, so I have an 
entry in /etc/posfix/virtual:

address@hidden    tshadwick

postmap -q address@hidden /etc/postfix/virtual

Life is good, right?  Nope.  I create throwaway addresses using 
plussing.  If I were to register with say,, when registering, 
I would give them address@hidden

postmap -q address@hidden /etc/postfix/virtual
<null return>

Make no mistake though - that would be delivered to my mailbox.  So on 
my own system, I edited spamass-milter.cpp to look like this:

        if (flag_expand)
                 /* open a pipe to sendmail so we can do address 
expansion */

                 char buf[1024];
                 char *popen_argv[3];

                 popen_argv[0] = 
                 popen_argv[1] = envrcpt[0];
                 popen_argv[2] = NULL;

                 debug(D_RCPT, "calling %s %s", 
"/home/tshadwick/perl-scripts/postfix-address-verification", envrcpt[0]);

                 p = popenv(popen_argv, "r");
                 if (!p)
                         debug(D_RCPT, "popenv failed(%s).  Will not 
expand aliases", strerror(errno));
                 } else
                         while (fgets(buf, sizeof(buf), p) != NULL)
                                 int i = strlen(buf);
                                 /* strip trailing EOLs */
                                 while (i > 0 && buf[i - 1] <= ' ')
                                 buf[i] = '\0';
                                 debug(D_RCPT, "expansion output: %s", buf);
                                 /*      From a quick scan of the 
sendmail source, a valid email
                                         address gets printed via either
                                             "deliverable: mailer %s, 
host %s, user %s"
                                         or  "deliverable: mailer %s, 
user %s"
//                              if (strstr(buf, "... deliverable: mailer "))
//                              {
//                                      char *p=strstr(buf,", user ");
//                                      /* anything after ", user " is 
the email address */
//                                      debug(D_RCPT, "user: %s", p+7);
//                              }
                         fclose(p); p = NULL;
         } else
         debug(D_RCPT, "Total of %d actual recipients", 

In short, I I changed it from calling `sendmail -bv` to call 
`/home/tshadwick/perl-script/postfix-address-verification`, that way I 
could deal with this in a language that I actually understand.  That 
script looks like this today:

#!/usr/bin/env perl
use strict;

my $postmap = '/usr/sbin/postmap';
my $virtual = '/etc/postfix/virtual';

exit() unless $ARGV[0];
my $recipient = $ARGV[0];

# Strip the envelope.
$recipient =~ s/<(.*?)>/$1/;

# Handle plussed addresses.
$recipient =~ s/(.+?)\+.+?(address@hidden)$/$1$2/;

# Strip out any pipes or semicolons.
$recipient =~ s/\||\;//g;

my $command = "$postmap -q $recipient $virtual";
my $output = `$command`;
exit unless $output;
print $output unless $output =~ /error:nouser/;

There are a few drawbacks to this that I'm aware of:

1.  It's insecure.  There's a known attack vector to it.  I attempt to 
mitigate with how I have postfix configured and within the perl script 
itself, but it would be nice to do this "the right way".  Unfortunately, 
I'm not sure how to make the resolution command both configurable *and* 
secure.  Help?

2.  It causes spamass-milter to leave zombies.  I restart spamass-milter 
nightly to clean them up.  From the looks of it, if a transaction drops 
out while my script is still executing, spamass-milter drops a zombie.  
Presumably the only reason that would happen is a lack of input, and 
I've attempted to account for that, but still with the zombies.

3.  It's not supported by anyone but me. :)  Seriously, I'd like to get 
a solution mainlined that everyone agrees upon so that postfix 
deployments of this type are supportable.

Anyone have thoughts?  When it comes right down to it, I'm just not a c 
or c++ programmer, else I would have attempted a better solution 
already.  This is a trial-and-error hack I thew together just to get it 
to let me write a perl script resolver.  Gotta be a better way, right?  
A way to put a proper resolver command in spamass-milter's config?

Tony Shadwick

reply via email to

[Prev in Thread] Current Thread [Next in Thread]