Re: [exim] How to enforce valid From: header on local mail?

Top Page
Delete this message
Reply to this message
Author: m. allan noah
Date:  
To: exim-users
Subject: Re: [exim] How to enforce valid From: header on local mail?
On Thu, Apr 22, 2010 at 9:39 AM, m. allan noah <kitno455@???> wrote:
> Hello- have a question about header rewriting in Exim, which I have
> spent a couple days trying to solve.
>
> I need to make sure that all locally generated email (from
> /usr/sbin/sendmail or from localhost via smtp) has a proper From:
> header. Basically trying to prevent outgoing spoofs from our
> (relatively untrusted) users. I would prefer to use perl, since some
> of the checks for validity (aliases, etc) are kinda complicated.
>
> So, I have tried adding headers_rewrite to a transport, or setting up
> a rule in the global rewrite section of exim.conf. Something like:
>
> *@* ${perl{foo}{$1}{$2}{$sender_host_address}} f
>
> Where my function foo() returns a 'corrected' address for local hosts.
> I think I can cover all the corner cases to make that work reasonably.
> Unfortunately, it does not seem to work if there is no From header in
> the mail.
>
> So, my question is this: How can I detect that no From header has been
> sent, and add one?


And here is what I have come up with:

warn hosts = $received_ip_address
          control = submission


in my acl_smtp_mail, which enables 'submission mode' when the sender
ip is the same as the receiver ip. This causes exim to add From: and
Date: headers if missing, while preventing the need to list all the
local and loopback IP addresses. This does not include local
'non-smtp' submissions, but it does not need to, as exim is already
going to modify those.

Then:

*@* "${if eq{$received_ip_address}{$sender_host_address} \
       {${perl{clean_from}}}{$1@$2} \
    }" Ffrs


in my global rewrite section, which sends 4 address headers into a
perl function if the mail is locally generated, or keeps the existing
address if not.

The perl code is a little more complex, and definitely specific to our
(linux) system, but pseudo code as follows:

1. get local_part, domain, sender/receiver ip & port using Exim::expand_string
2. get the uid of the connecting user: look in /proc/net/tcp if it is
smtp, use our current uid otherwise
3. return address: localpart@domain if the user owns it, user@hostname if not.

allan

--
"The truth is an offense, but not a sin"